8918 lines
355 KiB
JavaScript
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;
|
|
|
|
}));
|