For the complete documentation index, see llms.txt. This page is also available as Markdown.

MapSpace

The VPS map coordinate frame, positioned once per localization so every child follows

import { MapSpace } from '@multisetai/vps/three';

MapSpace marks one object as the origin of the scanned map. Nest your map-anchored content underneath it, and on every successful localization the frame is moved so its origin coincides with the map's origin. Every descendant follows by ordinary parenting.

A child's local position is therefore its map coordinate. You can paste a value straight from the portal's Map Viewer into a child's Transform.

This is what makes relocalization cheap. Only one transform changes, so anything computed relative to the frame stays valid: no re-anchoring, no recompute, and no visible jump when localization runs again in the background.

Two forms

Form
Import
Use in

Package class

import { MapSpace } from '@multisetai/vps/three'

Plain Three.js, or from code in a Needle project

Needle component

import { MapSpace } from './MapSpace.js'

Unity, as a template file copied into your src/scripts/ folder

The Needle component is a thin Behaviour that owns a package MapSpace bound to its GameObject and forwards to it, so behaviour is identical. The Unity to Three.js handedness correction lives in the package class, which keeps one verified implementation rather than a copy in every project.

Copy the template into your project with:

cp node_modules/@multisetai/vps/templates/MapSpace.ts <your-web-folder>/src/scripts/

Constructor

const mapSpace = new MapSpace(new THREE.Object3D(), { hideUntilLocalized: true });
scene.add(mapSpace.object);
mapSpace.connect(adapter);
Parameter
Type
Description

object

THREE.Object3D

The object to use as the map frame. Add it to your scene yourself.

options

IMapSpaceOptions

Optional. See below.

Options and fields

Name
Type
Default
Description

hideUntilLocalized

boolean

true

Hide the object until the first localization, and re-hide it when the session ends. This is a public mutable field, read live, so you can set it to false at runtime to keep content visible between sessions.

Properties

Property
Type
Description

object

THREE.Object3D

The wrapped object. Add this to your scene, and parent map content to it.

isLocalized

boolean

true once a localization has been applied in the current session.

Methods

Method
Description

connect(adapter: IVpsAdapter)

Subscribe to an adapter so the frame is positioned on every localization. Accepts ThreeAdapter or NeedleAdapter. Safe to call more than once, since previous subscriptions are removed first. If the adapter has already localized in the current session, that result is replayed immediately, so a MapSpace created mid-session is positioned at once.

disconnect()

Remove every subscription made by connect().

applyLocalization(result, worldFromMap)

Position the frame directly, bypassing events. Useful in tests, or from a component that receives the result by another route.

add(object: THREE.Object3D, mapCoordinate?: THREE.Vector3)

Parent an object to the frame, optionally at a map coordinate.

mapToWorld(v: THREE.Vector3, target?)

Convert map space to world space.

worldToMap(v: THREE.Vector3, target?)

Convert world space to map space. Use this to convert the camera pose before any map-space calculation.

dispose()

Same as disconnect().

Static methods

Method
Description

MapSpace.toLocal(unityCoord: THREE.Vector3, target?)

Convert a Unity (left-handed) coordinate copied from the portal's Map Viewer into map space.

Content authored in the Unity editor gets this conversion from Needle's exporter and must not use toLocal. Content created in code does need it:

Hiding behavior

In Unity

MultisetVPS discovers and wires all MapSpace components at startup. A scene should contain exactly one. MultisetVPS logs a warning if it finds more, because they would all be moved to the same origin.

The Needle component exposes connectAdapter(adapter) and applyLocalization(result, worldFromMap), matching MapAnchor, so it can also be registered at runtime with NeedleAdapter.registerAnchor(mapSpace).

Reach the underlying package object through .space:

MapSpace or MapAnchor

Use
Component

A layout of several objects, authored in the editor

MapSpace

Navigation

MapSpace, which is required

One object that must not inherit the map's rotation

MapAnchor with matchOrientation: false

One object in a scene that has no MapSpace

MapSpace is the preferred model for anything with more than one anchored object, because the layout you build in the editor is the layout you get in AR, with no per-object component and no offset fields to keep in sync.

Last updated

Was this helpful?