fix: match world splat initial camera to reference view
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-05-25 21:26:12 +08:00
parent 446b87443c
commit 161126bd4c

View File

@ -101,6 +101,7 @@ const DEFAULT_MESH_SETTINGS: Model3DViewerSettings = {
};
const WORLDLABS_ASSET_ROTATION: [number, number, number] = [Math.PI, 0, 0];
const WORLDLABS_REFERENCE_VIEW_AXIS = new THREE.Vector3(0, 0, 1);
const EMPTY_MOVEMENT_STATE: MovementState = {
forward: false,
@ -320,6 +321,14 @@ function getSplatWorldBounds(splatMesh: SparkSplatMesh) {
.applyMatrix4(splatMesh.matrixWorld);
}
function getWorldLabsDisplayGroundPlaneOffset(value: unknown) {
if (typeof value !== "number" || !Number.isFinite(value)) return null;
// World Labs semantics are authored before the SPZ/GLB is rotated into our
// Three.js display coordinates. The X-axis 180deg rotation flips vertical Y.
return -value;
}
function getLoadedSplatCount(splatMesh: SparkSplatMesh) {
try {
return Math.max(
@ -407,8 +416,12 @@ function positionCameraInsideWorld({
const center = worldBounds.getCenter(new THREE.Vector3());
const size = worldBounds.getSize(new THREE.Vector3());
const horizontalAxis =
const longestHorizontalAxis =
size.z >= size.x ? new THREE.Vector3(0, 0, 1) : new THREE.Vector3(1, 0, 0);
const horizontalAxis =
firstPerson && size.z >= 0.8
? WORLDLABS_REFERENCE_VIEW_AXIS.clone()
: longestHorizontalAxis;
const majorSpan = Math.max(horizontalAxis.z === 1 ? size.z : size.x, 1.4);
const clampInsideAxis = (
@ -1288,10 +1301,9 @@ function WorldSplatScene({
}),
[minimalFrame, onLoadProgress, splatBytes, splatFileName, splatUrl]
);
const groundPlaneOffset =
typeof semanticsMetadata?.ground_plane_offset === "number"
? semanticsMetadata.ground_plane_offset
: null;
const groundPlaneOffset = getWorldLabsDisplayGroundPlaneOffset(
semanticsMetadata?.ground_plane_offset
);
const handleOrbitControlsRef = React.useCallback((controls: any | null) => {
orbitControlsRef.current = controls;
setControlsMountVersion((version) => version + 1);