perf: applique les échelles aux assets instanciés

This commit is contained in:
tom-boullay
2026-05-28 15:49:26 +02:00
parent 0b3d49e8d1
commit fcdbf7270c
3 changed files with 48 additions and 18 deletions
+22 -4
View File
@@ -7,12 +7,13 @@ import {
normalizeMapScale,
useTerrainHeightSampler,
} from "@/hooks/three/useTerrainHeight";
import type { MapAssetInstance } from "@/hooks/world/useMapInstancingData";
import type { MapAssetInstance } from "@/types/map/mapScene";
import { optimizeGLTFSceneTextures } from "@/utils/three/optimizeGLTFScene";
interface InstancedMapAssetProps {
modelPath: string;
instances: MapAssetInstance[];
scaleMultiplier: number;
castShadow: boolean;
receiveShadow: boolean;
}
@@ -133,6 +134,7 @@ function extractMeshes(scene: THREE.Group): MeshData[] {
function setInstanceMatrices(
instancedMesh: THREE.InstancedMesh,
instances: MapAssetInstance[],
scaleMultiplier: number,
geometryBottomY: number,
): void {
const position = new THREE.Vector3();
@@ -148,7 +150,11 @@ function setInstanceMatrices(
position.set(...instance.position);
rotation.set(...instance.rotation);
quaternion.setFromEuler(rotation);
scale.set(...instance.scale);
scale.set(
instance.scale[0] * scaleMultiplier,
instance.scale[1] * scaleMultiplier,
instance.scale[2] * scaleMultiplier,
);
position.y += -geometryBottomY * scale.y;
matrix.compose(position, quaternion, scale);
instancedMesh.setMatrixAt(i, matrix);
@@ -174,6 +180,7 @@ function getMeshBottomY(meshDataList: MeshData[]): number {
export function InstancedMapAsset({
modelPath,
instances,
scaleMultiplier,
castShadow,
receiveShadow,
}: InstancedMapAssetProps): React.JSX.Element | null {
@@ -219,7 +226,12 @@ export function InstancedMapAsset({
groundedInstances.length,
);
setInstanceMatrices(instancedMesh, groundedInstances, geometryBottomY);
setInstanceMatrices(
instancedMesh,
groundedInstances,
scaleMultiplier,
geometryBottomY,
);
instancedMesh.castShadow = castShadow;
instancedMesh.receiveShadow = receiveShadow;
instancedMesh.name = `instanced-map-asset-${index}`;
@@ -239,7 +251,13 @@ export function InstancedMapAsset({
disposeInstancedMapMesh(mesh);
}
};
}, [castShadow, groundedInstances, meshDataList, receiveShadow]);
}, [
castShadow,
groundedInstances,
meshDataList,
receiveShadow,
scaleMultiplier,
]);
if (instances.length === 0) {
return null;
@@ -14,10 +14,13 @@ import {
type MapInstancingAssetConfig,
type MapInstancingAssetType,
} from "@/data/world/mapInstancingConfig";
import {
type MapAssetInstance,
useMapInstancingData,
} from "@/hooks/world/useMapInstancingData";
import { useMapInstancingData } from "@/hooks/world/useMapInstancingData";
import type { MapAssetInstance } from "@/types/map/mapScene";
interface MapInstancingSystemProps {
onlyModelName?: string | null;
streaming?: boolean;
}
interface MapAssetChunk {
key: string;
@@ -72,14 +75,20 @@ function createMapAssetChunks(
});
}
export function MapInstancingSystem(): React.JSX.Element | null {
export function MapInstancingSystem({
onlyModelName = null,
streaming = true,
}: MapInstancingSystemProps): React.JSX.Element | null {
const cameraMode = useCameraMode();
const sceneMode = useSceneMode();
const groups = useMapPerformanceStore((state) => state.groups);
const models = useMapPerformanceStore((state) => state.models);
const { data, isLoading } = useMapInstancingData();
const streamingEnabled =
CHUNK_CONFIG.enabled && sceneMode === "game" && cameraMode === "player";
streaming &&
CHUNK_CONFIG.enabled &&
sceneMode === "game" &&
cameraMode === "player";
const chunks = useMemo(() => {
if (!data) return [];
@@ -87,6 +96,8 @@ export function MapInstancingSystem(): React.JSX.Element | null {
return MAP_INSTANCING_ASSET_TYPES.flatMap((type) => {
const config = MAP_INSTANCING_ASSETS[type];
if (onlyModelName && config.mapName !== onlyModelName) return [];
if (
!config.enabled ||
!isMapModelVisible(config.mapName, { groups, models })
@@ -99,7 +110,7 @@ export function MapInstancingSystem(): React.JSX.Element | null {
return createMapAssetChunks(type, config, instances);
});
}, [data, groups, models]);
}, [data, groups, models, onlyModelName]);
const visibleChunks = useVisibleWorldChunks(chunks, streamingEnabled);
@@ -114,6 +125,7 @@ export function MapInstancingSystem(): React.JSX.Element | null {
<InstancedMapAsset
modelPath={chunk.config.modelPath}
instances={chunk.instances}
scaleMultiplier={chunk.config.scaleMultiplier}
castShadow={chunk.config.castShadow}
receiveShadow={chunk.config.receiveShadow}
/>