Refactor brush handling and geometry cloning in runtime-scene-build

This commit is contained in:
2026-04-15 07:53:36 +02:00
parent e6148bdad7
commit e5aeedf852

View File

@@ -35,13 +35,16 @@ import {
type RuntimeControlSurfaceDefinition type RuntimeControlSurfaceDefinition
} from "../controls/control-surface"; } from "../controls/control-surface";
import { import {
cloneBoxBrushGeometry, cloneBrushGeometry,
cloneBoxBrushVolumeSettings,
cloneBrush,
cloneBoxBrushVolumeSettings, cloneBoxBrushVolumeSettings,
cloneFaceUvState, cloneFaceUvState,
type BoxBrush, type Brush,
type BoxBrushGeometry, type BrushGeometry,
type BrushKind,
type BoxBrushVolumeSettings, type BoxBrushVolumeSettings,
type BoxFaceId, type WhiteboxFaceId,
type FaceUvState type FaceUvState
} from "../document/brushes"; } from "../document/brushes";
import type { SceneDocument } from "../document/scene-document"; import type { SceneDocument } from "../document/scene-document";
@@ -82,8 +85,9 @@ import {
type PlayerStartSprintSettings, type PlayerStartSprintSettings,
type PlayerStartMovementTemplate type PlayerStartMovementTemplate
} from "../entities/entity-instances"; } from "../entities/entity-instances";
import { getBoxBrushBounds } from "../geometry/box-brush"; import { getBrushBounds } from "../geometry/whitebox-brush";
import { buildBoxBrushDerivedMeshData } from "../geometry/box-brush-mesh"; import { buildBoxBrushDerivedMeshData } from "../geometry/box-brush-mesh";
import { getBrushFaceIds } from "../geometry/whitebox-topology";
import { import {
buildGeneratedModelCollider, buildGeneratedModelCollider,
type GeneratedColliderBounds, type GeneratedColliderBounds,
@@ -124,13 +128,14 @@ export interface RuntimeBrushFace {
export interface RuntimeBoxBrushInstance { export interface RuntimeBoxBrushInstance {
id: string; id: string;
kind: "box"; kind: BrushKind;
sideCount?: number;
visible: boolean; visible: boolean;
center: Vec3; center: Vec3;
rotationDegrees: Vec3; rotationDegrees: Vec3;
size: Vec3; size: Vec3;
geometry: BoxBrushGeometry; geometry: BrushGeometry;
faces: Record<BoxFaceId, RuntimeBrushFace>; faces: Record<WhiteboxFaceId, RuntimeBrushFace>;
volume: BoxBrushVolumeSettings; volume: BoxBrushVolumeSettings;
} }
@@ -614,54 +619,36 @@ function resolveRuntimeMaterial(
} }
function buildRuntimeBrush( function buildRuntimeBrush(
brush: BoxBrush, brush: Brush,
document: SceneDocument document: SceneDocument
): RuntimeBoxBrushInstance { ): RuntimeBoxBrushInstance {
return { return {
id: brush.id, id: brush.id,
kind: "box", kind: brush.kind,
sideCount: brush.kind === "radialPrism" ? brush.sideCount : undefined,
visible: brush.visible, visible: brush.visible,
center: cloneVec3(brush.center), center: cloneVec3(brush.center),
rotationDegrees: cloneVec3(brush.rotationDegrees), rotationDegrees: cloneVec3(brush.rotationDegrees),
size: cloneVec3(brush.size), size: cloneVec3(brush.size),
geometry: cloneBoxBrushGeometry(brush.geometry), geometry: cloneBrushGeometry(brush.geometry),
volume: cloneBoxBrushVolumeSettings(brush.volume), volume: cloneBoxBrushVolumeSettings(brush.volume),
faces: { faces: Object.fromEntries(
posX: { getBrushFaceIds(brush).map((faceId) => {
materialId: brush.faces.posX.materialId, const face = brush.faces[faceId];
material: resolveRuntimeMaterial(document, brush.faces.posX.materialId), return [
uv: cloneFaceUvState(brush.faces.posX.uv) faceId,
}, {
negX: { materialId: face.materialId,
materialId: brush.faces.negX.materialId, material: resolveRuntimeMaterial(document, face.materialId),
material: resolveRuntimeMaterial(document, brush.faces.negX.materialId), uv: cloneFaceUvState(face.uv)
uv: cloneFaceUvState(brush.faces.negX.uv) }
}, ];
posY: { })
materialId: brush.faces.posY.materialId, ) as Record<WhiteboxFaceId, RuntimeBrushFace>
material: resolveRuntimeMaterial(document, brush.faces.posY.materialId),
uv: cloneFaceUvState(brush.faces.posY.uv)
},
negY: {
materialId: brush.faces.negY.materialId,
material: resolveRuntimeMaterial(document, brush.faces.negY.materialId),
uv: cloneFaceUvState(brush.faces.negY.uv)
},
posZ: {
materialId: brush.faces.posZ.materialId,
material: resolveRuntimeMaterial(document, brush.faces.posZ.materialId),
uv: cloneFaceUvState(brush.faces.posZ.uv)
},
negZ: {
materialId: brush.faces.negZ.materialId,
material: resolveRuntimeMaterial(document, brush.faces.negZ.materialId),
uv: cloneFaceUvState(brush.faces.negZ.uv)
}
}
}; };
} }
function buildRuntimeFogVolume(brush: BoxBrush): RuntimeFogVolume { function buildRuntimeFogVolume(brush: Brush): RuntimeFogVolume {
if (brush.volume.mode !== "fog") { if (brush.volume.mode !== "fog") {
throw new Error(`Cannot build fog volume from non-fog brush ${brush.id}.`); throw new Error(`Cannot build fog volume from non-fog brush ${brush.id}.`);
} }
@@ -677,7 +664,7 @@ function buildRuntimeFogVolume(brush: BoxBrush): RuntimeFogVolume {
}; };
} }
function buildRuntimeWaterVolume(brush: BoxBrush): RuntimeWaterVolume { function buildRuntimeWaterVolume(brush: Brush): RuntimeWaterVolume {
if (brush.volume.mode !== "water") { if (brush.volume.mode !== "water") {
throw new Error( throw new Error(
`Cannot build water volume from non-water brush ${brush.id}.` `Cannot build water volume from non-water brush ${brush.id}.`
@@ -695,8 +682,8 @@ function buildRuntimeWaterVolume(brush: BoxBrush): RuntimeWaterVolume {
}; };
} }
function buildRuntimeCollider(brush: BoxBrush): RuntimeBrushTriMeshCollider { function buildRuntimeCollider(brush: Brush): RuntimeBrushTriMeshCollider {
const bounds = getBoxBrushBounds(brush); const bounds = getBrushBounds(brush);
const derivedMesh = buildBoxBrushDerivedMeshData(brush); const derivedMesh = buildBoxBrushDerivedMeshData(brush);
return { return {
@@ -1526,6 +1513,11 @@ export function buildRuntimeSceneFromDocument(
continue; continue;
} }
if (brush.kind !== "box") {
staticColliders.push(buildRuntimeCollider(brush));
continue;
}
if (brush.volume.mode === "fog") { if (brush.volume.mode === "fog") {
volumes.fog.push(buildRuntimeFogVolume(brush)); volumes.fog.push(buildRuntimeFogVolume(brush));
continue; continue;