@newkrok/three-particles 2.12.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.ts +182 -3
- package/dist/index.js +991 -150
- package/dist/index.js.map +1 -1
- package/dist/three-particles.min.js +1 -1
- package/dist/three-particles.min.js.map +1 -1
- package/llms-full.txt +37 -1
- package/llms.txt +20 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -174,6 +174,7 @@ var RendererType = /* @__PURE__ */ ((RendererType2) => {
|
|
|
174
174
|
RendererType2["POINTS"] = "POINTS";
|
|
175
175
|
RendererType2["INSTANCED"] = "INSTANCED";
|
|
176
176
|
RendererType2["TRAIL"] = "TRAIL";
|
|
177
|
+
RendererType2["MESH"] = "MESH";
|
|
177
178
|
return RendererType2;
|
|
178
179
|
})(RendererType || {});
|
|
179
180
|
var ForceFieldFalloff = /* @__PURE__ */ ((ForceFieldFalloff2) => {
|
|
@@ -310,6 +311,24 @@ var calculateRandomPositionAndVelocityOnRectangle = (position, quaternion, veloc
|
|
|
310
311
|
velocity.set(0, 0, speed);
|
|
311
312
|
velocity.applyQuaternion(quaternion);
|
|
312
313
|
};
|
|
314
|
+
var createDefaultMeshTexture = () => {
|
|
315
|
+
try {
|
|
316
|
+
const canvas = document.createElement("canvas");
|
|
317
|
+
canvas.width = 1;
|
|
318
|
+
canvas.height = 1;
|
|
319
|
+
const context = canvas.getContext("2d");
|
|
320
|
+
if (context) {
|
|
321
|
+
context.fillStyle = "white";
|
|
322
|
+
context.fillRect(0, 0, 1, 1);
|
|
323
|
+
const texture = new THREE4.CanvasTexture(canvas);
|
|
324
|
+
texture.needsUpdate = true;
|
|
325
|
+
return texture;
|
|
326
|
+
}
|
|
327
|
+
return null;
|
|
328
|
+
} catch {
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
313
332
|
var createDefaultParticleTexture = () => {
|
|
314
333
|
try {
|
|
315
334
|
const canvas = document.createElement("canvas");
|
|
@@ -494,6 +513,16 @@ var applyModifiers = ({
|
|
|
494
513
|
positionArr[positionIndex + 2] += noiseOnPosition * noisePower * positionAmount;
|
|
495
514
|
attributes.position.needsUpdate = true;
|
|
496
515
|
}
|
|
516
|
+
if (attributes.quat) {
|
|
517
|
+
const rotZ = attributes.rotation.array[particleIndex];
|
|
518
|
+
const halfZ = rotZ * 0.5;
|
|
519
|
+
const qi = particleIndex * 4;
|
|
520
|
+
attributes.quat.array[qi] = 0;
|
|
521
|
+
attributes.quat.array[qi + 1] = 0;
|
|
522
|
+
attributes.quat.array[qi + 2] = Math.sin(halfZ);
|
|
523
|
+
attributes.quat.array[qi + 3] = Math.cos(halfZ);
|
|
524
|
+
attributes.quat.needsUpdate = true;
|
|
525
|
+
}
|
|
497
526
|
};
|
|
498
527
|
|
|
499
528
|
// src/js/effects/three-particles/shaders/instanced-particle-fragment-shader.glsl.ts
|
|
@@ -506,6 +535,10 @@ var InstancedParticleFragmentShader = `
|
|
|
506
535
|
uniform bool discardBackgroundColor;
|
|
507
536
|
uniform vec3 backgroundColor;
|
|
508
537
|
uniform float backgroundColorTolerance;
|
|
538
|
+
uniform bool softParticlesEnabled;
|
|
539
|
+
uniform float softParticlesIntensity;
|
|
540
|
+
uniform sampler2D sceneDepthTexture;
|
|
541
|
+
uniform vec2 cameraNearFar;
|
|
509
542
|
|
|
510
543
|
varying vec2 vUv;
|
|
511
544
|
varying vec4 vColor;
|
|
@@ -513,10 +546,16 @@ var InstancedParticleFragmentShader = `
|
|
|
513
546
|
varying float vStartLifetime;
|
|
514
547
|
varying float vStartFrame;
|
|
515
548
|
varying float vRotation;
|
|
549
|
+
varying float vViewZ;
|
|
516
550
|
|
|
517
551
|
#include <common>
|
|
518
552
|
#include <logdepthbuf_pars_fragment>
|
|
519
553
|
|
|
554
|
+
float linearizeDepth(float depthSample, float near, float far) {
|
|
555
|
+
float z_ndc = 2.0 * depthSample - 1.0;
|
|
556
|
+
return 2.0 * near * far / (far + near - z_ndc * (far - near));
|
|
557
|
+
}
|
|
558
|
+
|
|
520
559
|
void main()
|
|
521
560
|
{
|
|
522
561
|
gl_FragColor = vColor;
|
|
@@ -559,6 +598,16 @@ var InstancedParticleFragmentShader = `
|
|
|
559
598
|
|
|
560
599
|
if (discardBackgroundColor && abs(length(rotatedTexture.rgb - backgroundColor.rgb)) < backgroundColorTolerance) discard;
|
|
561
600
|
|
|
601
|
+
if (softParticlesEnabled) {
|
|
602
|
+
vec2 screenUV = gl_FragCoord.xy / vec2(textureSize(sceneDepthTexture, 0));
|
|
603
|
+
float sceneDepthSample = texture2D(sceneDepthTexture, screenUV).r;
|
|
604
|
+
float sceneDepthLinear = linearizeDepth(sceneDepthSample, cameraNearFar.x, cameraNearFar.y);
|
|
605
|
+
float depthDiff = sceneDepthLinear - vViewZ;
|
|
606
|
+
float softFade = smoothstep(0.0, softParticlesIntensity, depthDiff);
|
|
607
|
+
gl_FragColor.a *= softFade;
|
|
608
|
+
if (gl_FragColor.a < 0.001) discard;
|
|
609
|
+
}
|
|
610
|
+
|
|
562
611
|
#include <logdepthbuf_fragment>
|
|
563
612
|
}
|
|
564
613
|
`;
|
|
@@ -585,6 +634,7 @@ var InstancedParticleVertexShader = `
|
|
|
585
634
|
varying float vStartLifetime;
|
|
586
635
|
varying float vStartFrame;
|
|
587
636
|
varying float vRotation;
|
|
637
|
+
varying float vViewZ;
|
|
588
638
|
|
|
589
639
|
#include <common>
|
|
590
640
|
#include <logdepthbuf_pars_vertex>
|
|
@@ -619,6 +669,7 @@ var InstancedParticleVertexShader = `
|
|
|
619
669
|
// identical to the Points renderer).
|
|
620
670
|
mvPosition.xy += position.xy * perspectiveSize;
|
|
621
671
|
|
|
672
|
+
vViewZ = -mvPosition.z;
|
|
622
673
|
gl_Position = projectionMatrix * mvPosition;
|
|
623
674
|
|
|
624
675
|
// Pass UV for texture sampling (quad ranges from -0.5..0.5, map to 0..1).
|
|
@@ -630,6 +681,151 @@ var InstancedParticleVertexShader = `
|
|
|
630
681
|
`;
|
|
631
682
|
var instanced_particle_vertex_shader_glsl_default = InstancedParticleVertexShader;
|
|
632
683
|
|
|
684
|
+
// src/js/effects/three-particles/shaders/mesh-particle-fragment-shader.glsl.ts
|
|
685
|
+
var MeshParticleFragmentShader = `
|
|
686
|
+
uniform sampler2D map;
|
|
687
|
+
uniform float elapsed;
|
|
688
|
+
uniform float fps;
|
|
689
|
+
uniform bool useFPSForFrameIndex;
|
|
690
|
+
uniform vec2 tiles;
|
|
691
|
+
uniform bool discardBackgroundColor;
|
|
692
|
+
uniform vec3 backgroundColor;
|
|
693
|
+
uniform float backgroundColorTolerance;
|
|
694
|
+
uniform bool softParticlesEnabled;
|
|
695
|
+
uniform float softParticlesIntensity;
|
|
696
|
+
uniform sampler2D sceneDepthTexture;
|
|
697
|
+
uniform vec2 cameraNearFar;
|
|
698
|
+
|
|
699
|
+
varying vec4 vColor;
|
|
700
|
+
varying float vLifetime;
|
|
701
|
+
varying float vStartLifetime;
|
|
702
|
+
varying float vStartFrame;
|
|
703
|
+
varying float vRotation;
|
|
704
|
+
varying vec3 vNormal;
|
|
705
|
+
varying vec2 vUv;
|
|
706
|
+
varying float vViewZ;
|
|
707
|
+
|
|
708
|
+
#include <common>
|
|
709
|
+
#include <logdepthbuf_pars_fragment>
|
|
710
|
+
|
|
711
|
+
float linearizeDepth(float depthSample, float near, float far) {
|
|
712
|
+
float z_ndc = 2.0 * depthSample - 1.0;
|
|
713
|
+
return 2.0 * near * far / (far + near - z_ndc * (far - near));
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
void main()
|
|
717
|
+
{
|
|
718
|
+
gl_FragColor = vColor;
|
|
719
|
+
|
|
720
|
+
// Use mesh UVs directly for texture sampling
|
|
721
|
+
vec2 uvPoint = vUv;
|
|
722
|
+
|
|
723
|
+
// Apply texture sheet animation if tiles > 1x1
|
|
724
|
+
if (tiles.x > 1.0 || tiles.y > 1.0) {
|
|
725
|
+
float frameIndex = round(vStartFrame) + (
|
|
726
|
+
useFPSForFrameIndex == true
|
|
727
|
+
? fps == 0.0
|
|
728
|
+
? 0.0
|
|
729
|
+
: max((vLifetime / 1000.0) * fps, 0.0)
|
|
730
|
+
: max(min(floor(min(vLifetime / vStartLifetime, 1.0) * (tiles.x * tiles.y)), tiles.x * tiles.y - 1.0), 0.0)
|
|
731
|
+
);
|
|
732
|
+
|
|
733
|
+
float spriteXIndex = floor(mod(frameIndex, tiles.x));
|
|
734
|
+
float spriteYIndex = floor(mod(frameIndex / tiles.x, tiles.y));
|
|
735
|
+
|
|
736
|
+
uvPoint = vec2(
|
|
737
|
+
vUv.x / tiles.x + spriteXIndex / tiles.x,
|
|
738
|
+
vUv.y / tiles.y + spriteYIndex / tiles.y
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
vec4 texColor = texture2D(map, uvPoint);
|
|
743
|
+
gl_FragColor = gl_FragColor * texColor;
|
|
744
|
+
|
|
745
|
+
if (discardBackgroundColor && abs(length(texColor.rgb - backgroundColor.rgb)) < backgroundColorTolerance) discard;
|
|
746
|
+
|
|
747
|
+
// Simple directional lighting from camera direction
|
|
748
|
+
float lightIntensity = 0.5 + 0.5 * max(dot(vNormal, vec3(0.0, 0.0, 1.0)), 0.0);
|
|
749
|
+
gl_FragColor.rgb *= lightIntensity;
|
|
750
|
+
|
|
751
|
+
if (softParticlesEnabled) {
|
|
752
|
+
vec2 screenUV = gl_FragCoord.xy / vec2(textureSize(sceneDepthTexture, 0));
|
|
753
|
+
float sceneDepthSample = texture2D(sceneDepthTexture, screenUV).r;
|
|
754
|
+
float sceneDepthLinear = linearizeDepth(sceneDepthSample, cameraNearFar.x, cameraNearFar.y);
|
|
755
|
+
float depthDiff = sceneDepthLinear - vViewZ;
|
|
756
|
+
float softFade = smoothstep(0.0, softParticlesIntensity, depthDiff);
|
|
757
|
+
gl_FragColor.a *= softFade;
|
|
758
|
+
if (gl_FragColor.a < 0.001) discard;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
#include <logdepthbuf_fragment>
|
|
762
|
+
}
|
|
763
|
+
`;
|
|
764
|
+
var mesh_particle_fragment_shader_glsl_default = MeshParticleFragmentShader;
|
|
765
|
+
|
|
766
|
+
// src/js/effects/three-particles/shaders/mesh-particle-vertex-shader.glsl.ts
|
|
767
|
+
var MeshParticleVertexShader = `
|
|
768
|
+
attribute float instanceSize;
|
|
769
|
+
attribute float instanceColorR;
|
|
770
|
+
attribute float instanceColorG;
|
|
771
|
+
attribute float instanceColorB;
|
|
772
|
+
attribute float instanceColorA;
|
|
773
|
+
attribute float instanceLifetime;
|
|
774
|
+
attribute float instanceStartLifetime;
|
|
775
|
+
attribute float instanceRotation;
|
|
776
|
+
attribute float instanceStartFrame;
|
|
777
|
+
attribute vec3 instanceOffset;
|
|
778
|
+
attribute vec4 instanceQuat;
|
|
779
|
+
|
|
780
|
+
varying vec4 vColor;
|
|
781
|
+
varying float vLifetime;
|
|
782
|
+
varying float vStartLifetime;
|
|
783
|
+
varying float vStartFrame;
|
|
784
|
+
varying float vRotation;
|
|
785
|
+
varying vec3 vNormal;
|
|
786
|
+
varying vec2 vUv;
|
|
787
|
+
varying float vViewZ;
|
|
788
|
+
|
|
789
|
+
#include <common>
|
|
790
|
+
#include <logdepthbuf_pars_vertex>
|
|
791
|
+
|
|
792
|
+
vec3 applyQuaternion(vec3 v, vec4 q) {
|
|
793
|
+
vec3 t = 2.0 * cross(q.xyz, v);
|
|
794
|
+
return v + q.w * t + cross(q.xyz, t);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
void main()
|
|
798
|
+
{
|
|
799
|
+
vColor = vec4(instanceColorR, instanceColorG, instanceColorB, instanceColorA);
|
|
800
|
+
vLifetime = instanceLifetime;
|
|
801
|
+
vStartLifetime = instanceStartLifetime;
|
|
802
|
+
vStartFrame = instanceStartFrame;
|
|
803
|
+
vRotation = instanceRotation;
|
|
804
|
+
|
|
805
|
+
// Apply quaternion rotation to the mesh vertex position
|
|
806
|
+
vec3 rotatedPosition = applyQuaternion(position, instanceQuat);
|
|
807
|
+
|
|
808
|
+
// Scale mesh by particle size
|
|
809
|
+
vec3 scaledPosition = rotatedPosition * instanceSize;
|
|
810
|
+
|
|
811
|
+
// Apply instance offset (particle world position)
|
|
812
|
+
vec3 worldPos = scaledPosition + instanceOffset;
|
|
813
|
+
|
|
814
|
+
vec4 mvPosition = modelViewMatrix * vec4(worldPos, 1.0);
|
|
815
|
+
vViewZ = -mvPosition.z;
|
|
816
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
817
|
+
|
|
818
|
+
// Transform normal by quaternion for lighting
|
|
819
|
+
vNormal = normalize((modelViewMatrix * vec4(applyQuaternion(normal, instanceQuat), 0.0)).xyz);
|
|
820
|
+
|
|
821
|
+
// Pass through UVs from the mesh geometry
|
|
822
|
+
vUv = uv;
|
|
823
|
+
|
|
824
|
+
#include <logdepthbuf_vertex>
|
|
825
|
+
}
|
|
826
|
+
`;
|
|
827
|
+
var mesh_particle_vertex_shader_glsl_default = MeshParticleVertexShader;
|
|
828
|
+
|
|
633
829
|
// src/js/effects/three-particles/shaders/particle-system-fragment-shader.glsl.ts
|
|
634
830
|
var ParticleSystemFragmentShader = `
|
|
635
831
|
uniform sampler2D map;
|
|
@@ -640,16 +836,26 @@ var ParticleSystemFragmentShader = `
|
|
|
640
836
|
uniform bool discardBackgroundColor;
|
|
641
837
|
uniform vec3 backgroundColor;
|
|
642
838
|
uniform float backgroundColorTolerance;
|
|
839
|
+
uniform bool softParticlesEnabled;
|
|
840
|
+
uniform float softParticlesIntensity;
|
|
841
|
+
uniform sampler2D sceneDepthTexture;
|
|
842
|
+
uniform vec2 cameraNearFar;
|
|
643
843
|
|
|
644
844
|
varying vec4 vColor;
|
|
645
845
|
varying float vLifetime;
|
|
646
846
|
varying float vStartLifetime;
|
|
647
847
|
varying float vRotation;
|
|
648
848
|
varying float vStartFrame;
|
|
849
|
+
varying float vViewZ;
|
|
649
850
|
|
|
650
851
|
#include <common>
|
|
651
852
|
#include <logdepthbuf_pars_fragment>
|
|
652
853
|
|
|
854
|
+
float linearizeDepth(float depthSample, float near, float far) {
|
|
855
|
+
float z_ndc = 2.0 * depthSample - 1.0;
|
|
856
|
+
return 2.0 * near * far / (far + near - z_ndc * (far - near));
|
|
857
|
+
}
|
|
858
|
+
|
|
653
859
|
void main()
|
|
654
860
|
{
|
|
655
861
|
gl_FragColor = vColor;
|
|
@@ -697,7 +903,17 @@ var ParticleSystemFragmentShader = `
|
|
|
697
903
|
gl_FragColor = gl_FragColor * rotatedTexture;
|
|
698
904
|
|
|
699
905
|
if (discardBackgroundColor && abs(length(rotatedTexture.rgb - backgroundColor.rgb)) < backgroundColorTolerance) discard;
|
|
700
|
-
|
|
906
|
+
|
|
907
|
+
if (softParticlesEnabled) {
|
|
908
|
+
vec2 screenUV = gl_FragCoord.xy / vec2(textureSize(sceneDepthTexture, 0));
|
|
909
|
+
float sceneDepthSample = texture2D(sceneDepthTexture, screenUV).r;
|
|
910
|
+
float sceneDepthLinear = linearizeDepth(sceneDepthSample, cameraNearFar.x, cameraNearFar.y);
|
|
911
|
+
float depthDiff = sceneDepthLinear - vViewZ;
|
|
912
|
+
float softFade = smoothstep(0.0, softParticlesIntensity, depthDiff);
|
|
913
|
+
gl_FragColor.a *= softFade;
|
|
914
|
+
if (gl_FragColor.a < 0.001) discard;
|
|
915
|
+
}
|
|
916
|
+
|
|
701
917
|
#include <logdepthbuf_fragment>
|
|
702
918
|
}
|
|
703
919
|
`;
|
|
@@ -721,6 +937,7 @@ var ParticleSystemVertexShader = `
|
|
|
721
937
|
varying float vStartLifetime;
|
|
722
938
|
varying float vRotation;
|
|
723
939
|
varying float vStartFrame;
|
|
940
|
+
varying float vViewZ;
|
|
724
941
|
|
|
725
942
|
#include <common>
|
|
726
943
|
#include <logdepthbuf_pars_vertex>
|
|
@@ -735,6 +952,7 @@ var ParticleSystemVertexShader = `
|
|
|
735
952
|
|
|
736
953
|
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
|
737
954
|
gl_PointSize = size * (100.0 / length(mvPosition.xyz));
|
|
955
|
+
vViewZ = -mvPosition.z;
|
|
738
956
|
gl_Position = projectionMatrix * mvPosition;
|
|
739
957
|
|
|
740
958
|
#include <logdepthbuf_vertex>
|
|
@@ -749,14 +967,24 @@ var TrailFragmentShader = `
|
|
|
749
967
|
uniform bool discardBackgroundColor;
|
|
750
968
|
uniform vec3 backgroundColor;
|
|
751
969
|
uniform float backgroundColorTolerance;
|
|
970
|
+
uniform bool softParticlesEnabled;
|
|
971
|
+
uniform float softParticlesIntensity;
|
|
972
|
+
uniform sampler2D sceneDepthTexture;
|
|
973
|
+
uniform vec2 cameraNearFar;
|
|
752
974
|
|
|
753
975
|
varying float vAlpha;
|
|
754
976
|
varying vec4 vColor;
|
|
755
977
|
varying vec2 vUv;
|
|
978
|
+
varying float vViewZ;
|
|
756
979
|
|
|
757
980
|
#include <common>
|
|
758
981
|
#include <logdepthbuf_pars_fragment>
|
|
759
982
|
|
|
983
|
+
float linearizeDepth(float depthSample, float near, float far) {
|
|
984
|
+
float z_ndc = 2.0 * depthSample - 1.0;
|
|
985
|
+
return 2.0 * near * far / (far + near - z_ndc * (far - near));
|
|
986
|
+
}
|
|
987
|
+
|
|
760
988
|
void main()
|
|
761
989
|
{
|
|
762
990
|
// Soft edge: always fade near ribbon edges
|
|
@@ -777,6 +1005,16 @@ var TrailFragmentShader = `
|
|
|
777
1005
|
|
|
778
1006
|
if (gl_FragColor.a < 0.001) discard;
|
|
779
1007
|
|
|
1008
|
+
if (softParticlesEnabled) {
|
|
1009
|
+
vec2 screenUV = gl_FragCoord.xy / vec2(textureSize(sceneDepthTexture, 0));
|
|
1010
|
+
float sceneDepthSample = texture2D(sceneDepthTexture, screenUV).r;
|
|
1011
|
+
float sceneDepthLinear = linearizeDepth(sceneDepthSample, cameraNearFar.x, cameraNearFar.y);
|
|
1012
|
+
float depthDiff = sceneDepthLinear - vViewZ;
|
|
1013
|
+
float softFade = smoothstep(0.0, softParticlesIntensity, depthDiff);
|
|
1014
|
+
gl_FragColor.a *= softFade;
|
|
1015
|
+
if (gl_FragColor.a < 0.001) discard;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
780
1018
|
if (discardBackgroundColor && abs(length(gl_FragColor.rgb - backgroundColor.rgb)) < backgroundColorTolerance) discard;
|
|
781
1019
|
|
|
782
1020
|
#include <logdepthbuf_fragment>
|
|
@@ -796,6 +1034,7 @@ var TrailVertexShader = `
|
|
|
796
1034
|
varying float vAlpha;
|
|
797
1035
|
varying vec4 vColor;
|
|
798
1036
|
varying vec2 vUv;
|
|
1037
|
+
varying float vViewZ;
|
|
799
1038
|
|
|
800
1039
|
#include <common>
|
|
801
1040
|
#include <logdepthbuf_pars_vertex>
|
|
@@ -822,28 +1061,27 @@ var TrailVertexShader = `
|
|
|
822
1061
|
float perpLen = length(perp);
|
|
823
1062
|
|
|
824
1063
|
// When tangent is nearly parallel to view direction, the cross product
|
|
825
|
-
// collapses and the ribbon becomes edge-on (invisible).
|
|
826
|
-
// perpendicular from
|
|
827
|
-
//
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
upPerp = cross(tangent, vec3(1.0, 0.0, 0.0));
|
|
832
|
-
upPerpLen = length(upPerp);
|
|
833
|
-
}
|
|
834
|
-
upPerp = upPerp / max(upPerpLen, 0.0001);
|
|
1064
|
+
// collapses and the ribbon becomes edge-on (invisible). Build a stable
|
|
1065
|
+
// fallback perpendicular from the camera's right axis \u2014 this keeps the
|
|
1066
|
+
// ribbon in screen-space and prevents it from flipping into an arbitrary
|
|
1067
|
+
// plane when viewed edge-on.
|
|
1068
|
+
vec3 camRight = vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]);
|
|
1069
|
+
vec3 fallbackPerp = normalize(camRight - tangent * dot(camRight, tangent));
|
|
835
1070
|
|
|
836
1071
|
if (perpLen < 0.0001) {
|
|
837
|
-
perp =
|
|
1072
|
+
perp = fallbackPerp;
|
|
838
1073
|
} else {
|
|
839
1074
|
perp = perp / perpLen;
|
|
840
|
-
//
|
|
841
|
-
|
|
842
|
-
|
|
1075
|
+
// Smoothly blend toward the fallback when the billboard perp weakens.
|
|
1076
|
+
// The wide range (0..0.7) ensures a gradual transition so the ribbon
|
|
1077
|
+
// does not snap abruptly when rotating toward edge-on.
|
|
1078
|
+
float blendFactor = smoothstep(0.0, 0.7, perpLen);
|
|
1079
|
+
perp = normalize(mix(fallbackPerp, perp, blendFactor));
|
|
843
1080
|
}
|
|
844
1081
|
|
|
845
1082
|
vec3 offsetPos = position + perp * trailOffset * trailHalfWidth;
|
|
846
1083
|
vec4 mvPosition = modelViewMatrix * vec4(offsetPos, 1.0);
|
|
1084
|
+
vViewZ = -mvPosition.z;
|
|
847
1085
|
gl_Position = projectionMatrix * mvPosition;
|
|
848
1086
|
|
|
849
1087
|
#include <logdepthbuf_vertex>
|
|
@@ -1016,7 +1254,11 @@ var DEFAULT_PARTICLE_SYSTEM_CONFIG = {
|
|
|
1016
1254
|
backgroundColor: { r: 1, g: 1, b: 1 },
|
|
1017
1255
|
transparent: true,
|
|
1018
1256
|
depthTest: true,
|
|
1019
|
-
depthWrite: false
|
|
1257
|
+
depthWrite: false,
|
|
1258
|
+
softParticles: {
|
|
1259
|
+
enabled: false,
|
|
1260
|
+
intensity: 1
|
|
1261
|
+
}
|
|
1020
1262
|
},
|
|
1021
1263
|
velocityOverLifetime: {
|
|
1022
1264
|
isActive: false,
|
|
@@ -1239,7 +1481,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1239
1481
|
config,
|
|
1240
1482
|
{ applyToFirstObject: false, skippedProperties: [] }
|
|
1241
1483
|
);
|
|
1242
|
-
let particleMap = normalizedConfig.map || createDefaultParticleTexture();
|
|
1484
|
+
let particleMap = normalizedConfig.map || (normalizedConfig.renderer.rendererType === "MESH" /* MESH */ ? createDefaultMeshTexture() : createDefaultParticleTexture());
|
|
1243
1485
|
const {
|
|
1244
1486
|
transform,
|
|
1245
1487
|
duration,
|
|
@@ -1424,7 +1666,9 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1424
1666
|
}));
|
|
1425
1667
|
}
|
|
1426
1668
|
const useTrail = renderer.rendererType === "TRAIL" /* TRAIL */;
|
|
1427
|
-
const
|
|
1669
|
+
const useMesh = renderer.rendererType === "MESH" /* MESH */;
|
|
1670
|
+
const useInstancing = !useTrail && !useMesh && renderer.rendererType === "INSTANCED" /* INSTANCED */;
|
|
1671
|
+
const useInstancedAttributes = useInstancing || useMesh;
|
|
1428
1672
|
const defaultTrailCurve = {
|
|
1429
1673
|
type: "BEZIER" /* BEZIER */,
|
|
1430
1674
|
scale: 1,
|
|
@@ -1444,7 +1688,13 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1444
1688
|
renderer.trail?.opacityOverTrail,
|
|
1445
1689
|
defaultTrailCurve
|
|
1446
1690
|
),
|
|
1447
|
-
colorOverTrail: renderer.trail?.colorOverTrail
|
|
1691
|
+
colorOverTrail: renderer.trail?.colorOverTrail,
|
|
1692
|
+
minVertexDistance: renderer.trail?.minVertexDistance ?? 0,
|
|
1693
|
+
maxTime: renderer.trail?.maxTime ?? 0,
|
|
1694
|
+
smoothing: renderer.trail?.smoothing ?? false,
|
|
1695
|
+
smoothingSubdivisions: renderer.trail?.smoothingSubdivisions ?? 3,
|
|
1696
|
+
twistPrevention: renderer.trail?.twistPrevention ?? false,
|
|
1697
|
+
ribbonId: renderer.trail?.ribbonId
|
|
1448
1698
|
} : void 0;
|
|
1449
1699
|
if (useTrail && trailConfig) {
|
|
1450
1700
|
const trailLength = trailConfig.length;
|
|
@@ -1454,9 +1704,21 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1454
1704
|
);
|
|
1455
1705
|
generalData.positionHistoryIndex = new Uint16Array(maxParticles);
|
|
1456
1706
|
generalData.positionHistoryCount = new Uint16Array(maxParticles);
|
|
1707
|
+
if (trailConfig.minVertexDistance > 0) {
|
|
1708
|
+
generalData.trailLastSampledPosition = new Float32Array(maxParticles * 3);
|
|
1709
|
+
}
|
|
1710
|
+
if (trailConfig.maxTime > 0) {
|
|
1711
|
+
generalData.trailSampleTimes = new Float64Array(
|
|
1712
|
+
maxParticles * trailLength
|
|
1713
|
+
);
|
|
1714
|
+
}
|
|
1715
|
+
if (trailConfig.twistPrevention) {
|
|
1716
|
+
generalData.trailPrevNormal = new Float32Array(maxParticles * 3);
|
|
1717
|
+
}
|
|
1457
1718
|
}
|
|
1458
|
-
const attr = (name) =>
|
|
1459
|
-
const posAttr =
|
|
1719
|
+
const attr = (name) => useInstancedAttributes ? `instance${name.charAt(0).toUpperCase()}${name.slice(1)}` : name;
|
|
1720
|
+
const posAttr = useInstancedAttributes ? "instanceOffset" : "position";
|
|
1721
|
+
const softParticlesEnabled = !!(renderer.softParticles?.enabled && renderer.softParticles?.depthTexture);
|
|
1460
1722
|
const sharedUniforms = {
|
|
1461
1723
|
elapsed: { value: 0 },
|
|
1462
1724
|
map: { value: particleMap },
|
|
@@ -1468,19 +1730,56 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1468
1730
|
backgroundColor: { value: renderer.backgroundColor },
|
|
1469
1731
|
discardBackgroundColor: { value: renderer.discardBackgroundColor },
|
|
1470
1732
|
backgroundColorTolerance: { value: renderer.backgroundColorTolerance },
|
|
1471
|
-
...useInstancing ? { viewportHeight: { value: 1 } } : {}
|
|
1733
|
+
...useInstancing ? { viewportHeight: { value: 1 } } : {},
|
|
1734
|
+
softParticlesEnabled: { value: softParticlesEnabled },
|
|
1735
|
+
softParticlesIntensity: {
|
|
1736
|
+
value: Math.max(renderer.softParticles?.intensity ?? 1, 1e-3)
|
|
1737
|
+
},
|
|
1738
|
+
sceneDepthTexture: {
|
|
1739
|
+
value: renderer.softParticles?.depthTexture ?? null
|
|
1740
|
+
},
|
|
1741
|
+
cameraNearFar: { value: new THREE4.Vector2(0.1, 1e3) }
|
|
1742
|
+
};
|
|
1743
|
+
const getVertexShader = () => {
|
|
1744
|
+
if (useMesh) return mesh_particle_vertex_shader_glsl_default;
|
|
1745
|
+
if (useInstancing) return instanced_particle_vertex_shader_glsl_default;
|
|
1746
|
+
return particle_system_vertex_shader_glsl_default;
|
|
1747
|
+
};
|
|
1748
|
+
const getFragmentShader = () => {
|
|
1749
|
+
if (useMesh) return mesh_particle_fragment_shader_glsl_default;
|
|
1750
|
+
if (useInstancing) return instanced_particle_fragment_shader_glsl_default;
|
|
1751
|
+
return particle_system_fragment_shader_glsl_default;
|
|
1472
1752
|
};
|
|
1473
1753
|
const material = new THREE4.ShaderMaterial({
|
|
1474
1754
|
uniforms: sharedUniforms,
|
|
1475
|
-
vertexShader:
|
|
1476
|
-
fragmentShader:
|
|
1755
|
+
vertexShader: getVertexShader(),
|
|
1756
|
+
fragmentShader: getFragmentShader(),
|
|
1477
1757
|
transparent: renderer.transparent,
|
|
1478
1758
|
blending: renderer.blending,
|
|
1479
1759
|
depthTest: renderer.depthTest,
|
|
1480
1760
|
depthWrite: renderer.depthWrite
|
|
1481
1761
|
});
|
|
1482
1762
|
let geometry;
|
|
1483
|
-
if (
|
|
1763
|
+
if (useMesh) {
|
|
1764
|
+
const meshConfig = renderer.mesh;
|
|
1765
|
+
if (!meshConfig?.geometry) {
|
|
1766
|
+
throw new Error(
|
|
1767
|
+
"RendererType.MESH requires a mesh configuration with a geometry. Set renderer.mesh.geometry to a THREE.BufferGeometry instance."
|
|
1768
|
+
);
|
|
1769
|
+
}
|
|
1770
|
+
const instancedGeometry = new THREE4.InstancedBufferGeometry();
|
|
1771
|
+
const sourceGeom = meshConfig.geometry;
|
|
1772
|
+
const srcPos = sourceGeom.getAttribute("position");
|
|
1773
|
+
if (srcPos) instancedGeometry.setAttribute("position", srcPos);
|
|
1774
|
+
const srcNormal = sourceGeom.getAttribute("normal");
|
|
1775
|
+
if (srcNormal) instancedGeometry.setAttribute("normal", srcNormal);
|
|
1776
|
+
const srcUv = sourceGeom.getAttribute("uv");
|
|
1777
|
+
if (srcUv) instancedGeometry.setAttribute("uv", srcUv);
|
|
1778
|
+
const srcIndex = sourceGeom.getIndex();
|
|
1779
|
+
if (srcIndex) instancedGeometry.setIndex(srcIndex);
|
|
1780
|
+
instancedGeometry.instanceCount = maxParticles;
|
|
1781
|
+
geometry = instancedGeometry;
|
|
1782
|
+
} else if (useInstancing) {
|
|
1484
1783
|
const instancedGeometry = new THREE4.InstancedBufferGeometry();
|
|
1485
1784
|
const quadPositions = new Float32Array([
|
|
1486
1785
|
-0.5,
|
|
@@ -1521,28 +1820,28 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1521
1820
|
positionArray[i * 3 + 1] = startPositions[i].y;
|
|
1522
1821
|
positionArray[i * 3 + 2] = startPositions[i].z;
|
|
1523
1822
|
}
|
|
1524
|
-
const positionAttribute =
|
|
1823
|
+
const positionAttribute = useInstancedAttributes ? new THREE4.InstancedBufferAttribute(positionArray, 3) : new THREE4.BufferAttribute(positionArray, 3);
|
|
1525
1824
|
geometry.setAttribute(posAttr, positionAttribute);
|
|
1526
1825
|
createFloat32Attributes({
|
|
1527
1826
|
geometry,
|
|
1528
1827
|
propertyName: attr("isActive"),
|
|
1529
1828
|
maxParticles,
|
|
1530
1829
|
factory: 0,
|
|
1531
|
-
instanced:
|
|
1830
|
+
instanced: useInstancedAttributes
|
|
1532
1831
|
});
|
|
1533
1832
|
createFloat32Attributes({
|
|
1534
1833
|
geometry,
|
|
1535
1834
|
propertyName: attr("lifetime"),
|
|
1536
1835
|
maxParticles,
|
|
1537
1836
|
factory: 0,
|
|
1538
|
-
instanced:
|
|
1837
|
+
instanced: useInstancedAttributes
|
|
1539
1838
|
});
|
|
1540
1839
|
createFloat32Attributes({
|
|
1541
1840
|
geometry,
|
|
1542
1841
|
propertyName: attr("startLifetime"),
|
|
1543
1842
|
maxParticles,
|
|
1544
1843
|
factory: () => calculateValue(generalData.particleSystemId, startLifetime, 0) * 1e3,
|
|
1545
|
-
instanced:
|
|
1844
|
+
instanced: useInstancedAttributes
|
|
1546
1845
|
});
|
|
1547
1846
|
createFloat32Attributes({
|
|
1548
1847
|
geometry,
|
|
@@ -1553,21 +1852,21 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1553
1852
|
textureSheetAnimation.startFrame,
|
|
1554
1853
|
0
|
|
1555
1854
|
) : 0,
|
|
1556
|
-
instanced:
|
|
1855
|
+
instanced: useInstancedAttributes
|
|
1557
1856
|
});
|
|
1558
1857
|
createFloat32Attributes({
|
|
1559
1858
|
geometry,
|
|
1560
1859
|
propertyName: attr("size"),
|
|
1561
1860
|
maxParticles,
|
|
1562
1861
|
factory: (_, index) => generalData.startValues.startSize[index],
|
|
1563
|
-
instanced:
|
|
1862
|
+
instanced: useInstancedAttributes
|
|
1564
1863
|
});
|
|
1565
1864
|
createFloat32Attributes({
|
|
1566
1865
|
geometry,
|
|
1567
1866
|
propertyName: attr("rotation"),
|
|
1568
1867
|
maxParticles,
|
|
1569
1868
|
factory: 0,
|
|
1570
|
-
instanced:
|
|
1869
|
+
instanced: useInstancedAttributes
|
|
1571
1870
|
});
|
|
1572
1871
|
const colorRandomRatio = Math.random();
|
|
1573
1872
|
createFloat32Attributes({
|
|
@@ -1575,29 +1874,39 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1575
1874
|
propertyName: attr("colorR"),
|
|
1576
1875
|
maxParticles,
|
|
1577
1876
|
factory: () => startColor.min.r + colorRandomRatio * (startColor.max.r - startColor.min.r),
|
|
1578
|
-
instanced:
|
|
1877
|
+
instanced: useInstancedAttributes
|
|
1579
1878
|
});
|
|
1580
1879
|
createFloat32Attributes({
|
|
1581
1880
|
geometry,
|
|
1582
1881
|
propertyName: attr("colorG"),
|
|
1583
1882
|
maxParticles,
|
|
1584
1883
|
factory: () => startColor.min.g + colorRandomRatio * (startColor.max.g - startColor.min.g),
|
|
1585
|
-
instanced:
|
|
1884
|
+
instanced: useInstancedAttributes
|
|
1586
1885
|
});
|
|
1587
1886
|
createFloat32Attributes({
|
|
1588
1887
|
geometry,
|
|
1589
1888
|
propertyName: attr("colorB"),
|
|
1590
1889
|
maxParticles,
|
|
1591
1890
|
factory: () => startColor.min.b + colorRandomRatio * (startColor.max.b - startColor.min.b),
|
|
1592
|
-
instanced:
|
|
1891
|
+
instanced: useInstancedAttributes
|
|
1593
1892
|
});
|
|
1594
1893
|
createFloat32Attributes({
|
|
1595
1894
|
geometry,
|
|
1596
1895
|
propertyName: attr("colorA"),
|
|
1597
1896
|
maxParticles,
|
|
1598
1897
|
factory: 0,
|
|
1599
|
-
instanced:
|
|
1898
|
+
instanced: useInstancedAttributes
|
|
1600
1899
|
});
|
|
1900
|
+
if (useMesh) {
|
|
1901
|
+
const quatArray = new Float32Array(maxParticles * 4);
|
|
1902
|
+
for (let i = 0; i < maxParticles; i++) {
|
|
1903
|
+
quatArray[i * 4 + 3] = 1;
|
|
1904
|
+
}
|
|
1905
|
+
geometry.setAttribute(
|
|
1906
|
+
attr("quat"),
|
|
1907
|
+
new THREE4.InstancedBufferAttribute(quatArray, 4)
|
|
1908
|
+
);
|
|
1909
|
+
}
|
|
1601
1910
|
const a = geometry.attributes;
|
|
1602
1911
|
const aIsActive = a[attr("isActive")];
|
|
1603
1912
|
const aColorR = a[attr("colorR")];
|
|
@@ -1610,6 +1919,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1610
1919
|
const aRotation = a[attr("rotation")];
|
|
1611
1920
|
const aLifetime = a[attr("lifetime")];
|
|
1612
1921
|
const aPosition = a[posAttr];
|
|
1922
|
+
const aQuat = useMesh ? a[attr("quat")] : void 0;
|
|
1613
1923
|
const deactivateParticle = (particleIndex) => {
|
|
1614
1924
|
aIsActive.array[particleIndex] = 0;
|
|
1615
1925
|
aColorA.array[particleIndex] = 0;
|
|
@@ -1626,6 +1936,18 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1626
1936
|
if (generalData.positionHistoryCount) {
|
|
1627
1937
|
generalData.positionHistoryCount[particleIndex] = 0;
|
|
1628
1938
|
generalData.positionHistoryIndex[particleIndex] = 0;
|
|
1939
|
+
if (generalData.trailLastSampledPosition) {
|
|
1940
|
+
const lsIdx = particleIndex * 3;
|
|
1941
|
+
generalData.trailLastSampledPosition[lsIdx] = 0;
|
|
1942
|
+
generalData.trailLastSampledPosition[lsIdx + 1] = 0;
|
|
1943
|
+
generalData.trailLastSampledPosition[lsIdx + 2] = 0;
|
|
1944
|
+
}
|
|
1945
|
+
if (generalData.trailPrevNormal) {
|
|
1946
|
+
const nIdx = particleIndex * 3;
|
|
1947
|
+
generalData.trailPrevNormal[nIdx] = 0;
|
|
1948
|
+
generalData.trailPrevNormal[nIdx + 1] = 0;
|
|
1949
|
+
generalData.trailPrevNormal[nIdx + 2] = 0;
|
|
1950
|
+
}
|
|
1629
1951
|
}
|
|
1630
1952
|
if (generalData.noise.offsets)
|
|
1631
1953
|
generalData.noise.offsets[particleIndex] = Math.random() * 100;
|
|
@@ -1671,6 +1993,16 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1671
1993
|
generalData.normalizedLifetimePercentage
|
|
1672
1994
|
);
|
|
1673
1995
|
aRotation.needsUpdate = true;
|
|
1996
|
+
if (aQuat) {
|
|
1997
|
+
const rotZ = aRotation.array[particleIndex];
|
|
1998
|
+
const halfZ = rotZ * 0.5;
|
|
1999
|
+
const qi = particleIndex * 4;
|
|
2000
|
+
aQuat.array[qi] = 0;
|
|
2001
|
+
aQuat.array[qi + 1] = 0;
|
|
2002
|
+
aQuat.array[qi + 2] = Math.sin(halfZ);
|
|
2003
|
+
aQuat.array[qi + 3] = Math.cos(halfZ);
|
|
2004
|
+
aQuat.needsUpdate = true;
|
|
2005
|
+
}
|
|
1674
2006
|
if (normalizedConfig.rotationOverLifetime.isActive)
|
|
1675
2007
|
generalData.lifetimeValues.rotationOverLifetime[particleIndex] = THREE4.MathUtils.randFloat(
|
|
1676
2008
|
normalizedConfig.rotationOverLifetime.min,
|
|
@@ -1796,7 +2128,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1796
2128
|
},
|
|
1797
2129
|
renderer: {
|
|
1798
2130
|
...subConfig.config.renderer ?? {},
|
|
1799
|
-
rendererType: renderer.rendererType
|
|
2131
|
+
...subConfig.config.renderer?.rendererType ? {} : renderer.rendererType === "MESH" /* MESH */ || renderer.rendererType === "TRAIL" /* TRAIL */ ? {} : { rendererType: renderer.rendererType }
|
|
1800
2132
|
},
|
|
1801
2133
|
...inheritVelocity > 0 ? {
|
|
1802
2134
|
startSpeed: (typeof subConfig.config.startSpeed === "number" ? subConfig.config.startSpeed : typeof subConfig.config.startSpeed === "object" && subConfig.config.startSpeed !== null && "min" in subConfig.config.startSpeed ? subConfig.config.startSpeed.min ?? 0 : 0) + velocity.length() * inheritVelocity
|
|
@@ -1881,7 +2213,15 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1881
2213
|
useMap: { value: !!particleMap },
|
|
1882
2214
|
discardBackgroundColor: { value: renderer.discardBackgroundColor },
|
|
1883
2215
|
backgroundColor: { value: renderer.backgroundColor },
|
|
1884
|
-
backgroundColorTolerance: { value: renderer.backgroundColorTolerance }
|
|
2216
|
+
backgroundColorTolerance: { value: renderer.backgroundColorTolerance },
|
|
2217
|
+
softParticlesEnabled: { value: softParticlesEnabled },
|
|
2218
|
+
softParticlesIntensity: {
|
|
2219
|
+
value: Math.max(renderer.softParticles?.intensity ?? 1, 1e-3)
|
|
2220
|
+
},
|
|
2221
|
+
sceneDepthTexture: {
|
|
2222
|
+
value: renderer.softParticles?.depthTexture ?? null
|
|
2223
|
+
},
|
|
2224
|
+
cameraNearFar: { value: new THREE4.Vector2(0.1, 1e3) }
|
|
1885
2225
|
},
|
|
1886
2226
|
vertexShader: trail_vertex_shader_glsl_default,
|
|
1887
2227
|
fragmentShader: trail_fragment_shader_glsl_default,
|
|
@@ -1896,6 +2236,14 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1896
2236
|
const trailCameraPos = new THREE4.Vector3();
|
|
1897
2237
|
trailMesh.onBeforeRender = (_renderer, _scene, camera) => {
|
|
1898
2238
|
camera.getWorldPosition(trailCameraPos);
|
|
2239
|
+
if (softParticlesEnabled && camera.isPerspectiveCamera) {
|
|
2240
|
+
const perspCam = camera;
|
|
2241
|
+
const trailUniforms = trailMaterial.uniforms;
|
|
2242
|
+
trailUniforms.cameraNearFar.value.set(
|
|
2243
|
+
perspCam.near,
|
|
2244
|
+
perspCam.far
|
|
2245
|
+
);
|
|
2246
|
+
}
|
|
1899
2247
|
};
|
|
1900
2248
|
generalData.trailCameraPosition = trailCameraPos;
|
|
1901
2249
|
trailWidthCurveFn = getCurveFunctionFromConfig(
|
|
@@ -1923,11 +2271,20 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1923
2271
|
};
|
|
1924
2272
|
}
|
|
1925
2273
|
}
|
|
1926
|
-
let particleSystem = useInstancing ? new THREE4.Mesh(geometry, material) : new THREE4.Points(geometry, material);
|
|
1927
|
-
if (useInstancing) {
|
|
1928
|
-
particleSystem.onBeforeRender = (glRenderer) => {
|
|
1929
|
-
|
|
1930
|
-
|
|
2274
|
+
let particleSystem = useInstancing || useMesh ? new THREE4.Mesh(geometry, material) : new THREE4.Points(geometry, material);
|
|
2275
|
+
if (useInstancing || softParticlesEnabled) {
|
|
2276
|
+
particleSystem.onBeforeRender = (glRenderer, _scene, camera) => {
|
|
2277
|
+
if (useInstancing) {
|
|
2278
|
+
const size = glRenderer.getSize(new THREE4.Vector2());
|
|
2279
|
+
sharedUniforms.viewportHeight.value = size.y * glRenderer.getPixelRatio();
|
|
2280
|
+
}
|
|
2281
|
+
if (softParticlesEnabled && camera.isPerspectiveCamera) {
|
|
2282
|
+
const perspCam = camera;
|
|
2283
|
+
sharedUniforms.cameraNearFar.value.set(
|
|
2284
|
+
perspCam.near,
|
|
2285
|
+
perspCam.far
|
|
2286
|
+
);
|
|
2287
|
+
}
|
|
1931
2288
|
};
|
|
1932
2289
|
}
|
|
1933
2290
|
if (useTrail && trailMesh) {
|
|
@@ -1950,7 +2307,8 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1950
2307
|
colorR: aColorR,
|
|
1951
2308
|
colorG: aColorG,
|
|
1952
2309
|
colorB: aColorB,
|
|
1953
|
-
colorA: aColorA
|
|
2310
|
+
colorA: aColorA,
|
|
2311
|
+
...useMesh ? { quat: aQuat } : {}
|
|
1954
2312
|
};
|
|
1955
2313
|
const calculatedCreationTime = now + calculateValue(generalData.particleSystemId, startDelay) * 1e3;
|
|
1956
2314
|
let wrapper;
|
|
@@ -2022,7 +2380,13 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2022
2380
|
trailColorOverTrailFns,
|
|
2023
2381
|
trailConfig: {
|
|
2024
2382
|
length: trailConfig.length,
|
|
2025
|
-
width: trailConfig.width
|
|
2383
|
+
width: trailConfig.width,
|
|
2384
|
+
minVertexDistance: trailConfig.minVertexDistance,
|
|
2385
|
+
maxTime: trailConfig.maxTime,
|
|
2386
|
+
smoothing: trailConfig.smoothing,
|
|
2387
|
+
smoothingSubdivisions: trailConfig.smoothingSubdivisions,
|
|
2388
|
+
twistPrevention: trailConfig.twistPrevention,
|
|
2389
|
+
ribbonId: trailConfig.ribbonId
|
|
2026
2390
|
}
|
|
2027
2391
|
} : {}
|
|
2028
2392
|
};
|
|
@@ -2284,10 +2648,84 @@ var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|
|
|
2284
2648
|
particleSystem
|
|
2285
2649
|
});
|
|
2286
2650
|
if (props.trailMesh) {
|
|
2287
|
-
updateTrailGeometry(props);
|
|
2651
|
+
updateTrailGeometry(props, now);
|
|
2288
2652
|
}
|
|
2289
2653
|
};
|
|
2290
|
-
var
|
|
2654
|
+
var catmullRom = (out, outIdx, p0x, p0y, p0z, p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z, t) => {
|
|
2655
|
+
const t2 = t * t;
|
|
2656
|
+
const t3 = t2 * t;
|
|
2657
|
+
out[outIdx] = 0.5 * (2 * p1x + (-p0x + p2x) * t + (2 * p0x - 5 * p1x + 4 * p2x - p3x) * t2 + (-p0x + 3 * p1x - 3 * p2x + p3x) * t3);
|
|
2658
|
+
out[outIdx + 1] = 0.5 * (2 * p1y + (-p0y + p2y) * t + (2 * p0y - 5 * p1y + 4 * p2y - p3y) * t2 + (-p0y + 3 * p1y - 3 * p2y + p3y) * t3);
|
|
2659
|
+
out[outIdx + 2] = 0.5 * (2 * p1z + (-p0z + p2z) * t + (2 * p0z - 5 * p1z + 4 * p2z - p3z) * t2 + (-p0z + 3 * p1z - 3 * p2z + p3z) * t3);
|
|
2660
|
+
};
|
|
2661
|
+
var clearTrailVertex = (vIdx, cIdx, aIdx, uvIdx, trailPosArr, trailNextArr, trailHalfWidthArr, trailUVArr, trailAlphaArr, trailColorArr, fallbackX, fallbackY, fallbackZ) => {
|
|
2662
|
+
trailPosArr[vIdx] = fallbackX;
|
|
2663
|
+
trailPosArr[vIdx + 1] = fallbackY;
|
|
2664
|
+
trailPosArr[vIdx + 2] = fallbackZ;
|
|
2665
|
+
trailPosArr[vIdx + 3] = fallbackX;
|
|
2666
|
+
trailPosArr[vIdx + 4] = fallbackY;
|
|
2667
|
+
trailPosArr[vIdx + 5] = fallbackZ;
|
|
2668
|
+
trailNextArr[vIdx] = fallbackX;
|
|
2669
|
+
trailNextArr[vIdx + 1] = fallbackY;
|
|
2670
|
+
trailNextArr[vIdx + 2] = fallbackZ;
|
|
2671
|
+
trailNextArr[vIdx + 3] = fallbackX;
|
|
2672
|
+
trailNextArr[vIdx + 4] = fallbackY;
|
|
2673
|
+
trailNextArr[vIdx + 5] = fallbackZ;
|
|
2674
|
+
trailHalfWidthArr[aIdx] = 0;
|
|
2675
|
+
trailHalfWidthArr[aIdx + 1] = 0;
|
|
2676
|
+
trailUVArr[uvIdx] = 0;
|
|
2677
|
+
trailUVArr[uvIdx + 1] = 0;
|
|
2678
|
+
trailUVArr[uvIdx + 2] = 0;
|
|
2679
|
+
trailUVArr[uvIdx + 3] = 0;
|
|
2680
|
+
trailAlphaArr[aIdx] = 0;
|
|
2681
|
+
trailAlphaArr[aIdx + 1] = 0;
|
|
2682
|
+
trailColorArr[cIdx] = 0;
|
|
2683
|
+
trailColorArr[cIdx + 1] = 0;
|
|
2684
|
+
trailColorArr[cIdx + 2] = 0;
|
|
2685
|
+
trailColorArr[cIdx + 3] = 0;
|
|
2686
|
+
trailColorArr[cIdx + 4] = 0;
|
|
2687
|
+
trailColorArr[cIdx + 5] = 0;
|
|
2688
|
+
trailColorArr[cIdx + 6] = 0;
|
|
2689
|
+
trailColorArr[cIdx + 7] = 0;
|
|
2690
|
+
};
|
|
2691
|
+
var writeTrailVertex = (vIdx, cIdx, aIdx, uvIdx, hx, hy, hz, nx, ny, nz, halfWidth, t, alpha, fr, fg, fb, ca, trailPosArr, trailNextArr, trailHalfWidthArr, trailUVArr, trailAlphaArr, trailColorArr) => {
|
|
2692
|
+
trailPosArr[vIdx] = hx;
|
|
2693
|
+
trailPosArr[vIdx + 1] = hy;
|
|
2694
|
+
trailPosArr[vIdx + 2] = hz;
|
|
2695
|
+
trailPosArr[vIdx + 3] = hx;
|
|
2696
|
+
trailPosArr[vIdx + 4] = hy;
|
|
2697
|
+
trailPosArr[vIdx + 5] = hz;
|
|
2698
|
+
trailNextArr[vIdx] = nx;
|
|
2699
|
+
trailNextArr[vIdx + 1] = ny;
|
|
2700
|
+
trailNextArr[vIdx + 2] = nz;
|
|
2701
|
+
trailNextArr[vIdx + 3] = nx;
|
|
2702
|
+
trailNextArr[vIdx + 4] = ny;
|
|
2703
|
+
trailNextArr[vIdx + 5] = nz;
|
|
2704
|
+
trailHalfWidthArr[aIdx] = halfWidth;
|
|
2705
|
+
trailHalfWidthArr[aIdx + 1] = halfWidth;
|
|
2706
|
+
trailUVArr[uvIdx] = 0;
|
|
2707
|
+
trailUVArr[uvIdx + 1] = t;
|
|
2708
|
+
trailUVArr[uvIdx + 2] = 1;
|
|
2709
|
+
trailUVArr[uvIdx + 3] = t;
|
|
2710
|
+
trailAlphaArr[aIdx] = alpha;
|
|
2711
|
+
trailAlphaArr[aIdx + 1] = alpha;
|
|
2712
|
+
trailColorArr[cIdx] = fr;
|
|
2713
|
+
trailColorArr[cIdx + 1] = fg;
|
|
2714
|
+
trailColorArr[cIdx + 2] = fb;
|
|
2715
|
+
trailColorArr[cIdx + 3] = ca;
|
|
2716
|
+
trailColorArr[cIdx + 4] = fr;
|
|
2717
|
+
trailColorArr[cIdx + 5] = fg;
|
|
2718
|
+
trailColorArr[cIdx + 6] = fb;
|
|
2719
|
+
trailColorArr[cIdx + 7] = ca;
|
|
2720
|
+
};
|
|
2721
|
+
var _rawPoints = null;
|
|
2722
|
+
var _rawPointsSize = 0;
|
|
2723
|
+
var _smoothedPoints = null;
|
|
2724
|
+
var _smoothedPointsSize = 0;
|
|
2725
|
+
var _ribbonIndices = null;
|
|
2726
|
+
var _ribbonIndicesSize = 0;
|
|
2727
|
+
var _ribbonCount = 0;
|
|
2728
|
+
var updateTrailGeometry = (props, now) => {
|
|
2291
2729
|
const {
|
|
2292
2730
|
generalData,
|
|
2293
2731
|
trailPositionAttr,
|
|
@@ -2305,13 +2743,23 @@ var updateTrailGeometry = (props) => {
|
|
|
2305
2743
|
const positionHistory = generalData.positionHistory;
|
|
2306
2744
|
const historyIndex = generalData.positionHistoryIndex;
|
|
2307
2745
|
const historyCount = generalData.positionHistoryCount;
|
|
2746
|
+
const sampleTimes = generalData.trailSampleTimes;
|
|
2747
|
+
const lastSampledPos = generalData.trailLastSampledPosition;
|
|
2748
|
+
const prevNormal = generalData.trailPrevNormal;
|
|
2749
|
+
const minVertexDist = trailConfig.minVertexDistance;
|
|
2750
|
+
const minVertexDistSq = minVertexDist * minVertexDist;
|
|
2751
|
+
const maxTime = trailConfig.maxTime;
|
|
2752
|
+
const maxTimeMs = maxTime * 1e3;
|
|
2753
|
+
const useSmoothing = trailConfig.smoothing;
|
|
2754
|
+
const subdivisions = trailConfig.smoothingSubdivisions;
|
|
2755
|
+
const useTwistPrevention = trailConfig.twistPrevention;
|
|
2756
|
+
const ribbonId = trailConfig.ribbonId;
|
|
2308
2757
|
const isActiveArr = ma.isActive.array;
|
|
2309
2758
|
const positionArr = ma.position.array;
|
|
2310
2759
|
const colorRArr = ma.colorR.array;
|
|
2311
2760
|
const colorGArr = ma.colorG.array;
|
|
2312
2761
|
const colorBArr = ma.colorB.array;
|
|
2313
2762
|
const colorAArr = ma.colorA.array;
|
|
2314
|
-
ma.size.array;
|
|
2315
2763
|
const trailPosArr = trailPositionAttr.array;
|
|
2316
2764
|
const trailAlphaArr = trailAlphaAttr.array;
|
|
2317
2765
|
const trailColorArr = trailColorAttr.array;
|
|
@@ -2322,115 +2770,329 @@ var updateTrailGeometry = (props) => {
|
|
|
2322
2770
|
const verticesPerParticle = trailLength * 2;
|
|
2323
2771
|
const creationTimesLength = generalData.creationTimes.length;
|
|
2324
2772
|
let hasUpdates = false;
|
|
2773
|
+
const useRibbon = ribbonId !== void 0;
|
|
2774
|
+
let ribbonLeader = -1;
|
|
2775
|
+
if (useRibbon) {
|
|
2776
|
+
if (!_ribbonIndices || _ribbonIndicesSize < creationTimesLength) {
|
|
2777
|
+
_ribbonIndices = new Uint16Array(creationTimesLength);
|
|
2778
|
+
_ribbonIndicesSize = creationTimesLength;
|
|
2779
|
+
}
|
|
2780
|
+
_ribbonCount = 0;
|
|
2781
|
+
for (let i = 0; i < creationTimesLength; i++) {
|
|
2782
|
+
if (isActiveArr[i]) _ribbonIndices[_ribbonCount++] = i;
|
|
2783
|
+
}
|
|
2784
|
+
for (let i = 1; i < _ribbonCount; i++) {
|
|
2785
|
+
const key = _ribbonIndices[i];
|
|
2786
|
+
const keyTime = generalData.creationTimes[key];
|
|
2787
|
+
let j = i - 1;
|
|
2788
|
+
while (j >= 0 && generalData.creationTimes[_ribbonIndices[j]] > keyTime) {
|
|
2789
|
+
_ribbonIndices[j + 1] = _ribbonIndices[j];
|
|
2790
|
+
j--;
|
|
2791
|
+
}
|
|
2792
|
+
_ribbonIndices[j + 1] = key;
|
|
2793
|
+
}
|
|
2794
|
+
if (_ribbonCount > 0) ribbonLeader = _ribbonIndices[0];
|
|
2795
|
+
}
|
|
2325
2796
|
for (let index = 0; index < creationTimesLength; index++) {
|
|
2326
2797
|
const vertBase = index * verticesPerParticle;
|
|
2327
2798
|
if (isActiveArr[index]) {
|
|
2799
|
+
if (useRibbon && _ribbonCount >= 2 && index !== ribbonLeader) {
|
|
2800
|
+
const posIdx2 = index * 3;
|
|
2801
|
+
const px2 = positionArr[posIdx2];
|
|
2802
|
+
const py2 = positionArr[posIdx2 + 1];
|
|
2803
|
+
const pz2 = positionArr[posIdx2 + 2];
|
|
2804
|
+
const histBase = (index * trailLength + historyIndex[index]) * 3;
|
|
2805
|
+
positionHistory[histBase] = px2;
|
|
2806
|
+
positionHistory[histBase + 1] = py2;
|
|
2807
|
+
positionHistory[histBase + 2] = pz2;
|
|
2808
|
+
if (sampleTimes) {
|
|
2809
|
+
sampleTimes[index * trailLength + historyIndex[index]] = now;
|
|
2810
|
+
}
|
|
2811
|
+
historyIndex[index] = (historyIndex[index] + 1) % trailLength;
|
|
2812
|
+
if (historyCount[index] < trailLength) historyCount[index]++;
|
|
2813
|
+
continue;
|
|
2814
|
+
}
|
|
2328
2815
|
hasUpdates = true;
|
|
2329
2816
|
const posIdx = index * 3;
|
|
2330
2817
|
const px = positionArr[posIdx];
|
|
2331
2818
|
const py = positionArr[posIdx + 1];
|
|
2332
2819
|
const pz = positionArr[posIdx + 2];
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2820
|
+
let shouldSample = true;
|
|
2821
|
+
if (minVertexDist > 0 && lastSampledPos && historyCount[index] > 0) {
|
|
2822
|
+
const lsIdx = index * 3;
|
|
2823
|
+
const dx = px - lastSampledPos[lsIdx];
|
|
2824
|
+
const dy = py - lastSampledPos[lsIdx + 1];
|
|
2825
|
+
const dz = pz - lastSampledPos[lsIdx + 2];
|
|
2826
|
+
if (dx * dx + dy * dy + dz * dz < minVertexDistSq) {
|
|
2827
|
+
shouldSample = false;
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
if (shouldSample) {
|
|
2831
|
+
const histBase = (index * trailLength + historyIndex[index]) * 3;
|
|
2832
|
+
positionHistory[histBase] = px;
|
|
2833
|
+
positionHistory[histBase + 1] = py;
|
|
2834
|
+
positionHistory[histBase + 2] = pz;
|
|
2835
|
+
if (sampleTimes) {
|
|
2836
|
+
sampleTimes[index * trailLength + historyIndex[index]] = now;
|
|
2837
|
+
}
|
|
2838
|
+
historyIndex[index] = (historyIndex[index] + 1) % trailLength;
|
|
2839
|
+
if (historyCount[index] < trailLength) historyCount[index]++;
|
|
2840
|
+
if (lastSampledPos) {
|
|
2841
|
+
const lsIdx = index * 3;
|
|
2842
|
+
lastSampledPos[lsIdx] = px;
|
|
2843
|
+
lastSampledPos[lsIdx + 1] = py;
|
|
2844
|
+
lastSampledPos[lsIdx + 2] = pz;
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
let rawCount = historyCount[index];
|
|
2848
|
+
let effectiveCount = rawCount;
|
|
2849
|
+
if (maxTime > 0 && sampleTimes && rawCount > 0) {
|
|
2850
|
+
const sampleBase = index * trailLength;
|
|
2851
|
+
effectiveCount = 0;
|
|
2852
|
+
for (let s = 0; s < rawCount; s++) {
|
|
2853
|
+
const sampleSlot = (historyIndex[index] - 1 - s + trailLength * 2) % trailLength;
|
|
2854
|
+
const age = now - sampleTimes[sampleBase + sampleSlot];
|
|
2855
|
+
if (age <= maxTimeMs) {
|
|
2856
|
+
effectiveCount++;
|
|
2857
|
+
} else {
|
|
2858
|
+
break;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
const count = effectiveCount;
|
|
2340
2863
|
const ribbonWidth = trailConfig.width;
|
|
2341
2864
|
const cr = colorRArr[index];
|
|
2342
2865
|
const cg = colorGArr[index];
|
|
2343
2866
|
const cb = colorBArr[index];
|
|
2344
2867
|
const ca = colorAArr[index];
|
|
2345
2868
|
const ringOff = index * trailLength * 3;
|
|
2869
|
+
const rawPtsSize = count * 3;
|
|
2870
|
+
if (!_rawPoints || _rawPointsSize < rawPtsSize) {
|
|
2871
|
+
_rawPoints = new Float32Array(rawPtsSize);
|
|
2872
|
+
_rawPointsSize = rawPtsSize;
|
|
2873
|
+
}
|
|
2874
|
+
const rawPts = _rawPoints;
|
|
2875
|
+
for (let s = 0; s < count; s++) {
|
|
2876
|
+
const histSlot = (historyIndex[index] - 1 - s + trailLength * 2) % trailLength * 3 + ringOff;
|
|
2877
|
+
rawPts[s * 3] = positionHistory[histSlot];
|
|
2878
|
+
rawPts[s * 3 + 1] = positionHistory[histSlot + 1];
|
|
2879
|
+
rawPts[s * 3 + 2] = positionHistory[histSlot + 2];
|
|
2880
|
+
}
|
|
2881
|
+
let finalPts;
|
|
2882
|
+
let finalCount;
|
|
2883
|
+
if (useSmoothing && count >= 3) {
|
|
2884
|
+
const segmentCount = count - 1;
|
|
2885
|
+
finalCount = segmentCount * subdivisions + 1;
|
|
2886
|
+
const neededSize = finalCount * 3;
|
|
2887
|
+
if (!_smoothedPoints || _smoothedPointsSize < neededSize) {
|
|
2888
|
+
_smoothedPoints = new Float32Array(neededSize);
|
|
2889
|
+
_smoothedPointsSize = neededSize;
|
|
2890
|
+
}
|
|
2891
|
+
finalPts = _smoothedPoints;
|
|
2892
|
+
for (let seg = 0; seg < segmentCount; seg++) {
|
|
2893
|
+
const i0 = Math.max(0, seg - 1);
|
|
2894
|
+
const i1 = seg;
|
|
2895
|
+
const i2 = Math.min(count - 1, seg + 1);
|
|
2896
|
+
const i3 = Math.min(count - 1, seg + 2);
|
|
2897
|
+
const p0x = rawPts[i0 * 3], p0y = rawPts[i0 * 3 + 1], p0z = rawPts[i0 * 3 + 2];
|
|
2898
|
+
const p1x = rawPts[i1 * 3], p1y = rawPts[i1 * 3 + 1], p1z = rawPts[i1 * 3 + 2];
|
|
2899
|
+
const p2x = rawPts[i2 * 3], p2y = rawPts[i2 * 3 + 1], p2z = rawPts[i2 * 3 + 2];
|
|
2900
|
+
const p3x = rawPts[i3 * 3], p3y = rawPts[i3 * 3 + 1], p3z = rawPts[i3 * 3 + 2];
|
|
2901
|
+
for (let sub = 0; sub < subdivisions; sub++) {
|
|
2902
|
+
const t = sub / subdivisions;
|
|
2903
|
+
const outIdx = (seg * subdivisions + sub) * 3;
|
|
2904
|
+
catmullRom(
|
|
2905
|
+
finalPts,
|
|
2906
|
+
outIdx,
|
|
2907
|
+
p0x,
|
|
2908
|
+
p0y,
|
|
2909
|
+
p0z,
|
|
2910
|
+
p1x,
|
|
2911
|
+
p1y,
|
|
2912
|
+
p1z,
|
|
2913
|
+
p2x,
|
|
2914
|
+
p2y,
|
|
2915
|
+
p2z,
|
|
2916
|
+
p3x,
|
|
2917
|
+
p3y,
|
|
2918
|
+
p3z,
|
|
2919
|
+
t
|
|
2920
|
+
);
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
const lastOutIdx = (finalCount - 1) * 3;
|
|
2924
|
+
finalPts[lastOutIdx] = rawPts[(count - 1) * 3];
|
|
2925
|
+
finalPts[lastOutIdx + 1] = rawPts[(count - 1) * 3 + 1];
|
|
2926
|
+
finalPts[lastOutIdx + 2] = rawPts[(count - 1) * 3 + 2];
|
|
2927
|
+
} else {
|
|
2928
|
+
finalPts = rawPts;
|
|
2929
|
+
finalCount = count;
|
|
2930
|
+
}
|
|
2931
|
+
if (finalCount > trailLength) finalCount = trailLength;
|
|
2932
|
+
if (useSmoothing && finalCount >= 2) {
|
|
2933
|
+
const MIN_SEG_DIST_SQ = 1e-4 * 1e-4;
|
|
2934
|
+
for (let d = 1; d < finalCount; d++) {
|
|
2935
|
+
const pi = (d - 1) * 3;
|
|
2936
|
+
const ci = d * 3;
|
|
2937
|
+
const dx = finalPts[ci] - finalPts[pi];
|
|
2938
|
+
const dy = finalPts[ci + 1] - finalPts[pi + 1];
|
|
2939
|
+
const dz = finalPts[ci + 2] - finalPts[pi + 2];
|
|
2940
|
+
if (dx * dx + dy * dy + dz * dz < MIN_SEG_DIST_SQ) {
|
|
2941
|
+
finalPts[ci] = finalPts[pi];
|
|
2942
|
+
finalPts[ci + 1] = finalPts[pi + 1];
|
|
2943
|
+
finalPts[ci + 2] = finalPts[pi + 2];
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2346
2947
|
for (let s = 0; s < trailLength; s++) {
|
|
2347
2948
|
const vIdx = (vertBase + s * 2) * 3;
|
|
2348
2949
|
const cIdx = (vertBase + s * 2) * 4;
|
|
2349
2950
|
const aIdx = vertBase + s * 2;
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
trailUVArr[uvIdx2 + 1] = 0;
|
|
2368
|
-
trailUVArr[uvIdx2 + 2] = 0;
|
|
2369
|
-
trailUVArr[uvIdx2 + 3] = 0;
|
|
2370
|
-
trailAlphaArr[aIdx] = 0;
|
|
2371
|
-
trailAlphaArr[aIdx + 1] = 0;
|
|
2372
|
-
trailColorArr[cIdx] = 0;
|
|
2373
|
-
trailColorArr[cIdx + 1] = 0;
|
|
2374
|
-
trailColorArr[cIdx + 2] = 0;
|
|
2375
|
-
trailColorArr[cIdx + 3] = 0;
|
|
2376
|
-
trailColorArr[cIdx + 4] = 0;
|
|
2377
|
-
trailColorArr[cIdx + 5] = 0;
|
|
2378
|
-
trailColorArr[cIdx + 6] = 0;
|
|
2379
|
-
trailColorArr[cIdx + 7] = 0;
|
|
2951
|
+
const uvIdxBase = (vertBase + s * 2) * 2;
|
|
2952
|
+
if (s >= finalCount) {
|
|
2953
|
+
clearTrailVertex(
|
|
2954
|
+
vIdx,
|
|
2955
|
+
cIdx,
|
|
2956
|
+
aIdx,
|
|
2957
|
+
uvIdxBase,
|
|
2958
|
+
trailPosArr,
|
|
2959
|
+
trailNextArr,
|
|
2960
|
+
trailHalfWidthArr,
|
|
2961
|
+
trailUVArr,
|
|
2962
|
+
trailAlphaArr,
|
|
2963
|
+
trailColorArr,
|
|
2964
|
+
px,
|
|
2965
|
+
py,
|
|
2966
|
+
pz
|
|
2967
|
+
);
|
|
2380
2968
|
continue;
|
|
2381
2969
|
}
|
|
2382
|
-
const
|
|
2383
|
-
const
|
|
2384
|
-
const
|
|
2385
|
-
const hz = positionHistory[histIdx + 2];
|
|
2970
|
+
const hx = finalPts[s * 3];
|
|
2971
|
+
const hy = finalPts[s * 3 + 1];
|
|
2972
|
+
const hz = finalPts[s * 3 + 2];
|
|
2386
2973
|
let nx, ny, nz;
|
|
2387
|
-
if (s <
|
|
2388
|
-
const
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2974
|
+
if (s > 0 && s < finalCount - 1) {
|
|
2975
|
+
const px2 = finalPts[(s - 1) * 3];
|
|
2976
|
+
const py2 = finalPts[(s - 1) * 3 + 1];
|
|
2977
|
+
const pz2 = finalPts[(s - 1) * 3 + 2];
|
|
2978
|
+
const nx2 = finalPts[(s + 1) * 3];
|
|
2979
|
+
const ny2 = finalPts[(s + 1) * 3 + 1];
|
|
2980
|
+
const nz2 = finalPts[(s + 1) * 3 + 2];
|
|
2981
|
+
const atx = nx2 - px2;
|
|
2982
|
+
const aty = ny2 - py2;
|
|
2983
|
+
const atz = nz2 - pz2;
|
|
2984
|
+
const atLen = Math.sqrt(atx * atx + aty * aty + atz * atz);
|
|
2985
|
+
if (atLen > 1e-4) {
|
|
2986
|
+
nx = hx + atx / atLen;
|
|
2987
|
+
ny = hy + aty / atLen;
|
|
2988
|
+
nz = hz + atz / atLen;
|
|
2989
|
+
} else {
|
|
2990
|
+
nx = finalPts[(s + 1) * 3];
|
|
2991
|
+
ny = finalPts[(s + 1) * 3 + 1];
|
|
2992
|
+
nz = finalPts[(s + 1) * 3 + 2];
|
|
2993
|
+
}
|
|
2994
|
+
} else if (s < finalCount - 1) {
|
|
2995
|
+
nx = finalPts[(s + 1) * 3];
|
|
2996
|
+
ny = finalPts[(s + 1) * 3 + 1];
|
|
2997
|
+
nz = finalPts[(s + 1) * 3 + 2];
|
|
2392
2998
|
} else {
|
|
2393
2999
|
nx = hx;
|
|
2394
3000
|
ny = hy + 1e-3;
|
|
2395
3001
|
nz = hz;
|
|
2396
3002
|
}
|
|
2397
|
-
const t =
|
|
3003
|
+
const t = finalCount > 1 ? s / (finalCount - 1) : 0;
|
|
3004
|
+
let timeFade = 1;
|
|
3005
|
+
if (maxTime > 0 && sampleTimes && effectiveCount > 0) {
|
|
3006
|
+
const rawS = useSmoothing ? Math.min(
|
|
3007
|
+
Math.floor(s / Math.max(finalCount - 1, 1) * (rawCount - 1)),
|
|
3008
|
+
rawCount - 1
|
|
3009
|
+
) : Math.min(s, rawCount - 1);
|
|
3010
|
+
const sampleSlot = (historyIndex[index] - 1 - rawS + trailLength * 2) % trailLength;
|
|
3011
|
+
const sampleBase = index * trailLength;
|
|
3012
|
+
const age = now - sampleTimes[sampleBase + sampleSlot];
|
|
3013
|
+
timeFade = 1 - Math.min(age / maxTimeMs, 1);
|
|
3014
|
+
}
|
|
2398
3015
|
const widthScale = trailWidthCurveFn(t);
|
|
2399
3016
|
const opacityScale = trailOpacityCurveFn(t);
|
|
2400
3017
|
const halfWidth = ribbonWidth * widthScale * 0.5;
|
|
2401
|
-
|
|
2402
|
-
trailPosArr[vIdx + 1] = hy;
|
|
2403
|
-
trailPosArr[vIdx + 2] = hz;
|
|
2404
|
-
trailPosArr[vIdx + 3] = hx;
|
|
2405
|
-
trailPosArr[vIdx + 4] = hy;
|
|
2406
|
-
trailPosArr[vIdx + 5] = hz;
|
|
2407
|
-
trailNextArr[vIdx] = nx;
|
|
2408
|
-
trailNextArr[vIdx + 1] = ny;
|
|
2409
|
-
trailNextArr[vIdx + 2] = nz;
|
|
2410
|
-
trailNextArr[vIdx + 3] = nx;
|
|
2411
|
-
trailNextArr[vIdx + 4] = ny;
|
|
2412
|
-
trailNextArr[vIdx + 5] = nz;
|
|
2413
|
-
trailHalfWidthArr[aIdx] = halfWidth;
|
|
2414
|
-
trailHalfWidthArr[aIdx + 1] = halfWidth;
|
|
2415
|
-
const uvIdx = (vertBase + s * 2) * 2;
|
|
2416
|
-
trailUVArr[uvIdx] = 0;
|
|
2417
|
-
trailUVArr[uvIdx + 1] = t;
|
|
2418
|
-
trailUVArr[uvIdx + 2] = 1;
|
|
2419
|
-
trailUVArr[uvIdx + 3] = t;
|
|
2420
|
-
const alpha = ca * opacityScale;
|
|
2421
|
-
trailAlphaArr[aIdx] = alpha;
|
|
2422
|
-
trailAlphaArr[aIdx + 1] = alpha;
|
|
3018
|
+
const alpha = ca * opacityScale * timeFade;
|
|
2423
3019
|
const fr = trailColorOverTrailFns ? cr * trailColorOverTrailFns.r(t) : cr;
|
|
2424
3020
|
const fg = trailColorOverTrailFns ? cg * trailColorOverTrailFns.g(t) : cg;
|
|
2425
3021
|
const fb = trailColorOverTrailFns ? cb * trailColorOverTrailFns.b(t) : cb;
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
3022
|
+
writeTrailVertex(
|
|
3023
|
+
vIdx,
|
|
3024
|
+
cIdx,
|
|
3025
|
+
aIdx,
|
|
3026
|
+
uvIdxBase,
|
|
3027
|
+
hx,
|
|
3028
|
+
hy,
|
|
3029
|
+
hz,
|
|
3030
|
+
nx,
|
|
3031
|
+
ny,
|
|
3032
|
+
nz,
|
|
3033
|
+
halfWidth,
|
|
3034
|
+
t,
|
|
3035
|
+
alpha,
|
|
3036
|
+
fr,
|
|
3037
|
+
fg,
|
|
3038
|
+
fb,
|
|
3039
|
+
ca,
|
|
3040
|
+
trailPosArr,
|
|
3041
|
+
trailNextArr,
|
|
3042
|
+
trailHalfWidthArr,
|
|
3043
|
+
trailUVArr,
|
|
3044
|
+
trailAlphaArr,
|
|
3045
|
+
trailColorArr
|
|
3046
|
+
);
|
|
3047
|
+
}
|
|
3048
|
+
if (useTwistPrevention && prevNormal && finalCount >= 2) {
|
|
3049
|
+
const nIdx = index * 3;
|
|
3050
|
+
const tx = finalPts[3] - finalPts[0];
|
|
3051
|
+
const ty = finalPts[4] - finalPts[1];
|
|
3052
|
+
const tz = finalPts[5] - finalPts[2];
|
|
3053
|
+
const tLen = Math.sqrt(tx * tx + ty * ty + tz * tz);
|
|
3054
|
+
if (tLen > 1e-4) {
|
|
3055
|
+
const ntx = tx / tLen;
|
|
3056
|
+
const nty = ty / tLen;
|
|
3057
|
+
const ntz = tz / tLen;
|
|
3058
|
+
let upx = 0, upy = 1, upz = 0;
|
|
3059
|
+
const dot = ntx * upx + nty * upy + ntz * upz;
|
|
3060
|
+
if (Math.abs(dot) > 0.999) {
|
|
3061
|
+
upx = 1;
|
|
3062
|
+
upy = 0;
|
|
3063
|
+
upz = 0;
|
|
3064
|
+
}
|
|
3065
|
+
let cnx = nty * upz - ntz * upy;
|
|
3066
|
+
let cny = ntz * upx - ntx * upz;
|
|
3067
|
+
let cnz = ntx * upy - nty * upx;
|
|
3068
|
+
const cnLen = Math.sqrt(cnx * cnx + cny * cny + cnz * cnz);
|
|
3069
|
+
if (cnLen > 1e-4) {
|
|
3070
|
+
cnx /= cnLen;
|
|
3071
|
+
cny /= cnLen;
|
|
3072
|
+
cnz /= cnLen;
|
|
3073
|
+
}
|
|
3074
|
+
const prevNx = prevNormal[nIdx];
|
|
3075
|
+
const prevNy = prevNormal[nIdx + 1];
|
|
3076
|
+
const prevNz = prevNormal[nIdx + 2];
|
|
3077
|
+
const hasPrev = prevNx !== 0 || prevNy !== 0 || prevNz !== 0;
|
|
3078
|
+
if (hasPrev) {
|
|
3079
|
+
const normalDot = cnx * prevNx + cny * prevNy + cnz * prevNz;
|
|
3080
|
+
if (normalDot < 0) {
|
|
3081
|
+
for (let s = 0; s < Math.min(finalCount, trailLength); s++) {
|
|
3082
|
+
const aIdx = vertBase + s * 2;
|
|
3083
|
+
const hw = trailHalfWidthArr[aIdx];
|
|
3084
|
+
trailHalfWidthArr[aIdx] = -hw;
|
|
3085
|
+
trailHalfWidthArr[aIdx + 1] = -hw;
|
|
3086
|
+
}
|
|
3087
|
+
cnx = -cnx;
|
|
3088
|
+
cny = -cny;
|
|
3089
|
+
cnz = -cnz;
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
prevNormal[nIdx] = cnx;
|
|
3093
|
+
prevNormal[nIdx + 1] = cny;
|
|
3094
|
+
prevNormal[nIdx + 2] = cnz;
|
|
3095
|
+
}
|
|
2434
3096
|
}
|
|
2435
3097
|
} else if (historyCount[index] > 0) {
|
|
2436
3098
|
hasUpdates = true;
|
|
@@ -2440,30 +3102,209 @@ var updateTrailGeometry = (props) => {
|
|
|
2440
3102
|
const vIdx = (vertBase + s * 2) * 3;
|
|
2441
3103
|
const cIdx = (vertBase + s * 2) * 4;
|
|
2442
3104
|
const aIdx = vertBase + s * 2;
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
3105
|
+
const uvIdxBase = (vertBase + s * 2) * 2;
|
|
3106
|
+
clearTrailVertex(
|
|
3107
|
+
vIdx,
|
|
3108
|
+
cIdx,
|
|
3109
|
+
aIdx,
|
|
3110
|
+
uvIdxBase,
|
|
3111
|
+
trailPosArr,
|
|
3112
|
+
trailNextArr,
|
|
3113
|
+
trailHalfWidthArr,
|
|
3114
|
+
trailUVArr,
|
|
3115
|
+
trailAlphaArr,
|
|
3116
|
+
trailColorArr,
|
|
3117
|
+
0,
|
|
3118
|
+
0,
|
|
3119
|
+
0
|
|
3120
|
+
);
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
if (useRibbon && _ribbonCount >= 2 && _ribbonIndices) {
|
|
3125
|
+
hasUpdates = true;
|
|
3126
|
+
const leader = _ribbonIndices[0];
|
|
3127
|
+
const leaderVertBase = leader * verticesPerParticle;
|
|
3128
|
+
const controlCount = _ribbonCount;
|
|
3129
|
+
const filledCount = Math.min(
|
|
3130
|
+
trailLength,
|
|
3131
|
+
Math.max(controlCount * 4, controlCount)
|
|
3132
|
+
);
|
|
3133
|
+
const chainSize = filledCount * 3;
|
|
3134
|
+
if (!_rawPoints || _rawPointsSize < chainSize) {
|
|
3135
|
+
_rawPoints = new Float32Array(chainSize);
|
|
3136
|
+
_rawPointsSize = chainSize;
|
|
3137
|
+
}
|
|
3138
|
+
if (controlCount === 2) {
|
|
3139
|
+
const p0Idx = _ribbonIndices[0] * 3;
|
|
3140
|
+
const p1Idx = _ribbonIndices[1] * 3;
|
|
3141
|
+
for (let i = 0; i < filledCount; i++) {
|
|
3142
|
+
const t = i / (filledCount - 1);
|
|
3143
|
+
_rawPoints[i * 3] = positionArr[p0Idx] + t * (positionArr[p1Idx] - positionArr[p0Idx]);
|
|
3144
|
+
_rawPoints[i * 3 + 1] = positionArr[p0Idx + 1] + t * (positionArr[p1Idx + 1] - positionArr[p0Idx + 1]);
|
|
3145
|
+
_rawPoints[i * 3 + 2] = positionArr[p0Idx + 2] + t * (positionArr[p1Idx + 2] - positionArr[p0Idx + 2]);
|
|
3146
|
+
}
|
|
3147
|
+
} else {
|
|
3148
|
+
const segments = controlCount - 1;
|
|
3149
|
+
const ptsPerSeg = Math.max(1, Math.floor((filledCount - 1) / segments));
|
|
3150
|
+
let wi = 0;
|
|
3151
|
+
for (let seg = 0; seg < segments && wi < filledCount; seg++) {
|
|
3152
|
+
const i0 = Math.max(0, seg - 1);
|
|
3153
|
+
const i1 = seg;
|
|
3154
|
+
const i2 = Math.min(controlCount - 1, seg + 1);
|
|
3155
|
+
const i3 = Math.min(controlCount - 1, seg + 2);
|
|
3156
|
+
const p0i = _ribbonIndices[i0] * 3;
|
|
3157
|
+
const p1i = _ribbonIndices[i1] * 3;
|
|
3158
|
+
const p2i = _ribbonIndices[i2] * 3;
|
|
3159
|
+
const p3i = _ribbonIndices[i3] * 3;
|
|
3160
|
+
const subCount = seg === segments - 1 ? filledCount - wi : ptsPerSeg;
|
|
3161
|
+
for (let sub = 0; sub < subCount && wi < filledCount; sub++) {
|
|
3162
|
+
const t = sub / subCount;
|
|
3163
|
+
catmullRom(
|
|
3164
|
+
_rawPoints,
|
|
3165
|
+
wi * 3,
|
|
3166
|
+
positionArr[p0i],
|
|
3167
|
+
positionArr[p0i + 1],
|
|
3168
|
+
positionArr[p0i + 2],
|
|
3169
|
+
positionArr[p1i],
|
|
3170
|
+
positionArr[p1i + 1],
|
|
3171
|
+
positionArr[p1i + 2],
|
|
3172
|
+
positionArr[p2i],
|
|
3173
|
+
positionArr[p2i + 1],
|
|
3174
|
+
positionArr[p2i + 2],
|
|
3175
|
+
positionArr[p3i],
|
|
3176
|
+
positionArr[p3i + 1],
|
|
3177
|
+
positionArr[p3i + 2],
|
|
3178
|
+
t
|
|
3179
|
+
);
|
|
3180
|
+
wi++;
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
if (wi > 0) {
|
|
3184
|
+
const lastPIdx = _ribbonIndices[controlCount - 1] * 3;
|
|
3185
|
+
_rawPoints[(wi - 1) * 3] = positionArr[lastPIdx];
|
|
3186
|
+
_rawPoints[(wi - 1) * 3 + 1] = positionArr[lastPIdx + 1];
|
|
3187
|
+
_rawPoints[(wi - 1) * 3 + 2] = positionArr[lastPIdx + 2];
|
|
3188
|
+
}
|
|
3189
|
+
}
|
|
3190
|
+
const leaderCr = colorRArr[leader];
|
|
3191
|
+
const leaderCg = colorGArr[leader];
|
|
3192
|
+
const leaderCb = colorBArr[leader];
|
|
3193
|
+
const leaderCa = colorAArr[leader];
|
|
3194
|
+
for (let s = 0; s < trailLength; s++) {
|
|
3195
|
+
const vIdx = (leaderVertBase + s * 2) * 3;
|
|
3196
|
+
const cIdx = (leaderVertBase + s * 2) * 4;
|
|
3197
|
+
const aIdx = leaderVertBase + s * 2;
|
|
3198
|
+
const uvIdxBase = (leaderVertBase + s * 2) * 2;
|
|
3199
|
+
if (s >= filledCount) {
|
|
3200
|
+
clearTrailVertex(
|
|
3201
|
+
vIdx,
|
|
3202
|
+
cIdx,
|
|
3203
|
+
aIdx,
|
|
3204
|
+
uvIdxBase,
|
|
3205
|
+
trailPosArr,
|
|
3206
|
+
trailNextArr,
|
|
3207
|
+
trailHalfWidthArr,
|
|
3208
|
+
trailUVArr,
|
|
3209
|
+
trailAlphaArr,
|
|
3210
|
+
trailColorArr,
|
|
3211
|
+
0,
|
|
3212
|
+
0,
|
|
3213
|
+
0
|
|
3214
|
+
);
|
|
3215
|
+
continue;
|
|
3216
|
+
}
|
|
3217
|
+
const ptIdx = s * 3;
|
|
3218
|
+
const ptx = _rawPoints[ptIdx];
|
|
3219
|
+
const pty = _rawPoints[ptIdx + 1];
|
|
3220
|
+
const ptz = _rawPoints[ptIdx + 2];
|
|
3221
|
+
let nx, ny, nz;
|
|
3222
|
+
if (s > 0 && s < filledCount - 1) {
|
|
3223
|
+
const px2 = _rawPoints[(s - 1) * 3];
|
|
3224
|
+
const py2 = _rawPoints[(s - 1) * 3 + 1];
|
|
3225
|
+
const pz2 = _rawPoints[(s - 1) * 3 + 2];
|
|
3226
|
+
const nx2 = _rawPoints[(s + 1) * 3];
|
|
3227
|
+
const ny2 = _rawPoints[(s + 1) * 3 + 1];
|
|
3228
|
+
const nz2 = _rawPoints[(s + 1) * 3 + 2];
|
|
3229
|
+
const atx = nx2 - px2;
|
|
3230
|
+
const aty = ny2 - py2;
|
|
3231
|
+
const atz = nz2 - pz2;
|
|
3232
|
+
const atLen = Math.sqrt(atx * atx + aty * aty + atz * atz);
|
|
3233
|
+
if (atLen > 1e-4) {
|
|
3234
|
+
nx = ptx + atx / atLen;
|
|
3235
|
+
ny = pty + aty / atLen;
|
|
3236
|
+
nz = ptz + atz / atLen;
|
|
3237
|
+
} else {
|
|
3238
|
+
nx = _rawPoints[(s + 1) * 3];
|
|
3239
|
+
ny = _rawPoints[(s + 1) * 3 + 1];
|
|
3240
|
+
nz = _rawPoints[(s + 1) * 3 + 2];
|
|
3241
|
+
}
|
|
3242
|
+
} else if (s < filledCount - 1) {
|
|
3243
|
+
nx = _rawPoints[(s + 1) * 3];
|
|
3244
|
+
ny = _rawPoints[(s + 1) * 3 + 1];
|
|
3245
|
+
nz = _rawPoints[(s + 1) * 3 + 2];
|
|
3246
|
+
} else {
|
|
3247
|
+
nx = ptx;
|
|
3248
|
+
ny = pty + 1e-3;
|
|
3249
|
+
nz = ptz;
|
|
3250
|
+
}
|
|
3251
|
+
const t = filledCount > 1 ? s / (filledCount - 1) : 0;
|
|
3252
|
+
const widthScale = trailWidthCurveFn(t);
|
|
3253
|
+
const opacityScale = trailOpacityCurveFn(t);
|
|
3254
|
+
const halfWidth = trailConfig.width * widthScale * 0.5;
|
|
3255
|
+
const alpha = leaderCa * opacityScale;
|
|
3256
|
+
const fr = trailColorOverTrailFns ? leaderCr * trailColorOverTrailFns.r(t) : leaderCr;
|
|
3257
|
+
const fg = trailColorOverTrailFns ? leaderCg * trailColorOverTrailFns.g(t) : leaderCg;
|
|
3258
|
+
const fb = trailColorOverTrailFns ? leaderCb * trailColorOverTrailFns.b(t) : leaderCb;
|
|
3259
|
+
writeTrailVertex(
|
|
3260
|
+
vIdx,
|
|
3261
|
+
cIdx,
|
|
3262
|
+
aIdx,
|
|
3263
|
+
uvIdxBase,
|
|
3264
|
+
ptx,
|
|
3265
|
+
pty,
|
|
3266
|
+
ptz,
|
|
3267
|
+
nx,
|
|
3268
|
+
ny,
|
|
3269
|
+
nz,
|
|
3270
|
+
halfWidth,
|
|
3271
|
+
t,
|
|
3272
|
+
alpha,
|
|
3273
|
+
fr,
|
|
3274
|
+
fg,
|
|
3275
|
+
fb,
|
|
3276
|
+
leaderCa,
|
|
3277
|
+
trailPosArr,
|
|
3278
|
+
trailNextArr,
|
|
3279
|
+
trailHalfWidthArr,
|
|
3280
|
+
trailUVArr,
|
|
3281
|
+
trailAlphaArr,
|
|
3282
|
+
trailColorArr
|
|
3283
|
+
);
|
|
3284
|
+
}
|
|
3285
|
+
for (let ri = 1; ri < _ribbonCount; ri++) {
|
|
3286
|
+
const pIdx = _ribbonIndices[ri];
|
|
3287
|
+
const pVertBase = pIdx * verticesPerParticle;
|
|
3288
|
+
for (let s = 0; s < trailLength; s++) {
|
|
3289
|
+
const vIdx = (pVertBase + s * 2) * 3;
|
|
3290
|
+
const cIdx = (pVertBase + s * 2) * 4;
|
|
3291
|
+
const aIdx = pVertBase + s * 2;
|
|
3292
|
+
const uvIdxBase = (pVertBase + s * 2) * 2;
|
|
3293
|
+
clearTrailVertex(
|
|
3294
|
+
vIdx,
|
|
3295
|
+
cIdx,
|
|
3296
|
+
aIdx,
|
|
3297
|
+
uvIdxBase,
|
|
3298
|
+
trailPosArr,
|
|
3299
|
+
trailNextArr,
|
|
3300
|
+
trailHalfWidthArr,
|
|
3301
|
+
trailUVArr,
|
|
3302
|
+
trailAlphaArr,
|
|
3303
|
+
trailColorArr,
|
|
3304
|
+
0,
|
|
3305
|
+
0,
|
|
3306
|
+
0
|
|
3307
|
+
);
|
|
2467
3308
|
}
|
|
2468
3309
|
}
|
|
2469
3310
|
}
|
|
@@ -2491,6 +3332,6 @@ var updateParticleSystems = (cycleData) => {
|
|
|
2491
3332
|
);
|
|
2492
3333
|
};
|
|
2493
3334
|
|
|
2494
|
-
export { CurveFunctionId, EmitFrom, ForceFieldFalloff, ForceFieldType, LifeTimeCurve, RendererType, Shape, SimulationSpace, SubEmitterTrigger, TimeMode, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
|
|
3335
|
+
export { CurveFunctionId, EmitFrom, ForceFieldFalloff, ForceFieldType, LifeTimeCurve, RendererType, Shape, SimulationSpace, SubEmitterTrigger, TimeMode, applyModifiers, blendingMap, calculateRandomPositionAndVelocityOnBox, calculateRandomPositionAndVelocityOnCircle, calculateRandomPositionAndVelocityOnCone, calculateRandomPositionAndVelocityOnRectangle, calculateRandomPositionAndVelocityOnSphere, calculateValue, createBezierCurveFunction, createDefaultMeshTexture, createDefaultParticleTexture, createParticleSystem, curveFunctionIdMap, getBezierCacheSize, getCurveFunction, getCurveFunctionFromConfig, getDefaultParticleSystemConfig, isLifeTimeCurve, removeBezierCurveFunction, updateParticleSystems };
|
|
2495
3336
|
//# sourceMappingURL=index.js.map
|
|
2496
3337
|
//# sourceMappingURL=index.js.map
|