forked from phenom/healer-man
68 lines
2.6 KiB
TypeScript
68 lines
2.6 KiB
TypeScript
import { useGLTF } from "@react-three/drei";
|
|
import { useThree } from "@react-three/fiber";
|
|
import { useCallback, type ReactNode } from "react";
|
|
import type { WebGLRenderer } from "three";
|
|
import { KTX2Loader, type GLTFLoader } from "three-stdlib";
|
|
import { resolveContentUrl } from "../content/contentManager";
|
|
import { configureRunewakerTerrainLoader } from "./runewakerTerrainMaterial";
|
|
import { configureRunewakerSurfaceDetailLoader } from "./runewakerSurfaceDetailMaterial";
|
|
import { configureRunewakerWaterLoader } from "./runewakerWaterMaterial";
|
|
import { configureWowTerrainLoader } from "./wowTerrainMaterial";
|
|
|
|
export const KTX2_TRANSCODER_PATH = `${import.meta.env.BASE_URL}basis/`;
|
|
|
|
const ktx2Loaders = new WeakMap<WebGLRenderer, KTX2Loader>();
|
|
|
|
function ktx2LoaderFor(renderer: WebGLRenderer): KTX2Loader {
|
|
const cached = ktx2Loaders.get(renderer);
|
|
if (cached) return cached;
|
|
|
|
const loader = new KTX2Loader();
|
|
loader.setTranscoderPath(KTX2_TRANSCODER_PATH);
|
|
loader.detectSupport(renderer);
|
|
ktx2Loaders.set(renderer, loader);
|
|
return loader;
|
|
}
|
|
|
|
/**
|
|
* Marks the part of a Canvas that shares its GLTF decoder. KTX2Loader instances
|
|
* intentionally live with their weakly referenced renderer: disposing one from
|
|
* React cleanup can abort a GLB that is still decoding or cached by useGLTF.
|
|
*/
|
|
export function GameGltfLoaderLifecycle({ children }: { readonly children: ReactNode }) {
|
|
return children;
|
|
}
|
|
|
|
/**
|
|
* Loads shipped world and creature GLBs with Meshopt and KTX2 support.
|
|
* Keeping one KTX2Loader per renderer also keeps Three from creating a worker
|
|
* pool for every mounted model.
|
|
*/
|
|
export function useGameGLTF(url: string) {
|
|
const resolvedUrl = resolveContentUrl(url);
|
|
const renderer = useThree((state) => state.gl);
|
|
const extendLoader = useCallback((loader: GLTFLoader) => {
|
|
loader.setKTX2Loader(ktx2LoaderFor(renderer));
|
|
configureRunewakerTerrainLoader(loader);
|
|
configureRunewakerSurfaceDetailLoader(loader);
|
|
configureRunewakerWaterLoader(loader);
|
|
configureWowTerrainLoader(loader);
|
|
}, [renderer]);
|
|
|
|
return useGLTF(resolvedUrl, false, true, extendLoader);
|
|
}
|
|
|
|
export function useGameGLTFs(urls: readonly string[]) {
|
|
const resolvedUrls = urls.map(resolveContentUrl);
|
|
const renderer = useThree((state) => state.gl);
|
|
const extendLoader = useCallback((loader: GLTFLoader) => {
|
|
loader.setKTX2Loader(ktx2LoaderFor(renderer));
|
|
configureRunewakerTerrainLoader(loader);
|
|
configureRunewakerSurfaceDetailLoader(loader);
|
|
configureRunewakerWaterLoader(loader);
|
|
configureWowTerrainLoader(loader);
|
|
}, [renderer]);
|
|
|
|
return useGLTF(resolvedUrls, false, true, extendLoader);
|
|
}
|