Back to Poly Dogfight
SOURCE / PINNED RELEASE

Made of little things.

Poly Dogfight

Release
b8511ee374e3…
Author-recorded commit
5579434b9d8b…
License
LICENSE
Author’s source reference
nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.napplet.soy%2F/n-44f63e5422b

Archive hash verified: bcadd2430d8ea2bc…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

src/world/geometry.ts
import { BufferAttribute, Color, Euler, Matrix4, Quaternion, Vector3, type BufferGeometry } from 'three';
import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';

/** Translate/rotate/scale helper for composing low-poly parts. */
export function T(x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0, sx = 1, sy = sx, sz = sx): Matrix4 {
  return new Matrix4().compose(
    new Vector3(x, y, z),
    new Quaternion().setFromEuler(new Euler(rx, ry, rz)),
    new Vector3(sx, sy, sz),
  );
}

/** A flat-coloured, non-indexed part ready for merging (position + color only). */
export function part(geometry: BufferGeometry, color: number, matrix?: Matrix4, jitter = 0): BufferGeometry {
  const g = geometry.index ? geometry.toNonIndexed() : geometry;
  g.deleteAttribute('uv');
  g.deleteAttribute('normal');
  if (matrix) g.applyMatrix4(matrix);
  const pos = g.getAttribute('position') as BufferAttribute;
  if (jitter > 0) {
    // Deterministic per-vertex wobble keyed by position, so shared corners stay shared.
    for (let i = 0; i < pos.count; i++) {
      const x = pos.getX(i);
      const y = pos.getY(i);
      const z = pos.getZ(i);
      const n = Math.sin(x * 12.9898 + y * 78.233 + z * 37.719) * 43758.5453;
      const m = Math.sin(x * 93.989 + y * 67.345 + z * 11.135) * 24634.6345;
      pos.setXYZ(i, x + (n - Math.floor(n) - 0.5) * jitter, y, z + (m - Math.floor(m) - 0.5) * jitter);
    }
  }
  const c = new Color(color);
  const colors = new Float32Array(pos.count * 3);
  for (let i = 0; i < pos.count; i++) {
    colors[i * 3] = c.r;
    colors[i * 3 + 1] = c.g;
    colors[i * 3 + 2] = c.b;
  }
  g.setAttribute('color', new BufferAttribute(colors, 3));
  return g;
}

export function merge(parts: BufferGeometry[]): BufferGeometry {
  const merged = mergeGeometries(parts, false);
  if (!merged) throw new Error('Could not merge geometry parts');
  merged.computeBoundingSphere();
  return merged;
}