feat(04-01): add Vec3.lerp and ParticleTrail sampler with JUnit suite

- Vec3.lerp(other, t) for linear interpolation between two points
- ParticleTrail.sample(from, to, density) emits density-based interpolated
  points strictly between endpoints (endpoints excluded by construction)
- TRAIL_DENSITY = 4.0 particles per block
- 6 ParticleTrail tests + 3 Vec3.lerp tests, all green
- Zero Hytale imports — chain/ frontier preserved
This commit is contained in:
2026-04-27 13:00:47 +02:00
parent 6f8efa94c5
commit 8d868a28ca
4 changed files with 177 additions and 0 deletions
@@ -0,0 +1,56 @@
package com.mythlane.chainlightning.chain;
import java.util.ArrayList;
import java.util.List;
/**
* Pure-Java sampler for the electric trail between two endpoints.
* <p>
* Produces evenly-spaced interpolated points strictly between {@code from} and
* {@code to}; both endpoints are excluded by construction (the parametric
* interpolation parameter {@code t} never reaches 0 or 1).
* <p>
* Density is expressed in particles per block. The sample count for a given
* segment is {@code ceil(distance * density)}.
* <p>
* This class has ZERO Hytale imports — it lives behind the Phase 2 sealed
* frontier so it can be unit-tested without runtime dependencies.
*/
public final class ParticleTrail {
/** Default trail density in particles per block. */
public static final double TRAIL_DENSITY = 4.0;
private ParticleTrail() {
// utility class — no instances
}
/**
* Sample interpolated points strictly between {@code from} and {@code to}.
* Endpoints are NOT included in the returned list. The list is freshly
* allocated on each call.
*
* @param from start endpoint (excluded from output)
* @param to end endpoint (excluded from output)
* @param density particles per block
* @return newly-allocated list of interpolated points; empty if the
* endpoints coincide or {@code density} produces a non-positive
* count.
*/
public static List<Vec3> sample(Vec3 from, Vec3 to, double density) {
double dist = from.distance(to);
if (dist <= 0) {
return List.of();
}
int count = (int) Math.ceil(dist * density);
if (count <= 0) {
return List.of();
}
List<Vec3> out = new ArrayList<>(count);
for (int i = 1; i <= count; i++) {
double t = (double) i / (count + 1);
out.add(from.lerp(to, t));
}
return out;
}
}
@@ -22,4 +22,13 @@ public record Vec3(double x, double y, double z) {
public double distance(Vec3 other) {
return Math.sqrt(distanceSquared(other));
}
/** Linear interpolation: t=0 returns this, t=1 returns other. */
public Vec3 lerp(Vec3 other, double t) {
return new Vec3(
this.x + (other.x - this.x) * t,
this.y + (other.y - this.y) * t,
this.z + (other.z - this.z) * t
);
}
}