/** * three.quarks v0.15.6 build Fri Jan 17 2025 * https://quarks.art * Copyright 2025 Alchemist0823 , MIT */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) : typeof define === 'function' && define.amd ? define(['exports', 'three'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.THREE = global.THREE || {}, global.THREE.QUARKS = {}), global.THREE)); })(this, (function (exports, three) { 'use strict'; var soft_fragment = /* glsl */"\n#ifdef SOFT_PARTICLES\n\n /* #ifdef LOGDEPTH\n float distSample = linearize_depth_log(sampleDepth, near, far);\n #else\n float distSample = ortho ? linearize_depth_ortho(sampleDepth, near, far) : linearize_depth(sampleDepth, near, far);\n #endif */\n\n vec2 p2 = projPosition.xy / projPosition.w;\n \n p2 = 0.5 * p2 + 0.5;\n\n float readDepth = texture2D(depthTexture, p2.xy).r;\n float viewDepth = linearize_depth(readDepth);\n\n float softParticlesFade = saturate(SOFT_INV_FADE_DISTANCE * ((viewDepth - SOFT_NEAR_FADE) - linearDepth));\n \n gl_FragColor *= softParticlesFade;\n\n //gl_FragColor = vec4(softParticlesFade , 0, 0, 1);\n#endif\n"; var soft_pars_fragment = /* glsl */"\n#ifdef SOFT_PARTICLES\n\n uniform sampler2D depthTexture;\n uniform vec4 projParams;\n uniform vec2 softParams;\n\n varying vec4 projPosition;\n varying float linearDepth;\n\n #define SOFT_NEAR_FADE softParams.x\n #define SOFT_INV_FADE_DISTANCE softParams.y\n\n #define zNear projParams.x\n #define zFar projParams.y\n\n float linearize_depth(float d)\n {\n return (zFar * zNear) / (zFar - d * (zFar - zNear));\n }\n\n#endif\n"; var soft_pars_vertex = /* glsl */"\n#ifdef SOFT_PARTICLES\n varying vec4 projPosition;\n varying float linearDepth;\n#endif\n"; var soft_vertex = /* glsl */"\n#ifdef SOFT_PARTICLES\n projPosition = gl_Position;\n linearDepth = -mvPosition.z;\n#endif\n"; var tile_fragment = /* glsl */"\n#ifdef USE_MAP\n vec4 texelColor = texture2D( map, vUv);\n #ifdef TILE_BLEND\n texelColor = mix( texelColor, texture2D( map, vUvNext ), vUvBlend );\n #endif\n diffuseColor *= texelColor;\n#endif\n"; var tile_pars_fragment = /* glsl */"\n#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\n\tvarying vec2 vUv;\n#ifdef TILE_BLEND\n varying vec2 vUvNext;\n varying float vUvBlend;\n#endif\n\n#endif\n#ifdef USE_MAP\n\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#ifdef TILE_BLEND\n varying vec2 vMapUvNext;\n#endif\n\n#endif\n#ifdef USE_ALPHAMAP\n\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n\n#endif\n#ifdef USE_LIGHTMAP\n\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n\n#endif\n#ifdef USE_AOMAP\n\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n\n#endif\n#ifdef USE_BUMPMAP\n\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n\n#endif\n#ifdef USE_NORMALMAP\n\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n\n#endif\n#ifdef USE_EMISSIVEMAP\n\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n\n#endif\n#ifdef USE_METALNESSMAP\n\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n\n#endif\n#ifdef USE_ROUGHNESSMAP\n\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n\n#endif\n#ifdef USE_ANISOTROPYMAP\n\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n\n#endif\n#ifdef USE_CLEARCOATMAP\n\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n\n#endif\n#ifdef USE_SPECULARMAP\n\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n\n#endif\n#ifdef USE_THICKNESSMAP\n\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n\n#endif\n"; var tile_pars_vertex = /* glsl */"\n#ifdef UV_TILE\n attribute float uvTile;\n uniform vec2 tileCount;\n \n mat3 makeTileTransform(float uvTile) {\n float col = mod(uvTile, tileCount.x);\n float row = (tileCount.y - floor(uvTile / tileCount.x) - 1.0);\n \n return mat3(\n 1.0 / tileCount.x, 0.0, 0.0,\n 0.0, 1.0 / tileCount.y, 0.0, \n col / tileCount.x, row / tileCount.y, 1.0);\n }\n#else\n mat3 makeTileTransform(float uvTile) {\n return mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);\n }\n#endif\n\n#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\n\tvarying vec2 vUv;\n#ifdef TILE_BLEND\n varying vec2 vUvNext;\n varying float vUvBlend;\n#endif\n\n#endif\n#ifdef USE_MAP\n\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#ifdef TILE_BLEND\n varying vec2 vMapUvNext;\n#endif\n\n#endif\n#ifdef USE_ALPHAMAP\n\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n\n#endif\n#ifdef USE_LIGHTMAP\n\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n\n#endif\n#ifdef USE_AOMAP\n\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n\n#endif\n#ifdef USE_BUMPMAP\n\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n\n#endif\n#ifdef USE_NORMALMAP\n\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n\n#endif\n#ifdef USE_EMISSIVEMAP\n\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n\n#endif\n#ifdef USE_METALNESSMAP\n\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n\n#endif\n#ifdef USE_ROUGHNESSMAP\n\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n\n#endif\n#ifdef USE_ANISOTROPYMAP\n\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n\n#endif\n#ifdef USE_CLEARCOATMAP\n\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n\n#endif\n#ifdef USE_SPECULARMAP\n\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n\n#endif\n#ifdef USE_THICKNESSMAP\n\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n\n#endif\n"; var tile_vertex = /* glsl */"\n#ifdef UV_TILE\n mat3 tileTransform = makeTileTransform(floor(uvTile));\n #ifdef TILE_BLEND\n mat3 nextTileTransform = makeTileTransform(ceil(uvTile));\n vUvBlend = fract(uvTile);\n #endif\n#else\n mat3 tileTransform = makeTileTransform(0.0);\n#endif\n\n#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\nvUv = (tileTransform *vec3( uv, 1 )).xy;\n#if defined( TILE_BLEND ) && defined( UV_TILE )\n vUvNext = (nextTileTransform *vec3( uv, 1 )).xy;\n#endif\n\n#endif\n#ifdef USE_MAP\n\nvMapUv = ( tileTransform * (mapTransform * vec3( MAP_UV, 1 ) )).xy;\n#if defined( TILE_BLEND ) && defined( UV_TILE )\n vMapUvNext = (nextTileTransform * (mapTransform * vec3( MAP_UV, 1 ))).xy;\n#endif\n\n#endif\n#ifdef USE_ALPHAMAP\n\nvAlphaMapUv = ( tileTransform * (alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) )).xy;\n \n#endif\n#ifdef USE_LIGHTMAP\n\nvLightMapUv = ( tileTransform * (lightMapTransform * vec3( LIGHTMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_AOMAP\n\nvAoMapUv = ( tileTransform * (aoMapTransform * vec3( AOMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_BUMPMAP\n\nvBumpMapUv = ( tileTransform * (bumpMapTransform * vec3( BUMPMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_NORMALMAP\n\nvNormalMapUv = ( tileTransform * (normalMapTransform * vec3( NORMALMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\nvDisplacementMapUv = ( tileTransform * (displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_EMISSIVEMAP\n\nvEmissiveMapUv = ( tileTransform * (emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_METALNESSMAP\n\nvMetalnessMapUv = ( tileTransform * (metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_ROUGHNESSMAP\n\nvRoughnessMapUv = ( tileTransform * (roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_ANISOTROPYMAP\n\nvAnisotropyMapUv = ( tileTransform * (anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_CLEARCOATMAP\n\nvClearcoatMapUv = ( tileTransform * (clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\nvClearcoatNormalMapUv = ( tileTransform * (clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\nvClearcoatRoughnessMapUv = ( tileTransform * (clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\nvIridescenceMapUv = ( tileTransform * (iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\nvIridescenceThicknessMapUv = ( tileTransform * (iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\nvSheenColorMapUv = ( tileTransform * (sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\nvSheenRoughnessMapUv = ( tileTransform * (sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_SPECULARMAP\n\nvSpecularMapUv = ( tileTransform * (specularMapTransform * vec3( SPECULARMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\nvSpecularColorMapUv = ( tileTransform * (specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\nvSpecularIntensityMapUv = ( tileTransform * (specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\nvTransmissionMapUv = ( tileTransform * transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) )).xy;\n\n#endif\n#ifdef USE_THICKNESSMAP\n\nvThicknessMapUv = ( tileTransform * thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) )).xy;\n\n#endif\n\n"; var ShaderChunk = three.ShaderChunk; function registerShaderChunks() { ShaderChunk['tile_pars_vertex'] = tile_pars_vertex; ShaderChunk['tile_vertex'] = tile_vertex; ShaderChunk['tile_pars_fragment'] = tile_pars_fragment; ShaderChunk['tile_fragment'] = tile_fragment; ShaderChunk['soft_pars_vertex'] = soft_pars_vertex; ShaderChunk['soft_vertex'] = soft_vertex; ShaderChunk['soft_pars_fragment'] = soft_pars_fragment; ShaderChunk['soft_fragment'] = soft_fragment; } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var n = 0, F = function () {}; return { s: F, n: function () { return n >= r.length ? { done: !0 } : { done: !1, value: r[n++] }; }, e: function (r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function () { t = t.call(r); }, n: function () { var r = t.next(); return a = r.done, r; }, e: function (r) { u = !0, o = r; }, f: function () { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _get() { return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } /** * Interface representing metadata used in Threejs object toJSON method. */ /** * Class representing a three.quarks particle emitter. particle emitter is a node in the three.js scene graph * every particle emitter only associates with a particle system. * particle system * @extends Object3D * @template E - Type of the event map. */ var ParticleEmitter = /*#__PURE__*/function (_Object3D) { /** * Creates an instance of ParticleEmitter. * @param {IParticleSystem} system - The particle system to be used. */ function ParticleEmitter(system) { var _this; _classCallCheck(this, ParticleEmitter); _this = _callSuper(this, ParticleEmitter); _defineProperty(_this, "type", 'ParticleEmitter'); _defineProperty(_this, "system", void 0); _this.system = system; return _this; } /** * Clones the particle emitter. * @returns {ParticleEmitter} A new instance of ParticleEmitter. */ _inherits(ParticleEmitter, _Object3D); return _createClass(ParticleEmitter, [{ key: "clone", value: function clone() { var system = this.system.clone(); system.emitter.copy(this, true); return system.emitter; } /** * Disposes the particle emitter. */ }, { key: "dispose", value: function dispose() {} /** * Extracts data from the cache. * @param {any} cache - The cache to extract data from. * @returns {any[]} An array of extracted data without metadata. */ }, { key: "extractFromCache", value: function extractFromCache(cache) { var values = []; for (var key in cache) { var data = cache[key]; delete data.metadata; values.push(data); } return values; } /** * Converts the particle emitter to JSON. * @param {MetaData} [meta] - Optional metadata. * @param {SerializationOptions} [options={}] - Optional serialization options. * @returns {any} The JSON representation of the particle emitter. */ }, { key: "toJSON", value: function toJSON(meta) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var children = this.children; this.children = this.children.filter(function (child) { return child.type !== 'ParticleSystemPreview'; }); var data = _get(_getPrototypeOf(ParticleEmitter.prototype), "toJSON", this).call(this, meta); this.children = children; if (this.system !== null) data.object.ps = this.system.toJSON(meta, options); return data; } }]); }(three.Object3D); /** * quarks.core v0.15.4 build Fri Jan 17 2025 * https://quarks.art * Copyright 2025 Alchemist0823 , MIT */ 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; 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]; return uuid.toLowerCase(); } function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } function euclideanModulo(n, m) { return ((n % m) + m) % m; } function mapLinear(x, a1, a2, b1, b2) { return b1 + (x - a1) * (b2 - b1) / (a2 - a1); } function inverseLerp(x, y, value) { if (x !== y) { return (value - x) / (y - x); } else { return 0; } } function lerp(x, y, t) { return (1 - t) * x + t * y; } function damp(x, y, lambda, dt) { return lerp(x, y, 1 - Math.exp(-lambda * dt)); } function pingpong(x, length = 1) { return length - Math.abs(euclideanModulo(x, length * 2) - length); } 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); } function randInt(low, high) { return low + Math.floor(Math.random() * (high - low + 1)); } function randFloat(low, high) { return low + Math.random() * (high - low); } function randFloatSpread(range) { return range * (0.5 - Math.random()); } function seededRandom(s) { if (s !== undefined) _seed = s; 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) { 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('../math.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order); } } function denormalize(value, array) { switch (array.constructor) { case Float32Array: return value; case Uint32Array: return value / 4294967295.0; case Uint16Array: return value / 65535.0; case Uint8Array: return value / 255.0; case Int32Array: return Math.max(value / 2147483647.0, -1.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 Uint32Array: return Math.round(value * 4294967295.0); case Uint16Array: return Math.round(value * 65535.0); case Uint8Array: return Math.round(value * 255.0); case Int32Array: return Math.round(value * 2147483647.0); case Int16Array: return Math.round(value * 32767.0); case Int8Array: return Math.round(value * 127.0); default: throw new Error('Invalid component type.'); } } const MathUtils = { 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) { 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; 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; 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 Quaternion(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 = true) { const x = euler._x, y = euler._y, z = euler._z, order = euler._order; 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('../math.Quaternion: .setFromEuler() encountered an unknown order: ' + order); } if (update === true) this._onChangeCallback(); return this; } setFromAxisAngle(axis, angle) { 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) { 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) { let r = vFrom.dot(vTo) + 1; if (r < Number.EPSILON) { 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 { 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() { 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) { 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; 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(); 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() { const theta1 = 2 * Math.PI * Math.random(); const theta2 = 2 * Math.PI * Math.random(); const x0 = Math.random(); const r1 = Math.sqrt(1 - x0); const r2 = Math.sqrt(x0); return this.set(r1 * Math.sin(theta1), r1 * Math.cos(theta1), r2 * Math.sin(theta2), r2 * Math.cos(theta2)); } 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; } toJSON() { return this.toArray(); } _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) { this.isVector3 = true; Vector3.prototype.isVector3 = true; this.x = x; this.y = y; this.z = z; } set(x, y, z) { if (z === undefined) z = this.z; 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 Vector3(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 vx = this.x, vy = this.y, vz = this.z; const qx = q.x, qy = q.y, qz = q.z, qw = q.w; const tx = 2 * (qy * vz - qz * vy); const ty = 2 * (qz * vx - qx * vz); const tz = 2 * (qx * vy - qy * vx); this.x = vx + qw * tx + qy * tz - qz * ty; this.y = vy + qw * ty + qz * tx - qx * tz; this.z = vz + qw * tz + qx * ty - qy * tx; return this; } transformDirection(m) { 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) { 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 = Math.trunc(this.x); this.y = Math.trunc(this.y); this.z = Math.trunc(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; } 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.copy(this).projectOnVector(planeNormal); return this.sub(_vector); } reflect(normal) { return this.sub(_vector.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; 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); } 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; } 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; } random() { this.x = Math.random(); this.y = Math.random(); this.z = Math.random(); return this; } randomDirection() { const theta = Math.random() * Math.PI * 2; const u = Math.random() * 2 - 1; const c = Math.sqrt(1 - u * u); this.x = c * Math.cos(theta); this.y = u; this.z = c * Math.sin(theta); return this; } abs() { this.x = Math.abs(this.x); this.y = Math.abs(this.y); this.z = Math.abs(this.z); return this; } *[Symbol.iterator]() { yield this.x; yield this.y; yield this.z; } } const _vector = new Vector3(); const _quaternion$1 = new Quaternion(); const WebGLCoordinateSystem = 2000; const WebGPUCoordinateSystem = 2001; class Matrix4 { constructor(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) { this.isMatrix4 = true; Matrix4.prototype.isMatrix4 = true; this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; if (n11 !== undefined) { this.set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44); } } extractPosition(m) { console.warn('THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().'); return this.copyPosition(m); } multiplyToArray(a, b, r) { console.error('THREE.Matrix4: .multiplyToArray() has been removed.'); return this; } setRotationFromQuaternion(q) { return this.makeRotationFromQuaternion(q); } set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) { const te = this.elements; te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14; te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24; te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34; te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44; return this; } identity() { this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); return this; } clone() { return new Matrix4().fromArray(this.elements); } copy(m) { const te = this.elements; const me = m.elements; te[0] = me[0]; te[1] = me[1]; te[2] = me[2]; te[3] = me[3]; te[4] = me[4]; te[5] = me[5]; te[6] = me[6]; te[7] = me[7]; te[8] = me[8]; te[9] = me[9]; te[10] = me[10]; te[11] = me[11]; te[12] = me[12]; te[13] = me[13]; te[14] = me[14]; te[15] = me[15]; return this; } copyPosition(m) { const te = this.elements, me = m.elements; te[12] = me[12]; te[13] = me[13]; te[14] = me[14]; return this; } setFromMatrix3(m) { const me = m.elements; this.set(me[0], me[3], me[6], 0, me[1], me[4], me[7], 0, me[2], me[5], me[8], 0, 0, 0, 0, 1); return this; } extractBasis(xAxis, yAxis, zAxis) { xAxis.setFromMatrixColumn(this, 0); yAxis.setFromMatrixColumn(this, 1); zAxis.setFromMatrixColumn(this, 2); return this; } makeBasis(xAxis, yAxis, zAxis) { this.set(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, 0, 0, 0, 1); return this; } extractRotation(m) { const te = this.elements; const me = m.elements; const scaleX = 1 / _v1.setFromMatrixColumn(m, 0).length(); const scaleY = 1 / _v1.setFromMatrixColumn(m, 1).length(); const scaleZ = 1 / _v1.setFromMatrixColumn(m, 2).length(); te[0] = me[0] * scaleX; te[1] = me[1] * scaleX; te[2] = me[2] * scaleX; te[3] = 0; te[4] = me[4] * scaleY; te[5] = me[5] * scaleY; te[6] = me[6] * scaleY; te[7] = 0; te[8] = me[8] * scaleZ; te[9] = me[9] * scaleZ; te[10] = me[10] * scaleZ; te[11] = 0; te[12] = 0; te[13] = 0; te[14] = 0; te[15] = 1; return this; } makeRotationFromEuler(euler) { const te = this.elements; const x = euler.x, y = euler.y, z = euler.z; const a = Math.cos(x), b = Math.sin(x); const c = Math.cos(y), d = Math.sin(y); const e = Math.cos(z), f = Math.sin(z); if (euler.order === 'XYZ') { const ae = a * e, af = a * f, be = b * e, bf = b * f; te[0] = c * e; te[4] = -c * f; te[8] = d; te[1] = af + be * d; te[5] = ae - bf * d; te[9] = -b * c; te[2] = bf - ae * d; te[6] = be + af * d; te[10] = a * c; } else if (euler.order === 'YXZ') { const ce = c * e, cf = c * f, de = d * e, df = d * f; te[0] = ce + df * b; te[4] = de * b - cf; te[8] = a * d; te[1] = a * f; te[5] = a * e; te[9] = -b; te[2] = cf * b - de; te[6] = df + ce * b; te[10] = a * c; } else if (euler.order === 'ZXY') { const ce = c * e, cf = c * f, de = d * e, df = d * f; te[0] = ce - df * b; te[4] = -a * f; te[8] = de + cf * b; te[1] = cf + de * b; te[5] = a * e; te[9] = df - ce * b; te[2] = -a * d; te[6] = b; te[10] = a * c; } else if (euler.order === 'ZYX') { const ae = a * e, af = a * f, be = b * e, bf = b * f; te[0] = c * e; te[4] = be * d - af; te[8] = ae * d + bf; te[1] = c * f; te[5] = bf * d + ae; te[9] = af * d - be; te[2] = -d; te[6] = b * c; te[10] = a * c; } else if (euler.order === 'YZX') { const ac = a * c, ad = a * d, bc = b * c, bd = b * d; te[0] = c * e; te[4] = bd - ac * f; te[8] = bc * f + ad; te[1] = f; te[5] = a * e; te[9] = -b * e; te[2] = -d * e; te[6] = ad * f + bc; te[10] = ac - bd * f; } else if (euler.order === 'XZY') { const ac = a * c, ad = a * d, bc = b * c, bd = b * d; te[0] = c * e; te[4] = -f; te[8] = d * e; te[1] = ac * f + bd; te[5] = a * e; te[9] = ad * f - bc; te[2] = bc * f - ad; te[6] = b * e; te[10] = bd * f + ac; } te[3] = 0; te[7] = 0; te[11] = 0; te[12] = 0; te[13] = 0; te[14] = 0; te[15] = 1; return this; } makeRotationFromQuaternion(q) { return this.compose(_zero, q, _one); } lookAt(eye, target, up) { const te = this.elements; _z.subVectors(eye, target); if (_z.lengthSq() === 0) { _z.z = 1; } _z.normalize(); _x.crossVectors(up, _z); if (_x.lengthSq() === 0) { if (Math.abs(up.z) === 1) { _z.x += 0.0001; } else { _z.z += 0.0001; } _z.normalize(); _x.crossVectors(up, _z); } _x.normalize(); _y.crossVectors(_z, _x); te[0] = _x.x; te[4] = _y.x; te[8] = _z.x; te[1] = _x.y; te[5] = _y.y; te[9] = _z.y; te[2] = _x.z; te[6] = _y.z; te[10] = _z.z; return this; } multiply(m) { return this.multiplyMatrices(this, m); } premultiply(m) { return this.multiplyMatrices(m, this); } multiplyMatrices(a, b) { const ae = a.elements; const be = b.elements; const te = this.elements; const a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12]; const a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13]; const a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14]; const a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15]; const b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12]; const b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13]; const b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14]; const b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15]; te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; return this; } multiplyScalar(s) { const te = this.elements; te[0] *= s; te[4] *= s; te[8] *= s; te[12] *= s; te[1] *= s; te[5] *= s; te[9] *= s; te[13] *= s; te[2] *= s; te[6] *= s; te[10] *= s; te[14] *= s; te[3] *= s; te[7] *= s; te[11] *= s; te[15] *= s; return this; } determinant() { const te = this.elements; const n11 = te[0], n12 = te[4], n13 = te[8], n14 = te[12]; const n21 = te[1], n22 = te[5], n23 = te[9], n24 = te[13]; const n31 = te[2], n32 = te[6], n33 = te[10], n34 = te[14]; const n41 = te[3], n42 = te[7], n43 = te[11], n44 = te[15]; return (n41 * (+n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34) + n42 * (+n11 * n23 * n34 - n11 * n24 * n33 + n14 * n21 * n33 - n13 * n21 * n34 + n13 * n24 * n31 - n14 * n23 * n31) + n43 * (+n11 * n24 * n32 - n11 * n22 * n34 - n14 * n21 * n32 + n12 * n21 * n34 + n14 * n22 * n31 - n12 * n24 * n31) + n44 * (-n13 * n22 * n31 - n11 * n23 * n32 + n11 * n22 * n33 + n13 * n21 * n32 - n12 * n21 * n33 + n12 * n23 * n31)); } transpose() { const te = this.elements; let tmp; tmp = te[1]; te[1] = te[4]; te[4] = tmp; tmp = te[2]; te[2] = te[8]; te[8] = tmp; tmp = te[6]; te[6] = te[9]; te[9] = tmp; tmp = te[3]; te[3] = te[12]; te[12] = tmp; tmp = te[7]; te[7] = te[13]; te[13] = tmp; tmp = te[11]; te[11] = te[14]; te[14] = tmp; return this; } setPosition(x, y, z) { const te = this.elements; if (x.isVector3) { te[12] = x.x; te[13] = x.y; te[14] = x.z; } else { te[12] = x; te[13] = y; te[14] = z; } return this; } invert() { const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n41 = te[3], n12 = te[4], n22 = te[5], n32 = te[6], n42 = te[7], n13 = te[8], n23 = te[9], n33 = te[10], n43 = te[11], n14 = te[12], n24 = te[13], n34 = te[14], n44 = te[15], t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); const detInv = 1 / det; te[0] = t11 * detInv; te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv; te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv; te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv; te[4] = t12 * detInv; te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv; te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv; te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv; te[8] = t13 * detInv; te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv; te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv; te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv; te[12] = t14 * detInv; te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv; te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv; te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv; return this; } scale(v) { const te = this.elements; const x = v.x, y = v.y, z = v.z; te[0] *= x; te[4] *= y; te[8] *= z; te[1] *= x; te[5] *= y; te[9] *= z; te[2] *= x; te[6] *= y; te[10] *= z; te[3] *= x; te[7] *= y; te[11] *= z; return this; } getMaxScaleOnAxis() { const te = this.elements; const scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2]; const scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6]; const scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10]; return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq)); } makeTranslation(x, y, z) { if (x.isVector3) { this.set(1, 0, 0, x.x, 0, 1, 0, x.y, 0, 0, 1, x.z, 0, 0, 0, 1); } else { this.set(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1); } return this; } makeRotationX(theta) { const c = Math.cos(theta), s = Math.sin(theta); this.set(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1); return this; } makeRotationY(theta) { const c = Math.cos(theta), s = Math.sin(theta); this.set(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1); return this; } makeRotationZ(theta) { const c = Math.cos(theta), s = Math.sin(theta); this.set(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); return this; } makeRotationAxis(axis, angle) { const c = Math.cos(angle); const s = Math.sin(angle); const t = 1 - c; const x = axis.x, y = axis.y, z = axis.z; const tx = t * x, ty = t * y; this.set(tx * x + c, tx * y - s * z, tx * z + s * y, 0, tx * y + s * z, ty * y + c, ty * z - s * x, 0, tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 0, 0, 0, 1); return this; } makeScale(x, y, z) { this.set(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1); return this; } makeShear(xy, xz, yx, yz, zx, zy) { this.set(1, yx, zx, 0, xy, 1, zy, 0, xz, yz, 1, 0, 0, 0, 0, 1); return this; } compose(position, quaternion, scale) { const te = this.elements; const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; const x2 = x + x, y2 = y + y, z2 = z + z; const xx = x * x2, xy = x * y2, xz = x * z2; const yy = y * y2, yz = y * z2, zz = z * z2; const wx = w * x2, wy = w * y2, wz = w * z2; const sx = scale.x, sy = scale.y, sz = scale.z; te[0] = (1 - (yy + zz)) * sx; te[1] = (xy + wz) * sx; te[2] = (xz - wy) * sx; te[3] = 0; te[4] = (xy - wz) * sy; te[5] = (1 - (xx + zz)) * sy; te[6] = (yz + wx) * sy; te[7] = 0; te[8] = (xz + wy) * sz; te[9] = (yz - wx) * sz; te[10] = (1 - (xx + yy)) * sz; te[11] = 0; te[12] = position.x; te[13] = position.y; te[14] = position.z; te[15] = 1; return this; } decompose(position, quaternion, scale) { const te = this.elements; let sx = _v1.set(te[0], te[1], te[2]).length(); const sy = _v1.set(te[4], te[5], te[6]).length(); const sz = _v1.set(te[8], te[9], te[10]).length(); const det = this.determinant(); if (det < 0) sx = -sx; position.x = te[12]; position.y = te[13]; position.z = te[14]; _m1.copy(this); const invSX = 1 / sx; const invSY = 1 / sy; const invSZ = 1 / sz; _m1.elements[0] *= invSX; _m1.elements[1] *= invSX; _m1.elements[2] *= invSX; _m1.elements[4] *= invSY; _m1.elements[5] *= invSY; _m1.elements[6] *= invSY; _m1.elements[8] *= invSZ; _m1.elements[9] *= invSZ; _m1.elements[10] *= invSZ; quaternion.setFromRotationMatrix(_m1); scale.x = sx; scale.y = sy; scale.z = sz; return this; } makePerspective(left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem) { const te = this.elements; const x = (2 * near) / (right - left); const y = (2 * near) / (top - bottom); const a = (right + left) / (right - left); const b = (top + bottom) / (top - bottom); let c, d; if (coordinateSystem === WebGLCoordinateSystem) { c = -(far + near) / (far - near); d = (-2 * far * near) / (far - near); } else if (coordinateSystem === WebGPUCoordinateSystem) { c = -far / (far - near); d = (-far * near) / (far - near); } else { throw new Error('Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem); } te[0] = x; te[4] = 0; te[8] = a; te[12] = 0; te[1] = 0; te[5] = y; te[9] = b; te[13] = 0; te[2] = 0; te[6] = 0; te[10] = c; te[14] = d; te[3] = 0; te[7] = 0; te[11] = -1; te[15] = 0; return this; } makeOrthographic(left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem) { const te = this.elements; const w = 1.0 / (right - left); const h = 1.0 / (top - bottom); const p = 1.0 / (far - near); const x = (right + left) * w; const y = (top + bottom) * h; let z, zInv; if (coordinateSystem === WebGLCoordinateSystem) { z = (far + near) * p; zInv = -2 * p; } else if (coordinateSystem === WebGPUCoordinateSystem) { z = near * p; zInv = -1 * p; } else { throw new Error('../math.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem); } te[0] = 2 * w; te[4] = 0; te[8] = 0; te[12] = -x; te[1] = 0; te[5] = 2 * h; te[9] = 0; te[13] = -y; te[2] = 0; te[6] = 0; te[10] = zInv; te[14] = -z; te[3] = 0; te[7] = 0; te[11] = 0; te[15] = 1; return this; } equals(matrix) { const te = this.elements; const me = matrix.elements; for (let i = 0; i < 16; i++) { if (te[i] !== me[i]) return false; } return true; } fromArray(array, offset = 0) { for (let i = 0; i < 16; i++) { this.elements[i] = array[i + offset]; } return this; } toArray(array = [], offset = 0) { const te = this.elements; array[offset] = te[0]; array[offset + 1] = te[1]; array[offset + 2] = te[2]; array[offset + 3] = te[3]; array[offset + 4] = te[4]; array[offset + 5] = te[5]; array[offset + 6] = te[6]; array[offset + 7] = te[7]; array[offset + 8] = te[8]; array[offset + 9] = te[9]; array[offset + 10] = te[10]; array[offset + 11] = te[11]; array[offset + 12] = te[12]; array[offset + 13] = te[13]; array[offset + 14] = te[14]; array[offset + 15] = te[15]; return array; } } const _v1 = new Vector3(); const _m1 = new Matrix4(); const _zero = new Vector3(0, 0, 0); const _one = new Vector3(1, 1, 1); const _x = new Vector3(); const _y = new Vector3(); const _z = new Vector3(); const _matrix = new Matrix4(); const _quaternion = new Quaternion(); class Euler { constructor(x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER) { this.isEuler = true; this._x = x; this._y = y; this._z = z; this._order = order; } 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 order() { return this._order; } set order(value) { this._order = value; this._onChangeCallback(); } set(x, y, z, order = this._order) { this._x = x; this._y = y; this._z = z; this._order = order; this._onChangeCallback(); return this; } clone() { return new Euler(this._x, this._y, this._z, this._order); } copy(euler) { this._x = euler._x; this._y = euler._y; this._z = euler._z; this._order = euler._order; this._onChangeCallback(); return this; } setFromRotationMatrix(m, order = this._order, update = true) { const te = m.elements; const m11 = te[0], m12 = te[4], m13 = te[8]; const m21 = te[1], m22 = te[5], m23 = te[9]; const m31 = te[2], m32 = te[6], m33 = te[10]; switch (order) { case 'XYZ': this._y = Math.asin(clamp(m13, -1, 1)); if (Math.abs(m13) < 0.9999999) { this._x = Math.atan2(-m23, m33); this._z = Math.atan2(-m12, m11); } else { this._x = Math.atan2(m32, m22); this._z = 0; } break; case 'YXZ': this._x = Math.asin(-clamp(m23, -1, 1)); if (Math.abs(m23) < 0.9999999) { this._y = Math.atan2(m13, m33); this._z = Math.atan2(m21, m22); } else { this._y = Math.atan2(-m31, m11); this._z = 0; } break; case 'ZXY': this._x = Math.asin(clamp(m32, -1, 1)); if (Math.abs(m32) < 0.9999999) { this._y = Math.atan2(-m31, m33); this._z = Math.atan2(-m12, m22); } else { this._y = 0; this._z = Math.atan2(m21, m11); } break; case 'ZYX': this._y = Math.asin(-clamp(m31, -1, 1)); if (Math.abs(m31) < 0.9999999) { this._x = Math.atan2(m32, m33); this._z = Math.atan2(m21, m11); } else { this._x = 0; this._z = Math.atan2(-m12, m22); } break; case 'YZX': this._z = Math.asin(clamp(m21, -1, 1)); if (Math.abs(m21) < 0.9999999) { this._x = Math.atan2(-m23, m22); this._y = Math.atan2(-m31, m11); } else { this._x = 0; this._y = Math.atan2(m13, m33); } break; case 'XZY': this._z = Math.asin(-clamp(m12, -1, 1)); if (Math.abs(m12) < 0.9999999) { this._x = Math.atan2(m32, m22); this._y = Math.atan2(m13, m11); } else { this._x = Math.atan2(-m23, m33); this._y = 0; } break; default: console.warn('../math.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order); } this._order = order; if (update === true) this._onChangeCallback(); return this; } setFromQuaternion(q, order, update) { _matrix.makeRotationFromQuaternion(q); return this.setFromRotationMatrix(_matrix, order, update); } setFromVector3(v, order = this._order) { return this.set(v.x, v.y, v.z, order); } reorder(newOrder) { _quaternion.setFromEuler(this); return this.setFromQuaternion(_quaternion, newOrder); } equals(euler) { return euler._x === this._x && euler._y === this._y && euler._z === this._z && euler._order === this._order; } fromArray(array) { this._x = array[0]; this._y = array[1]; this._z = array[2]; if (array[3] !== undefined) this._order = array[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._order; return array; } _onChange(callback) { this._onChangeCallback = callback; return this; } _onChangeCallback(euler) { } *[Symbol.iterator]() { yield this._x; yield this._y; yield this._z; yield this._order; } } Euler.DEFAULT_ORDER = 'XYZ'; class Vector2 { constructor(x = 0, y = 0) { 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 Vector2(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) { 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 = Math.trunc(this.x); this.y = Math.trunc(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() { const angle = Math.atan2(-this.y, -this.x) + Math.PI; return angle; } angleTo(v) { const denominator = Math.sqrt(this.lengthSq() * v.lengthSq()); if (denominator === 0) return Math.PI / 2; const theta = this.dot(v) / denominator; 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; 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; } 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; } } Vector2.isVector2 = true; class Vector4 { constructor(x = 0, y = 0, z = 0, w = 1) { Vector4.prototype.isVector4 = true; this.x = x; this.y = y; this.z = z; this.w = w; } get width() { return this.z; } set width(value) { this.z = value; } get height() { return this.w; } set height(value) { this.w = value; } set(x, y, z, w) { this.x = x; this.y = y; this.z = z; this.w = w; return this; } setScalar(scalar) { this.x = scalar; this.y = scalar; this.z = scalar; this.w = scalar; return this; } setX(x) { this.x = x; return this; } setY(y) { this.y = y; return this; } setZ(z) { this.z = z; return this; } setW(w) { this.w = w; 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; case 3: this.w = 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; case 3: return this.w; default: throw new Error('index is out of range: ' + index); } } clone() { return new Vector4(this.x, this.y, this.z, this.w); } copy(v) { this.x = v.x; this.y = v.y; this.z = v.z; this.w = v.w; return this; } add(v) { this.x += v.x; this.y += v.y; this.z += v.z; this.w += v.w; return this; } addScalar(scalar) { this.x += scalar; this.y += scalar; this.z += scalar; this.w += scalar; return this; } addVectors(a, b) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; this.w = a.w + b.w; return this; } addScaledVector(v, s) { this.x += v.x * s; this.y += v.y * s; this.z += v.z * s; this.w += v.w * s; return this; } sub(v) { this.x -= v.x; this.y -= v.y; this.z -= v.z; this.w -= v.w; return this; } subScalar(scalar) { this.x -= scalar; this.y -= scalar; this.z -= scalar; this.w -= scalar; return this; } subVectors(a, b) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; this.w = a.w - b.w; return this; } multiply(v) { this.x *= v.x; this.y *= v.y; this.z *= v.z; this.w *= v.w; return this; } multiplyScalar(scalar) { this.x *= scalar; this.y *= scalar; this.z *= scalar; this.w *= scalar; return this; } applyMatrix4(m) { const x = this.x, y = this.y, z = this.z, w = this.w; const e = m.elements; this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w; this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w; this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w; this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w; return this; } divideScalar(scalar) { return this.multiplyScalar(1 / scalar); } setAxisAngleFromQuaternion(q) { this.w = 2 * Math.acos(q.w); const s = Math.sqrt(1 - q.w * q.w); if (s < 0.0001) { this.x = 1; this.y = 0; this.z = 0; } else { this.x = q.x / s; this.y = q.y / s; this.z = q.z / s; } return this; } setAxisAngleFromRotationMatrix(m) { let angle, x, y, z; const epsilon = 0.01, epsilon2 = 0.1, te = m.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10]; if (Math.abs(m12 - m21) < epsilon && Math.abs(m13 - m31) < epsilon && Math.abs(m23 - m32) < epsilon) { if (Math.abs(m12 + m21) < epsilon2 && Math.abs(m13 + m31) < epsilon2 && Math.abs(m23 + m32) < epsilon2 && Math.abs(m11 + m22 + m33 - 3) < epsilon2) { this.set(1, 0, 0, 0); return this; } angle = Math.PI; const xx = (m11 + 1) / 2; const yy = (m22 + 1) / 2; const zz = (m33 + 1) / 2; const xy = (m12 + m21) / 4; const xz = (m13 + m31) / 4; const yz = (m23 + m32) / 4; if (xx > yy && xx > zz) { if (xx < epsilon) { x = 0; y = 0.707106781; z = 0.707106781; } else { x = Math.sqrt(xx); y = xy / x; z = xz / x; } } else if (yy > zz) { if (yy < epsilon) { x = 0.707106781; y = 0; z = 0.707106781; } else { y = Math.sqrt(yy); x = xy / y; z = yz / y; } } else { if (zz < epsilon) { x = 0.707106781; y = 0.707106781; z = 0; } else { z = Math.sqrt(zz); x = xz / z; y = yz / z; } } this.set(x, y, z, angle); return this; } let s = Math.sqrt((m32 - m23) * (m32 - m23) + (m13 - m31) * (m13 - m31) + (m21 - m12) * (m21 - m12)); if (Math.abs(s) < 0.001) s = 1; this.x = (m32 - m23) / s; this.y = (m13 - m31) / s; this.z = (m21 - m12) / s; this.w = Math.acos((m11 + m22 + m33 - 1) / 2); return this; } min(v) { this.x = Math.min(this.x, v.x); this.y = Math.min(this.y, v.y); this.z = Math.min(this.z, v.z); this.w = Math.min(this.w, v.w); 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); this.w = Math.max(this.w, v.w); return this; } clamp(min, max) { this.x = Math.max(min.x, Math.min(max.x, this.x)); this.y = Math.max(min.y, Math.min(max.y, this.y)); this.z = Math.max(min.z, Math.min(max.z, this.z)); this.w = Math.max(min.w, Math.min(max.w, this.w)); return this; } 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)); this.w = Math.max(minVal, Math.min(maxVal, this.w)); 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); this.w = Math.floor(this.w); return this; } ceil() { this.x = Math.ceil(this.x); this.y = Math.ceil(this.y); this.z = Math.ceil(this.z); this.w = Math.ceil(this.w); return this; } round() { this.x = Math.round(this.x); this.y = Math.round(this.y); this.z = Math.round(this.z); this.w = Math.round(this.w); return this; } roundToZero() { this.x = Math.trunc(this.x); this.y = Math.trunc(this.y); this.z = Math.trunc(this.z); this.w = Math.trunc(this.w); return this; } negate() { this.x = -this.x; this.y = -this.y; this.z = -this.z; this.w = -this.w; 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); } manhattanLength() { return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w); } 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; this.w += (v.w - this.w) * 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; this.w = v1.w + (v2.w - v1.w) * alpha; return this; } equals(v) { return v.x === this.x && v.y === this.y && v.z === this.z && v.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]; 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; } random() { this.x = Math.random(); this.y = Math.random(); this.z = Math.random(); this.w = Math.random(); return this; } *[Symbol.iterator]() { yield this.x; yield this.y; yield this.z; yield this.w; } } class Matrix3 { constructor(n11, n12, n13, n21, n22, n23, n31, n32, n33) { Matrix3.prototype.isMatrix3 = true; this.elements = [1, 0, 0, 0, 1, 0, 0, 0, 1]; if (n11 !== undefined) { this.set(n11, n12, n13, n21, n22, n23, n31, n32, n33); } } set(n11, n12, n13, n21, n22, n23, n31, n32, n33) { const te = this.elements; te[0] = n11; te[1] = n21; te[2] = n31; te[3] = n12; te[4] = n22; te[5] = n32; te[6] = n13; te[7] = n23; te[8] = n33; return this; } identity() { this.set(1, 0, 0, 0, 1, 0, 0, 0, 1); return this; } copy(m) { const te = this.elements; const me = m.elements; te[0] = me[0]; te[1] = me[1]; te[2] = me[2]; te[3] = me[3]; te[4] = me[4]; te[5] = me[5]; te[6] = me[6]; te[7] = me[7]; te[8] = me[8]; return this; } extractBasis(xAxis, yAxis, zAxis) { xAxis.setFromMatrix3Column(this, 0); yAxis.setFromMatrix3Column(this, 1); zAxis.setFromMatrix3Column(this, 2); return this; } setFromMatrix4(m) { const me = m.elements; this.set(me[0], me[4], me[8], me[1], me[5], me[9], me[2], me[6], me[10]); return this; } multiply(m) { return this.multiplyMatrices(this, m); } premultiply(m) { return this.multiplyMatrices(m, this); } multiplyMatrices(a, b) { const ae = a.elements; const be = b.elements; const te = this.elements; const a11 = ae[0], a12 = ae[3], a13 = ae[6]; const a21 = ae[1], a22 = ae[4], a23 = ae[7]; const a31 = ae[2], a32 = ae[5], a33 = ae[8]; const b11 = be[0], b12 = be[3], b13 = be[6]; const b21 = be[1], b22 = be[4], b23 = be[7]; const b31 = be[2], b32 = be[5], b33 = be[8]; te[0] = a11 * b11 + a12 * b21 + a13 * b31; te[3] = a11 * b12 + a12 * b22 + a13 * b32; te[6] = a11 * b13 + a12 * b23 + a13 * b33; te[1] = a21 * b11 + a22 * b21 + a23 * b31; te[4] = a21 * b12 + a22 * b22 + a23 * b32; te[7] = a21 * b13 + a22 * b23 + a23 * b33; te[2] = a31 * b11 + a32 * b21 + a33 * b31; te[5] = a31 * b12 + a32 * b22 + a33 * b32; te[8] = a31 * b13 + a32 * b23 + a33 * b33; return this; } multiplyScalar(s) { const te = this.elements; te[0] *= s; te[3] *= s; te[6] *= s; te[1] *= s; te[4] *= s; te[7] *= s; te[2] *= s; te[5] *= s; te[8] *= s; return this; } determinant() { const te = this.elements; const a = te[0], b = te[1], c = te[2], d = te[3], e = te[4], f = te[5], g = te[6], h = te[7], i = te[8]; return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; } invert() { const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n12 = te[3], n22 = te[4], n32 = te[5], n13 = te[6], n23 = te[7], n33 = te[8], t11 = n33 * n22 - n32 * n23, t12 = n32 * n13 - n33 * n12, t13 = n23 * n12 - n22 * n13, det = n11 * t11 + n21 * t12 + n31 * t13; if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0); const detInv = 1 / det; te[0] = t11 * detInv; te[1] = (n31 * n23 - n33 * n21) * detInv; te[2] = (n32 * n21 - n31 * n22) * detInv; te[3] = t12 * detInv; te[4] = (n33 * n11 - n31 * n13) * detInv; te[5] = (n31 * n12 - n32 * n11) * detInv; te[6] = t13 * detInv; te[7] = (n21 * n13 - n23 * n11) * detInv; te[8] = (n22 * n11 - n21 * n12) * detInv; return this; } transpose() { let tmp; const m = this.elements; tmp = m[1]; m[1] = m[3]; m[3] = tmp; tmp = m[2]; m[2] = m[6]; m[6] = tmp; tmp = m[5]; m[5] = m[7]; m[7] = tmp; return this; } getNormalMatrix(matrix4) { return this.setFromMatrix4(matrix4).invert().transpose(); } transposeIntoArray(r) { const m = this.elements; r[0] = m[0]; r[1] = m[3]; r[2] = m[6]; r[3] = m[1]; r[4] = m[4]; r[5] = m[7]; r[6] = m[2]; r[7] = m[5]; r[8] = m[8]; return this; } setUvTransform(tx, ty, sx, sy, rotation, cx, cy) { const c = Math.cos(rotation); const s = Math.sin(rotation); this.set(sx * c, sx * s, -sx * (c * cx + s * cy) + cx + tx, -sy * s, sy * c, -sy * (-s * cx + c * cy) + cy + ty, 0, 0, 1); return this; } scale(sx, sy) { this.premultiply(_m3.makeScale(sx, sy)); return this; } rotate(theta) { this.premultiply(_m3.makeRotation(-theta)); return this; } translate(tx, ty) { this.premultiply(_m3.makeTranslation(tx, ty)); return this; } makeTranslation(x, y) { if (x.isVector2) { this.set(1, 0, x.x, 0, 1, x.y, 0, 0, 1); } else { this.set(1, 0, x, 0, 1, y, 0, 0, 1); } return this; } makeRotation(theta) { const c = Math.cos(theta); const s = Math.sin(theta); this.set(c, -s, 0, s, c, 0, 0, 0, 1); return this; } makeScale(x, y) { this.set(x, 0, 0, 0, y, 0, 0, 0, 1); return this; } equals(matrix) { const te = this.elements; const me = matrix.elements; for (let i = 0; i < 9; i++) { if (te[i] !== me[i]) return false; } return true; } fromArray(array, offset = 0) { for (let i = 0; i < 9; i++) { this.elements[i] = array[i + offset]; } return this; } toArray(array = [], offset = 0) { const te = this.elements; array[offset] = te[0]; array[offset + 1] = te[1]; array[offset + 2] = te[2]; array[offset + 3] = te[3]; array[offset + 4] = te[4]; array[offset + 5] = te[5]; array[offset + 6] = te[6]; array[offset + 7] = te[7]; array[offset + 8] = te[8]; return array; } clone() { return new Matrix3().fromArray(this.elements); } } const _m3 = new Matrix3(); exports.EmitterMode = void 0; (function (EmitterMode) { EmitterMode[EmitterMode["Random"] = 0] = "Random"; EmitterMode[EmitterMode["Loop"] = 1] = "Loop"; EmitterMode[EmitterMode["PingPong"] = 2] = "PingPong"; EmitterMode[EmitterMode["Burst"] = 3] = "Burst"; })(exports.EmitterMode || (exports.EmitterMode = {})); function getValueFromEmitterMode(mode, currentValue, spread, emissionState) { let u; if (exports.EmitterMode.Random === mode) { currentValue = Math.random(); } else if (exports.EmitterMode.Burst === mode && emissionState.isBursting) { currentValue = emissionState.burstParticleIndex / emissionState.burstParticleCount; } if (spread > 0) { u = Math.floor(currentValue / spread) * spread; } else { u = currentValue; } switch (mode) { case exports.EmitterMode.Loop: u = u % 1; break; case exports.EmitterMode.PingPong: u = Math.abs((u % 2) - 1); break; } return u; } class Bezier { constructor(p1, p2, p3, p4) { this.p = [p1, p2, p3, p4]; } genValue(t) { const t2 = t * t; const t3 = t * t * t; const mt = 1 - t; const mt2 = mt * mt; const mt3 = mt2 * mt; return this.p[0] * mt3 + this.p[1] * mt2 * t * 3 + this.p[2] * mt * t2 * 3 + this.p[3] * t3; } derivativeCoefficients(points) { const dpoints = []; for (let p = points, c = p.length - 1; c > 0; c--) { const list = []; for (let j = 0; j < c; j++) { const dpt = c * (p[j + 1] - p[j]); list.push(dpt); } dpoints.push(list); p = list; } return dpoints; } getSlope(t) { const p = this.derivativeCoefficients(this.p)[0]; const mt = 1 - t; const a = mt * mt; const b = mt * t * 2; const c = t * t; return a * p[0] + b * p[1] + c * p[2]; } controlCurve(d0, d1) { this.p[1] = d0 / 3 + this.p[0]; this.p[2] = this.p[3] - d1 / 3; } hull(t) { let p = this.p; let _p = [], pt, idx = 0, i = 0, l = 0; const q = []; q[idx++] = p[0]; q[idx++] = p[1]; q[idx++] = p[2]; q[idx++] = p[3]; while (p.length > 1) { _p = []; for (i = 0, l = p.length - 1; i < l; i++) { pt = t * p[i] + (1 - t) * p[i + 1]; q[idx++] = pt; _p.push(pt); } p = _p; } return q; } split(t) { const q = this.hull(t); const result = { left: new Bezier(q[0], q[4], q[7], q[9]), right: new Bezier(q[9], q[8], q[6], q[3]), span: q }; return result; } clone() { return new Bezier(this.p[0], this.p[1], this.p[2], this.p[3]); } toJSON() { return { p0: this.p[0], p1: this.p[1], p2: this.p[2], p3: this.p[3], }; } static fromJSON(json) { return new Bezier(json.p0, json.p1, json.p2, json.p3); } } const ColorToJSON = (color) => { return { r: color.x, g: color.y, b: color.z, a: color.w }; }; const JSONToColor = (json) => { return new Vector4(json.r, json.g, json.b, json.a); }; const JSONToValue = (json, type) => { switch (type) { case 'Vector3': return new Vector3(json.x, json.y, json.z); case 'Vector4': return new Vector4(json.x, json.y, json.z, json.w); case 'Color': return new Vector3(json.r, json.g, json.b); case 'Number': return json; default: return json; } }; const ValueToJSON = (value, type) => { switch (type) { case 'Vector3': return { x: value.x, y: value.y, z: value.z }; case 'Vector4': return { x: value.x, y: value.y, z: value.z, w: value.w }; case 'Color': return { r: value.x, g: value.y, b: value.z }; case 'Number': return value; default: return value; } }; class RandomColor { constructor(a, b) { this.a = a; this.b = b; this.type = 'value'; } startGen(memory) { } genColor(memory, color) { const rand = Math.random(); return color.copy(this.a).lerp(this.b, rand); } toJSON() { return { type: 'RandomColor', a: ColorToJSON(this.a), b: ColorToJSON(this.b), }; } static fromJSON(json) { return new RandomColor(JSONToColor(json.a), JSONToColor(json.b)); } clone() { return new RandomColor(this.a.clone(), this.b.clone()); } } class ColorRange { constructor(a, b) { this.a = a; this.b = b; this.indexCount = -1; this.type = 'value'; } startGen(memory) { this.indexCount = memory.length; memory.push(Math.random()); } genColor(memory, color) { if (this.indexCount === -1) { this.startGen(memory); } return color.copy(this.a).lerp(this.b, memory[this.indexCount]); } toJSON() { return { type: 'ColorRange', a: ColorToJSON(this.a), b: ColorToJSON(this.b), }; } static fromJSON(json) { return new ColorRange(JSONToColor(json.a), JSONToColor(json.b)); } clone() { return new ColorRange(this.a.clone(), this.b.clone()); } } class ContinuousLinearFunction { constructor(keys, subType) { this.subType = subType; this.type = 'function'; this.keys = keys; } findKey(t) { let mid = 0; let left = 0, right = this.keys.length - 1; while (left + 1 < right) { mid = Math.floor((left + right) / 2); if (t < this.getStartX(mid)) right = mid - 1; else if (t > this.getEndX(mid)) left = mid + 1; else return mid; } for (let i = left; i <= right; i++) { if (t >= this.getStartX(i) && t <= this.getEndX(i)) return i; } return -1; } getStartX(index) { return this.keys[index][1]; } getEndX(index) { if (index + 1 < this.keys.length) return this.keys[index + 1][1]; return 1; } genValue(value, t) { const index = this.findKey(t); if (this.subType === 'Number') { if (index === -1) { return this.keys[0][0]; } else if (index + 1 >= this.keys.length) { return this.keys[this.keys.length - 1][0]; } return ((this.keys[index + 1][0] - this.keys[index][0]) * ((t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index))) + this.keys[index][0]); } else { if (index === -1) { return value.copy(this.keys[0][0]); } if (index + 1 >= this.keys.length) { return value.copy(this.keys[this.keys.length - 1][0]); } return value .copy(this.keys[index][0]) .lerp(this.keys[index + 1][0], (t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index))); } } toJSON() { this.keys[0][0].constructor.name; return { type: 'CLinearFunction', subType: this.subType, keys: this.keys.map(([color, pos]) => ({ value: ValueToJSON(color, this.subType), pos: pos })), }; } static fromJSON(json) { return new ContinuousLinearFunction(json.keys.map((pair) => [JSONToValue(pair.value, json.subType), pair.pos]), json.subType); } clone() { if (this.subType === 'Number') { return new ContinuousLinearFunction(this.keys.map(([value, pos]) => [value, pos]), this.subType); } else { return new ContinuousLinearFunction(this.keys.map(([value, pos]) => [value.clone(), pos]), this.subType); } } } const tempVec3 = new Vector3(); class Gradient { constructor(color = [ [new Vector3(0, 0, 0), 0], [new Vector3(1, 1, 1), 0], ], alpha = [ [1, 0], [1, 1], ]) { this.type = 'function'; this.color = new ContinuousLinearFunction(color, 'Color'); this.alpha = new ContinuousLinearFunction(alpha, 'Number'); } genColor(memory, color, t) { this.color.genValue(tempVec3, t); return color.set(tempVec3.x, tempVec3.y, tempVec3.z, this.alpha.genValue(1, t)); } toJSON() { return { type: 'Gradient', color: this.color.toJSON(), alpha: this.alpha.toJSON(), }; } static fromJSON(json) { if (json.functions) { const keys = json.functions.map((func) => [ColorRange.fromJSON(func.function).a, func.start]); if (json.functions.length > 0) { keys.push([ColorRange.fromJSON(json.functions[json.functions.length - 1].function).b, 1]); } return new Gradient(keys.map((key) => [new Vector3(key[0].x, key[0].y, key[0].z), key[1]]), keys.map((key) => [key[0].w, key[1]])); } else { const gradient = new Gradient(); gradient.alpha = ContinuousLinearFunction.fromJSON(json.alpha); gradient.color = ContinuousLinearFunction.fromJSON(json.color); return gradient; } } clone() { const gradient = new Gradient(); gradient.alpha = this.alpha.clone(); gradient.color = this.color.clone(); return gradient; } startGen(memory) { } } const tempColor = new Vector4(); class RandomColorBetweenGradient { constructor(gradient1, gradient2) { this.indexCount = 0; this.type = 'function'; this.gradient1 = gradient1; this.gradient2 = gradient2; } startGen(memory) { this.indexCount = memory.length; memory.push(Math.random()); } genColor(memory, color, t) { this.gradient1.genColor(memory, color, t); this.gradient2.genColor(memory, tempColor, t); if (memory && memory[this.indexCount] !== undefined) { color.lerp(tempColor, memory[this.indexCount]); } else { color.lerp(tempColor, Math.random()); } return color; } toJSON() { return { type: 'RandomColorBetweenGradient', gradient1: this.gradient1.toJSON(), gradient2: this.gradient2.toJSON(), }; } static fromJSON(json) { return new RandomColorBetweenGradient(Gradient.fromJSON(json.gradient1), Gradient.fromJSON(json.gradient2)); } clone() { return new RandomColorBetweenGradient(this.gradient1.clone(), this.gradient2.clone()); } } class ConstantColor { constructor(color) { this.color = color; this.type = 'value'; } startGen(memory) { } genColor(memoryGenerator, color) { return color.copy(this.color); } toJSON() { return { type: 'ConstantColor', color: ColorToJSON(this.color), }; } static fromJSON(json) { return new ConstantColor(JSONToColor(json.color)); } clone() { return new ConstantColor(this.color.clone()); } } function ColorGeneratorFromJSON(json) { switch (json.type) { case 'ConstantColor': return ConstantColor.fromJSON(json); case 'ColorRange': return ColorRange.fromJSON(json); case 'RandomColor': return RandomColor.fromJSON(json); case 'Gradient': return Gradient.fromJSON(json); case 'RandomColorBetweenGradient': return RandomColorBetweenGradient.fromJSON(json); default: return new ConstantColor(new Vector4(1, 1, 1, 1)); } } class ConstantValue { constructor(value) { this.value = value; this.type = 'value'; } startGen(memory) { } genValue(memory) { return this.value; } toJSON() { return { type: 'ConstantValue', value: this.value, }; } static fromJSON(json) { return new ConstantValue(json.value); } clone() { return new ConstantValue(this.value); } } class IntervalValue { constructor(a, b) { this.a = a; this.b = b; this.indexCount = -1; this.type = 'value'; } startGen(memory) { this.indexCount = memory.length; memory.push(Math.random()); } genValue(memory) { if (this.indexCount === -1) { this.startGen(memory); } return MathUtils.lerp(this.a, this.b, memory[this.indexCount]); } toJSON() { return { type: 'IntervalValue', a: this.a, b: this.b, }; } static fromJSON(json) { return new IntervalValue(json.a, json.b); } clone() { return new IntervalValue(this.a, this.b); } } class PiecewiseFunction { constructor() { this.functions = new Array(); } findFunction(t) { let mid = 0; let left = 0, right = this.functions.length - 1; while (left + 1 < right) { mid = Math.floor((left + right) / 2); if (t < this.getStartX(mid)) right = mid - 1; else if (t > this.getEndX(mid)) left = mid + 1; else return mid; } for (let i = left; i <= right; i++) { if (t >= this.functions[i][1] && t <= this.getEndX(i)) return i; } return -1; } getStartX(index) { return this.functions[index][1]; } setStartX(index, x) { if (index > 0) this.functions[index][1] = x; } getEndX(index) { if (index + 1 < this.functions.length) return this.functions[index + 1][1]; return 1; } setEndX(index, x) { if (index + 1 < this.functions.length) this.functions[index + 1][1] = x; } insertFunction(t, func) { const index = this.findFunction(t); this.functions.splice(index + 1, 0, [func, t]); } removeFunction(index) { return this.functions.splice(index, 1)[0][0]; } getFunction(index) { return this.functions[index][0]; } setFunction(index, func) { this.functions[index][0] = func; } get numOfFunctions() { return this.functions.length; } } class PiecewiseBezier extends PiecewiseFunction { constructor(curves = [[new Bezier(0, 1.0 / 3, (1.0 / 3) * 2, 1), 0]]) { super(); this.type = 'function'; this.functions = curves; } genValue(memory, t = 0) { const index = this.findFunction(t); if (index === -1) { return 0; } return this.functions[index][0].genValue((t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index))); } toSVG(length, segments) { if (segments < 1) return ''; let result = ['M', 0, this.functions[0][0].p[0]].join(' '); for (let i = 1.0 / segments; i <= 1; i += 1.0 / segments) { result = [result, 'L', i * length, this.genValue(undefined, i)].join(' '); } return result; } toJSON() { return { type: 'PiecewiseBezier', functions: this.functions.map(([bezier, start]) => ({ function: bezier.toJSON(), start: start })), }; } static fromJSON(json) { return new PiecewiseBezier(json.functions.map((piecewiseFunction) => [ Bezier.fromJSON(piecewiseFunction.function), piecewiseFunction.start, ])); } clone() { return new PiecewiseBezier(this.functions.map(([bezier, start]) => [bezier.clone(), start])); } startGen(memory) { } } function ValueGeneratorFromJSON(json) { switch (json.type) { case 'ConstantValue': return ConstantValue.fromJSON(json); case 'IntervalValue': return IntervalValue.fromJSON(json); case 'PiecewiseBezier': return PiecewiseBezier.fromJSON(json); default: return new ConstantValue(0); } } class RandomQuatGenerator { constructor() { this.indexCount = 0; this.type = 'rotation'; } startGen(memory) { this.indexCount = memory.length; memory.push(new Quaternion()); let x, y, z, u, v, w; do { x = Math.random() * 2 - 1; y = Math.random() * 2 - 1; z = x * x + y * y; } while (z > 1); do { u = Math.random() * 2 - 1; v = Math.random() * 2 - 1; w = u * u + v * v; } while (w > 1); const s = Math.sqrt((1 - z) / w); memory[this.indexCount].set(x, y, s * u, s * v); } genValue(memory, quat, delta, t) { if (this.indexCount === -1) { this.startGen(memory); } quat.copy(memory[this.indexCount]); return quat; } toJSON() { return { type: 'RandomQuat', }; } static fromJSON(json) { return new RandomQuatGenerator(); } clone() { return new RandomQuatGenerator(); } } class AxisAngleGenerator { constructor(axis, angle) { this.axis = axis; this.angle = angle; this.type = 'rotation'; } startGen(memory) { this.angle.startGen(memory); } genValue(memory, quat, delta, t) { return quat.setFromAxisAngle(this.axis, this.angle.genValue(memory, t) * delta); } toJSON() { return { type: 'AxisAngle', axis: { x: this.axis.x, y: this.axis.y, z: this.axis.z }, angle: this.angle.toJSON(), }; } static fromJSON(json) { return new AxisAngleGenerator(new Vector3(json.axis.x, json.axis.y, json.axis.z), ValueGeneratorFromJSON(json.angle)); } clone() { return new AxisAngleGenerator(this.axis.clone(), this.angle.clone()); } } class EulerGenerator { constructor(angleX, angleY, angleZ, eulerOrder) { this.angleX = angleX; this.angleY = angleY; this.angleZ = angleZ; this.type = 'rotation'; this.eular = new Euler(0, 0, 0, eulerOrder); } startGen(memory) { this.angleX.startGen(memory); this.angleY.startGen(memory); this.angleZ.startGen(memory); } genValue(memory, quat, delta, t) { this.eular.set(this.angleX.genValue(memory, t) * delta, this.angleY.genValue(memory, t) * delta, this.angleZ.genValue(memory, t) * delta); return quat.setFromEuler(this.eular); } toJSON() { return { type: 'Euler', angleX: this.angleX.toJSON(), angleY: this.angleY.toJSON(), angleZ: this.angleZ.toJSON(), eulerOrder: this.eular.order, }; } static fromJSON(json) { return new EulerGenerator(ValueGeneratorFromJSON(json.angleX), ValueGeneratorFromJSON(json.angleY), ValueGeneratorFromJSON(json.angleZ), json.eulerOrder); } clone() { return new EulerGenerator(this.angleX, this.angleY, this.angleZ, this.eular.order); } } function RotationGeneratorFromJSON(json) { switch (json.type) { case 'AxisAngle': return AxisAngleGenerator.fromJSON(json); case 'Euler': return EulerGenerator.fromJSON(json); case 'RandomQuat': return RandomQuatGenerator.fromJSON(json); default: return new RandomQuatGenerator(); } } class Vector3Function { constructor(x, y, z) { this.x = x; this.y = y; this.z = z; this.type = 'vec3function'; } startGen(memory) { this.x.startGen(memory); this.y.startGen(memory); this.z.startGen(memory); } genValue(memory, vec, t) { return vec.set(this.x.genValue(memory, t), this.y.genValue(memory, t), this.z.genValue(memory, t)); } toJSON() { return { type: 'Vector3Function', x: this.x.toJSON(), y: this.y.toJSON(), z: this.z.toJSON(), }; } static fromJSON(json) { return new Vector3Function(ValueGeneratorFromJSON(json.x), ValueGeneratorFromJSON(json.y), ValueGeneratorFromJSON(json.z)); } clone() { return new Vector3Function(this.x, this.y, this.z); } } function Vector3GeneratorFromJSON(json) { switch (json.type) { case 'Vector3Function': return Vector3Function.fromJSON(json); default: return new Vector3Function(new ConstantValue(0), new ConstantValue(0), new ConstantValue(0)); } } function GeneratorFromJSON(json) { switch (json.type) { case 'ConstantValue': case 'IntervalValue': case 'PiecewiseBezier': return ValueGeneratorFromJSON(json); case 'AxisAngle': case 'RandomQuat': case 'Euler': return RotationGeneratorFromJSON(json); case 'Vector3Function': return Vector3GeneratorFromJSON(json); default: return new ConstantValue(0); } } class ConeEmitter { constructor(parameters = {}) { var _a, _b, _c, _d, _e, _f, _g; this.type = 'cone'; this.currentValue = 0; this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10; this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI; this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1; this.angle = (_d = parameters.angle) !== null && _d !== void 0 ? _d : Math.PI / 6; this.mode = (_e = parameters.mode) !== null && _e !== void 0 ? _e : exports.EmitterMode.Random; this.spread = (_f = parameters.spread) !== null && _f !== void 0 ? _f : 0; this.speed = (_g = parameters.speed) !== null && _g !== void 0 ? _g : new ConstantValue(1); this.memory = []; } update(system, delta) { if (exports.EmitterMode.Random != this.mode) { this.currentValue += this.speed.genValue(this.memory, system.emissionState.time / system.duration) * delta; } } initialize(p, emissionState) { const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread, emissionState); const rand = MathUtils.lerp(1 - this.thickness, 1, Math.random()); const theta = u * this.arc; const r = Math.sqrt(rand); const sinTheta = Math.sin(theta); const cosTheta = Math.cos(theta); p.position.x = r * cosTheta; p.position.y = r * sinTheta; p.position.z = 0; const angle = this.angle * r; p.velocity.set(0, 0, Math.cos(angle)).addScaledVector(p.position, Math.sin(angle)).multiplyScalar(p.startSpeed); p.position.multiplyScalar(this.radius); } toJSON() { return { type: 'cone', radius: this.radius, arc: this.arc, thickness: this.thickness, angle: this.angle, mode: this.mode, spread: this.spread, speed: this.speed.toJSON(), }; } static fromJSON(json) { return new ConeEmitter({ radius: json.radius, arc: json.arc, thickness: json.thickness, angle: json.angle, mode: json.mode, speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined, spread: json.spread, }); } clone() { return new ConeEmitter({ radius: this.radius, arc: this.arc, thickness: this.thickness, angle: this.angle, mode: this.mode, speed: this.speed.clone(), spread: this.spread, }); } } class CircleEmitter { constructor(parameters = {}) { var _a, _b, _c, _d, _e, _f; this.type = 'circle'; this.currentValue = 0; this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10; this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI; this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1; this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : exports.EmitterMode.Random; this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0; this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1); this.memory = []; } update(system, delta) { this.currentValue += this.speed.genValue(this.memory, system.emissionState.time / system.duration) * delta; } initialize(p, emissionState) { const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread, emissionState); const r = MathUtils.lerp(1 - this.thickness, 1, Math.random()); const theta = u * this.arc; p.position.x = Math.cos(theta); p.position.y = Math.sin(theta); p.position.z = 0; p.velocity.copy(p.position).multiplyScalar(p.startSpeed); p.position.multiplyScalar(this.radius * r); } toJSON() { return { type: 'circle', radius: this.radius, arc: this.arc, thickness: this.thickness, mode: this.mode, spread: this.spread, speed: this.speed.toJSON(), }; } static fromJSON(json) { return new CircleEmitter({ radius: json.radius, arc: json.arc, thickness: json.thickness, mode: json.mode, speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined, spread: json.spread, }); } clone() { return new CircleEmitter({ radius: this.radius, arc: this.arc, thickness: this.thickness, mode: this.mode, speed: this.speed.clone(), spread: this.spread, }); } } function randomInt(a, b) { return Math.floor(Math.random() * (b - a)) + a; } const UP_VEC3 = new Vector3(0, 1, 0); const ZERO_VEC3 = new Vector3(0, 0, 0); const ONE_VEC3 = new Vector3(1, 1, 1); const Z_VEC3 = new Vector3(0, 0, 1); class DonutEmitter { constructor(parameters = {}) { var _a, _b, _c, _d, _e, _f, _g; this.type = 'donut'; this.currentValue = 0; this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10; this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI; this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1; this.donutRadius = (_d = parameters.donutRadius) !== null && _d !== void 0 ? _d : this.radius * 0.2; this.mode = (_e = parameters.mode) !== null && _e !== void 0 ? _e : exports.EmitterMode.Random; this.spread = (_f = parameters.spread) !== null && _f !== void 0 ? _f : 0; this.speed = (_g = parameters.speed) !== null && _g !== void 0 ? _g : new ConstantValue(1); this.memory = []; this._m1 = new Matrix4(); } update(system, delta) { if (exports.EmitterMode.Random != this.mode) { this.currentValue += this.speed.genValue(this.memory, system.emissionState.time / system.duration) * delta; } } initialize(p, emissionState) { const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread, emissionState); const v = Math.random(); const rand = MathUtils.lerp(1 - this.thickness, 1, Math.random()); const theta = u * this.arc; const phi = v * Math.PI * 2; const sinTheta = Math.sin(theta); const cosTheta = Math.cos(theta); p.position.x = this.radius * cosTheta; p.position.y = this.radius * sinTheta; p.position.z = 0; p.velocity.z = this.donutRadius * rand * Math.sin(phi); p.velocity.x = this.donutRadius * rand * Math.cos(phi) * cosTheta; p.velocity.y = this.donutRadius * rand * Math.cos(phi) * sinTheta; p.position.add(p.velocity); p.velocity.normalize().multiplyScalar(p.startSpeed); if (p.rotation instanceof Quaternion) { this._m1.lookAt(ZERO_VEC3, p.velocity, UP_VEC3); p.rotation.setFromRotationMatrix(this._m1); } } toJSON() { return { type: 'donut', radius: this.radius, arc: this.arc, thickness: this.thickness, donutRadius: this.donutRadius, mode: this.mode, spread: this.spread, speed: this.speed.toJSON(), }; } static fromJSON(json) { return new DonutEmitter({ radius: json.radius, arc: json.arc, thickness: json.thickness, donutRadius: json.donutRadius, mode: json.mode, speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined, spread: json.spread, }); } clone() { return new DonutEmitter({ radius: this.radius, arc: this.arc, thickness: this.thickness, donutRadius: this.donutRadius, mode: this.mode, speed: this.speed.clone(), spread: this.spread, }); } } class PointEmitter { constructor() { this.type = 'point'; this._m1 = new Matrix4(); } update(system, delta) { } initialize(p) { const u = Math.random(); const v = Math.random(); const theta = u * Math.PI * 2; const phi = Math.acos(2.0 * v - 1.0); const r = Math.cbrt(Math.random()); const sinTheta = Math.sin(theta); const cosTheta = Math.cos(theta); const sinPhi = Math.sin(phi); const cosPhi = Math.cos(phi); p.velocity.x = r * sinPhi * cosTheta; p.velocity.y = r * sinPhi * sinTheta; p.velocity.z = r * cosPhi; p.velocity.multiplyScalar(p.startSpeed); p.position.setScalar(0); if (p.rotation instanceof Quaternion) { this._m1.lookAt(ZERO_VEC3, p.position, UP_VEC3); p.rotation.setFromRotationMatrix(this._m1); } } toJSON() { return { type: 'point', }; } static fromJSON(json) { return new PointEmitter(); } clone() { return new PointEmitter(); } } class SphereEmitter { constructor(parameters = {}) { var _a, _b, _c, _d, _e, _f; this.type = 'sphere'; this.currentValue = 0; this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10; this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI; this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1; this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : exports.EmitterMode.Random; this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0; this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1); this.memory = []; this._m1 = new Matrix4(); } update(system, delta) { if (exports.EmitterMode.Random != this.mode) { this.currentValue += this.speed.genValue(this.memory, system.emissionState.time / system.duration) * delta; } } initialize(p, emissionState) { const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread, emissionState); const v = Math.random(); const rand = MathUtils.lerp(1 - this.thickness, 1, Math.random()); const theta = u * this.arc; const phi = Math.acos(2.0 * v - 1.0); const sinTheta = Math.sin(theta); const cosTheta = Math.cos(theta); const sinPhi = Math.sin(phi); const cosPhi = Math.cos(phi); p.position.x = sinPhi * cosTheta; p.position.y = sinPhi * sinTheta; p.position.z = cosPhi; p.velocity.copy(p.position).multiplyScalar(p.startSpeed); p.position.multiplyScalar(this.radius * rand); if (p.rotation instanceof Quaternion) { this._m1.lookAt(ZERO_VEC3, p.position, UP_VEC3); p.rotation.setFromRotationMatrix(this._m1); } } toJSON() { return { type: 'sphere', radius: this.radius, arc: this.arc, thickness: this.thickness, mode: this.mode, spread: this.spread, speed: this.speed.toJSON(), }; } static fromJSON(json) { return new SphereEmitter({ radius: json.radius, arc: json.arc, thickness: json.thickness, mode: json.mode, speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined, spread: json.spread, }); } clone() { return new SphereEmitter({ radius: this.radius, arc: this.arc, thickness: this.thickness, mode: this.mode, speed: this.speed.clone(), spread: this.spread, }); } } class HemisphereEmitter { constructor(parameters = {}) { var _a, _b, _c, _d, _e, _f; this.type = 'sphere'; this.currentValue = 0; this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10; this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI; this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1; this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : exports.EmitterMode.Random; this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0; this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1); this.memory = []; this._m1 = new Matrix4(); } update(system, delta) { if (exports.EmitterMode.Random != this.mode) { this.currentValue += this.speed.genValue(this.memory, system.emissionState.time / system.duration) * delta; } } initialize(p, emissionState) { const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread, emissionState); const v = Math.random(); const rand = MathUtils.lerp(1 - this.thickness, 1, Math.random()); const theta = u * this.arc; const phi = Math.acos(v); const sinTheta = Math.sin(theta); const cosTheta = Math.cos(theta); const sinPhi = Math.sin(phi); const cosPhi = Math.cos(phi); p.position.x = sinPhi * cosTheta; p.position.y = sinPhi * sinTheta; p.position.z = cosPhi; p.velocity.copy(p.position).multiplyScalar(p.startSpeed); p.position.multiplyScalar(this.radius * rand); if (p.rotation instanceof Quaternion) { this._m1.lookAt(ZERO_VEC3, p.position, UP_VEC3); p.rotation.setFromRotationMatrix(this._m1); } } toJSON() { return { type: 'hemisphere', radius: this.radius, arc: this.arc, thickness: this.thickness, mode: this.mode, spread: this.spread, speed: this.speed.toJSON(), }; } static fromJSON(json) { return new HemisphereEmitter({ radius: json.radius, arc: json.arc, thickness: json.thickness, mode: json.mode, speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined, spread: json.spread, }); } clone() { return new HemisphereEmitter({ radius: this.radius, arc: this.arc, thickness: this.thickness, mode: this.mode, speed: this.speed.clone(), spread: this.spread, }); } } class GridEmitter { constructor(parameters = {}) { var _a, _b, _c, _d; this.type = 'grid'; this.width = (_a = parameters.width) !== null && _a !== void 0 ? _a : 1; this.height = (_b = parameters.height) !== null && _b !== void 0 ? _b : 1; this.column = (_c = parameters.column) !== null && _c !== void 0 ? _c : 10; this.row = (_d = parameters.row) !== null && _d !== void 0 ? _d : 10; } initialize(p) { const r = Math.floor(Math.random() * this.row); const c = Math.floor(Math.random() * this.column); p.position.x = (c * this.width) / this.column - this.width / 2; p.position.y = (r * this.height) / this.row - this.height / 2; p.position.z = 0; p.velocity.set(0, 0, p.startSpeed); } toJSON() { return { type: 'grid', width: this.width, height: this.height, column: this.column, row: this.row, }; } static fromJSON(json) { return new GridEmitter(json); } clone() { return new GridEmitter({ width: this.width, height: this.height, column: this.column, row: this.row, }); } update(system, delta) { } } const EmitterShapes = { circle: { type: 'circle', params: [ ['radius', ['number']], ['arc', ['radian']], ['thickness', ['number']], ['mode', ['emitterMode']], ['spread', ['number']], ['speed', ['valueFunc']], ], constructor: CircleEmitter, loadJSON: CircleEmitter.fromJSON, }, cone: { type: 'cone', params: [ ['radius', ['number']], ['arc', ['radian']], ['thickness', ['number']], ['angle', ['radian']], ['mode', ['emitterMode']], ['spread', ['number']], ['speed', ['valueFunc']], ], constructor: ConeEmitter, loadJSON: ConeEmitter.fromJSON, }, donut: { type: 'donut', params: [ ['radius', ['number']], ['arc', ['radian']], ['thickness', ['number']], ['donutRadius', ['number']], ['mode', ['emitterMode']], ['spread', ['number']], ['speed', ['valueFunc']], ], constructor: DonutEmitter, loadJSON: DonutEmitter.fromJSON, }, point: { type: 'point', params: [], constructor: PointEmitter, loadJSON: PointEmitter.fromJSON }, sphere: { type: 'sphere', params: [ ['radius', ['number']], ['arc', ['radian']], ['thickness', ['number']], ['angle', ['radian']], ['mode', ['emitterMode']], ['spread', ['number']], ['speed', ['valueFunc']], ], constructor: SphereEmitter, loadJSON: SphereEmitter.fromJSON, }, hemisphere: { type: 'hemisphere', params: [ ['radius', ['number']], ['arc', ['radian']], ['thickness', ['number']], ['angle', ['radian']], ['mode', ['emitterMode']], ['spread', ['number']], ['speed', ['valueFunc']], ], constructor: HemisphereEmitter, loadJSON: HemisphereEmitter.fromJSON, }, grid: { type: 'grid', params: [ ['width', ['number']], ['height', ['number']], ['rows', ['number']], ['column', ['number']], ], constructor: GridEmitter, loadJSON: GridEmitter.fromJSON, }, }; function EmitterFromJSON(json, meta) { return EmitterShapes[json.type].loadJSON(json, meta); } class ColorOverLife { constructor(color) { this.color = color; this.type = 'ColorOverLife'; } initialize(particle) { this.color.startGen(particle.memory); } update(particle, delta) { this.color.genColor(particle.memory, particle.color, particle.age / particle.life); particle.color.x *= particle.startColor.x; particle.color.y *= particle.startColor.y; particle.color.z *= particle.startColor.z; particle.color.w *= particle.startColor.w; } frameUpdate(delta) { } toJSON() { return { type: this.type, color: this.color.toJSON(), }; } static fromJSON(json) { return new ColorOverLife(ColorGeneratorFromJSON(json.color)); } clone() { return new ColorOverLife(this.color.clone()); } reset() { } } class RotationOverLife { constructor(angularVelocity) { this.angularVelocity = angularVelocity; this.type = 'RotationOverLife'; } initialize(particle) { if (typeof particle.rotation === 'number') { this.angularVelocity.startGen(particle.memory); } } update(particle, delta) { if (typeof particle.rotation === 'number') { particle.rotation += delta * this.angularVelocity.genValue(particle.memory, particle.age / particle.life); } } toJSON() { return { type: this.type, angularVelocity: this.angularVelocity.toJSON(), }; } static fromJSON(json) { return new RotationOverLife(ValueGeneratorFromJSON(json.angularVelocity)); } frameUpdate(delta) { } clone() { return new RotationOverLife(this.angularVelocity.clone()); } reset() { } } class Rotation3DOverLife { constructor(angularVelocity) { this.angularVelocity = angularVelocity; this.type = 'Rotation3DOverLife'; this.tempQuat = new Quaternion(); this.tempQuat2 = new Quaternion(); } initialize(particle) { if (particle.rotation instanceof Quaternion) { particle.angularVelocity = new Quaternion(); this.angularVelocity.startGen(particle.memory); } } update(particle, delta) { if (particle.rotation instanceof Quaternion) { this.angularVelocity.genValue(particle.memory, this.tempQuat, delta, particle.age / particle.life); particle.rotation.multiply(this.tempQuat); } } toJSON() { return { type: this.type, angularVelocity: this.angularVelocity.toJSON(), }; } static fromJSON(json) { return new Rotation3DOverLife(RotationGeneratorFromJSON(json.angularVelocity)); } frameUpdate(delta) { } clone() { return new Rotation3DOverLife(this.angularVelocity.clone()); } reset() { } } class ForceOverLife { initialize(particle, particleSystem) { this.ps = particleSystem; this.x.startGen(particle.memory); this.y.startGen(particle.memory); this.z.startGen(particle.memory); } constructor(x, y, z) { this.x = x; this.y = y; this.z = z; this.type = 'ForceOverLife'; this._temp = new Vector3(); this._tempScale = new Vector3(); this._tempQ = new Quaternion(); } update(particle, delta) { this._temp.set(this.x.genValue(particle.memory, particle.age / particle.life), this.y.genValue(particle.memory, particle.age / particle.life), this.z.genValue(particle.memory, particle.age / particle.life)); if (this.ps.worldSpace) { particle.velocity.addScaledVector(this._temp, delta); } else { this._temp.multiply(this._tempScale).applyQuaternion(this._tempQ); particle.velocity.addScaledVector(this._temp, delta); } } toJSON() { return { type: this.type, x: this.x.toJSON(), y: this.y.toJSON(), z: this.z.toJSON(), }; } static fromJSON(json) { return new ForceOverLife(ValueGeneratorFromJSON(json.x), ValueGeneratorFromJSON(json.y), ValueGeneratorFromJSON(json.z)); } frameUpdate(delta) { if (this.ps && !this.ps.worldSpace) { const translation = this._temp; const quaternion = this._tempQ; const scale = this._tempScale; this.ps.emitter.matrixWorld.decompose(translation, quaternion, scale); quaternion.invert(); scale.set(1 / scale.x, 1 / scale.y, 1 / scale.z); } } clone() { return new ForceOverLife(this.x.clone(), this.y.clone(), this.z.clone()); } reset() { } } class SizeOverLife { initialize(particle) { this.size.startGen(particle.memory); } constructor(size) { this.size = size; this.type = 'SizeOverLife'; } update(particle) { if (this.size instanceof Vector3Function) { this.size.genValue(particle.memory, particle.size, particle.age / particle.life).multiply(particle.startSize); } else { particle.size.copy(particle.startSize).multiplyScalar(this.size.genValue(particle.memory, particle.age / particle.life)); } } toJSON() { return { type: this.type, size: this.size.toJSON(), }; } static fromJSON(json) { return new SizeOverLife(GeneratorFromJSON(json.size)); } frameUpdate(delta) { } clone() { return new SizeOverLife(this.size.clone()); } reset() { } } class SpeedOverLife { initialize(particle) { this.speed.startGen(particle.memory); } constructor(speed) { this.speed = speed; this.type = 'SpeedOverLife'; } update(particle) { particle.speedModifier = this.speed.genValue(particle.memory, particle.age / particle.life); } toJSON() { return { type: this.type, speed: this.speed.toJSON(), }; } static fromJSON(json) { return new SpeedOverLife(ValueGeneratorFromJSON(json.speed)); } frameUpdate(delta) { } clone() { return new SpeedOverLife(this.speed.clone()); } reset() { } } class FrameOverLife { constructor(frame) { this.frame = frame; this.type = 'FrameOverLife'; } initialize(particle) { this.frame.startGen(particle.memory); } update(particle, delta) { if (this.frame instanceof PiecewiseBezier) { particle.uvTile = this.frame.genValue(particle.memory, particle.age / particle.life); } } frameUpdate(delta) { } toJSON() { return { type: this.type, frame: this.frame.toJSON(), }; } static fromJSON(json) { return new FrameOverLife(ValueGeneratorFromJSON(json.frame)); } clone() { return new FrameOverLife(this.frame.clone()); } reset() { } } class OrbitOverLife { constructor(orbitSpeed, axis = new Vector3(0, 1, 0)) { this.orbitSpeed = orbitSpeed; this.axis = axis; this.type = 'OrbitOverLife'; this.temp = new Vector3(); this.rotation = new Quaternion(); } initialize(particle) { this.orbitSpeed.startGen(particle.memory); } update(particle, delta) { this.temp.copy(particle.position).projectOnVector(this.axis); this.rotation.setFromAxisAngle(this.axis, this.orbitSpeed.genValue(particle.memory, particle.age / particle.life) * delta); particle.position.sub(this.temp); particle.position.applyQuaternion(this.rotation); particle.position.add(this.temp); } frameUpdate(delta) { } toJSON() { return { type: this.type, orbitSpeed: this.orbitSpeed.toJSON(), axis: [this.axis.x, this.axis.y, this.axis.z], }; } static fromJSON(json) { return new OrbitOverLife(ValueGeneratorFromJSON(json.orbitSpeed), json.axis ? new Vector3(json.axis[0], json.axis[1], json.axis[2]) : undefined); } clone() { return new OrbitOverLife(this.orbitSpeed.clone()); } reset() { } } class LinkedListNode { constructor(data) { this.data = data; this.next = null; this.prev = null; } hasPrev() { return this.prev !== null; } hasNext() { return this.next !== null; } } class LinkedList { constructor() { this.length = 0; this.head = this.tail = null; } isEmpty() { return this.head === null; } clear() { this.length = 0; this.head = this.tail = null; } front() { if (this.head === null) return null; return this.head.data; } back() { if (this.tail === null) return null; return this.tail.data; } dequeue() { if (this.head) { const value = this.head.data; this.head = this.head.next; if (!this.head) { this.tail = null; } else { this.head.prev = null; } this.length--; return value; } return undefined; } pop() { if (this.tail) { const value = this.tail.data; this.tail = this.tail.prev; if (!this.tail) { this.head = null; } else { this.tail.next = null; } this.length--; return value; } return undefined; } queue(data) { const node = new LinkedListNode(data); if (!this.tail) { this.tail = node; } if (this.head) { this.head.prev = node; node.next = this.head; } this.head = node; this.length++; } push(data) { const node = new LinkedListNode(data); if (!this.head) { this.head = node; } if (this.tail) { this.tail.next = node; node.prev = this.tail; } this.tail = node; this.length++; } insertBefore(node, data) { const newNode = new LinkedListNode(data); newNode.next = node; newNode.prev = node.prev; if (newNode.prev !== null) { newNode.prev.next = newNode; } newNode.next.prev = newNode; if (node == this.head) { this.head = newNode; } this.length++; } remove(data) { if (this.head === null || this.tail === null) { return; } let tempNode = this.head; if (data === this.head.data) { this.head = this.head.next; } if (data === this.tail.data) { this.tail = this.tail.prev; } while (tempNode.next !== null && tempNode.data !== data) { tempNode = tempNode.next; } if (tempNode.data === data) { if (tempNode.prev !== null) tempNode.prev.next = tempNode.next; if (tempNode.next !== null) tempNode.next.prev = tempNode.prev; this.length--; } } *values() { let current = this.head; while (current !== null) { yield current.data; current = current.next; } } } class NodeParticle { constructor() { this.position = new Vector3(); this.velocity = new Vector3(); this.age = 0; this.life = 1; this.size = new Vector3(); this.rotation = 0; this.color = new Vector4(1, 1, 1, 1); this.uvTile = 0; this.memory = []; } get died() { return this.age >= this.life; } reset() { this.memory.length = 0; this.position.set(0, 0, 0); this.velocity.set(0, 0, 0); this.age = 0; this.life = 1; this.size.set(1, 1, 1); this.rotation = 0; this.color.set(1, 1, 1, 1); this.uvTile = 0; } } class SpriteParticle { constructor() { this.startSpeed = 0; this.startColor = new Vector4(); this.startSize = new Vector3(1, 1, 1); this.position = new Vector3(); this.velocity = new Vector3(); this.age = 0; this.life = 1; this.size = new Vector3(1, 1, 1); this.speedModifier = 1; this.rotation = 0; this.color = new Vector4(); this.uvTile = 0; this.memory = []; } get died() { return this.age >= this.life; } reset() { this.memory.length = 0; } } class RecordState { constructor(position, size, color) { this.position = position; this.size = size; this.color = color; } } class TrailParticle { constructor() { this.startSpeed = 0; this.startColor = new Vector4(); this.startSize = new Vector3(1, 1, 1); this.position = new Vector3(); this.velocity = new Vector3(); this.age = 0; this.life = 1; this.size = new Vector3(1, 1, 1); this.length = 100; this.speedModifier = 1; this.color = new Vector4(); this.previous = new LinkedList(); this.uvTile = 0; this.memory = []; } update() { if (this.age <= this.life) { this.previous.push(new RecordState(this.position.clone(), this.size.x, this.color.clone())); } else { if (this.previous.length > 0) { this.previous.dequeue(); } } while (this.previous.length > this.length) { this.previous.dequeue(); } } get died() { return this.age >= this.life; } reset() { this.memory.length = 0; this.previous.clear(); } } class WidthOverLength { initialize(particle) { this.width.startGen(particle.memory); } constructor(width) { this.width = width; this.type = 'WidthOverLength'; } update(particle) { if (particle instanceof TrailParticle) { const iter = particle.previous.values(); for (let i = 0; i < particle.previous.length; i++) { const cur = iter.next(); cur.value.size = this.width.genValue(particle.memory, (particle.previous.length - i) / particle.length); } } } frameUpdate(delta) { } toJSON() { return { type: this.type, width: this.width.toJSON(), }; } static fromJSON(json) { return new WidthOverLength(ValueGeneratorFromJSON(json.width)); } clone() { return new WidthOverLength(this.width.clone()); } reset() { } } class ApplyForce { constructor(direction, magnitude) { this.direction = direction; this.magnitude = magnitude; this.type = 'ApplyForce'; this.memory = { data: [], dataCount: 0, }; this.magnitudeValue = this.magnitude.genValue(this.memory); } initialize(particle) { } update(particle, delta) { particle.velocity.addScaledVector(this.direction, this.magnitudeValue * delta); } frameUpdate(delta) { this.magnitudeValue = this.magnitude.genValue(this.memory); } toJSON() { return { type: this.type, direction: [this.direction.x, this.direction.y, this.direction.z], magnitude: this.magnitude.toJSON(), }; } static fromJSON(json) { var _a; return new ApplyForce(new Vector3(json.direction[0], json.direction[1], json.direction[2]), ValueGeneratorFromJSON((_a = json.magnitude) !== null && _a !== void 0 ? _a : json.force)); } clone() { return new ApplyForce(this.direction.clone(), this.magnitude.clone()); } reset() { } } class GravityForce { constructor(center, magnitude) { this.center = center; this.magnitude = magnitude; this.type = 'GravityForce'; this.temp = new Vector3(); } initialize(particle) { } update(particle, delta) { this.temp.copy(this.center).sub(particle.position).normalize(); particle.velocity.addScaledVector(this.temp, (this.magnitude / particle.position.distanceToSquared(this.center)) * delta); } frameUpdate(delta) { } toJSON() { return { type: this.type, center: [this.center.x, this.center.y, this.center.z], magnitude: this.magnitude, }; } static fromJSON(json) { return new GravityForce(new Vector3(json.center[0], json.center[1], json.center[2]), json.magnitude); } clone() { return new GravityForce(this.center.clone(), this.magnitude); } reset() { } } class ChangeEmitDirection { constructor(angle) { this.angle = angle; this.type = 'ChangeEmitDirection'; this._temp = new Vector3(); this._q = new Quaternion(); this.memory = { data: [], dataCount: 0 }; } initialize(particle) { const len = particle.velocity.length(); if (len == 0) return; particle.velocity.normalize(); if (particle.velocity.x === 0 && particle.velocity.y === 0) { this._temp.set(0, particle.velocity.z, 0); } else { this._temp.set(-particle.velocity.y, particle.velocity.x, 0); } this.angle.startGen(this.memory); this._q.setFromAxisAngle(this._temp.normalize(), this.angle.genValue(this.memory)); this._temp.copy(particle.velocity); particle.velocity.applyQuaternion(this._q); this._q.setFromAxisAngle(this._temp, Math.random() * Math.PI * 2); particle.velocity.applyQuaternion(this._q); particle.velocity.setLength(len); } update(particle, delta) { } frameUpdate(delta) { } toJSON() { return { type: this.type, angle: this.angle.toJSON(), }; } static fromJSON(json) { return new ChangeEmitDirection(ValueGeneratorFromJSON(json.angle)); } clone() { return new ChangeEmitDirection(this.angle); } reset() { } } exports.SubParticleEmitMode = void 0; (function (SubParticleEmitMode) { SubParticleEmitMode[SubParticleEmitMode["Death"] = 0] = "Death"; SubParticleEmitMode[SubParticleEmitMode["Birth"] = 1] = "Birth"; SubParticleEmitMode[SubParticleEmitMode["Frame"] = 2] = "Frame"; })(exports.SubParticleEmitMode || (exports.SubParticleEmitMode = {})); class EmitSubParticleSystem { constructor(particleSystem, useVelocityAsBasis, subParticleSystem, mode = exports.SubParticleEmitMode.Frame, emitProbability = 1) { this.particleSystem = particleSystem; this.useVelocityAsBasis = useVelocityAsBasis; this.subParticleSystem = subParticleSystem; this.mode = mode; this.emitProbability = emitProbability; this.type = 'EmitSubParticleSystem'; this.q_ = new Quaternion(); this.v_ = new Vector3(); this.v2_ = new Vector3(); this.subEmissions = new Array(); if (this.subParticleSystem && this.subParticleSystem.system) { this.subParticleSystem.system.onlyUsedByOther = true; } } initialize(particle) { } update(particle, delta) { if (this.mode === exports.SubParticleEmitMode.Frame) { this.emit(particle, delta); } else if (this.mode === exports.SubParticleEmitMode.Birth && particle.age === 0) { this.emit(particle, delta); } else if (this.mode === exports.SubParticleEmitMode.Death && particle.age + delta >= particle.life) { this.emit(particle, delta); } } emit(particle, delta) { if (!this.subParticleSystem) return; if (Math.random() > this.emitProbability) { return; } const m = new Matrix4(); this.setMatrixFromParticle(m, particle); this.subEmissions.push({ burstParticleCount: 0, burstParticleIndex: 0, isBursting: false, burstIndex: 0, burstWaveIndex: 0, time: 0, waitEmiting: 0, matrix: m, travelDistance: 0, particle: particle, }); } frameUpdate(delta) { if (!this.subParticleSystem) return; for (let i = 0; i < this.subEmissions.length; i++) { if (this.subEmissions[i].time >= this.subParticleSystem.system.duration) { this.subEmissions[i] = this.subEmissions[this.subEmissions.length - 1]; this.subEmissions.length = this.subEmissions.length - 1; i--; } else { const subEmissionState = this.subEmissions[i]; if (subEmissionState.particle && subEmissionState.particle.age < subEmissionState.particle.life) { this.setMatrixFromParticle(subEmissionState.matrix, subEmissionState.particle); } else { subEmissionState.particle = undefined; } this.subParticleSystem.system.emit(delta, subEmissionState, subEmissionState.matrix); } } } toJSON() { return { type: this.type, subParticleSystem: this.subParticleSystem ? this.subParticleSystem.uuid : '', useVelocityAsBasis: this.useVelocityAsBasis, mode: this.mode, emitProbability: this.emitProbability, }; } static fromJSON(json, particleSystem) { return new EmitSubParticleSystem(particleSystem, json.useVelocityAsBasis, json.subParticleSystem, json.mode, json.emitProbability); } clone() { return new EmitSubParticleSystem(this.particleSystem, this.useVelocityAsBasis, this.subParticleSystem, this.mode, this.emitProbability); } reset() { } setMatrixFromParticle(m, particle) { let rotation; if (particle.rotation === undefined || this.useVelocityAsBasis) { if (particle.velocity.x === 0 && particle.velocity.y === 0 && (particle.velocity.z === 1 || particle.velocity.z === 0)) { m.set(1, 0, 0, particle.position.x, 0, 1, 0, particle.position.y, 0, 0, 1, particle.position.z, 0, 0, 0, 1); } else { this.v_.copy(Z_VEC3).cross(particle.velocity); this.v2_.copy(particle.velocity).cross(this.v_); const len = this.v_.length(); const len2 = this.v2_.length(); m.set(this.v_.x / len, this.v2_.x / len2, particle.velocity.x, particle.position.x, this.v_.y / len, this.v2_.y / len2, particle.velocity.y, particle.position.y, this.v_.z / len, this.v2_.z / len2, particle.velocity.z, particle.position.z, 0, 0, 0, 1); } } else { if (particle.rotation instanceof Quaternion) { rotation = particle.rotation; } else { this.q_.setFromAxisAngle(Z_VEC3, particle.rotation); rotation = this.q_; } m.compose(particle.position, rotation, ONE_VEC3); } if (!this.particleSystem.worldSpace) { m.multiplyMatrices(this.particleSystem.emitter.matrixWorld, m); } } } const F2 = 0.5 * (Math.sqrt(3.0) - 1.0); const G2 = (3.0 - Math.sqrt(3.0)) / 6.0; const F3 = 1.0 / 3.0; const G3 = 1.0 / 6.0; const F4 = (Math.sqrt(5.0) - 1.0) / 4.0; const G4 = (5.0 - Math.sqrt(5.0)) / 20.0; const grad3 = new Float32Array([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]); const grad4 = new Float32Array([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]); class SimplexNoise { constructor(randomOrSeed = Math.random) { const random = typeof randomOrSeed == 'function' ? randomOrSeed : alea(randomOrSeed); this.p = buildPermutationTable(random); this.perm = new Uint8Array(512); this.permMod12 = new Uint8Array(512); for (let i = 0; i < 512; i++) { this.perm[i] = this.p[i & 255]; this.permMod12[i] = this.perm[i] % 12; } } noise2D(x, y) { const permMod12 = this.permMod12; const perm = this.perm; let n0 = 0; let n1 = 0; let n2 = 0; const s = (x + y) * F2; const i = Math.floor(x + s); const j = Math.floor(y + s); const t = (i + j) * G2; const X0 = i - t; const Y0 = j - t; const x0 = x - X0; const y0 = y - Y0; let i1, j1; if (x0 > y0) { i1 = 1; j1 = 0; } else { i1 = 0; j1 = 1; } const x1 = x0 - i1 + G2; const y1 = y0 - j1 + G2; const x2 = x0 - 1.0 + 2.0 * G2; const y2 = y0 - 1.0 + 2.0 * G2; const ii = i & 255; const jj = j & 255; let t0 = 0.5 - x0 * x0 - y0 * y0; if (t0 >= 0) { const gi0 = permMod12[ii + perm[jj]] * 3; t0 *= t0; n0 = t0 * t0 * (grad3[gi0] * x0 + grad3[gi0 + 1] * y0); } let t1 = 0.5 - x1 * x1 - y1 * y1; if (t1 >= 0) { const gi1 = permMod12[ii + i1 + perm[jj + j1]] * 3; t1 *= t1; n1 = t1 * t1 * (grad3[gi1] * x1 + grad3[gi1 + 1] * y1); } let t2 = 0.5 - x2 * x2 - y2 * y2; if (t2 >= 0) { const gi2 = permMod12[ii + 1 + perm[jj + 1]] * 3; t2 *= t2; n2 = t2 * t2 * (grad3[gi2] * x2 + grad3[gi2 + 1] * y2); } return 70.0 * (n0 + n1 + n2); } noise3D(x, y, z) { const permMod12 = this.permMod12; const perm = this.perm; let n0, n1, n2, n3; const s = (x + y + z) * F3; const i = Math.floor(x + s); const j = Math.floor(y + s); const k = Math.floor(z + s); const t = (i + j + k) * G3; const X0 = i - t; const Y0 = j - t; const Z0 = k - t; const x0 = x - X0; const y0 = y - Y0; const z0 = z - Z0; let i1, j1, k1; let i2, j2, k2; if (x0 >= y0) { if (y0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } } else { if (y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } else if (x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } } const x1 = x0 - i1 + G3; const y1 = y0 - j1 + G3; const z1 = z0 - k1 + G3; const x2 = x0 - i2 + 2.0 * G3; const y2 = y0 - j2 + 2.0 * G3; const z2 = z0 - k2 + 2.0 * G3; const x3 = x0 - 1.0 + 3.0 * G3; const y3 = y0 - 1.0 + 3.0 * G3; const z3 = z0 - 1.0 + 3.0 * G3; const ii = i & 255; const jj = j & 255; const kk = k & 255; let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; if (t0 < 0) n0 = 0.0; else { const gi0 = permMod12[ii + perm[jj + perm[kk]]] * 3; t0 *= t0; n0 = t0 * t0 * (grad3[gi0] * x0 + grad3[gi0 + 1] * y0 + grad3[gi0 + 2] * z0); } let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; if (t1 < 0) n1 = 0.0; else { const gi1 = permMod12[ii + i1 + perm[jj + j1 + perm[kk + k1]]] * 3; t1 *= t1; n1 = t1 * t1 * (grad3[gi1] * x1 + grad3[gi1 + 1] * y1 + grad3[gi1 + 2] * z1); } let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; if (t2 < 0) n2 = 0.0; else { const gi2 = permMod12[ii + i2 + perm[jj + j2 + perm[kk + k2]]] * 3; t2 *= t2; n2 = t2 * t2 * (grad3[gi2] * x2 + grad3[gi2 + 1] * y2 + grad3[gi2 + 2] * z2); } let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; if (t3 < 0) n3 = 0.0; else { const gi3 = permMod12[ii + 1 + perm[jj + 1 + perm[kk + 1]]] * 3; t3 *= t3; n3 = t3 * t3 * (grad3[gi3] * x3 + grad3[gi3 + 1] * y3 + grad3[gi3 + 2] * z3); } return 32.0 * (n0 + n1 + n2 + n3); } noise4D(x, y, z, w) { const perm = this.perm; let n0, n1, n2, n3, n4; const s = (x + y + z + w) * F4; 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; const X0 = i - t; const Y0 = j - t; const Z0 = k - t; const W0 = l - t; const x0 = x - X0; const y0 = y - Y0; const z0 = z - Z0; const w0 = w - W0; let rankx = 0; let ranky = 0; let rankz = 0; let rankw = 0; if (x0 > y0) rankx++; else ranky++; if (x0 > z0) rankx++; else rankz++; if (x0 > w0) rankx++; else rankw++; if (y0 > z0) ranky++; else rankz++; if (y0 > w0) ranky++; else rankw++; if (z0 > w0) rankz++; else rankw++; const i1 = rankx >= 3 ? 1 : 0; const j1 = ranky >= 3 ? 1 : 0; const k1 = rankz >= 3 ? 1 : 0; const l1 = rankw >= 3 ? 1 : 0; const i2 = rankx >= 2 ? 1 : 0; const j2 = ranky >= 2 ? 1 : 0; const k2 = rankz >= 2 ? 1 : 0; const l2 = rankw >= 2 ? 1 : 0; const i3 = rankx >= 1 ? 1 : 0; const j3 = ranky >= 1 ? 1 : 0; const k3 = rankz >= 1 ? 1 : 0; const l3 = rankw >= 1 ? 1 : 0; const x1 = x0 - i1 + G4; const y1 = y0 - j1 + G4; const z1 = z0 - k1 + G4; const w1 = w0 - l1 + G4; const x2 = x0 - i2 + 2.0 * G4; 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; 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; const y4 = y0 - 1.0 + 4.0 * G4; const z4 = z0 - 1.0 + 4.0 * G4; const w4 = w0 - 1.0 + 4.0 * G4; const ii = i & 255; const jj = j & 255; const kk = k & 255; const ll = l & 255; let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; if (t0 < 0) n0 = 0.0; else { const gi0 = (perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32) * 4; t0 *= t0; n0 = t0 * t0 * (grad4[gi0] * x0 + grad4[gi0 + 1] * y0 + grad4[gi0 + 2] * z0 + grad4[gi0 + 3] * w0); } let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; if (t1 < 0) n1 = 0.0; else { const gi1 = (perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32) * 4; t1 *= t1; n1 = t1 * t1 * (grad4[gi1] * x1 + grad4[gi1 + 1] * y1 + grad4[gi1 + 2] * z1 + grad4[gi1 + 3] * w1); } let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; if (t2 < 0) n2 = 0.0; else { const gi2 = (perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32) * 4; t2 *= t2; n2 = t2 * t2 * (grad4[gi2] * x2 + grad4[gi2 + 1] * y2 + grad4[gi2 + 2] * z2 + grad4[gi2 + 3] * w2); } let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; if (t3 < 0) n3 = 0.0; else { const gi3 = (perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32) * 4; t3 *= t3; n3 = t3 * t3 * (grad4[gi3] * x3 + grad4[gi3 + 1] * y3 + grad4[gi3 + 2] * z3 + grad4[gi3 + 3] * w3); } let t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; if (t4 < 0) n4 = 0.0; else { const gi4 = (perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32) * 4; t4 *= t4; n4 = t4 * t4 * (grad4[gi4] * x4 + grad4[gi4 + 1] * y4 + grad4[gi4 + 2] * z4 + grad4[gi4 + 3] * w4); } return 27.0 * (n0 + n1 + n2 + n3 + n4); } } function buildPermutationTable(random) { const p = new Uint8Array(256); for (let i = 0; i < 256; i++) { p[i] = i; } for (let i = 0; i < 255; i++) { const r = i + ~~(random() * (256 - i)); const aux = p[i]; p[i] = p[r]; p[r] = aux; } return p; } function alea(seed) { let s0 = 0; let s1 = 0; let s2 = 0; let c = 1; const mash = masher(); s0 = mash(' '); s1 = mash(' '); s2 = mash(' '); s0 -= mash(seed); if (s0 < 0) { s0 += 1; } s1 -= mash(seed); if (s1 < 0) { s1 += 1; } s2 -= mash(seed); if (s2 < 0) { s2 += 1; } return function () { const t = 2091639 * s0 + c * 2.3283064365386963e-10; s0 = s1; s1 = s2; return s2 = t - (c = t | 0); }; } function masher() { let n = 0xefc8249d; return function (data) { data = data.toString(); for (let i = 0; i < data.length; i++) { n += data.charCodeAt(i); let h = 0.02519603282416938 * n; n = h >>> 0; h -= n; h *= n; n = h >>> 0; h -= n; n += h * 0x100000000; } return (n >>> 0) * 2.3283064365386963e-10; }; } class TurbulenceField { constructor(scale, octaves, velocityMultiplier, timeScale) { this.scale = scale; this.octaves = octaves; this.velocityMultiplier = velocityMultiplier; this.timeScale = timeScale; this.type = 'TurbulenceField'; this.generator = new SimplexNoise(); this.timeOffset = new Vector3(); this.temp = new Vector3(); this.temp2 = new Vector3(); this.timeOffset.x = (Math.random() / this.scale.x) * this.timeScale.x; this.timeOffset.y = (Math.random() / this.scale.y) * this.timeScale.y; this.timeOffset.z = (Math.random() / this.scale.z) * this.timeScale.z; } initialize(particle) { } update(particle, delta) { const x = particle.position.x / this.scale.x; const y = particle.position.y / this.scale.y; const z = particle.position.z / this.scale.z; this.temp.set(0, 0, 0); let lvl = 1; for (let i = 0; i < this.octaves; i++) { this.temp2.set(this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.x * lvl) / lvl, this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.y * lvl) / lvl, this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.z * lvl) / lvl); this.temp.add(this.temp2); lvl *= 2; } this.temp.multiply(this.velocityMultiplier); particle.velocity.addScaledVector(this.temp, delta); } toJSON() { return { type: this.type, scale: [this.scale.x, this.scale.y, this.scale.z], octaves: this.octaves, velocityMultiplier: [this.velocityMultiplier.x, this.velocityMultiplier.y, this.velocityMultiplier.z], timeScale: [this.timeScale.x, this.timeScale.y, this.timeScale.z], }; } frameUpdate(delta) { this.timeOffset.x += delta * this.timeScale.x; this.timeOffset.y += delta * this.timeScale.y; this.timeOffset.z += delta * this.timeScale.z; } static fromJSON(json) { return new TurbulenceField(new Vector3(json.scale[0], json.scale[1], json.scale[2]), json.octaves, new Vector3(json.velocityMultiplier[0], json.velocityMultiplier[1], json.velocityMultiplier[2]), new Vector3(json.timeScale[0], json.timeScale[1], json.timeScale[2])); } clone() { return new TurbulenceField(this.scale.clone(), this.octaves, this.velocityMultiplier.clone(), this.timeScale.clone()); } reset() { } } const generators = []; const tempV$1 = new Vector3(); const tempQ$1 = new Quaternion(); class Noise { constructor(frequency, power, positionAmount = new ConstantValue(1), rotationAmount = new ConstantValue(0)) { this.frequency = frequency; this.power = power; this.positionAmount = positionAmount; this.rotationAmount = rotationAmount; this.type = 'Noise'; this.duration = 0; if (generators.length === 0) { for (let i = 0; i < 100; i++) { generators.push(new SimplexNoise()); } } } initialize(particle) { particle.lastPosNoise = new Vector3(); if (typeof particle.rotation === 'number') { particle.lastRotNoise = 0; } else { particle.lastRotNoise = new Quaternion(); } particle.generatorIndex = [randomInt(0, 100), randomInt(0, 100), randomInt(0, 100), randomInt(0, 100)]; this.positionAmount.startGen(particle.memory); this.rotationAmount.startGen(particle.memory); this.frequency.startGen(particle.memory); this.power.startGen(particle.memory); } update(particle, _) { let frequency = this.frequency.genValue(particle.memory, particle.age / particle.life); let power = this.power.genValue(particle.memory, particle.age / particle.life); let positionAmount = this.positionAmount.genValue(particle.memory, particle.age / particle.life); let rotationAmount = this.rotationAmount.genValue(particle.memory, particle.age / particle.life); if (positionAmount > 0 && particle.lastPosNoise !== undefined) { particle.position.sub(particle.lastPosNoise); tempV$1.set(generators[particle.generatorIndex[0]].noise2D(0, particle.age * frequency) * power * positionAmount, generators[particle.generatorIndex[1]].noise2D(0, particle.age * frequency) * power * positionAmount, generators[particle.generatorIndex[2]].noise2D(0, particle.age * frequency) * power * positionAmount); particle.position.add(tempV$1); particle.lastPosNoise.copy(tempV$1); } if (rotationAmount > 0 && particle.lastRotNoise !== undefined) { if (typeof particle.rotation === 'number') { particle.rotation -= particle.lastRotNoise; particle.rotation += generators[particle.generatorIndex[3]].noise2D(0, particle.age * frequency) * Math.PI * power * rotationAmount; } else { particle.lastRotNoise.invert(); particle.rotation.multiply(particle.lastRotNoise); tempQ$1 .set(generators[particle.generatorIndex[0]].noise2D(0, particle.age * frequency) * power * rotationAmount, generators[particle.generatorIndex[1]].noise2D(0, particle.age * frequency) * power * rotationAmount, generators[particle.generatorIndex[2]].noise2D(0, particle.age * frequency) * power * rotationAmount, generators[particle.generatorIndex[3]].noise2D(0, particle.age * frequency) * power * rotationAmount) .normalize(); particle.rotation.multiply(tempQ$1); particle.lastRotNoise.copy(tempQ$1); } } } toJSON() { return { type: this.type, frequency: this.frequency.toJSON(), power: this.power.toJSON(), positionAmount: this.positionAmount.toJSON(), rotationAmount: this.rotationAmount.toJSON(), }; } frameUpdate(delta) { this.duration += delta; } static fromJSON(json) { return new Noise(ValueGeneratorFromJSON(json.frequency), ValueGeneratorFromJSON(json.power), ValueGeneratorFromJSON(json.positionAmount), ValueGeneratorFromJSON(json.rotationAmount)); } clone() { return new Noise(this.frequency.clone(), this.power.clone(), this.positionAmount.clone(), this.rotationAmount.clone()); } reset() { } } class TextureSequencer { constructor(scaleX = 0, scaleY = 0, position = new Vector3()) { this.scaleX = scaleX; this.scaleY = scaleY; this.position = position; this.locations = []; } transform(position, index) { position.x = this.locations[index % this.locations.length].x * this.scaleX + this.position.x; position.y = this.locations[index % this.locations.length].y * this.scaleY + this.position.y; position.z = this.position.z; } static fromJSON(json) { const textureSequencer = new TextureSequencer(json.scaleX, json.scaleY, new Vector3(json.position[0], json.position[1], json.position[2])); textureSequencer.locations = json.locations.map((loc) => new Vector2(loc.x, loc.y)); return textureSequencer; } clone() { const textureSequencer = new TextureSequencer(this.scaleX, this.scaleY, this.position.clone()); textureSequencer.locations = this.locations.map((loc) => loc.clone()); return textureSequencer; } toJSON() { return { scaleX: this.scaleX, scaleY: this.scaleY, position: this.position, locations: this.locations.map((loc) => ({ x: loc.x, y: loc.y, })), }; } fromImage(img, threshold) { const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); if (!ctx) { return; } ctx.drawImage(img, 0, 0); const data = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: 'srgb' }); canvas.remove(); this.locations.length = 0; for (let i = 0; i < data.height; i++) { for (let j = 0; j < data.width; j++) { if (data.data[(i * data.width + j) * 4 + 3] > threshold) { this.locations.push(new Vector2(j, data.height - i)); } } } } } function SequencerFromJSON(json) { switch (json.type) { case 'TextureSequencer': return TextureSequencer.fromJSON(json); default: return new TextureSequencer(); } } class ApplySequences { constructor(delayBetweenParticles) { this.type = 'ApplySequences'; this.sequencers = []; this.time = 0; this.index = 0; this.pCount = 0; this.tempV = new Vector3(); this.delay = delayBetweenParticles; } initialize(particle) { particle.id = this.pCount; particle.dst = new Vector3(); particle.begin = new Vector3(); particle.inMotion = false; this.pCount++; } reset() { this.time = 0; this.index = 0; this.pCount = 0; } update(particle, delta) { const sequencer = this.sequencers[this.index]; const delay = particle.id * this.delay; if (this.time >= sequencer[0].a + delay && this.time <= sequencer[0].b + delay) { if (!particle.inMotion) { particle.inMotion = true; particle.begin.copy(particle.position); sequencer[1].transform(particle.dst, particle.id); } particle.position.lerpVectors(particle.begin, particle.dst, ApplySequences.BEZIER.genValue((this.time - sequencer[0].a - delay) / (sequencer[0].b - sequencer[0].a))); } else if (this.time > sequencer[0].b + delay) { particle.inMotion = false; } } frameUpdate(delta) { while (this.index + 1 < this.sequencers.length && this.time >= this.sequencers[this.index + 1][0].a) { this.index++; } this.time += delta; } appendSequencer(range, sequencer) { this.sequencers.push([range, sequencer]); } toJSON() { return { type: this.type, delay: this.delay, sequencers: this.sequencers.map(([range, sequencer]) => ({ range: range.toJSON(), sequencer: sequencer.toJSON(), })), }; } static fromJSON(json) { const seq = new ApplySequences(json.delay); json.sequencers.forEach((sequencerJson) => { seq.sequencers.push([ ValueGeneratorFromJSON(sequencerJson.range), SequencerFromJSON(sequencerJson.sequencer), ]); }); return seq; } clone() { const applySequences = new ApplySequences(this.delay); applySequences.sequencers = this.sequencers.map((seq) => [seq[0].clone(), seq[1].clone()]); return applySequences; } } ApplySequences.BEZIER = new Bezier(0, 0, 1, 1); let physicsResolver; function setPhysicsResolver(resolver) { physicsResolver = resolver; } function getPhysicsResolver() { return physicsResolver; } class ApplyCollision { constructor(resolver, bounce) { this.resolver = resolver; this.bounce = bounce; this.type = 'ApplyCollision'; this.tempV = new Vector3(); } initialize(particle) { } update(particle, delta) { if (this.resolver.resolve(particle.position, this.tempV)) { particle.velocity.reflect(this.tempV).multiplyScalar(this.bounce); } } frameUpdate(delta) { } toJSON() { return { type: this.type, bounce: this.bounce, }; } static fromJSON(json) { return new ApplyCollision(getPhysicsResolver(), json.bounce); } clone() { return new ApplyCollision(this.resolver, this.bounce); } reset() { } } class ColorBySpeed { constructor(color, speedRange) { this.color = color; this.speedRange = speedRange; this.type = 'ColorBySpeed'; } initialize(particle) { this.color.startGen(particle.memory); } update(particle, delta) { const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a); this.color.genColor(particle.memory, particle.color, t); particle.color.x *= particle.startColor.x; particle.color.y *= particle.startColor.y; particle.color.z *= particle.startColor.z; particle.color.w *= particle.startColor.w; } frameUpdate(delta) { } toJSON() { return { type: this.type, color: this.color.toJSON(), speedRange: this.speedRange.toJSON(), }; } static fromJSON(json) { return new ColorBySpeed(ColorGeneratorFromJSON(json.color), IntervalValue.fromJSON(json.speedRange)); } clone() { return new ColorBySpeed(this.color.clone(), this.speedRange.clone()); } reset() { } } class SizeBySpeed { initialize(particle) { this.size.startGen(particle.memory); } constructor(size, speedRange) { this.size = size; this.speedRange = speedRange; this.type = 'SizeBySpeed'; } update(particle) { const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a); if (this.size instanceof Vector3Function) { this.size.genValue(particle.memory, particle.size, t).multiply(particle.startSize); } else { particle.size.copy(particle.startSize).multiplyScalar(this.size.genValue(particle.memory, t)); } } toJSON() { return { type: this.type, size: this.size.toJSON(), speedRange: this.speedRange.toJSON(), }; } static fromJSON(json) { return new SizeBySpeed(GeneratorFromJSON(json.size), IntervalValue.fromJSON(json.speedRange)); } frameUpdate(delta) { } clone() { return new SizeBySpeed(this.size.clone(), this.speedRange.clone()); } reset() { } } class RotationBySpeed { constructor(angularVelocity, speedRange) { this.angularVelocity = angularVelocity; this.speedRange = speedRange; this.type = 'RotationBySpeed'; this.tempQuat = new Quaternion(); } initialize(particle) { if (typeof particle.rotation === 'number') { this.angularVelocity.startGen(particle.memory); } } update(particle, delta) { if (typeof particle.rotation === 'number') { const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a); particle.rotation += delta * this.angularVelocity.genValue(particle.memory, t); } } toJSON() { return { type: this.type, angularVelocity: this.angularVelocity.toJSON(), speedRange: this.speedRange.toJSON(), }; } static fromJSON(json) { return new RotationBySpeed(ValueGeneratorFromJSON(json.angularVelocity), IntervalValue.fromJSON(json.speedRange)); } frameUpdate(delta) { } clone() { return new RotationBySpeed(this.angularVelocity.clone(), this.speedRange.clone()); } reset() { } } class LimitSpeedOverLife { initialize(particle) { this.speed.startGen(particle.memory); } constructor(speed, dampen) { this.speed = speed; this.dampen = dampen; this.type = 'LimitSpeedOverLife'; } update(particle, delta) { let speed = particle.velocity.length(); let limit = this.speed.genValue(particle.memory, particle.age / particle.life); if (speed > limit) { const percent = (speed - limit) / speed; particle.velocity.multiplyScalar(1 - percent * this.dampen * delta * 20); } } toJSON() { return { type: this.type, speed: this.speed.toJSON(), dampen: this.dampen, }; } static fromJSON(json) { return new LimitSpeedOverLife(ValueGeneratorFromJSON(json.speed), json.dampen); } frameUpdate(delta) { } clone() { return new LimitSpeedOverLife(this.speed.clone(), this.dampen); } reset() { } } const BehaviorTypes = { ApplyForce: { type: 'ApplyForce', constructor: ApplyForce, params: [ ['direction', ['vec3']], ['magnitude', ['value']], ], loadJSON: ApplyForce.fromJSON, }, Noise: { type: 'Noise', constructor: Noise, params: [ ['frequency', ['value']], ['power', ['value']], ['positionAmount', ['value']], ['rotationAmount', ['value']], ], loadJSON: Noise.fromJSON, }, TurbulenceField: { type: 'TurbulenceField', constructor: TurbulenceField, params: [ ['scale', ['vec3']], ['octaves', ['number']], ['velocityMultiplier', ['vec3']], ['timeScale', ['vec3']], ], loadJSON: TurbulenceField.fromJSON, }, GravityForce: { type: 'GravityForce', constructor: GravityForce, params: [ ['center', ['vec3']], ['magnitude', ['number']], ], loadJSON: GravityForce.fromJSON, }, ColorOverLife: { type: 'ColorOverLife', constructor: ColorOverLife, params: [['color', ['colorFunc']]], loadJSON: ColorOverLife.fromJSON, }, RotationOverLife: { type: 'RotationOverLife', constructor: RotationOverLife, params: [['angularVelocity', ['value', 'valueFunc']]], loadJSON: RotationOverLife.fromJSON, }, Rotation3DOverLife: { type: 'Rotation3DOverLife', constructor: Rotation3DOverLife, params: [['angularVelocity', ['rotationFunc']]], loadJSON: Rotation3DOverLife.fromJSON, }, SizeOverLife: { type: 'SizeOverLife', constructor: SizeOverLife, params: [['size', ['value', 'valueFunc', 'vec3Func']]], loadJSON: SizeOverLife.fromJSON, }, ColorBySpeed: { type: 'ColorBySpeed', constructor: ColorBySpeed, params: [ ['color', ['colorFunc']], ['speedRange', ['range']], ], loadJSON: ColorBySpeed.fromJSON, }, RotationBySpeed: { type: 'RotationBySpeed', constructor: RotationBySpeed, params: [ ['angularVelocity', ['value', 'valueFunc']], ['speedRange', ['range']], ], loadJSON: RotationBySpeed.fromJSON, }, SizeBySpeed: { type: 'SizeBySpeed', constructor: SizeBySpeed, params: [ ['size', ['value', 'valueFunc', 'vec3Func']], ['speedRange', ['range']], ], loadJSON: SizeBySpeed.fromJSON, }, SpeedOverLife: { type: 'SpeedOverLife', constructor: SpeedOverLife, params: [['speed', ['value', 'valueFunc']]], loadJSON: SpeedOverLife.fromJSON, }, FrameOverLife: { type: 'FrameOverLife', constructor: FrameOverLife, params: [['frame', ['value', 'valueFunc']]], loadJSON: FrameOverLife.fromJSON, }, ForceOverLife: { type: 'ForceOverLife', constructor: ForceOverLife, params: [ ['x', ['value', 'valueFunc']], ['y', ['value', 'valueFunc']], ['z', ['value', 'valueFunc']], ], loadJSON: ForceOverLife.fromJSON, }, OrbitOverLife: { type: 'OrbitOverLife', constructor: OrbitOverLife, params: [ ['orbitSpeed', ['value', 'valueFunc']], ['axis', ['vec3']], ], loadJSON: OrbitOverLife.fromJSON, }, WidthOverLength: { type: 'WidthOverLength', constructor: WidthOverLength, params: [['width', ['value', 'valueFunc']]], loadJSON: WidthOverLength.fromJSON, }, ChangeEmitDirection: { type: 'ChangeEmitDirection', constructor: ChangeEmitDirection, params: [['angle', ['value']]], loadJSON: ChangeEmitDirection.fromJSON, }, EmitSubParticleSystem: { type: 'EmitSubParticleSystem', constructor: EmitSubParticleSystem, params: [ ['particleSystem', ['self']], ['useVelocityAsBasis', ['boolean']], ['subParticleSystem', ['particleSystem']], ['mode', ['number']], ['emitProbability', ['number']], ], loadJSON: EmitSubParticleSystem.fromJSON, }, LimitSpeedOverLife: { type: 'LimitSpeedOverLife', constructor: LimitSpeedOverLife, params: [ ['speed', ['value', 'valueFunc']], ['dampen', ['number']], ], loadJSON: LimitSpeedOverLife.fromJSON, }, }; function BehaviorFromJSON(json, particleSystem) { return BehaviorTypes[json.type].loadJSON(json, particleSystem); } const Plugins = []; function loadPlugin(plugin) { const existing = Plugins.find((item) => item.id === plugin.id); if (!existing) { plugin.initialize(); for (const emitterShape of plugin.emitterShapes) { if (!EmitterShapes[emitterShape.type]) { EmitterShapes[emitterShape.type] = emitterShape; } } for (const behavior of plugin.behaviors) { if (!BehaviorTypes[behavior.type]) { BehaviorTypes[behavior.type] = behavior; } } } } function unloadPlugin(pluginId) { const plugin = Plugins.find((item) => item.id === pluginId); if (plugin) { for (const emitterShape of plugin.emitterShapes) { if (EmitterShapes[emitterShape.type]) { delete EmitterShapes[emitterShape.type]; } } for (const behavior of plugin.behaviors) { if (BehaviorTypes[behavior.type]) { delete BehaviorTypes[behavior.type]; } } } } /** * Enum representing the render modes for particles. */ var RenderMode = /*#__PURE__*/function (RenderMode) { RenderMode[RenderMode["BillBoard"] = 0] = "BillBoard"; RenderMode[RenderMode["StretchedBillBoard"] = 1] = "StretchedBillBoard"; RenderMode[RenderMode["Mesh"] = 2] = "Mesh"; RenderMode[RenderMode["Trail"] = 3] = "Trail"; RenderMode[RenderMode["HorizontalBillBoard"] = 4] = "HorizontalBillBoard"; RenderMode[RenderMode["VerticalBillBoard"] = 5] = "VerticalBillBoard"; return RenderMode; }({}); /** * Base class for VFX batches. */ var VFXBatch = /*#__PURE__*/function (_Mesh) { function VFXBatch(settings) { var _this; _classCallCheck(this, VFXBatch); _this = _callSuper(this, VFXBatch); _defineProperty(_this, "type", 'VFXBatch'); _defineProperty(_this, "systems", void 0); _defineProperty(_this, "settings", void 0); _defineProperty(_this, "maxParticles", void 0); _this.maxParticles = 1000; _this.systems = new Set(); var layers = new three.Layers(); layers.mask = settings.layers.mask; var newMat = settings.material.clone(); newMat.defines = {}; Object.assign(newMat.defines, settings.material.defines); _this.settings = { instancingGeometry: settings.instancingGeometry, renderMode: settings.renderMode, renderOrder: settings.renderOrder, material: newMat, uTileCount: settings.uTileCount, vTileCount: settings.vTileCount, blendTiles: settings.blendTiles, softParticles: settings.softParticles, softNearFade: settings.softNearFade, softFarFade: settings.softFarFade, layers: layers }; _this.frustumCulled = false; _this.renderOrder = _this.settings.renderOrder; return _this; } _inherits(VFXBatch, _Mesh); return _createClass(VFXBatch, [{ key: "addSystem", value: function addSystem(system) { this.systems.add(system); } }, { key: "removeSystem", value: function removeSystem(system) { this.systems["delete"](system); } }, { key: "applyDepthTexture", value: function applyDepthTexture(depthTexture) { var uniform = this.material.uniforms['depthTexture']; if (uniform) { if (uniform.value !== depthTexture) { uniform.value = depthTexture; this.material.needsUpdate = true; } } } }]); }(three.Mesh); var UP = new Vector3(0, 0, 1); var tempQ = new Quaternion(); var tempV = new Vector3(); var tempV2 = new Vector3(); new Vector3(); var PREWARM_FPS = 60; /** * Interface representing the JSON parameters for a burst. */ /** * Interface representing the parameters for a particle system. */ var DEFAULT_GEOMETRY = new three.PlaneGeometry(1, 1, 1, 1); /** * ParticleSystem represents a system that generates and controls particles with similar attributes. * * @class */ var ParticleSystem = /*#__PURE__*/function () { function ParticleSystem(parameters) { var _parameters$duration, _parameters$startLife, _parameters$startSpee, _parameters$startRota, _parameters$startSize, _parameters$startColo, _parameters$emissionO, _parameters$emissionO2, _parameters$emissionB, _parameters$onlyUsedB, _parameters$shape, _parameters$behaviors, _parameters$worldSpac, _parameters$rendererE, _parameters$instancin, _parameters$renderMod, _parameters$renderOrd, _parameters$uTileCoun, _parameters$vTileCoun, _parameters$blendTile, _parameters$softParti, _parameters$softNearF, _parameters$softFarFa, _parameters$layers, _this = this; _classCallCheck(this, ParticleSystem); /** * whether the ParticleSystem should be automatically disposed when it finishes emitting particles. * * @type {boolean} */ _defineProperty(this, "autoDestroy", void 0); /** * Determines whether a looping ParticleSystem should prewarm, i.e., the Particle System looks like it has already simulated for one loop when first becoming visible. * * @type {boolean} */ _defineProperty(this, "prewarm", void 0); /** * Determines whether the ParticleSystem should loop, i.e., restart emitting particles after the duration of the particle system is expired. * * @type {boolean} */ _defineProperty(this, "looping", void 0); /** * The duration of the ParticleSystem in seconds. * * @type {number} */ _defineProperty(this, "duration", void 0); /** * The value generator or function value generator for the starting life of particles. * * @type {ValueGenerator | FunctionValueGenerator} */ _defineProperty(this, "startLife", void 0); /** * The value generator or function value generator for the starting speed of particles. * * @type {ValueGenerator | FunctionValueGenerator} */ _defineProperty(this, "startSpeed", void 0); /** * The value generator or function value generator or rotation generator for the starting rotation of particles. * * @type {ValueGenerator | FunctionValueGenerator | RotationGenerator} */ _defineProperty(this, "startRotation", void 0); /** * The value generator or function value generator for the starting size of particles. * * @type {ValueGenerator | FunctionValueGenerator} */ _defineProperty(this, "startSize", void 0); /** * The color generator or function color generator for the starting color of particles. * * @type {ColorGenerator | FunctionColorGenerator} */ _defineProperty(this, "startColor", void 0); /** * The value generator for the starting tile index of particles. * * @type {ValueGenerator} */ _defineProperty(this, "startTileIndex", void 0); /** * The renderer emitter settings for the ParticleSystem. * * @type {TrailSettings | MeshSettings | BillBoardSettings | StretchedBillBoardSettings} */ _defineProperty(this, "rendererEmitterSettings", void 0); /** * The value generator or function value generator for the emission rate of particles over time. * * @type {ValueGenerator | FunctionValueGenerator} */ _defineProperty(this, "emissionOverTime", void 0); /** * The value generator or function value generator for the emission rate of particles over distance. * * @type {ValueGenerator | FunctionValueGenerator} */ _defineProperty(this, "emissionOverDistance", void 0); /** * An array of burst parameters for the ParticleSystem. * * @type {Array} */ _defineProperty(this, "emissionBursts", void 0); /** * Determines whether the ParticleSystem is only used by other ParticleSystems. * * @type {boolean} */ _defineProperty(this, "onlyUsedByOther", void 0); /** * Determines whether the ParticleSystem is in world space or local space. * * @type {boolean} */ _defineProperty(this, "worldSpace", void 0); /** * The number of particles in the ParticleSystem. * * @type {number} */ _defineProperty(this, "particleNum", void 0); /** * Determines whether the ParticleSystem is paused. * * @type {boolean} */ _defineProperty(this, "paused", void 0); /** * All the particles in the ParticleSystem. * * @type {Array} */ _defineProperty(this, "particles", void 0); /** * the shape of the emitter. * * @type {EmitterShape} */ _defineProperty(this, "emitterShape", void 0); /** * the emitter object that should be added in the scene. * * @type {ParticleEmitter} */ _defineProperty(this, "emitter", void 0); /** * the VFX renderer settings for the batch renderer * * @type {VFXBatchSettings} */ _defineProperty(this, "rendererSettings", void 0); /** * whether needs to update renderer settings for the batch renderer * * @type {boolean} */ _defineProperty(this, "neededToUpdateRender", void 0); /** * a list of particle behaviors in the particle system * * @type {Array} */ _defineProperty(this, "behaviors", void 0); _defineProperty(this, "emissionState", void 0); _defineProperty(this, "prewarmed", void 0); _defineProperty(this, "emitEnded", void 0); _defineProperty(this, "markForDestroy", void 0); _defineProperty(this, "previousWorldPos", void 0); _defineProperty(this, "temp", new Vector3()); _defineProperty(this, "travelDistance", 0); _defineProperty(this, "normalMatrix", new Matrix3()); _defineProperty(this, "memory", []); _defineProperty(this, "listeners", {}); /** @internal **/ _defineProperty(this, "_renderer", void 0); _defineProperty(this, "firstTimeUpdate", true); this.autoDestroy = parameters.autoDestroy === undefined ? false : parameters.autoDestroy; this.duration = (_parameters$duration = parameters.duration) !== null && _parameters$duration !== void 0 ? _parameters$duration : 1; this.looping = parameters.looping === undefined ? true : parameters.looping; this.prewarm = parameters.prewarm === undefined ? false : parameters.prewarm; this.startLife = (_parameters$startLife = parameters.startLife) !== null && _parameters$startLife !== void 0 ? _parameters$startLife : new ConstantValue(5); this.startSpeed = (_parameters$startSpee = parameters.startSpeed) !== null && _parameters$startSpee !== void 0 ? _parameters$startSpee : new ConstantValue(0); this.startRotation = (_parameters$startRota = parameters.startRotation) !== null && _parameters$startRota !== void 0 ? _parameters$startRota : new ConstantValue(0); this.startSize = (_parameters$startSize = parameters.startSize) !== null && _parameters$startSize !== void 0 ? _parameters$startSize : new ConstantValue(1); this.startColor = (_parameters$startColo = parameters.startColor) !== null && _parameters$startColo !== void 0 ? _parameters$startColo : new ConstantColor(new Vector4(1, 1, 1, 1)); //this.startLength = parameters.startLength ?? new ConstantValue(30); this.emissionOverTime = (_parameters$emissionO = parameters.emissionOverTime) !== null && _parameters$emissionO !== void 0 ? _parameters$emissionO : new ConstantValue(10); this.emissionOverDistance = (_parameters$emissionO2 = parameters.emissionOverDistance) !== null && _parameters$emissionO2 !== void 0 ? _parameters$emissionO2 : new ConstantValue(0); this.emissionBursts = (_parameters$emissionB = parameters.emissionBursts) !== null && _parameters$emissionB !== void 0 ? _parameters$emissionB : []; this.onlyUsedByOther = (_parameters$onlyUsedB = parameters.onlyUsedByOther) !== null && _parameters$onlyUsedB !== void 0 ? _parameters$onlyUsedB : false; this.emitterShape = (_parameters$shape = parameters.shape) !== null && _parameters$shape !== void 0 ? _parameters$shape : new SphereEmitter(); this.behaviors = (_parameters$behaviors = parameters.behaviors) !== null && _parameters$behaviors !== void 0 ? _parameters$behaviors : new Array(); this.worldSpace = (_parameters$worldSpac = parameters.worldSpace) !== null && _parameters$worldSpac !== void 0 ? _parameters$worldSpac : false; this.rendererEmitterSettings = (_parameters$rendererE = parameters.rendererEmitterSettings) !== null && _parameters$rendererE !== void 0 ? _parameters$rendererE : {}; if (parameters.renderMode === RenderMode.StretchedBillBoard) { var _stretchedBillboardSe, _stretchedBillboardSe2; var stretchedBillboardSettings = this.rendererEmitterSettings; if (parameters.speedFactor !== undefined) { stretchedBillboardSettings.speedFactor = parameters.speedFactor; } stretchedBillboardSettings.speedFactor = (_stretchedBillboardSe = stretchedBillboardSettings.speedFactor) !== null && _stretchedBillboardSe !== void 0 ? _stretchedBillboardSe : 0; stretchedBillboardSettings.lengthFactor = (_stretchedBillboardSe2 = stretchedBillboardSettings.lengthFactor) !== null && _stretchedBillboardSe2 !== void 0 ? _stretchedBillboardSe2 : 0; } this.rendererSettings = { instancingGeometry: (_parameters$instancin = parameters.instancingGeometry) !== null && _parameters$instancin !== void 0 ? _parameters$instancin : DEFAULT_GEOMETRY, renderMode: (_parameters$renderMod = parameters.renderMode) !== null && _parameters$renderMod !== void 0 ? _parameters$renderMod : RenderMode.BillBoard, renderOrder: (_parameters$renderOrd = parameters.renderOrder) !== null && _parameters$renderOrd !== void 0 ? _parameters$renderOrd : 0, material: parameters.material, uTileCount: (_parameters$uTileCoun = parameters.uTileCount) !== null && _parameters$uTileCoun !== void 0 ? _parameters$uTileCoun : 1, vTileCount: (_parameters$vTileCoun = parameters.vTileCount) !== null && _parameters$vTileCoun !== void 0 ? _parameters$vTileCoun : 1, blendTiles: (_parameters$blendTile = parameters.blendTiles) !== null && _parameters$blendTile !== void 0 ? _parameters$blendTile : false, softParticles: (_parameters$softParti = parameters.softParticles) !== null && _parameters$softParti !== void 0 ? _parameters$softParti : false, softNearFade: (_parameters$softNearF = parameters.softNearFade) !== null && _parameters$softNearF !== void 0 ? _parameters$softNearF : 0, softFarFade: (_parameters$softFarFa = parameters.softFarFade) !== null && _parameters$softFarFa !== void 0 ? _parameters$softFarFa : 0, layers: (_parameters$layers = parameters.layers) !== null && _parameters$layers !== void 0 ? _parameters$layers : new three.Layers() }; this.neededToUpdateRender = true; this.particles = new Array(); this.startTileIndex = parameters.startTileIndex || new ConstantValue(0); this.emitter = new ParticleEmitter(this); this.paused = false; this.particleNum = 0; this.emissionState = { isBursting: false, burstParticleIndex: 0, burstParticleCount: 0, burstIndex: 0, burstWaveIndex: 0, time: 0, waitEmiting: 0, travelDistance: 0 }; this.emissionBursts.forEach(function (burst) { return burst.count.startGen(_this.memory); }); this.emissionOverDistance.startGen(this.memory); this.emitEnded = false; this.markForDestroy = false; this.prewarmed = false; } /** * Pause the simulation of the particle system */ return _createClass(ParticleSystem, [{ key: "time", get: /** * get the current time of the playback of the particle system */ function get() { return this.emissionState.time; } /** * layers control visibility of the object. * currently if you change the layers setting, you need manually set this.neededToUpdateRender = true; * @type {Layers} * @see {@link https://threejs.org/docs/index.html#api/en/core/Layers | Official Documentation} * @see {@link https://github.com/mrdoob/three.js/blob/master/src/core/Layers.js | Source} */, set: /** * set the time of the playback of the particle system * @param time */ function set(time) { this.emissionState.time = time; } }, { key: "layers", get: function get() { return this.rendererSettings.layers; } /** * get the texture of the particle system */ }, { key: "texture", get: function get() { return this.rendererSettings.material.map; } /** * Set the texture of the particle system * It will rebuild the material */, set: function set(texture) { this.rendererSettings.material.map = texture; this.neededToUpdateRender = true; //this.emitter.material.uniforms.map.value = texture; } /** * Get the material of the particle system */ }, { key: "material", get: function get() { return this.rendererSettings.material; } /** * Set the material of the particle system * It will rebuild the material */, set: function set(material) { this.rendererSettings.material = material; this.neededToUpdateRender = true; } /** * Get the number of horizontal tiles in the texture. */ }, { key: "uTileCount", get: function get() { return this.rendererSettings.uTileCount; } /** * Set the number of horizontal tiles in the texture. * @param u */, set: function set(u) { this.rendererSettings.uTileCount = u; this.neededToUpdateRender = true; } /** * Get the number of vertical tiles in the texture. */ }, { key: "vTileCount", get: function get() { return this.rendererSettings.vTileCount; } /** * Set the number of vertical tiles in the texture. * @param v */, set: function set(v) { this.rendererSettings.vTileCount = v; this.neededToUpdateRender = true; } /** * get whether the particle texture blends tile transitions */ }, { key: "blendTiles", get: function get() { return this.rendererSettings.blendTiles; } /** * Set whether the particle texture blends tile transitions * @param v */, set: function set(v) { this.rendererSettings.blendTiles = v; this.neededToUpdateRender = true; } /** * Get whether the particle system uses soft particles. * Soft particles are particles that fade out when they are close to geometry. */ }, { key: "softParticles", get: function get() { return this.rendererSettings.softParticles; } /** * Set whether the particle system uses soft particles. * Soft particles are particles that fade out when they are close to geometry. * @param v */, set: function set(v) { this.rendererSettings.softParticles = v; this.neededToUpdateRender = true; } }, { key: "softNearFade", get: function get() { return this.rendererSettings.softNearFade; }, set: function set(v) { this.rendererSettings.softNearFade = v; this.neededToUpdateRender = true; } }, { key: "softFarFade", get: function get() { return this.rendererSettings.softFarFade; }, set: function set(v) { this.rendererSettings.softFarFade = v; this.neededToUpdateRender = true; } /** * Get the instancing geometry of the particle system. * @param geometry */ }, { key: "instancingGeometry", get: function get() { return this.rendererSettings.instancingGeometry; } /** * Set the instancing geometry of the particle system. * @param geometry */, set: function set(geometry) { this.restart(); this.particles.length = 0; this.rendererSettings.instancingGeometry = geometry; this.neededToUpdateRender = true; } /** * Get the render mode of the particle system. * {@link RenderMode} */ }, { key: "renderMode", get: function get() { return this.rendererSettings.renderMode; } /** * Set the render mode of the particle system. * {@link RenderMode} */, set: function set(renderMode) { if (this.rendererSettings.renderMode != RenderMode.Trail && renderMode === RenderMode.Trail || this.rendererSettings.renderMode == RenderMode.Trail && renderMode !== RenderMode.Trail) { this.restart(); this.particles.length = 0; } if (this.rendererSettings.renderMode !== renderMode) { switch (renderMode) { case RenderMode.Trail: this.rendererEmitterSettings = { startLength: new ConstantValue(30), followLocalOrigin: false }; break; case RenderMode.Mesh: this.rendererEmitterSettings = { geometry: new three.PlaneGeometry(1, 1) }; this.startRotation = new AxisAngleGenerator(new Vector3(0, 1, 0), new ConstantValue(0)); break; case RenderMode.StretchedBillBoard: this.rendererEmitterSettings = { speedFactor: 0, lengthFactor: 2 }; if (this.rendererSettings.renderMode === RenderMode.Mesh) { this.startRotation = new ConstantValue(0); } break; case RenderMode.BillBoard: case RenderMode.VerticalBillBoard: case RenderMode.HorizontalBillBoard: this.rendererEmitterSettings = {}; if (this.rendererSettings.renderMode === RenderMode.Mesh) { this.startRotation = new ConstantValue(0); } break; } } this.rendererSettings.renderMode = renderMode; this.neededToUpdateRender = true; //this.emitter.rebuildMaterial(); } /** * get the render order of the particle system in render pipeline. * the higher the value, the later the particle system is rendered. */ }, { key: "renderOrder", get: function get() { return this.rendererSettings.renderOrder; } /** * set the render order of the particle system in render pipeline. * the higher the value, the later the particle system is rendered. */, set: function set(renderOrder) { this.rendererSettings.renderOrder = renderOrder; this.neededToUpdateRender = true; //this.emitter.rebuildMaterial(); } /** * get which blending to use. * @default THREE.NormalBlending */ }, { key: "blending", get: function get() { return this.rendererSettings.material.blending; } /** * Set which blending to use. * @default THREE.NormalBlending */, set: function set(blending) { this.rendererSettings.material.blending = blending; this.neededToUpdateRender = true; } }, { key: "pause", value: function pause() { this.paused = true; } /** * Unpause the simulation of the particle system */ }, { key: "play", value: function play() { this.paused = false; } /** * remove all existing particles, reset the particle system * and pause at the beginning */ }, { key: "stop", value: function stop() { this.restart(); this.pause(); } }, { key: "spawn", value: function spawn(count, emissionState, matrix) { tempQ.setFromRotationMatrix(matrix); var translation = tempV; var quaternion = tempQ; var scale = tempV2; matrix.decompose(translation, quaternion, scale); for (var i = 0; i < count; i++) { emissionState.burstParticleIndex = i; this.particleNum++; while (this.particles.length < this.particleNum) { if (this.rendererSettings.renderMode === RenderMode.Trail) { this.particles.push(new TrailParticle()); } else { this.particles.push(new SpriteParticle()); } } var particle = this.particles[this.particleNum - 1]; particle.reset(); particle.speedModifier = 1; this.startColor.startGen(particle.memory); this.startColor.genColor(particle.memory, particle.startColor, this.emissionState.time); particle.color.copy(particle.startColor); this.startSpeed.startGen(particle.memory); particle.startSpeed = this.startSpeed.genValue(particle.memory, emissionState.time / this.duration); this.startLife.startGen(particle.memory); particle.life = this.startLife.genValue(particle.memory, emissionState.time / this.duration); particle.age = 0; this.startSize.startGen(particle.memory); if (this.startSize.type === "vec3function") { this.startSize.genValue(particle.memory, particle.startSize, emissionState.time / this.duration); } else { var size = this.startSize.genValue(particle.memory, emissionState.time / this.duration); particle.startSize.set(size, size, size); } this.startTileIndex.startGen(particle.memory); particle.uvTile = this.startTileIndex.genValue(particle.memory); particle.size.copy(particle.startSize); if (this.rendererSettings.renderMode === RenderMode.Mesh || this.rendererSettings.renderMode === RenderMode.BillBoard || this.rendererSettings.renderMode === RenderMode.VerticalBillBoard || this.rendererSettings.renderMode === RenderMode.HorizontalBillBoard || this.rendererSettings.renderMode === RenderMode.StretchedBillBoard) { var sprite = particle; this.startRotation.startGen(particle.memory); if (this.rendererSettings.renderMode === RenderMode.Mesh) { if (!(sprite.rotation instanceof Quaternion)) { sprite.rotation = new Quaternion(); } if (this.startRotation.type === 'rotation') { this.startRotation.genValue(particle.memory, sprite.rotation, 1, emissionState.time / this.duration); } else { sprite.rotation.setFromAxisAngle(UP, this.startRotation.genValue(sprite.memory, emissionState.time / this.duration)); } } else { if (this.startRotation.type === 'rotation') { sprite.rotation = 0; } else { sprite.rotation = this.startRotation.genValue(sprite.memory, emissionState.time / this.duration); } } } else if (this.rendererSettings.renderMode === RenderMode.Trail) { var trail = particle; this.rendererEmitterSettings.startLength.startGen(trail.memory); trail.length = this.rendererEmitterSettings.startLength.genValue(trail.memory, emissionState.time / this.duration); } this.emitterShape.initialize(particle, emissionState); if (this.rendererSettings.renderMode === RenderMode.Trail && this.rendererEmitterSettings.followLocalOrigin) { var _trail = particle; _trail.localPosition = new Vector3().copy(_trail.position); } if (this.worldSpace) { particle.position.applyMatrix4(matrix); particle.startSize.multiply(scale).abs(); particle.size.copy(particle.startSize); particle.velocity.multiply(scale).applyMatrix3(this.normalMatrix); if (particle.rotation && particle.rotation instanceof Quaternion) { particle.rotation.multiplyQuaternions(tempQ, particle.rotation); } } else { if (this.onlyUsedByOther) { particle.parentMatrix = matrix; } } for (var j = 0; j < this.behaviors.length; j++) { this.behaviors[j].initialize(particle, this); } } } /** * Stops emitting particles */ }, { key: "endEmit", value: function endEmit() { this.emitEnded = true; if (this.autoDestroy) { this.markForDestroy = true; } this.fire({ type: "emitEnd", particleSystem: this }); } /** * remove the particle system's emitter from the scene */ }, { key: "dispose", value: function dispose() { if (this._renderer) this._renderer.deleteSystem(this); this.emitter.dispose(); if (this.emitter.parent) this.emitter.parent.remove(this.emitter); this.fire({ type: "destroy", particleSystem: this }); } /** * remove all existing particles, reset the particle system * and restart the particle system */ }, { key: "restart", value: function restart() { var _this2 = this; this.memory.length = 0; this.paused = false; this.particleNum = 0; this.emissionState.isBursting = false; this.emissionState.burstIndex = 0; this.emissionState.burstWaveIndex = 0; this.emissionState.time = 0; this.emissionState.waitEmiting = 0; this.behaviors.forEach(function (behavior) { behavior.reset(); }); this.emitEnded = false; this.markForDestroy = false; this.prewarmed = false; this.emissionBursts.forEach(function (burst) { return burst.count.startGen(_this2.memory); }); this.emissionOverDistance.startGen(this.memory); } }, { key: "update", value: /** * Update the particle system per frame * @param delta * @private */ function update(delta) { if (this.paused) return; var currentParent = this.emitter; while (currentParent.parent) { currentParent = currentParent.parent; } if (currentParent.type !== 'Scene') { this.dispose(); return; } if (this.firstTimeUpdate) { this.firstTimeUpdate = false; this.emitter.updateWorldMatrix(true, false); } if (this.emitEnded && this.particleNum === 0) { if (this.markForDestroy && this.emitter.parent) this.dispose(); return; } if (this.looping && this.prewarm && !this.prewarmed) { this.prewarmed = true; for (var i = 0; i < this.duration * PREWARM_FPS; i++) { // stack overflow? this.update(1.0 / PREWARM_FPS); } } if (delta > 0.1) { delta = 0.1; } if (this.neededToUpdateRender) { if (this._renderer) this._renderer.updateSystem(this); this.neededToUpdateRender = false; } if (!this.onlyUsedByOther) { this.emit(delta, this.emissionState, this.emitter.matrixWorld); } // simulate this.emitterShape.update(this, delta); for (var j = 0; j < this.behaviors.length; j++) { this.behaviors[j].frameUpdate(delta); for (var _i = 0; _i < this.particleNum; _i++) { if (!this.particles[_i].died) { this.behaviors[j].update(this.particles[_i], delta); } } } for (var _i2 = 0; _i2 < this.particleNum; _i2++) { if (this.rendererEmitterSettings.followLocalOrigin && this.particles[_i2].localPosition) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.particles[_i2].position.copy(this.particles[_i2].localPosition); if (this.particles[_i2].parentMatrix) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.particles[_i2].position.applyMatrix4(this.particles[_i2].parentMatrix); } else { this.particles[_i2].position.applyMatrix4(this.emitter.matrixWorld); } } else { this.particles[_i2].position.addScaledVector(this.particles[_i2].velocity, delta * this.particles[_i2].speedModifier); } this.particles[_i2].age += delta; } if (this.rendererSettings.renderMode === RenderMode.Trail) { for (var _i3 = 0; _i3 < this.particleNum; _i3++) { var particle = this.particles[_i3]; particle.update(); } } // particle die for (var _i4 = 0; _i4 < this.particleNum; _i4++) { var _particle = this.particles[_i4]; if (_particle.died && (!(_particle instanceof TrailParticle) || _particle.previous.length === 0)) { this.particles[_i4] = this.particles[this.particleNum - 1]; this.particles[this.particleNum - 1] = _particle; this.particleNum--; _i4--; this.fire({ type: "particleDied", particleSystem: this, particle: _particle }); } } } /** * Emit particles * @param delta the duration of the frame * @param emissionState the state of the emission * @param emitterMatrix the matrix of the emitter */ }, { key: "emit", value: function emit(delta, emissionState, emitterMatrix) { if (emissionState.time > this.duration) { if (this.looping) { emissionState.time -= this.duration; emissionState.burstIndex = 0; this.behaviors.forEach(function (behavior) { behavior.reset(); }); } else { if (!this.emitEnded && !this.onlyUsedByOther) { this.endEmit(); } } } this.normalMatrix.getNormalMatrix(emitterMatrix); // spawn var totalSpawn = Math.ceil(emissionState.waitEmiting); this.spawn(totalSpawn, emissionState, emitterMatrix); emissionState.waitEmiting -= totalSpawn; // spawn burst while (emissionState.burstIndex < this.emissionBursts.length && this.emissionBursts[emissionState.burstIndex].time <= emissionState.time) { if (Math.random() < this.emissionBursts[emissionState.burstIndex].probability) { var count = this.emissionBursts[emissionState.burstIndex].count.genValue(this.memory, this.time); emissionState.isBursting = true; emissionState.burstParticleCount = count; this.spawn(count, emissionState, emitterMatrix); emissionState.isBursting = false; } emissionState.burstIndex++; } if (!this.emitEnded) { emissionState.waitEmiting += delta * this.emissionOverTime.genValue(this.memory, emissionState.time / this.duration); if (emissionState.previousWorldPos != undefined) { this.temp.set(emitterMatrix.elements[12], emitterMatrix.elements[13], emitterMatrix.elements[14]); emissionState.travelDistance += emissionState.previousWorldPos.distanceTo(this.temp); var emitPerMeter = this.emissionOverDistance.genValue(this.memory, emissionState.time / this.duration); if (emissionState.travelDistance * emitPerMeter > 0) { var _count = Math.floor(emissionState.travelDistance * emitPerMeter); emissionState.travelDistance -= _count / emitPerMeter; emissionState.waitEmiting += _count; } } } if (emissionState.previousWorldPos === undefined) emissionState.previousWorldPos = new Vector3(); emissionState.previousWorldPos.set(emitterMatrix.elements[12], emitterMatrix.elements[13], emitterMatrix.elements[14]); emissionState.time += delta; } /** * output the particle system to JSON * @param meta serialization meta data * @param options serialization options */ }, { key: "toJSON", value: function toJSON(meta) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var isRootObject = meta === undefined || typeof meta === 'string'; if (isRootObject) { // initialize meta obj meta = { geometries: {}, materials: {}, textures: {}, images: {}, shapes: {}, skeletons: {}, animations: {}, nodes: {} }; } meta.materials[this.rendererSettings.material.uuid] = this.rendererSettings.material.toJSON(meta); if (options.useUrlForImage) { var _this$texture; if (((_this$texture = this.texture) === null || _this$texture === void 0 ? void 0 : _this$texture.source) !== undefined) { var image = this.texture.source; meta.images[image.uuid] = { uuid: image.uuid, url: this.texture.image.url }; } } // TODO: support URL var rendererSettingsJSON; if (this.renderMode === RenderMode.Trail) { rendererSettingsJSON = { startLength: this.rendererEmitterSettings.startLength.toJSON(), followLocalOrigin: this.rendererEmitterSettings.followLocalOrigin }; } else if (this.renderMode === RenderMode.Mesh) { rendererSettingsJSON = {}; /*;*/ } else if (this.renderMode === RenderMode.StretchedBillBoard) { rendererSettingsJSON = { speedFactor: this.rendererEmitterSettings.speedFactor, lengthFactor: this.rendererEmitterSettings.lengthFactor }; } else { rendererSettingsJSON = {}; } var geometry = this.rendererSettings.instancingGeometry; if (meta.geometries && !meta.geometries[geometry.uuid]) { meta.geometries[geometry.uuid] = geometry.toJSON(); } return { version: '3.0', autoDestroy: this.autoDestroy, looping: this.looping, prewarm: this.prewarm, duration: this.duration, shape: this.emitterShape.toJSON(), startLife: this.startLife.toJSON(), startSpeed: this.startSpeed.toJSON(), startRotation: this.startRotation.toJSON(), startSize: this.startSize.toJSON(), startColor: this.startColor.toJSON(), emissionOverTime: this.emissionOverTime.toJSON(), emissionOverDistance: this.emissionOverDistance.toJSON(), emissionBursts: this.emissionBursts.map(function (burst) { return { time: burst.time, count: burst.count.toJSON(), probability: burst.probability, interval: burst.interval, cycle: burst.cycle }; }), onlyUsedByOther: this.onlyUsedByOther, instancingGeometry: this.rendererSettings.instancingGeometry.uuid, //Array.from(this.emitter.interleavedBuffer.array as Float32Array), renderOrder: this.renderOrder, renderMode: this.renderMode, rendererEmitterSettings: rendererSettingsJSON, //speedFactor: this.renderMode === RenderMode.StretchedBillBoard ? this.speedFactor : 0, //texture: this.texture.uuid, material: this.rendererSettings.material.uuid, layers: this.layers.mask, startTileIndex: this.startTileIndex.toJSON(), uTileCount: this.uTileCount, vTileCount: this.vTileCount, blendTiles: this.blendTiles, softParticles: this.rendererSettings.softParticles, softFarFade: this.rendererSettings.softFarFade, softNearFade: this.rendererSettings.softNearFade, behaviors: this.behaviors.map(function (behavior) { return behavior.toJSON(); }), worldSpace: this.worldSpace }; } /** * Create a ParticleSystem from JSON * @param json the JSON data * @param meta serialization meta data * @param dependencies the dependencies of the particle system */ }, { key: "addBehavior", value: /** * Add a behavior to the particle system * @param behavior */ function addBehavior(behavior) { this.behaviors.push(behavior); } /** * Remove a behavior from the particle system */ }, { key: "getRendererSettings", value: function getRendererSettings() { return this.rendererSettings; } }, { key: "addEventListener", value: function addEventListener(event, callback) { if (!this.listeners[event]) this.listeners[event] = []; this.listeners[event].push(callback); } }, { key: "removeAllEventListeners", value: function removeAllEventListeners(event) { if (this.listeners[event]) this.listeners[event] = []; } }, { key: "removeEventListener", value: function removeEventListener(event, callback) { if (this.listeners[event]) { var index = this.listeners[event].indexOf(callback); if (index !== -1) { this.listeners[event].splice(index, 1); } } } }, { key: "fire", value: function fire(event) { if (this.listeners[event.type]) { this.listeners[event.type].forEach(function (callback) { return callback(event); }); } } /** * Clone the particle system */ }, { key: "clone", value: function clone() { var newEmissionBursts = []; var _iterator = _createForOfIteratorHelper(this.emissionBursts), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var emissionBurst = _step.value; var newEmissionBurst = {}; Object.assign(newEmissionBurst, emissionBurst); newEmissionBursts.push(newEmissionBurst); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } var newBehaviors = []; var _iterator2 = _createForOfIteratorHelper(this.behaviors), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var behavior = _step2.value; newBehaviors.push(behavior.clone()); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } var rendererEmitterSettings; if (this.renderMode === RenderMode.Trail) { rendererEmitterSettings = { startLength: this.rendererEmitterSettings.startLength.clone(), followLocalOrigin: this.rendererEmitterSettings.followLocalOrigin }; } else if (this.renderMode === RenderMode.StretchedBillBoard) { rendererEmitterSettings = { lengthFactor: this.rendererEmitterSettings.lengthFactor, speedFactor: this.rendererEmitterSettings.speedFactor }; } else { rendererEmitterSettings = {}; } var layers = new three.Layers(); layers.mask = this.layers.mask; return new ParticleSystem({ autoDestroy: this.autoDestroy, looping: this.looping, duration: this.duration, shape: this.emitterShape.clone(), startLife: this.startLife.clone(), startSpeed: this.startSpeed.clone(), startRotation: this.startRotation.clone(), startSize: this.startSize.clone(), startColor: this.startColor.clone(), emissionOverTime: this.emissionOverTime.clone(), emissionOverDistance: this.emissionOverDistance.clone(), emissionBursts: newEmissionBursts, onlyUsedByOther: this.onlyUsedByOther, instancingGeometry: this.rendererSettings.instancingGeometry, //.interleavedBuffer.array, renderMode: this.renderMode, renderOrder: this.renderOrder, rendererEmitterSettings: rendererEmitterSettings, material: this.rendererSettings.material, startTileIndex: this.startTileIndex, uTileCount: this.uTileCount, vTileCount: this.vTileCount, blendTiles: this.blendTiles, softParticles: this.softParticles, softFarFade: this.softFarFade, softNearFade: this.softNearFade, behaviors: newBehaviors, worldSpace: this.worldSpace, layers: layers }); } }], [{ key: "fromJSON", value: function fromJSON(json, meta, dependencies) { var _json$emissionBursts, _json$transparent; var shape = EmitterFromJSON(json.shape, meta); var rendererEmitterSettings; if (json.renderMode === RenderMode.Trail) { var trailSettings = json.rendererEmitterSettings; rendererEmitterSettings = { startLength: trailSettings.startLength != undefined ? ValueGeneratorFromJSON(trailSettings.startLength) : new ConstantValue(30), followLocalOrigin: trailSettings.followLocalOrigin }; } else if (json.renderMode === RenderMode.Mesh) { rendererEmitterSettings = {}; } else if (json.renderMode === RenderMode.StretchedBillBoard) { rendererEmitterSettings = json.rendererEmitterSettings; if (json.speedFactor != undefined) { rendererEmitterSettings.speedFactor = json.speedFactor; } } else { rendererEmitterSettings = {}; } var layers = new three.Layers(); if (json.layers) { layers.mask = json.layers; } var ps = new ParticleSystem({ autoDestroy: json.autoDestroy, looping: json.looping, prewarm: json.prewarm, duration: json.duration, shape: shape, startLife: ValueGeneratorFromJSON(json.startLife), startSpeed: ValueGeneratorFromJSON(json.startSpeed), startRotation: GeneratorFromJSON(json.startRotation), startSize: GeneratorFromJSON(json.startSize), startColor: ColorGeneratorFromJSON(json.startColor), emissionOverTime: ValueGeneratorFromJSON(json.emissionOverTime), emissionOverDistance: ValueGeneratorFromJSON(json.emissionOverDistance), emissionBursts: (_json$emissionBursts = json.emissionBursts) === null || _json$emissionBursts === void 0 ? void 0 : _json$emissionBursts.map(function (burst) { var _burst$probability, _burst$interval, _burst$cycle; return { time: burst.time, // backward compatibility count: typeof burst.count === 'number' ? new ConstantValue(burst.count) : ValueGeneratorFromJSON(burst.count), probability: (_burst$probability = burst.probability) !== null && _burst$probability !== void 0 ? _burst$probability : 1, interval: (_burst$interval = burst.interval) !== null && _burst$interval !== void 0 ? _burst$interval : 0.1, cycle: (_burst$cycle = burst.cycle) !== null && _burst$cycle !== void 0 ? _burst$cycle : 1 }; }), onlyUsedByOther: json.onlyUsedByOther, instancingGeometry: meta.geometries[json.instancingGeometry], renderMode: json.renderMode, rendererEmitterSettings: rendererEmitterSettings, renderOrder: json.renderOrder, layers: layers, material: json.material ? meta.materials[json.material] : json.texture ? new three.MeshBasicMaterial({ map: meta.textures[json.texture], transparent: (_json$transparent = json.transparent) !== null && _json$transparent !== void 0 ? _json$transparent : true, blending: json.blending, side: three.DoubleSide }) : new three.MeshBasicMaterial({ color: 0xffffff, transparent: true, blending: three.AdditiveBlending, side: three.DoubleSide }), startTileIndex: typeof json.startTileIndex === 'number' ? new ConstantValue(json.startTileIndex) : ValueGeneratorFromJSON(json.startTileIndex), uTileCount: json.uTileCount, vTileCount: json.vTileCount, blendTiles: json.blendTiles, softParticles: json.softParticles, softFarFade: json.softFarFade, softNearFade: json.softNearFade, behaviors: [], worldSpace: json.worldSpace }); ps.behaviors = json.behaviors.map(function (behaviorJson) { var behavior = BehaviorFromJSON(behaviorJson, ps); if (behavior.type === 'EmitSubParticleSystem') { dependencies[behaviorJson.subParticleSystem] = behavior; } return behavior; }); return ps; } }]); }(); var particle_frag = /* glsl */"\n\n#include \n#include \n#include \n#include \n#include \n#include \n\n#include \n#include \n\nvoid main() {\n\n #include \n \n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vColor;\n \n #include \n \n #include \n #include \n\n outgoingLight = diffuseColor.rgb;\n \n #ifdef USE_COLOR_AS_ALPHA\n gl_FragColor = vec4( outgoingLight, diffuseColor.r );\n #else\n gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n #endif\n \n #include \n #include \n}\n"; /* gl_FragColor = vec4(vUv.x, vUv.y, 1.0, 1.0); #ifdef USE_MAP vec4 texelColor = texture2D( map, vUv); diffuseColor *= texelColor; #endif outgoingLight = diffuseColor.rgb; gl_FragColor = vec4( outgoingLight, diffuseColor.a ); */ var particle_physics_frag = /* glsl */"\n#define STANDARD\n\n#ifdef PHYSICAL\n#define IOR\n#define USE_SPECULAR\n#endif\n\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n\n#ifdef IOR\nuniform float ior;\n#endif\n\n#ifdef USE_SPECULAR\nuniform float specularIntensity;\nuniform vec3 specularColor;\n\n#ifdef USE_SPECULAR_COLORMAP\nuniform sampler2D specularColorMap;\n#endif\n\n#ifdef USE_SPECULAR_INTENSITYMAP\nuniform sampler2D specularIntensityMap;\n#endif\n#endif\n\n#ifdef USE_CLEARCOAT\nuniform float clearcoat;\nuniform float clearcoatRoughness;\n#endif\n\n#ifdef USE_DISPERSION\nuniform float dispersion;\n#endif\n\n#ifdef USE_IRIDESCENCE\nuniform float iridescence;\nuniform float iridescenceIOR;\nuniform float iridescenceThicknessMinimum;\nuniform float iridescenceThicknessMaximum;\n#endif\n\n#ifdef USE_SHEEN\nuniform vec3 sheenColor;\nuniform float sheenRoughness;\n\n#ifdef USE_SHEEN_COLORMAP\nuniform sampler2D sheenColorMap;\n#endif\n\n#ifdef USE_SHEEN_ROUGHNESSMAP\nuniform sampler2D sheenRoughnessMap;\n#endif\n#endif\n\n#ifdef USE_ANISOTROPY\nuniform vec2 anisotropyVector;\n\n#ifdef USE_ANISOTROPYMAP\nuniform sampler2D anisotropyMap;\n#endif\n#endif\n\nvarying vec3 vViewPosition;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\nvec4 diffuseColor = vec4( diffuse, opacity );\n#include \n\nReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\nvec3 totalEmissiveRadiance = emissive;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\n// accumulation\n#include \n#include \n#include \n#include \n\n// modulation\n#include \n\nvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\nvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\n#include \n\nvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\n#ifdef USE_SHEEN\n\n// Sheen energy compensation approximation calculation can be found at the end of\n// https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing\nfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\noutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\n#endif\n\n#ifdef USE_CLEARCOAT\n\nfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\nvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\noutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n}"; var particle_vert = /* glsl */"\n#include \n#include \n#include \n#include \n\n#include \n#include \n\nattribute vec3 offset;\nattribute float rotation;\nattribute vec3 size;\n\nvoid main() {\n\t\n vec2 alignedPosition = position.xy * size.xy;\n \n vec2 rotatedPosition;\n rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n#ifdef HORIZONTAL\n vec4 mvPosition = modelMatrix * vec4( offset, 1.0 );\n mvPosition.x += rotatedPosition.x;\n mvPosition.z -= rotatedPosition.y;\n mvPosition = viewMatrix * mvPosition;\n#elif defined(VERTICAL)\n vec4 mvPosition = modelMatrix * vec4( offset, 1.0 );\n mvPosition.y += rotatedPosition.y;\n mvPosition = viewMatrix * mvPosition;\n mvPosition.x += rotatedPosition.x;\n#else\n vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );\n mvPosition.xy += rotatedPosition;\n#endif\n\n\tvColor = color;\n\n\tgl_Position = projectionMatrix * mvPosition;\n\n\t#include \n\n\t#include \n\n\t#include \n\t#include \n}\n"; /* #ifndef USE_SIZEATTENUATION bool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); if ( isPerspective ) computedSize *= - mvPosition.z; #endif */ var local_particle_vert = /* glsl */"\n#include \n#include \n#include \n#include \n#include \n#include \n\nattribute vec3 offset;\nattribute vec4 rotation;\nattribute vec3 size;\n// attribute vec4 color;\n\nvoid main() {\n\n float x2 = rotation.x + rotation.x, y2 = rotation.y + rotation.y, z2 = rotation.z + rotation.z;\n float xx = rotation.x * x2, xy = rotation.x * y2, xz = rotation.x * z2;\n float yy = rotation.y * y2, yz = rotation.y * z2, zz = rotation.z * z2;\n float wx = rotation.w * x2, wy = rotation.w * y2, wz = rotation.w * z2;\n float sx = size.x, sy = size.y, sz = size.z;\n \n mat4 matrix = mat4(( 1.0 - ( yy + zz ) ) * sx, ( xy + wz ) * sx, ( xz - wy ) * sx, 0.0, // 1. column\n ( xy - wz ) * sy, ( 1.0 - ( xx + zz ) ) * sy, ( yz + wx ) * sy, 0.0, // 2. column\n ( xz + wy ) * sz, ( yz - wx ) * sz, ( 1.0 - ( xx + yy ) ) * sz, 0.0, // 3. column\n offset.x, offset.y, offset.z, 1.0);\n \n vec4 mvPosition = modelViewMatrix * (matrix * vec4( position, 1.0 ));\n\n\tvColor = color;\n\n\tgl_Position = projectionMatrix * mvPosition;\n\n\t#include \n\t#include \n #include \n #include \n}\n"; var local_particle_physics_vert = /* glsl */"\n#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n\nattribute vec3 offset;\nattribute vec4 rotation;\nattribute vec3 size;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n #include \n float x2 = rotation.x + rotation.x, y2 = rotation.y + rotation.y, z2 = rotation.z + rotation.z;\n float xx = rotation.x * x2, xy = rotation.x * y2, xz = rotation.x * z2;\n float yy = rotation.y * y2, yz = rotation.y * z2, zz = rotation.z * z2;\n float wx = rotation.w * x2, wy = rotation.w * y2, wz = rotation.w * z2;\n float sx = size.x, sy = size.y, sz = size.z;\n\n mat4 particleMatrix = mat4(( 1.0 - ( yy + zz ) ) * sx, ( xy + wz ) * sx, ( xz - wy ) * sx, 0.0, // 1. column\n ( xy - wz ) * sy, ( 1.0 - ( xx + zz ) ) * sy, ( yz + wx ) * sy, 0.0, // 2. column\n ( xz + wy ) * sz, ( yz - wx ) * sz, ( 1.0 - ( xx + yy ) ) * sz, 0.0, // 3. column\n offset.x, offset.y, offset.z, 1.0);\n\n#include \n#include \n#include \n#include \n\n#include \n#include \n#include \n#include \n\n\t// replace defaultnormal_vertex\n\tvec3 transformedNormal = objectNormal;\n mat3 m = mat3( particleMatrix );\n transformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n transformedNormal = m * transformedNormal;\n transformedNormal = normalMatrix * transformedNormal;\n #ifdef FLIP_SIDED\n transformedNormal = - transformedNormal;\n #endif\n #ifdef USE_TANGENT\n vec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n #ifdef FLIP_SIDED\n transformedTangent = - transformedTangent;\n #endif\n #endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// replace include \n vec4 mvPosition = vec4( transformed, 1.0 );\n mvPosition = modelViewMatrix * (particleMatrix * mvPosition);\n\tgl_Position = projectionMatrix * mvPosition;\n\n\t#include \n\t#include \n\t\n\tvViewPosition = - mvPosition.xyz;\n\t\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n vWorldPosition = worldPosition.xyz;\n#endif\n}\n"; var stretched_bb_particle_vert = /* glsl */"\n#include \n#include \n#include \n#include \n\n#include \n#include \n\nattribute vec3 offset;\nattribute float rotation;\nattribute vec3 size;\nattribute vec4 velocity;\n\nuniform float speedFactor;\n\nvoid main() {\n float lengthFactor = velocity.w;\n float avgSize = (size.x + size.y) * 0.5;\n#ifdef USE_SKEW\n vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );\n vec3 viewVelocity = normalMatrix * velocity.xyz;\n\n vec3 scaledPos = vec3(position.xy * size.xy, position.z);\n float vlength = length(viewVelocity);\n vec3 projVelocity = dot(scaledPos, viewVelocity) * viewVelocity / vlength;\n mvPosition.xyz += scaledPos + projVelocity * (speedFactor / avgSize + lengthFactor / vlength);\n#else\n vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );\n vec3 viewVelocity = normalMatrix * velocity.xyz;\n float vlength = length(viewVelocity); \n mvPosition.xyz += position.y * normalize(cross(mvPosition.xyz, viewVelocity)) * avgSize; // switch the cross to match unity implementation\n mvPosition.xyz -= (position.x + 0.5) * viewVelocity * (1.0 + lengthFactor / vlength) * avgSize; // minus position.x to match unity implementation\n#endif\n\tvColor = color;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n"; /* vec3 instancePos = vec3(position.xy * size, position.z); instancePos += dot(instancePos, viewVelocity) * viewVelocity * speedFactor; mvPosition.xyz += instancePos; vColor = color; //vec4(1, 1, 1, 1); //color; //length(viewVelocity) * 0.1 #ifndef USE_SIZEATTENUATION bool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); if ( isPerspective ) computedSize *= - mvPosition.z; #endif */ function getMaterialUVChannelName(value) { if (value === 0) return 'uv'; return "uv".concat(value); } var ParticleMeshStandardMaterial = /*#__PURE__*/function (_MeshStandardMaterial) { function ParticleMeshStandardMaterial(parameters) { _classCallCheck(this, ParticleMeshStandardMaterial); return _callSuper(this, ParticleMeshStandardMaterial, [parameters]); } _inherits(ParticleMeshStandardMaterial, _MeshStandardMaterial); return _createClass(ParticleMeshStandardMaterial, [{ key: "onBeforeCompile", value: function onBeforeCompile(parameters, renderer) { _get(_getPrototypeOf(ParticleMeshStandardMaterial.prototype), "onBeforeCompile", this).call(this, parameters, renderer); parameters.vertexShader = local_particle_physics_vert; parameters.fragmentShader = particle_physics_frag; } }]); }(three.MeshStandardMaterial); var ParticleMeshPhysicsMaterial = /*#__PURE__*/function (_MeshPhysicalMaterial) { function ParticleMeshPhysicsMaterial(parameters) { _classCallCheck(this, ParticleMeshPhysicsMaterial); return _callSuper(this, ParticleMeshPhysicsMaterial, [parameters]); } _inherits(ParticleMeshPhysicsMaterial, _MeshPhysicalMaterial); return _createClass(ParticleMeshPhysicsMaterial, [{ key: "onBeforeCompile", value: function onBeforeCompile(parameters, renderer) { _get(_getPrototypeOf(ParticleMeshPhysicsMaterial.prototype), "onBeforeCompile", this).call(this, parameters, renderer); parameters.vertexShader = local_particle_physics_vert; parameters.fragmentShader = particle_physics_frag; } }]); }(three.MeshPhysicalMaterial); /** * A VFX batch that render sprites in a batch. */ var SpriteBatch = /*#__PURE__*/function (_VFXBatch) { function SpriteBatch(settings) { var _this; _classCallCheck(this, SpriteBatch); _this = _callSuper(this, SpriteBatch, [settings]); _defineProperty(_this, "offsetBuffer", void 0); _defineProperty(_this, "rotationBuffer", void 0); _defineProperty(_this, "sizeBuffer", void 0); _defineProperty(_this, "colorBuffer", void 0); _defineProperty(_this, "uvTileBuffer", void 0); _defineProperty(_this, "velocityBuffer", void 0); _defineProperty(_this, "vector_", new Vector3()); _defineProperty(_this, "vector2_", new Vector3()); _defineProperty(_this, "vector3_", new Vector3()); _defineProperty(_this, "quaternion_", new Quaternion()); _defineProperty(_this, "quaternion2_", new Quaternion()); _defineProperty(_this, "quaternion3_", new Quaternion()); _defineProperty(_this, "rotationMat_", new Matrix3()); _defineProperty(_this, "rotationMat2_", new Matrix3()); _this.maxParticles = 1000; _this.setupBuffers(); _this.rebuildMaterial(); // TODO: implement boundingVolume return _this; } _inherits(SpriteBatch, _VFXBatch); return _createClass(SpriteBatch, [{ key: "buildExpandableBuffers", value: function buildExpandableBuffers() { this.offsetBuffer = new three.InstancedBufferAttribute(new Float32Array(this.maxParticles * 3), 3); this.offsetBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('offset', this.offsetBuffer); this.colorBuffer = new three.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4); this.colorBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('color', this.colorBuffer); if (this.settings.renderMode === RenderMode.Mesh) { this.rotationBuffer = new three.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4); this.rotationBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('rotation', this.rotationBuffer); } else if (this.settings.renderMode === RenderMode.BillBoard || this.settings.renderMode === RenderMode.HorizontalBillBoard || this.settings.renderMode === RenderMode.VerticalBillBoard || this.settings.renderMode === RenderMode.StretchedBillBoard) { this.rotationBuffer = new three.InstancedBufferAttribute(new Float32Array(this.maxParticles), 1); this.rotationBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('rotation', this.rotationBuffer); } this.sizeBuffer = new three.InstancedBufferAttribute(new Float32Array(this.maxParticles * 3), 3); this.sizeBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('size', this.sizeBuffer); this.uvTileBuffer = new three.InstancedBufferAttribute(new Float32Array(this.maxParticles), 1); this.uvTileBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('uvTile', this.uvTileBuffer); if (this.settings.renderMode === RenderMode.StretchedBillBoard) { this.velocityBuffer = new three.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4); this.velocityBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('velocity', this.velocityBuffer); } } }, { key: "setupBuffers", value: function setupBuffers() { if (this.geometry) this.geometry.dispose(); this.geometry = new three.InstancedBufferGeometry(); this.geometry.setIndex(this.settings.instancingGeometry.getIndex()); if (this.settings.instancingGeometry.hasAttribute('normal')) { this.geometry.setAttribute('normal', this.settings.instancingGeometry.getAttribute('normal')); } this.geometry.setAttribute('position', this.settings.instancingGeometry.getAttribute('position')); //new InterleavedBufferAttribute(this.interleavedBuffer, 3, 0, false)); this.geometry.setAttribute('uv', this.settings.instancingGeometry.getAttribute('uv')); //new InterleavedBufferAttribute(this.interleavedBuffer, 2, 3, false)); this.buildExpandableBuffers(); } }, { key: "expandBuffers", value: function expandBuffers(target) { while (target >= this.maxParticles) { this.maxParticles *= 2; } this.setupBuffers(); } }, { key: "rebuildMaterial", value: function rebuildMaterial() { this.layers.mask = this.settings.layers.mask; var uniforms = {}; var defines = {}; if (this.settings.material.type !== 'MeshStandardMaterial' && this.settings.material.type !== 'MeshPhysicalMaterial') { uniforms['map'] = new three.Uniform(this.settings.material.map); } if (this.settings.material.alphaTest) { defines['USE_ALPHATEST'] = ''; uniforms['alphaTest'] = new three.Uniform(this.settings.material.alphaTest); } defines['USE_UV'] = ''; var uTileCount = this.settings.uTileCount; var vTileCount = this.settings.vTileCount; if (uTileCount > 1 || vTileCount > 1) { defines['UV_TILE'] = ''; uniforms['tileCount'] = new three.Uniform(new Vector2(uTileCount, vTileCount)); } if (this.settings.material.defines && this.settings.material.defines['USE_COLOR_AS_ALPHA'] !== undefined) { defines['USE_COLOR_AS_ALPHA'] = ''; } if (this.settings.material.normalMap) { defines['USE_NORMALMAP'] = ''; defines['NORMALMAP_UV'] = getMaterialUVChannelName(this.settings.material.normalMap.channel); uniforms['normalMapTransform'] = new three.Uniform(new Matrix3().copy(this.settings.material.normalMap.matrix)); } if (this.settings.material.map) { defines['USE_MAP'] = ''; if (this.settings.blendTiles) defines['TILE_BLEND'] = ''; defines['MAP_UV'] = getMaterialUVChannelName(this.settings.material.map.channel); uniforms['mapTransform'] = new three.Uniform(new Matrix3().copy(this.settings.material.map.matrix)); } defines['USE_COLOR_ALPHA'] = ''; var onBeforeRender; if (this.settings.softParticles) { defines['SOFT_PARTICLES'] = ''; var nearFade = this.settings.softNearFade; var invFadeDistance = 1.0 / (this.settings.softFarFade - this.settings.softNearFade); uniforms['softParams'] = new three.Uniform(new Vector2(nearFade, invFadeDistance)); uniforms['depthTexture'] = new three.Uniform(null); var projParams = uniforms['projParams'] = new three.Uniform(new Vector4()); onBeforeRender = function onBeforeRender(_renderer, _scene, camera) { projParams.value.set(camera.near, camera.far, 0, 0); }; } var needLights = false; if (this.settings.renderMode === RenderMode.BillBoard || this.settings.renderMode === RenderMode.VerticalBillBoard || this.settings.renderMode === RenderMode.HorizontalBillBoard || this.settings.renderMode === RenderMode.Mesh) { var vertexShader; var fragmentShader; if (this.settings.renderMode === RenderMode.Mesh) { if (this.settings.material.type === 'MeshStandardMaterial' || this.settings.material.type === 'MeshPhysicalMaterial') { defines['USE_COLOR'] = ''; vertexShader = local_particle_physics_vert; fragmentShader = particle_physics_frag; needLights = true; } else { vertexShader = local_particle_vert; fragmentShader = particle_frag; } } else { vertexShader = particle_vert; fragmentShader = particle_frag; } if (this.settings.renderMode === RenderMode.VerticalBillBoard) { defines['VERTICAL'] = ''; } else if (this.settings.renderMode === RenderMode.HorizontalBillBoard) { defines['HORIZONTAL'] = ''; } var specialMats = false; if (this.settings.renderMode === RenderMode.Mesh) { //const mat = this.settings.material as MeshStandardMaterial; if (this.settings.material.type === 'MeshStandardMaterial') { this.material = new ParticleMeshStandardMaterial({}); this.material.copy(this.settings.material); this.material.uniforms = uniforms; this.material.defines = defines; specialMats = true; } else if (this.settings.material.type === 'MeshPhysicalMaterial') { this.material = new ParticleMeshPhysicsMaterial({}); this.material.copy(this.settings.material); this.material.uniforms = uniforms; this.material.defines = defines; specialMats = true; } } if (!specialMats) { this.material = new three.ShaderMaterial({ uniforms: uniforms, defines: defines, vertexShader: vertexShader, fragmentShader: fragmentShader, transparent: this.settings.material.transparent, depthWrite: !this.settings.material.transparent, blending: this.settings.material.blending, blendDst: this.settings.material.blendDst, blendSrc: this.settings.material.blendSrc, blendEquation: this.settings.material.blendEquation, premultipliedAlpha: this.settings.material.premultipliedAlpha, side: this.settings.material.side, alphaTest: this.settings.material.alphaTest, depthTest: this.settings.material.depthTest, lights: needLights }); } } else if (this.settings.renderMode === RenderMode.StretchedBillBoard) { uniforms['speedFactor'] = new three.Uniform(1.0); this.material = new three.ShaderMaterial({ uniforms: uniforms, defines: defines, vertexShader: stretched_bb_particle_vert, fragmentShader: particle_frag, transparent: this.settings.material.transparent, depthWrite: !this.settings.material.transparent, blending: this.settings.material.blending, blendDst: this.settings.material.blendDst, blendSrc: this.settings.material.blendSrc, blendEquation: this.settings.material.blendEquation, premultipliedAlpha: this.settings.material.premultipliedAlpha, side: this.settings.material.side, alphaTest: this.settings.material.alphaTest, depthTest: this.settings.material.depthTest }); } else { throw new Error('render mode unavailable'); } if (this.material && onBeforeRender) { this.material.onBeforeRender = onBeforeRender; } } }, { key: "update", value: function update() { var _this2 = this; var index = 0; var particleCount = 0; this.systems.forEach(function (system) { particleCount += system.particleNum; }); if (particleCount > this.maxParticles) { this.expandBuffers(particleCount); } this.systems.forEach(function (system) { if (system.emitter.updateMatrixWorld) { system.emitter.updateWorldMatrix(true, false); system.emitter.updateMatrixWorld(true); } var particles = system.particles; var particleNum = system.particleNum; var rotation = _this2.quaternion2_; var translation = _this2.vector2_; var scale = _this2.vector3_; system.emitter.matrixWorld.decompose(translation, rotation, scale); _this2.rotationMat_.setFromMatrix4(system.emitter.matrixWorld); for (var j = 0; j < particleNum; j++, index++) { var particle = particles[j]; if (_this2.settings.renderMode === RenderMode.Mesh) { //this.quaternion_.setFromAxisAngle(UP, particle.rotation as number); var q = void 0; if (system.worldSpace) { q = particle.rotation; } else { var parentQ = void 0; if (particle.parentMatrix) { parentQ = _this2.quaternion3_.setFromRotationMatrix(particle.parentMatrix); } else { parentQ = rotation; } q = _this2.quaternion_; q.copy(parentQ).multiply(particle.rotation); } _this2.rotationBuffer.setXYZW(index, q.x, q.y, q.z, q.w); } else if (_this2.settings.renderMode === RenderMode.StretchedBillBoard || _this2.settings.renderMode === RenderMode.VerticalBillBoard || _this2.settings.renderMode === RenderMode.HorizontalBillBoard || _this2.settings.renderMode === RenderMode.BillBoard) { _this2.rotationBuffer.setX(index, particle.rotation); } var vec = void 0; if (system.worldSpace) { vec = particle.position; } else { vec = _this2.vector_; if (particle.parentMatrix) { vec.copy(particle.position).applyMatrix4(particle.parentMatrix); } else { vec.copy(particle.position).applyMatrix4(system.emitter.matrixWorld); } } _this2.offsetBuffer.setXYZ(index, vec.x, vec.y, vec.z); _this2.colorBuffer.setXYZW(index, particle.color.x, particle.color.y, particle.color.z, particle.color.w); if (system.worldSpace) { _this2.sizeBuffer.setXYZ(index, particle.size.x, particle.size.y, particle.size.z); } else { if (particle.parentMatrix) { _this2.sizeBuffer.setXYZ(index, particle.size.x, particle.size.y, particle.size.z); } else { _this2.sizeBuffer.setXYZ(index, particle.size.x * Math.abs(scale.x), particle.size.y * Math.abs(scale.y), particle.size.z * Math.abs(scale.z)); } } _this2.uvTileBuffer.setX(index, particle.uvTile); if (_this2.settings.renderMode === RenderMode.StretchedBillBoard && _this2.velocityBuffer) { var speedFactor = system.rendererEmitterSettings.speedFactor; if (speedFactor === 0) speedFactor = 0.001; // TODO: use an another buffer var lengthFactor = system.rendererEmitterSettings.lengthFactor; var _vec = void 0; if (system.worldSpace) { _vec = particle.velocity; } else { _vec = _this2.vector_; if (particle.parentMatrix) { _this2.rotationMat2_.setFromMatrix4(particle.parentMatrix); _vec.copy(particle.velocity).applyMatrix3(_this2.rotationMat2_); } else { _vec.copy(particle.velocity).applyMatrix3(_this2.rotationMat_); } } _this2.velocityBuffer.setXYZW(index, _vec.x * speedFactor, _vec.y * speedFactor, _vec.z * speedFactor, lengthFactor); } } }); this.geometry.instanceCount = index; if (index > 0) { this.offsetBuffer.clearUpdateRanges(); this.offsetBuffer.addUpdateRange(0, index * 3); this.offsetBuffer.needsUpdate = true; this.sizeBuffer.clearUpdateRanges(); this.sizeBuffer.addUpdateRange(0, index * 3); this.sizeBuffer.needsUpdate = true; this.colorBuffer.clearUpdateRanges(); this.colorBuffer.addUpdateRange(0, index * 4); this.colorBuffer.needsUpdate = true; this.uvTileBuffer.clearUpdateRanges(); this.uvTileBuffer.addUpdateRange(0, index); this.uvTileBuffer.needsUpdate = true; if (this.settings.renderMode === RenderMode.StretchedBillBoard && this.velocityBuffer) { this.velocityBuffer.clearUpdateRanges(); this.velocityBuffer.addUpdateRange(0, index * 4); this.velocityBuffer.needsUpdate = true; } if (this.settings.renderMode === RenderMode.Mesh) { this.rotationBuffer.clearUpdateRanges(); this.rotationBuffer.addUpdateRange(0, index * 4); this.rotationBuffer.needsUpdate = true; } else if (this.settings.renderMode === RenderMode.StretchedBillBoard || this.settings.renderMode === RenderMode.HorizontalBillBoard || this.settings.renderMode === RenderMode.VerticalBillBoard || this.settings.renderMode === RenderMode.BillBoard) { this.rotationBuffer.clearUpdateRanges(); this.rotationBuffer.addUpdateRange(0, index); this.rotationBuffer.needsUpdate = true; } } } }, { key: "dispose", value: function dispose() { this.geometry.dispose(); } }]); }(VFXBatch); var trail_frag = /* glsl */"\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nuniform sampler2D alphaMap;\nuniform float useAlphaMap;\nuniform float visibility;\nuniform float alphaTest;\n\nvarying vec4 vColor;\n \nvoid main() {\n #include \n #include \n\n vec4 diffuseColor = vColor;\n \n #ifdef USE_MAP\n #include \n #ifndef USE_COLOR_AS_ALPHA\n #endif\n #endif\n if( useAlphaMap == 1. ) diffuseColor.a *= texture2D( alphaMap, vUv).a;\n if( diffuseColor.a < alphaTest ) discard;\n gl_FragColor = diffuseColor;\n\n #include \n #include \n}"; var trail_vert = /* glsl */"\n#include \n#include \n#include \n#include \n#include \n#include \n\nattribute vec3 previous;\nattribute vec3 next;\nattribute float side;\nattribute float width;\n\nuniform vec2 resolution;\nuniform float lineWidth;\nuniform float sizeAttenuation;\n \nvec2 fix(vec4 i, float aspect) {\n vec2 res = i.xy / i.w;\n res.x *= aspect;\n return res;\n}\n \nvoid main() {\n\n #include \n \n float aspect = resolution.x / resolution.y;\n\n vColor = color;\n\n mat4 m = projectionMatrix * modelViewMatrix;\n vec4 finalPosition = m * vec4( position, 1.0 );\n vec4 prevPos = m * vec4( previous, 1.0 );\n vec4 nextPos = m * vec4( next, 1.0 );\n\n vec2 currentP = fix( finalPosition, aspect );\n vec2 prevP = fix( prevPos, aspect );\n vec2 nextP = fix( nextPos, aspect );\n\n float w = lineWidth * width;\n\n vec2 dir;\n if( nextP == currentP ) dir = normalize( currentP - prevP );\n else if( prevP == currentP ) dir = normalize( nextP - currentP );\n else {\n vec2 dir1 = normalize( currentP - prevP );\n vec2 dir2 = normalize( nextP - currentP );\n dir = normalize( dir1 + dir2 );\n\n vec2 perp = vec2( -dir1.y, dir1.x );\n vec2 miter = vec2( -dir.y, dir.x );\n //w = clamp( w / dot( miter, perp ), 0., 4., * lineWidth * width );\n\n }\n\n //vec2 normal = ( cross( vec3( dir, 0. ) vec3( 0., 0., 1. ) ) ).xy;\n vec4 normal = vec4( -dir.y, dir.x, 0., 1. );\n normal.xy *= .5 * w;\n normal *= projectionMatrix;\n if( sizeAttenuation == 0. ) {\n normal.xy *= finalPosition.w;\n normal.xy /= ( vec4( resolution, 0., 1. ) * projectionMatrix ).xy;\n }\n\n finalPosition.xy += normal.xy * side;\n\n gl_Position = finalPosition;\n\n\t#include \n\t#include \n\t\n vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n \n\t#include \n}"; /** * A VFX batch that render trails in a batch. */ var TrailBatch = /*#__PURE__*/function (_VFXBatch) { function TrailBatch(settings) { var _this; _classCallCheck(this, TrailBatch); _this = _callSuper(this, TrailBatch, [settings]); _defineProperty(_this, "positionBuffer", void 0); _defineProperty(_this, "previousBuffer", void 0); _defineProperty(_this, "nextBuffer", void 0); _defineProperty(_this, "uvBuffer", void 0); _defineProperty(_this, "sideBuffer", void 0); _defineProperty(_this, "widthBuffer", void 0); _defineProperty(_this, "colorBuffer", void 0); _defineProperty(_this, "indexBuffer", void 0); /* clone() { let system = this.system.clone(); return system.emitter as any; }*/ _defineProperty(_this, "vector_", new Vector3()); _defineProperty(_this, "vector2_", new Vector3()); _defineProperty(_this, "vector3_", new Vector3()); _defineProperty(_this, "quaternion_", new Quaternion()); _this.maxParticles = 10000; _this.setupBuffers(); _this.rebuildMaterial(); // TODO: implement boundingVolume return _this; } _inherits(TrailBatch, _VFXBatch); return _createClass(TrailBatch, [{ key: "setupBuffers", value: function setupBuffers() { if (this.geometry) this.geometry.dispose(); this.geometry = new three.BufferGeometry(); this.indexBuffer = new three.BufferAttribute(new Uint32Array(this.maxParticles * 6), 1); this.indexBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setIndex(this.indexBuffer); this.positionBuffer = new three.BufferAttribute(new Float32Array(this.maxParticles * 6), 3); this.positionBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('position', this.positionBuffer); this.previousBuffer = new three.BufferAttribute(new Float32Array(this.maxParticles * 6), 3); this.previousBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('previous', this.previousBuffer); this.nextBuffer = new three.BufferAttribute(new Float32Array(this.maxParticles * 6), 3); this.nextBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('next', this.nextBuffer); this.widthBuffer = new three.BufferAttribute(new Float32Array(this.maxParticles * 2), 1); this.widthBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('width', this.widthBuffer); this.sideBuffer = new three.BufferAttribute(new Float32Array(this.maxParticles * 2), 1); this.sideBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('side', this.sideBuffer); this.uvBuffer = new three.BufferAttribute(new Float32Array(this.maxParticles * 4), 2); this.uvBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('uv', this.uvBuffer); this.colorBuffer = new three.BufferAttribute(new Float32Array(this.maxParticles * 8), 4); this.colorBuffer.setUsage(three.DynamicDrawUsage); this.geometry.setAttribute('color', this.colorBuffer); } }, { key: "expandBuffers", value: function expandBuffers(target) { while (target >= this.maxParticles) { this.maxParticles *= 2; } this.setupBuffers(); } }, { key: "rebuildMaterial", value: function rebuildMaterial() { this.layers.mask = this.settings.layers.mask; var uniforms = { lineWidth: { value: 1 }, map: { value: null }, useMap: { value: 0 }, alphaMap: { value: null }, useAlphaMap: { value: 0 }, resolution: { value: new Vector2(1, 1) }, sizeAttenuation: { value: 1 }, visibility: { value: 1 }, alphaTest: { value: 0 } //repeat: {value: new Vector2(1, 1)}, }; var defines = {}; defines['USE_UV'] = ''; defines['USE_COLOR_ALPHA'] = ''; if (this.settings.material.map) { defines['USE_MAP'] = ''; defines['MAP_UV'] = getMaterialUVChannelName(this.settings.material.map.channel); uniforms['map'] = new three.Uniform(this.settings.material.map); uniforms['mapTransform'] = new three.Uniform(new Matrix3().copy(this.settings.material.map.matrix)); } if (this.settings.material.defines && this.settings.material.defines['USE_COLOR_AS_ALPHA'] !== undefined) { defines['USE_COLOR_AS_ALPHA'] = ''; } if (this.settings.renderMode === RenderMode.Trail) { this.material = new three.ShaderMaterial({ uniforms: uniforms, defines: defines, vertexShader: trail_vert, fragmentShader: trail_frag, transparent: this.settings.material.transparent, depthWrite: !this.settings.material.transparent, side: this.settings.material.side, blending: this.settings.material.blending || three.AdditiveBlending, blendDst: this.settings.material.blendDst, blendSrc: this.settings.material.blendSrc, blendEquation: this.settings.material.blendEquation, premultipliedAlpha: this.settings.material.premultipliedAlpha }); } else { throw new Error('render mode unavailable'); } } }, { key: "update", value: function update() { var _this2 = this; var index = 0; var triangles = 0; var particleCount = 0; this.systems.forEach(function (system) { for (var j = 0; j < system.particleNum; j++) { particleCount += system.particles[j].previous.length * 2; } }); if (particleCount > this.maxParticles) { this.expandBuffers(particleCount); } this.systems.forEach(function (system) { if (system.emitter.updateMatrixWorld) { system.emitter.updateWorldMatrix(true, false); system.emitter.updateMatrixWorld(true); } var rotation = _this2.quaternion_; var translation = _this2.vector2_; var scale = _this2.vector3_; system.emitter.matrixWorld.decompose(translation, rotation, scale); var particles = system.particles; var particleNum = system.particleNum; var uTileCount = _this2.settings.uTileCount; var vTileCount = _this2.settings.vTileCount; var tileWidth = 1 / uTileCount; var tileHeight = 1 / vTileCount; for (var j = 0; j < particleNum; j++) { var particle = particles[j]; var col = particle.uvTile % vTileCount; var row = Math.floor(particle.uvTile / vTileCount + 0.001); var iter = particle.previous.values(); var curIter = iter.next(); var previous = curIter.value; var current = previous; if (!curIter.done) curIter = iter.next(); var next = void 0; if (curIter.value !== undefined) { next = curIter.value; } else { next = current; } for (var i = 0; i < particle.previous.length; i++, index += 2) { _this2.positionBuffer.setXYZ(index, current.position.x, current.position.y, current.position.z); _this2.positionBuffer.setXYZ(index + 1, current.position.x, current.position.y, current.position.z); if (system.worldSpace) { _this2.positionBuffer.setXYZ(index, current.position.x, current.position.y, current.position.z); _this2.positionBuffer.setXYZ(index + 1, current.position.x, current.position.y, current.position.z); } else { if (particle.parentMatrix) { _this2.vector_.copy(current.position).applyMatrix4(particle.parentMatrix); } else { _this2.vector_.copy(current.position).applyMatrix4(system.emitter.matrixWorld); } _this2.positionBuffer.setXYZ(index, _this2.vector_.x, _this2.vector_.y, _this2.vector_.z); _this2.positionBuffer.setXYZ(index + 1, _this2.vector_.x, _this2.vector_.y, _this2.vector_.z); } if (system.worldSpace) { _this2.previousBuffer.setXYZ(index, previous.position.x, previous.position.y, previous.position.z); _this2.previousBuffer.setXYZ(index + 1, previous.position.x, previous.position.y, previous.position.z); } else { if (particle.parentMatrix) { _this2.vector_.copy(previous.position).applyMatrix4(particle.parentMatrix); } else { _this2.vector_.copy(previous.position).applyMatrix4(system.emitter.matrixWorld); } _this2.previousBuffer.setXYZ(index, _this2.vector_.x, _this2.vector_.y, _this2.vector_.z); _this2.previousBuffer.setXYZ(index + 1, _this2.vector_.x, _this2.vector_.y, _this2.vector_.z); } if (system.worldSpace) { _this2.nextBuffer.setXYZ(index, next.position.x, next.position.y, next.position.z); _this2.nextBuffer.setXYZ(index + 1, next.position.x, next.position.y, next.position.z); } else { if (particle.parentMatrix) { _this2.vector_.copy(next.position).applyMatrix4(particle.parentMatrix); } else { _this2.vector_.copy(next.position).applyMatrix4(system.emitter.matrixWorld); } _this2.nextBuffer.setXYZ(index, _this2.vector_.x, _this2.vector_.y, _this2.vector_.z); _this2.nextBuffer.setXYZ(index + 1, _this2.vector_.x, _this2.vector_.y, _this2.vector_.z); } _this2.sideBuffer.setX(index, -1); _this2.sideBuffer.setX(index + 1, 1); if (system.worldSpace) { _this2.widthBuffer.setX(index, current.size); _this2.widthBuffer.setX(index + 1, current.size); } else { if (particle.parentMatrix) { _this2.widthBuffer.setX(index, current.size); _this2.widthBuffer.setX(index + 1, current.size); } else { var objectScale = (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z)) / 3; _this2.widthBuffer.setX(index, current.size * objectScale); _this2.widthBuffer.setX(index + 1, current.size * objectScale); } } _this2.uvBuffer.setXY(index, (i / particle.previous.length + col) * tileWidth, (vTileCount - row - 1) * tileHeight); _this2.uvBuffer.setXY(index + 1, (i / particle.previous.length + col) * tileWidth, (vTileCount - row) * tileHeight); _this2.colorBuffer.setXYZW(index, current.color.x, current.color.y, current.color.z, current.color.w); _this2.colorBuffer.setXYZW(index + 1, current.color.x, current.color.y, current.color.z, current.color.w); if (i + 1 < particle.previous.length) { _this2.indexBuffer.setX(triangles * 3, index); _this2.indexBuffer.setX(triangles * 3 + 1, index + 1); _this2.indexBuffer.setX(triangles * 3 + 2, index + 2); triangles++; _this2.indexBuffer.setX(triangles * 3, index + 2); _this2.indexBuffer.setX(triangles * 3 + 1, index + 1); _this2.indexBuffer.setX(triangles * 3 + 2, index + 3); triangles++; } previous = current; current = next; if (!curIter.done) { curIter = iter.next(); if (curIter.value !== undefined) { next = curIter.value; } } } } }); this.positionBuffer.clearUpdateRanges(); this.positionBuffer.addUpdateRange(0, index * 3); this.positionBuffer.needsUpdate = true; this.previousBuffer.clearUpdateRanges(); this.previousBuffer.addUpdateRange(0, index * 3); this.previousBuffer.needsUpdate = true; this.nextBuffer.clearUpdateRanges(); this.nextBuffer.addUpdateRange(0, index * 3); this.nextBuffer.needsUpdate = true; this.sideBuffer.clearUpdateRanges(); this.sideBuffer.addUpdateRange(0, index); this.sideBuffer.needsUpdate = true; this.widthBuffer.clearUpdateRanges(); this.widthBuffer.addUpdateRange(0, index); this.widthBuffer.needsUpdate = true; this.uvBuffer.clearUpdateRanges(); this.uvBuffer.addUpdateRange(0, index * 2); this.uvBuffer.needsUpdate = true; this.colorBuffer.clearUpdateRanges(); this.colorBuffer.addUpdateRange(0, index * 4); this.colorBuffer.needsUpdate = true; this.indexBuffer.clearUpdateRanges(); this.indexBuffer.addUpdateRange(0, triangles * 3); this.indexBuffer.needsUpdate = true; this.geometry.setDrawRange(0, triangles * 3); } }, { key: "dispose", value: function dispose() { this.geometry.dispose(); } }]); }(VFXBatch); /** * A particle emitter that emits particles from the surface of a mesh uniformly. */ var MeshSurfaceEmitter = /*#__PURE__*/function () { function MeshSurfaceEmitter(geometry) { _classCallCheck(this, MeshSurfaceEmitter); _defineProperty(this, "type", 'mesh_surface'); _defineProperty(this, "_triangleIndexToArea", []); _defineProperty(this, "_geometry", void 0); _defineProperty(this, "_tempA", new three.Vector3()); _defineProperty(this, "_tempB", new three.Vector3()); _defineProperty(this, "_tempC", new three.Vector3()); if (!geometry) { return; } this.geometry = geometry; } return _createClass(MeshSurfaceEmitter, [{ key: "geometry", get: function get() { return this._geometry; }, set: function set(geometry) { this._geometry = geometry; if (geometry === undefined) { return; } if (typeof geometry === 'string') { return; } // optimization /*if (mesh.userData.triangleIndexToArea) { this._triangleIndexToArea = mesh.userData.triangleIndexToArea; return; }*/ var tri = new three.Triangle(); this._triangleIndexToArea.length = 0; var area = 0; if (!geometry.getIndex()) { return; } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var array = geometry.getIndex().array; var triCount = array.length / 3; this._triangleIndexToArea.push(0); for (var i = 0; i < triCount; i++) { tri.setFromAttributeAndIndices(geometry.getAttribute('position'), array[i * 3], array[i * 3 + 1], array[i * 3 + 2]); area += tri.getArea(); this._triangleIndexToArea.push(area); } geometry.userData.triangleIndexToArea = this._triangleIndexToArea; } }, { key: "initialize", value: function initialize(p) { var geometry = this._geometry; if (!geometry || geometry.getIndex() === null) { p.position.set(0, 0, 0); p.velocity.set(0, 0, 1).multiplyScalar(p.startSpeed); return; } var triCount = this._triangleIndexToArea.length - 1; var left = 0, right = triCount; var target = Math.random() * this._triangleIndexToArea[triCount]; while (left + 1 < right) { var mid = Math.floor((left + right) / 2); if (target < this._triangleIndexToArea[mid]) { right = mid; } else { left = mid; } } //const area = this._triangleIndexToArea[left + 1] - this._triangleIndexToArea[left]; //const percent = (target - this._triangleIndexToArea[left]) / area; var u1 = Math.random(); var u2 = Math.random(); if (u1 + u2 > 1) { u1 = 1 - u1; u2 = 1 - u2; } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var index1 = geometry.getIndex().array[left * 3]; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var index2 = geometry.getIndex().array[left * 3 + 1]; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var index3 = geometry.getIndex().array[left * 3 + 2]; var positionBuffer = geometry.getAttribute('position'); this._tempA.fromBufferAttribute(positionBuffer, index1); this._tempB.fromBufferAttribute(positionBuffer, index2); this._tempC.fromBufferAttribute(positionBuffer, index3); this._tempB.sub(this._tempA); this._tempC.sub(this._tempA); this._tempA.addScaledVector(this._tempB, u1).addScaledVector(this._tempC, u2); p.position.copy(this._tempA); // velocity based on tri normal this._tempA.copy(this._tempB).cross(this._tempC).normalize(); p.velocity.copy(this._tempA).normalize().multiplyScalar(p.startSpeed); /*p.position.applyMatrix4(this._mesh.matrixWorld); p.velocity.applyMatrix3(this._mesh.normalMatrix);*/ } }, { key: "toJSON", value: function toJSON() { return { type: 'mesh_surface', mesh: this._geometry ? this._geometry.uuid : '' }; } }, { key: "clone", value: function clone() { return new MeshSurfaceEmitter(this._geometry); } }, { key: "update", value: function update(system, delta) {} }], [{ key: "fromJSON", value: function fromJSON(json, meta) { return new MeshSurfaceEmitter(meta.geometries[json.geometry]); } }]); }(); loadPlugin({ id: "three.quarks", initialize: function initialize() {}, emitterShapes: [{ type: 'mesh_surface', params: [['geometry', ['geometry']]], constructor: MeshSurfaceEmitter, loadJSON: MeshSurfaceEmitter.fromJSON }], behaviors: [] }); /** * the settings for rendering a batch of VFX system. */ /** * the class represents the batch renderer. a three.js scene should only have one batchedRenderer * It keeps references of all particle systems and rendering batch. * It batches all particle systems that has the same rendering pipeline to a single VFXBatch. */ var BatchedRenderer = /*#__PURE__*/function (_Object3D) { function BatchedRenderer() { var _this; _classCallCheck(this, BatchedRenderer); _this = _callSuper(this, BatchedRenderer); /** * Batches for rendering. * @type {Array} */ _defineProperty(_this, "batches", []); /** * Map of systems to batch indices. * @type {Map} */ _defineProperty(_this, "systemToBatchIndex", new Map()); _defineProperty(_this, "type", 'BatchedRenderer'); /** * Depth texture. * @type {Texture | null} */ _defineProperty(_this, "depthTexture", null); return _this; } _inherits(BatchedRenderer, _Object3D); return _createClass(BatchedRenderer, [{ key: "addSystem", value: /** * Adds a particle system to a batch. * @param {IParticleSystem} system - The particle system to add. */ function addSystem(system) { system._renderer = this; var settings = system.getRendererSettings(); for (var i = 0; i < this.batches.length; i++) { if (BatchedRenderer.equals(this.batches[i].settings, settings)) { this.batches[i].addSystem(system); this.systemToBatchIndex.set(system, i); return; } } var batch; switch (settings.renderMode) { case RenderMode.Trail: batch = new TrailBatch(settings); break; case RenderMode.Mesh: case RenderMode.BillBoard: case RenderMode.VerticalBillBoard: case RenderMode.HorizontalBillBoard: case RenderMode.StretchedBillBoard: batch = new SpriteBatch(settings); break; } if (this.depthTexture) { batch.applyDepthTexture(this.depthTexture); } batch.addSystem(system); this.batches.push(batch); this.systemToBatchIndex.set(system, this.batches.length - 1); this.add(batch); } /** * Deletes a particle system from its batch. * @param {IParticleSystem} system - The particle system to delete. */ }, { key: "deleteSystem", value: function deleteSystem(system) { var batchIndex = this.systemToBatchIndex.get(system); if (batchIndex != undefined) { this.batches[batchIndex].removeSystem(system); this.systemToBatchIndex["delete"](system); } /*const settings = system.getRendererSettings(); for (let i = 0; i < this.batches.length; i++) { if (BatchedParticleRenderer.equals(this.batches[i].settings, settings)) { this.batches[i].removeSystem(system); return; } }*/ } /** * Sets the depth texture for all batches. it will be used for soft particles. * @param {Texture | null} depthTexture - The depth texture to set. */ }, { key: "setDepthTexture", value: function setDepthTexture(depthTexture) { this.depthTexture = depthTexture; var _iterator = _createForOfIteratorHelper(this.batches), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var batch = _step.value; batch.applyDepthTexture(depthTexture); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } /** * Updates a particle system when the particle system has changed requires reloading. * @param {IParticleSystem} system - The particle system to update. */ }, { key: "updateSystem", value: function updateSystem(system) { this.deleteSystem(system); this.addSystem(system); } /** * Updates all batches. * @param {number} delta - The time delta for the update. */ }, { key: "update", value: function update(delta) { this.systemToBatchIndex.forEach(function (value, ps) { ps.update(delta); }); for (var i = 0; i < this.batches.length; i++) { this.batches[i].update(); } } }], [{ key: "equals", value: function equals(a, b) { return a.material.side === b.material.side && a.material.blending === b.material.blending && a.material.blendSrc === b.material.blendSrc && a.material.blendDst === b.material.blendDst && a.material.blendEquation === b.material.blendEquation && a.material.premultipliedAlpha === b.material.premultipliedAlpha && a.material.transparent === b.material.transparent && a.material.depthTest === b.material.depthTest && a.material.type === b.material.type && a.material.alphaTest === b.material.alphaTest && a.material.map === b.material.map && a.renderMode === b.renderMode && a.blendTiles === b.blendTiles && a.softParticles === b.softParticles && a.softFarFade === b.softFarFade && a.softNearFade === b.softNearFade && a.uTileCount === b.uTileCount && a.vTileCount === b.vTileCount && a.instancingGeometry === b.instancingGeometry && a.renderOrder === b.renderOrder && a.layers.mask === b.layers.mask; } }]); }(three.Object3D); /** * @deprecated This constant is deprecated. * Use `BatchedRenderer` instead for batching particle systems into render batches to optimize draw call counts. */ var BatchedParticleRenderer = BatchedRenderer; /** * Loader for quarks particle system. */ var QuarksLoader = /*#__PURE__*/function (_ObjectLoader) { function QuarksLoader(manager) { _classCallCheck(this, QuarksLoader); return _callSuper(this, QuarksLoader, [manager]); } /** * Links the references of the particle system. * It's used to link the references of sub particle systems. * @param object the target object to link the references. */ _inherits(QuarksLoader, _ObjectLoader); return _createClass(QuarksLoader, [{ key: "linkReference", value: function linkReference(object) { var objectsMap = {}; object.traverse(function (child) { objectsMap[child.uuid] = child; }); object.traverse(function (child) { if (child.type === 'ParticleEmitter') { var system = child.system; system.emitterShape; /*if (shape instanceof MeshSurfaceEmitter) { shape.geometry = objectsMap[shape.geometry as any] as Mesh; }*/ for (var i = 0; i < system.behaviors.length; i++) { if (system.behaviors[i] instanceof EmitSubParticleSystem) { system.behaviors[i].subParticleSystem = objectsMap[system.behaviors[i].subParticleSystem]; } } } }); } /** * Parses the json data to create a quarks particle system. * @param json the json data to parse. * @param onLoad the callback function to be called after the object is loaded. */ }, { key: "parse", value: function parse(json, onLoad) { var object = _get(_getPrototypeOf(QuarksLoader.prototype), "parse", this).call(this, json, onLoad); this.linkReference(object); return object; } // @ts-ignore }, { key: "parseObject", value: function parseObject(data, geometries, materials, textures, animations) { var object; function getGeometry(name) { if (geometries[name] === undefined) { console.warn('THREE.ObjectLoader: Undefined geometry', name); } return geometries[name]; } function getMaterial(name) { if (name === undefined) return undefined; if (Array.isArray(name)) { var array = []; for (var i = 0, l = name.length; i < l; i++) { var uuid = name[i]; if (materials[uuid] === undefined) { console.warn('THREE.ObjectLoader: Undefined material', uuid); } array.push(materials[uuid]); } return array; } if (materials[name] === undefined) { console.warn('THREE.ObjectLoader: Undefined material', name); } return materials[name]; } function getTexture(uuid) { if (textures[uuid] === undefined) { console.warn('THREE.ObjectLoader: Undefined texture', uuid); } return textures[uuid]; } var geometry, material; var meta = { textures: textures, geometries: geometries, materials: materials }; var dependencies = {}; switch (data.type) { case 'ParticleEmitter': object = ParticleSystem.fromJSON(data.ps, meta, dependencies).emitter; break; case 'Scene': object = new three.Scene(); if (data.background !== undefined) { if (Number.isInteger(data.background)) { object.background = new three.Color(data.background); } else { object.background = getTexture(data.background); } } if (data.environment !== undefined) { object.environment = getTexture(data.environment); } if (data.fog !== undefined) { if (data.fog.type === 'Fog') { object.fog = new three.Fog(data.fog.color, data.fog.near, data.fog.far); } else if (data.fog.type === 'FogExp2') { object.fog = new three.FogExp2(data.fog.color, data.fog.density); } if (data.fog.name !== '') { object.fog.name = data.fog.name; } } if (data.backgroundBlurriness !== undefined) object.backgroundBlurriness = data.backgroundBlurriness; if (data.backgroundIntensity !== undefined) object.backgroundIntensity = data.backgroundIntensity; if (data.backgroundRotation !== undefined) object.backgroundRotation.fromArray(data.backgroundRotation); if (data.environmentIntensity !== undefined) object.environmentIntensity = data.environmentIntensity; if (data.environmentRotation !== undefined) object.environmentRotation.fromArray(data.environmentRotation); break; case 'PerspectiveCamera': object = new three.PerspectiveCamera(data.fov, data.aspect, data.near, data.far); if (data.focus !== undefined) object.focus = data.focus; if (data.zoom !== undefined) object.zoom = data.zoom; if (data.filmGauge !== undefined) object.filmGauge = data.filmGauge; if (data.filmOffset !== undefined) object.filmOffset = data.filmOffset; if (data.view !== undefined) object.view = Object.assign({}, data.view); break; case 'OrthographicCamera': object = new three.OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far); if (data.zoom !== undefined) object.zoom = data.zoom; if (data.view !== undefined) object.view = Object.assign({}, data.view); break; case 'AmbientLight': object = new three.AmbientLight(data.color, data.intensity); break; case 'DirectionalLight': object = new three.DirectionalLight(data.color, data.intensity); break; case 'PointLight': object = new three.PointLight(data.color, data.intensity, data.distance, data.decay); break; case 'RectAreaLight': object = new three.RectAreaLight(data.color, data.intensity, data.width, data.height); break; case 'SpotLight': object = new three.SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay); break; case 'HemisphereLight': object = new three.HemisphereLight(data.color, data.groundColor, data.intensity); break; case 'LightProbe': object = new three.LightProbe().fromJSON(data); break; case 'SkinnedMesh': geometry = getGeometry(data.geometry); material = getMaterial(data.material); object = new three.SkinnedMesh(geometry, material); if (data.bindMode !== undefined) object.bindMode = data.bindMode; if (data.bindMatrix !== undefined) object.bindMatrix.fromArray(data.bindMatrix); if (data.skeleton !== undefined) object.skeleton = data.skeleton; break; case 'Mesh': geometry = getGeometry(data.geometry); material = getMaterial(data.material); object = new three.Mesh(geometry, material); break; case 'InstancedMesh': { geometry = getGeometry(data.geometry); material = getMaterial(data.material); var count = data.count; var instanceMatrix = data.instanceMatrix; var instanceColor = data.instanceColor; object = new three.InstancedMesh(geometry, material, count); object.instanceMatrix = new three.InstancedBufferAttribute(new Float32Array(instanceMatrix.array), 16); if (instanceColor !== undefined) object.instanceColor = new three.InstancedBufferAttribute(new Float32Array(instanceColor.array), instanceColor.itemSize); break; } case 'BatchedMesh': geometry = getGeometry(data.geometry); material = getMaterial(data.material); object = new three.BatchedMesh(data.maxGeometryCount, data.maxVertexCount, data.maxIndexCount, material); object.geometry = geometry; object.perObjectFrustumCulled = data.perObjectFrustumCulled; object.sortObjects = data.sortObjects; object._drawRanges = data.drawRanges; object._reservedRanges = data.reservedRanges; object._visibility = data.visibility; object._active = data.active; object._bounds = data.bounds.map(function (bound) { var box = new three.Box3(); box.min.fromArray(bound.boxMin); box.max.fromArray(bound.boxMax); var sphere = new three.Sphere(); sphere.radius = bound.sphereRadius; sphere.center.fromArray(bound.sphereCenter); return { boxInitialized: bound.boxInitialized, box: box, sphereInitialized: bound.sphereInitialized, sphere: sphere }; }); object._maxGeometryCount = data.maxGeometryCount; object._maxVertexCount = data.maxVertexCount; object._maxIndexCount = data.maxIndexCount; object._geometryInitialized = data.geometryInitialized; object._geometryCount = data.geometryCount; object._matricesTexture = getTexture(data.matricesTexture.uuid); break; case 'LOD': object = new three.LOD(); break; case 'Line': object = new three.Line(getGeometry(data.geometry), getMaterial(data.material)); break; case 'LineLoop': object = new three.LineLoop(getGeometry(data.geometry), getMaterial(data.material)); break; case 'LineSegments': object = new three.LineSegments(getGeometry(data.geometry), getMaterial(data.material)); break; case 'PointCloud': case 'Points': object = new three.Points(getGeometry(data.geometry), getMaterial(data.material)); break; case 'Sprite': object = new three.Sprite(getMaterial(data.material)); break; case 'Group': object = new three.Group(); break; case 'Bone': object = new three.Bone(); break; default: object = new three.Object3D(); } object.uuid = data.uuid; if (data.name !== undefined) object.name = data.name; if (data.matrix !== undefined) { object.matrix.fromArray(data.matrix); if (data.matrixAutoUpdate !== undefined) object.matrixAutoUpdate = data.matrixAutoUpdate; if (object.matrixAutoUpdate) { object.matrix.decompose(object.position, object.quaternion, object.scale); if (isNaN(object.quaternion.x)) { object.quaternion.set(0, 0, 0, 1); } } } else { if (data.position !== undefined) object.position.fromArray(data.position); if (data.rotation !== undefined) object.rotation.fromArray(data.rotation); if (data.quaternion !== undefined) object.quaternion.fromArray(data.quaternion); if (data.scale !== undefined) object.scale.fromArray(data.scale); } if (data.up !== undefined) object.up.fromArray(data.up); if (data.castShadow !== undefined) object.castShadow = data.castShadow; if (data.receiveShadow !== undefined) object.receiveShadow = data.receiveShadow; if (data.shadow) { if (data.shadow.bias !== undefined) object.shadow.bias = data.shadow.bias; if (data.shadow.normalBias !== undefined) object.normalBias = data.shadow.normalBias; if (data.shadow.radius !== undefined) object.radius = data.shadow.radius; if (data.shadow.mapSize !== undefined) object.mapSize.fromArray(data.shadow.mapSize); if (data.shadow.camera !== undefined) { // @ts-ignore object.camera = this.parseObject(data.shadow.camera); } } if (data.visible !== undefined) object.visible = data.visible; if (data.frustumCulled !== undefined) object.frustumCulled = data.frustumCulled; if (data.renderOrder !== undefined) object.renderOrder = data.renderOrder; if (data.userData !== undefined) object.userData = data.userData; if (data.layers !== undefined) object.layers.mask = data.layers; if (data.children !== undefined) { var children = data.children; for (var i = 0; i < children.length; i++) { object.add(this.parseObject(children[i], geometries, materials, textures, animations)); } } if (data.animations !== undefined) { var objectAnimations = data.animations; for (var _i = 0; _i < objectAnimations.length; _i++) { var uuid = objectAnimations[_i]; object.animations.push(animations[uuid]); } } if (data.type === 'LOD') { if (data.autoUpdate !== undefined) object.autoUpdate = data.autoUpdate; var levels = data.levels; for (var l = 0; l < levels.length; l++) { var level = levels[l]; var child = object.getObjectByProperty('uuid', level.object); if (child !== undefined) { // @ts-ignore object.addLevel(child, level.distance); } } } return object; } }]); }(three.ObjectLoader); var QuarksUtil = /*#__PURE__*/function () { function QuarksUtil() { _classCallCheck(this, QuarksUtil); } return _createClass(QuarksUtil, null, [{ key: "runOnAllParticleEmitters", value: /** * Run a function on all particle emitters in the object and the object's children. * @param obj * @param func */ function runOnAllParticleEmitters(obj, func) { obj.traverse(function (child) { if (child.type === 'ParticleEmitter') { func(child); } }); if (obj.type === 'ParticleEmitter') { func(obj); } } /** * Add all particle systems in the object and the object's children to the batch renderer. * @param obj * @param batchRenderer */ }, { key: "addToBatchRenderer", value: function addToBatchRenderer(obj, batchRenderer) { QuarksUtil.runOnAllParticleEmitters(obj, function (ps) { batchRenderer.addSystem(ps.system); }); } /** * Start playing all particle systems in the object and the object's children. * @param obj */ }, { key: "play", value: function play(obj) { QuarksUtil.runOnAllParticleEmitters(obj, function (ps) { ps.system.play(); }); } /** * Stop all particle systems in the object and the object's children. * this call will clear all existing particles. * @param obj */ }, { key: "stop", value: function stop(obj) { QuarksUtil.runOnAllParticleEmitters(obj, function (ps) { ps.system.stop(); }); } }, { key: "setAutoDestroy", value: function setAutoDestroy(obj, value) { QuarksUtil.runOnAllParticleEmitters(obj, function (ps) { ps.system.autoDestroy = value; }); } /** * Stop emit new particles from all particle systems and * keep simulating the existing particles in the object and the object's children. * @param obj */ }, { key: "endEmit", value: function endEmit(obj) { QuarksUtil.runOnAllParticleEmitters(obj, function (ps) { ps.system.endEmit(); }); } /** * Restart all particle systems in the object and the object's children. * @param obj */ }, { key: "restart", value: function restart(obj) { QuarksUtil.runOnAllParticleEmitters(obj, function (ps) { ps.system.restart(); }); } /** * Pause the simulation of all particle systems in the object and the object's children. * @param obj */ }, { key: "pause", value: function pause(obj) { QuarksUtil.runOnAllParticleEmitters(obj, function (ps) { ps.system.pause(); }); } }]); }(); registerShaderChunks(); // remove this line if you have pro license console.log('%c Particle system powered by three.quarks. https://quarks.art/', 'font-size: 14px; font-weight: bold;'); exports.ApplyCollision = ApplyCollision; exports.ApplyForce = ApplyForce; exports.ApplySequences = ApplySequences; exports.AxisAngleGenerator = AxisAngleGenerator; exports.BatchedParticleRenderer = BatchedParticleRenderer; exports.BatchedRenderer = BatchedRenderer; exports.BehaviorFromJSON = BehaviorFromJSON; exports.BehaviorTypes = BehaviorTypes; exports.Bezier = Bezier; exports.ChangeEmitDirection = ChangeEmitDirection; exports.CircleEmitter = CircleEmitter; exports.ColorBySpeed = ColorBySpeed; exports.ColorGeneratorFromJSON = ColorGeneratorFromJSON; exports.ColorOverLife = ColorOverLife; exports.ColorRange = ColorRange; exports.ConeEmitter = ConeEmitter; exports.ConstantColor = ConstantColor; exports.ConstantValue = ConstantValue; exports.DEG2RAD = DEG2RAD; exports.DonutEmitter = DonutEmitter; exports.EmitSubParticleSystem = EmitSubParticleSystem; exports.EmitterFromJSON = EmitterFromJSON; exports.EmitterShapes = EmitterShapes; exports.Euler = Euler; exports.EulerGenerator = EulerGenerator; exports.ForceOverLife = ForceOverLife; exports.FrameOverLife = FrameOverLife; exports.GeneratorFromJSON = GeneratorFromJSON; exports.Gradient = Gradient; exports.GravityForce = GravityForce; exports.GridEmitter = GridEmitter; exports.HemisphereEmitter = HemisphereEmitter; exports.IntervalValue = IntervalValue; exports.LimitSpeedOverLife = LimitSpeedOverLife; exports.MathUtils = MathUtils; exports.Matrix3 = Matrix3; exports.Matrix4 = Matrix4; exports.MeshSurfaceEmitter = MeshSurfaceEmitter; exports.NodeParticle = NodeParticle; exports.Noise = Noise; exports.OrbitOverLife = OrbitOverLife; exports.ParticleEmitter = ParticleEmitter; exports.ParticleMeshPhysicsMaterial = ParticleMeshPhysicsMaterial; exports.ParticleMeshStandardMaterial = ParticleMeshStandardMaterial; exports.ParticleSystem = ParticleSystem; exports.PiecewiseBezier = PiecewiseBezier; exports.PiecewiseFunction = PiecewiseFunction; exports.Plugins = Plugins; exports.PointEmitter = PointEmitter; exports.QuarksLoader = QuarksLoader; exports.QuarksUtil = QuarksUtil; exports.Quaternion = Quaternion; exports.RAD2DEG = RAD2DEG; exports.RandomColor = RandomColor; exports.RandomColorBetweenGradient = RandomColorBetweenGradient; exports.RandomQuatGenerator = RandomQuatGenerator; exports.RecordState = RecordState; exports.RenderMode = RenderMode; exports.Rotation3DOverLife = Rotation3DOverLife; exports.RotationBySpeed = RotationBySpeed; exports.RotationGeneratorFromJSON = RotationGeneratorFromJSON; exports.RotationOverLife = RotationOverLife; exports.SequencerFromJSON = SequencerFromJSON; exports.SizeBySpeed = SizeBySpeed; exports.SizeOverLife = SizeOverLife; exports.SpeedOverLife = SpeedOverLife; exports.SphereEmitter = SphereEmitter; exports.SpriteBatch = SpriteBatch; exports.SpriteParticle = SpriteParticle; exports.TextureSequencer = TextureSequencer; exports.TrailBatch = TrailBatch; exports.TrailParticle = TrailParticle; exports.TurbulenceField = TurbulenceField; exports.VFXBatch = VFXBatch; exports.ValueGeneratorFromJSON = ValueGeneratorFromJSON; exports.Vector2 = Vector2; exports.Vector3 = Vector3; exports.Vector3Function = Vector3Function; exports.Vector3GeneratorFromJSON = Vector3GeneratorFromJSON; exports.Vector4 = Vector4; exports.WebGLCoordinateSystem = WebGLCoordinateSystem; exports.WebGPUCoordinateSystem = WebGPUCoordinateSystem; exports.WidthOverLength = WidthOverLength; exports.ceilPowerOfTwo = ceilPowerOfTwo; exports.clamp = clamp; exports.damp = damp; exports.degToRad = degToRad; exports.denormalize = denormalize; exports.euclideanModulo = euclideanModulo; exports.floorPowerOfTwo = floorPowerOfTwo; exports.generateUUID = generateUUID; exports.getPhysicsResolver = getPhysicsResolver; exports.getValueFromEmitterMode = getValueFromEmitterMode; exports.inverseLerp = inverseLerp; exports.isPowerOfTwo = isPowerOfTwo; exports.lerp = lerp; exports.loadPlugin = loadPlugin; exports.mapLinear = mapLinear; exports.normalize = normalize; exports.pingpong = pingpong; exports.radToDeg = radToDeg; exports.randFloat = randFloat; exports.randFloatSpread = randFloatSpread; exports.randInt = randInt; exports.registerShaderChunks = registerShaderChunks; exports.seededRandom = seededRandom; exports.setPhysicsResolver = setPhysicsResolver; exports.setQuaternionFromProperEuler = setQuaternionFromProperEuler; exports.smootherstep = smootherstep; exports.smoothstep = smoothstep; exports.unloadPlugin = unloadPlugin; }));