import * as THREE from 'three'; import type { TTSObject } from '@tts/shared'; /** * The per-object tint (`ColorDiffuse`, 0–1 per channel) as a three.js color, * defaulting to white when absent. TTS multiplies this by the object's base * color, so textured faces are tinted too. */ export function objectTint(object: TTSObject): THREE.Color { const c = object.ColorDiffuse; return c ? new THREE.Color(c.r, c.g, c.b) : new THREE.Color(1, 1, 1); } /** A stable cache key fragment for a tint, so tinted variants don't collide. */ export function tintKey(color: THREE.Color): string { return `${color.r},${color.g},${color.b}`; } /** Multiply a base color by the object's tint. */ export function tintedColor(base: THREE.Color, tint: THREE.Color): THREE.Color { return base.clone().multiply(tint); } /** * Module-level caches so the full-setup view can share geometry and materials * across many objects instead of rebuilding them per object. Keyed by a * canonical string describing the resource, so identical objects reuse one * instance. drei already caches textures globally by URL, so sharing the * material on top avoids per-object material allocation for tiles/tokens with * the same image. * * These caches live for the session (like drei's global texture cache) and are * not disposed on unmount; see `docs/status/full-setup-view.md`. */ const geometryCache = new Map(); const materialCache = new Map(); /** Get or create a geometry for `key`. */ export function getSharedGeometry( key: string, build: () => THREE.BufferGeometry, ): THREE.BufferGeometry { let geo = geometryCache.get(key); if (!geo) { geo = build(); geometryCache.set(key, geo); } return geo; } /** Get or create a standard material for `key`. */ export function getSharedMaterial( key: string, params: THREE.MeshStandardMaterialParameters, ): THREE.MeshStandardMaterial { let mat = materialCache.get(key); if (!mat) { mat = new THREE.MeshStandardMaterial(params); materialCache.set(key, mat); } return mat; }