Files
2025-11-30 08:35:03 +02:00

8918 lines
355 KiB
JavaScript

/**
* three.quarks v0.15.6 build Fri Jan 17 2025
* https://quarks.art
* Copyright 2025 Alchemist0823 <the.forrest.sun@gmail.com>, 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 <the.forrest.sun@gmail.com>, 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<BurstParameters>}
*/
_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<Particle>}
*/
_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<Object3DEventMap>}
*/
_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<Behavior>}
*/
_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 <common>\n#include <color_pars_fragment>\n#include <map_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n#include <alphatest_pars_fragment>\n\n#include <tile_pars_fragment>\n#include <soft_pars_fragment>\n\nvoid main() {\n\n #include <clipping_planes_fragment>\n \n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vColor;\n \n #include <logdepthbuf_fragment>\n \n #include <tile_fragment>\n #include <alphatest_fragment>\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 <soft_fragment>\n #include <tonemapping_fragment>\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 <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <iridescence_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvoid main() {\n\nvec4 diffuseColor = vec4( diffuse, opacity );\n#include <clipping_planes_fragment>\n\nReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\nvec3 totalEmissiveRadiance = emissive;\n\n#include <logdepthbuf_fragment>\n#include <map_fragment>\n#include <color_fragment>\n#include <alphamap_fragment>\n#include <alphatest_fragment>\n#include <alphahash_fragment>\n#include <roughnessmap_fragment>\n#include <metalnessmap_fragment>\n#include <normal_fragment_begin>\n#include <normal_fragment_maps>\n#include <clearcoat_normal_fragment_begin>\n#include <clearcoat_normal_fragment_maps>\n#include <emissivemap_fragment>\n\n// accumulation\n#include <lights_physical_fragment>\n#include <lights_fragment_begin>\n#include <lights_fragment_maps>\n#include <lights_fragment_end>\n\n// modulation\n#include <aomap_fragment>\n\nvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\nvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\n#include <transmission_fragment>\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 <opaque_fragment>\n#include <tonemapping_fragment>\n#include <colorspace_fragment>\n#include <fog_fragment>\n#include <premultiplied_alpha_fragment>\n#include <dithering_fragment>\n}";
var particle_vert = /* glsl */"\n#include <common>\n#include <color_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n\n#include <tile_pars_vertex>\n#include <soft_pars_vertex>\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 <logdepthbuf_vertex>\n\n\t#include <clipping_planes_vertex>\n\n\t#include <tile_vertex>\n\t#include <soft_vertex>\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 <common>\n#include <color_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n#include <tile_pars_vertex>\n#include <soft_pars_vertex>\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 <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n #include <tile_vertex>\n #include <soft_vertex>\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 <common>\n\nattribute vec3 offset;\nattribute vec4 rotation;\nattribute vec3 size;\n#include <tile_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n\nvoid main() {\n\n #include <tile_vertex>\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 <color_vertex>\n#include <morphinstance_vertex>\n#include <morphcolor_vertex>\n#include <batching_vertex>\n\n#include <beginnormal_vertex>\n#include <morphnormal_vertex>\n#include <skinbase_vertex>\n#include <skinnormal_vertex>\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 <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\n\t// replace include <project_vertex>\n vec4 mvPosition = vec4( transformed, 1.0 );\n mvPosition = modelViewMatrix * (particleMatrix * mvPosition);\n\tgl_Position = projectionMatrix * mvPosition;\n\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t\n\tvViewPosition = - mvPosition.xyz;\n\t\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n#ifdef USE_TRANSMISSION\n vWorldPosition = worldPosition.xyz;\n#endif\n}\n";
var stretched_bb_particle_vert = /* glsl */"\n#include <common>\n#include <color_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n\n#include <tile_pars_vertex>\n#include <soft_pars_vertex>\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 <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <tile_vertex>\n\t#include <soft_vertex>\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 <common>\n#include <tile_pars_fragment>\n#include <map_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nuniform sampler2D alphaMap;\nuniform float useAlphaMap;\nuniform float visibility;\nuniform float alphaTest;\n\nvarying vec4 vColor;\n \nvoid main() {\n #include <clipping_planes_fragment>\n #include <logdepthbuf_fragment>\n\n vec4 diffuseColor = vColor;\n \n #ifdef USE_MAP\n #include <tile_fragment>\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 <fog_fragment>\n #include <tonemapping_fragment>\n}";
var trail_vert = /* glsl */"\n#include <common>\n#include <tile_pars_vertex>\n#include <color_pars_vertex>\n#include <clipping_planes_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <fog_pars_vertex>\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 <tile_vertex>\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 <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t\n vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n \n\t#include <fog_vertex>\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<VFXBatch>}
*/
_defineProperty(_this, "batches", []);
/**
* Map of systems to batch indices.
* @type {Map<IParticleSystem, number>}
*/
_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;
}));