fix: runtime Box3 scaling + Alpine null-safety

- Replaced hardcoded SPECIES_LENGTH with runtime Box3 measurement
  (model added to parent group BEFORE measuring, so full GLB
  hierarchy transforms are included in world matrices)
- All 9 species now render at correct target size (0.13-0.32u)
- Added optional chaining (?.) to all Alpine template expressions
  referencing store.selectedFish to prevent null-reference errors
- Guarded getFishValue/canBreed calls with null checks
This commit is contained in:
2026-10-08 17:03:37 +00:00
parent 20ab0e91e4
commit 0f360d76cd
3 changed files with 23 additions and 66 deletions
-17
View File
@@ -59,27 +59,10 @@ function getSpeciesUrl(sp: FishSpecies): string {
};
return urls[sp];
}
// Per-species true longest rendered extent (model units), measured
// offline with scripts/measure-models.mjs (stride-safe rest-pose +
// swim-clip evaluation of the actual GLB data). Fish are scaled by
// targetLength / modelLength. This replaces the old
// Box3.setFromObject auto-measure, which under-reports armature-scaled
const SPECIES_LENGTH: Record<FishSpecies, number> = {
angelfish: 4.2139,
goldfish: 1.7386,
guppy: 2.8070,
betta: 1.0228,
blue_tang: 1.0192,
flower_horn: 1.0516,
neon_tetra: 3.6548,
oscar: 8.8411,
knifefish: 23.0140,
};
function fishToSpec(f: FishData): FishSpec {
return {
url: getSpeciesUrl(f.species),
targetLength: f.genetics.sizeMult * 0.5,
modelLength: SPECIES_LENGTH[f.species],
speed: [0.3 * f.genetics.speedMult, 0.7 * f.genetics.speedMult],
orient: isQuaternius(f.species) ? { y: Math.PI / 2 } : undefined,
genetics: f.genetics,