@cazala/party 0.1.0-next.43.f9fb257 → 0.1.0-next.45.433a20a

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/dist/index.js CHANGED
@@ -5720,15 +5720,11 @@ class Boundary extends Module {
5720
5720
  webgpu() {
5721
5721
  return {
5722
5722
  apply: ({ particleVar, getUniform }) => `{
5723
- // Bounce using global grid extents
5724
5723
  let halfSize = ${particleVar}.size;
5725
5724
  let minX = GRID_MINX();
5726
5725
  let maxX = GRID_MAXX();
5727
5726
  let minY = GRID_MINY();
5728
5727
  let maxY = GRID_MAXY();
5729
- let bounce = ${getUniform("restitution")};
5730
- let friction = ${getUniform("friction")};
5731
- let mode = ${getUniform("mode")};
5732
5728
  let repelDist = ${getUniform("repelDistance")};
5733
5729
  let repelStrength = ${getUniform("repelStrength")};
5734
5730
 
@@ -5773,34 +5769,54 @@ class Boundary extends Module {
5773
5769
  }
5774
5770
  ${particleVar}.acceleration += vec2<f32>(fx, fy);
5775
5771
  }
5772
+ }`,
5773
+ correct: ({ particleVar, prevPosVar, postPosVar, getUniform }) => `{
5774
+ // Resolve boundaries post-integration to reduce dt-dependent jitter.
5775
+ // We use prev/post integration positions (SIM_STATE) to detect crossings.
5776
+ let halfSize = ${particleVar}.size;
5777
+ let minX = GRID_MINX();
5778
+ let maxX = GRID_MAXX();
5779
+ let minY = GRID_MINY();
5780
+ let maxY = GRID_MAXY();
5781
+ let bounce = ${getUniform("restitution")};
5782
+ let friction = ${getUniform("friction")};
5783
+ let mode = ${getUniform("mode")};
5784
+
5785
+ let prevPos = ${prevPosVar};
5786
+ let postPos = ${postPosVar};
5787
+ var vel = ${particleVar}.velocity;
5776
5788
 
5777
5789
  if (mode == 0.0) {
5778
- // bounce
5779
- // X axis
5780
- if (${particleVar}.position.x - halfSize < minX) {
5790
+ // bounce (CCD-ish using prev/post)
5791
+ // Left wall
5792
+ if (postPos.x - halfSize < minX) {
5781
5793
  ${particleVar}.position.x = minX + halfSize;
5782
- ${particleVar}.velocity.x = -${particleVar}.velocity.x * bounce;
5783
- ${particleVar}.velocity.y *= max(0.0, 1.0 - friction);
5784
- } else if (${particleVar}.position.x + halfSize > maxX) {
5794
+ if (vel.x < 0.0) { vel.x = -vel.x * bounce; }
5795
+ vel.y = vel.y * max(0.0, 1.0 - friction);
5796
+ }
5797
+ // Right wall
5798
+ else if (postPos.x + halfSize > maxX) {
5785
5799
  ${particleVar}.position.x = maxX - halfSize;
5786
- ${particleVar}.velocity.x = -${particleVar}.velocity.x * bounce;
5787
- ${particleVar}.velocity.y *= max(0.0, 1.0 - friction);
5800
+ if (vel.x > 0.0) { vel.x = -vel.x * bounce; }
5801
+ vel.y = vel.y * max(0.0, 1.0 - friction);
5788
5802
  }
5789
5803
 
5790
- // Y axis
5791
- if (${particleVar}.position.y - halfSize < minY) {
5804
+ // Top
5805
+ if (postPos.y - halfSize < minY) {
5792
5806
  ${particleVar}.position.y = minY + halfSize;
5793
- ${particleVar}.velocity.y = -${particleVar}.velocity.y * bounce;
5794
- ${particleVar}.velocity.x *= max(0.0, 1.0 - friction);
5795
- } else if (${particleVar}.position.y + halfSize > maxY) {
5807
+ if (vel.y < 0.0) { vel.y = -vel.y * bounce; }
5808
+ vel.x = vel.x * max(0.0, 1.0 - friction);
5809
+ }
5810
+ // Bottom (floor)
5811
+ else if (postPos.y + halfSize > maxY) {
5796
5812
  ${particleVar}.position.y = maxY - halfSize;
5797
- ${particleVar}.velocity.y = -${particleVar}.velocity.y * bounce;
5798
- ${particleVar}.velocity.x *= max(0.0, 1.0 - friction);
5813
+ if (vel.y > 0.0) { vel.y = -vel.y * bounce; }
5814
+ vel.x = vel.x * max(0.0, 1.0 - friction);
5799
5815
  }
5816
+ ${particleVar}.velocity = vel;
5800
5817
  } else if (mode == 1.0) {
5801
- // warp
5802
- // Only warp once the particle is fully outside the bounds
5803
- let eps = 1.0; // spawn just outside the opposite edge so it slides in
5818
+ // warp (post-integration)
5819
+ let eps = 1.0;
5804
5820
  if (${particleVar}.position.x + halfSize < minX) {
5805
5821
  ${particleVar}.position.x = maxX + halfSize + eps;
5806
5822
  } else if (${particleVar}.position.x - halfSize > maxX) {
@@ -5812,24 +5828,15 @@ class Boundary extends Module {
5812
5828
  ${particleVar}.position.y = minY - halfSize - eps;
5813
5829
  }
5814
5830
  } else if (mode == 2.0) {
5815
- // kill
5816
- // Only kill once the particle is fully outside the bounds
5817
- if (${particleVar}.position.x - halfSize < minX) {
5818
- ${particleVar}.position.x = minX - halfSize * 4;
5819
- ${particleVar}.mass = 0.0;
5820
- } else if (${particleVar}.position.x + halfSize > maxX) {
5821
- ${particleVar}.position.x = maxX + halfSize * 4;
5831
+ // kill (post-integration)
5832
+ if (${particleVar}.position.x + halfSize < minX ||
5833
+ ${particleVar}.position.x - halfSize > maxX ||
5834
+ ${particleVar}.position.y + halfSize < minY ||
5835
+ ${particleVar}.position.y - halfSize > maxY) {
5822
5836
  ${particleVar}.mass = 0.0;
5823
5837
  }
5824
- if (${particleVar}.position.y - halfSize < minY) {
5825
- ${particleVar}.position.y = minY - halfSize * 4;
5826
- ${particleVar}.mass = 0.0;
5827
- } else if (${particleVar}.position.y + halfSize > maxY) {
5828
- ${particleVar}.position.y = maxY + halfSize * 4;
5829
- ${particleVar}.mass = 0.0;
5830
- }
5831
5838
  } else if (mode == 3.0) {
5832
- // none: no boundary constraints; repel force above still applies
5839
+ // none
5833
5840
  }
5834
5841
  }`,
5835
5842
  };
@@ -5848,9 +5855,6 @@ class Boundary extends Module {
5848
5855
  const minY = camera.y - halfH;
5849
5856
  const maxY = camera.y + halfH;
5850
5857
  const halfSize = particle.size;
5851
- const bounce = input.restitution;
5852
- const friction = input.friction;
5853
- const mode = input.mode;
5854
5858
  const repelDist = input.repelDistance;
5855
5859
  const repelStrength = input.repelStrength;
5856
5860
  // Repel force applied for all modes
@@ -5901,35 +5905,52 @@ class Boundary extends Module {
5901
5905
  }
5902
5906
  particle.acceleration.add(new Vector(fx, fy));
5903
5907
  }
5908
+ },
5909
+ correct: ({ particle, input, view }) => {
5910
+ // Resolve boundaries post-integration to reduce dt-dependent jitter.
5911
+ const camera = view.getCamera();
5912
+ const zoom = Math.max(view.getZoom(), 0.0001);
5913
+ const size = view.getSize();
5914
+ const halfW = size.width / (2 * zoom);
5915
+ const halfH = size.height / (2 * zoom);
5916
+ const minX = camera.x - halfW;
5917
+ const maxX = camera.x + halfW;
5918
+ const minY = camera.y - halfH;
5919
+ const maxY = camera.y + halfH;
5920
+ const halfSize = particle.size;
5921
+ const bounce = input.restitution;
5922
+ const friction = input.friction;
5923
+ const mode = input.mode;
5904
5924
  if (mode === 0) {
5905
5925
  // bounce
5906
- // X axis
5907
5926
  if (particle.position.x - halfSize < minX) {
5908
5927
  particle.position.x = minX + halfSize;
5909
- particle.velocity.x = -particle.velocity.x * bounce;
5928
+ if (particle.velocity.x < 0)
5929
+ particle.velocity.x = -particle.velocity.x * bounce;
5910
5930
  particle.velocity.y *= Math.max(0, 1 - friction);
5911
5931
  }
5912
5932
  else if (particle.position.x + halfSize > maxX) {
5913
5933
  particle.position.x = maxX - halfSize;
5914
- particle.velocity.x = -particle.velocity.x * bounce;
5934
+ if (particle.velocity.x > 0)
5935
+ particle.velocity.x = -particle.velocity.x * bounce;
5915
5936
  particle.velocity.y *= Math.max(0, 1 - friction);
5916
5937
  }
5917
- // Y axis
5918
5938
  if (particle.position.y - halfSize < minY) {
5919
5939
  particle.position.y = minY + halfSize;
5920
- particle.velocity.y = -particle.velocity.y * bounce;
5940
+ if (particle.velocity.y < 0)
5941
+ particle.velocity.y = -particle.velocity.y * bounce;
5921
5942
  particle.velocity.x *= Math.max(0, 1 - friction);
5922
5943
  }
5923
5944
  else if (particle.position.y + halfSize > maxY) {
5924
5945
  particle.position.y = maxY - halfSize;
5925
- particle.velocity.y = -particle.velocity.y * bounce;
5946
+ if (particle.velocity.y > 0)
5947
+ particle.velocity.y = -particle.velocity.y * bounce;
5926
5948
  particle.velocity.x *= Math.max(0, 1 - friction);
5927
5949
  }
5928
5950
  }
5929
5951
  else if (mode === 1) {
5930
5952
  // warp
5931
- // Only warp once the particle is fully outside the bounds
5932
- const eps = 1; // spawn just outside the opposite edge so it slides in
5953
+ const eps = 1;
5933
5954
  if (particle.position.x + halfSize < minX) {
5934
5955
  particle.position.x = maxX + halfSize + eps;
5935
5956
  }
@@ -5945,7 +5966,6 @@ class Boundary extends Module {
5945
5966
  }
5946
5967
  else if (mode === 2) {
5947
5968
  // kill
5948
- // Only kill once the particle is fully outside the bounds
5949
5969
  if (particle.position.x + halfSize < minX ||
5950
5970
  particle.position.x - halfSize > maxX ||
5951
5971
  particle.position.y + halfSize < minY ||
@@ -5953,7 +5973,6 @@ class Boundary extends Module {
5953
5973
  particle.mass = 0;
5954
5974
  }
5955
5975
  }
5956
- else ;
5957
5976
  },
5958
5977
  };
5959
5978
  }