memoize more components in the scene graph

This commit is contained in:
Brian Beck 2025-11-25 17:36:41 -08:00
parent 52d0a68d9d
commit b50ce94636
14 changed files with 54 additions and 39 deletions

View file

@ -1,4 +1,4 @@
import { useEffect, useRef } from "react";
import { memo, useEffect, useRef } from "react";
import { useThree, useFrame } from "@react-three/fiber";
import { PositionalAudio, Vector3 } from "three";
import { ConsoleObject, getPosition, getProperty } from "../mission";
@ -32,7 +32,11 @@ function getCachedAudioBuffer(
}
}
export function AudioEmitter({ object }: { object: ConsoleObject }) {
export const AudioEmitter = memo(function AudioEmitter({
object,
}: {
object: ConsoleObject;
}) {
const { debugMode } = useSettings();
const fileName = getProperty(object, "fileName")?.value ?? "";
const volume = parseFloat(getProperty(object, "volume")?.value ?? "1");
@ -217,4 +221,4 @@ export function AudioEmitter({ object }: { object: ConsoleObject }) {
</FloatingLabel>
</mesh>
) : null;
}
});

View file

@ -1,4 +1,4 @@
import { ReactNode, useEffect, useRef, useState } from "react";
import { memo, ReactNode, useEffect, useRef, useState } from "react";
import { Object3D } from "three";
import { useDistanceFromCamera } from "./useDistanceFromCamera";
import { useFrame } from "@react-three/fiber";
@ -6,7 +6,7 @@ import { Html } from "@react-three/drei";
const DEFAULT_POSITION = [0, 0, 0] as [x: number, y: number, z: number];
export function FloatingLabel({
export const FloatingLabel = memo(function FloatingLabel({
children,
color = "white",
position = DEFAULT_POSITION,
@ -55,4 +55,4 @@ export function FloatingLabel({
) : null}
</group>
);
}
});

View file

@ -1,4 +1,4 @@
import { Suspense, useMemo } from "react";
import { memo, Suspense, useMemo } from "react";
import { useGLTF, useTexture } from "@react-three/drei";
import { BASE_URL, shapeTextureToUrl, shapeToUrl } from "../loaders";
import { filterGeometryByVertexGroups, getHullBoneIndices } from "../meshUtils";
@ -30,7 +30,7 @@ export function ShapeTexture({
shapeName?: string;
}) {
const url = shapeTextureToUrl(material.name, FALLBACK_URL);
const isOrganic = shapeName && /borg|xorg|porg/i.test(shapeName);
const isOrganic = shapeName && /borg|xorg|porg|dorg/i.test(shapeName);
const texture = useTexture(url, (texture) => {
if (!isOrganic) {
@ -69,7 +69,7 @@ export function ShapePlaceholder({ color }: { color: string }) {
export type StaticShapeType = "StaticShape" | "TSStatic" | "Item" | "Turret";
export function ShapeModel() {
export const ShapeModel = memo(function ShapeModel() {
const { shapeName } = useShapeInfo();
const { debugMode } = useSettings();
const { nodes } = useStaticShape(shapeName);
@ -136,4 +136,4 @@ export function ShapeModel() {
{debugMode ? <FloatingLabel>{shapeName}</FloatingLabel> : null}
</group>
);
}
});

View file

@ -80,19 +80,21 @@ function InteriorPlaceholder() {
);
}
export const InteriorInstance = memo(
({ object }: { object: ConsoleObject }) => {
const interiorFile = getProperty(object, "interiorFile").value;
const position = useMemo(() => getPosition(object), [object]);
const scale = useMemo(() => getScale(object), [object]);
const q = useMemo(() => getRotation(object), [object]);
export const InteriorInstance = memo(function InteriorInstance({
object,
}: {
object: ConsoleObject;
}) {
const interiorFile = getProperty(object, "interiorFile").value;
const position = useMemo(() => getPosition(object), [object]);
const scale = useMemo(() => getScale(object), [object]);
const q = useMemo(() => getRotation(object), [object]);
return (
<group position={position} quaternion={q} scale={scale}>
<Suspense fallback={<InteriorPlaceholder />}>
<InteriorModel interiorFile={interiorFile} />
</Suspense>
</group>
);
}
);
return (
<group position={position} quaternion={q} scale={scale}>
<Suspense fallback={<InteriorPlaceholder />}>
<InteriorModel interiorFile={interiorFile} />
</Suspense>
</group>
);
});

View file

@ -1,6 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import { loadMission } from "../loaders";
import { renderObject } from "./renderObject";
import { memo } from "react";
function useMission(name: string) {
return useQuery({
@ -9,7 +10,7 @@ function useMission(name: string) {
});
}
export function Mission({ name }: { name: string }) {
export const Mission = memo(function Mission({ name }: { name: string }) {
const { data: mission } = useMission(name);
if (!mission) {
@ -17,4 +18,4 @@ export function Mission({ name }: { name: string }) {
}
return mission.objects.map((object, i) => renderObject(object, i));
}
});

View file

@ -1,4 +1,4 @@
import { Suspense, useCallback, useMemo } from "react";
import { memo, Suspense, useCallback, useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import {
DataTexture,
@ -201,7 +201,11 @@ function TerrainMaterial({
);
}
export function TerrainBlock({ object }: { object: ConsoleObject }) {
export const TerrainBlock = memo(function TerrainBlock({
object,
}: {
object: ConsoleObject;
}) {
const terrainFile: string = getProperty(object, "terrainFile").value;
const squareSize = useMemo(() => {
@ -265,4 +269,4 @@ export function TerrainBlock({ object }: { object: ConsoleObject }) {
</mesh>
</group>
);
}
});

View file

@ -1,4 +1,4 @@
import { Suspense, useEffect, useMemo } from "react";
import { memo, Suspense, useEffect, useMemo } from "react";
import { useTexture } from "@react-three/drei";
import { BoxGeometry, DoubleSide } from "three";
import { textureToUrl } from "../loaders";
@ -32,7 +32,11 @@ export function WaterMaterial({
);
}
export function WaterBlock({ object }: { object: ConsoleObject }) {
export const WaterBlock = memo(function WaterBlock({
object,
}: {
object: ConsoleObject;
}) {
const position = useMemo(() => getPosition(object), [object]);
const q = useMemo(() => getRotation(object), [object]);
const [scaleX, scaleY, scaleZ] = useMemo(() => getScale(object), [object]);
@ -99,4 +103,4 @@ export function WaterBlock({ object }: { object: ConsoleObject }) {
<meshStandardMaterial attach="material-5" transparent opacity={0} />
</mesh>
);
}
});