xr: false.| System | Browser Story | XR Story | Notes |
|---|---|---|---|
Transform, level, visibility, environment lighting | Ready | Ready | Core ECS and Three.js integration do not depend on XR. |
Pointer input | Ready | Ready | input.canvasPointerEvents forwards browser canvas pointer events; XR rays use input.xr.multiPointers. Both feed Hovered and Pressed. |
Spatial UI | Ready | Ready | PanelUI works in world space, and ScreenSpace panels are parented to world.camera outside XR. |
Audio | Ready | Ready | Audio sources and spatial audio are scene features, not XR-only features. |
Physics | Ready | Ready | Havok simulation is browser-safe. Physics colliders are separate from locomotion BVH collision. |
Locomotion | Opt-in browser bindings | Ready | The locomotor engine is shared. Browser apps can opt into keyboard/browser-gamepad action bindings while keeping camera behavior app-owned. |
Grabbing | Browser pointer selection ready; manipulation adapter TBD | Ready | Ray hover/press works in the browser. Near-field one/two-hand grabbing remains XR-oriented. |
Camera source | Ready | Ready | CameraSource uses browser media APIs and can run without an XR session when the camera feature is enabled. |
Scene understanding | XR-only | Ready | Planes, meshes, and anchors depend on WebXR session features. |
Environment raycast | XR-only | Ready | This is WebXR hit-test against real-world surfaces, not browser raycasting or locomotion BVH. |
Native XR layers | XR-first | Ready | Layer components use native WebXR composition layers when available; browser fallback promotion is a separate decision. |
world.input.xr for XR hands/controllers.world.input.keyboard for browser keyboard state.world.input.browserGamepads for standard browser gamepads.locomotion.movelocomotion.turnlocomotion.jumplocomotion.teleportAimlocomotion.teleportCommitinteraction.selectconst world = await World.create(container, {
xr: false,
features: {
locomotion: {
browserControls: true,
},
},
});
browserControls: true, IWSDK binds WASD/arrow keys and standard browser gamepads to locomotion actions. The app still owns the camera style. For first-person browser movement, drive world.camera orientation and let locomotion move world.player. For orbit, follow, editor, or third-person cameras, keep the camera logic in app systems and use locomotion only if the app wants a player origin that moves through the environment.examples/browser-first app uses xr: false, features.locomotion.browserControls, input.canvasPointerEvents, LocomotionEnvironment, browser-ready grab handles, ray interactables, physics, audio, and screen-space PanelUI together in one browser-first scene.@iwsdk/locomotor engine in browser and XR. The reusable pieces are:LocomotionEnvironment for walkable/collidable scene geometry.world.player as the moved origin.world.camera.position.x and .z at 0 under the player origin, then rotate the camera from pointer movement:let yaw = 0;
let pitch = 0;
canvas.addEventListener('click', () => canvas.requestPointerLock());
document.addEventListener('mousemove', (event) => {
if (document.pointerLockElement !== canvas) return;
yaw -= event.movementX * 0.002;
pitch = Math.max(-1.2, Math.min(1.2, pitch - event.movementY * 0.002));
world.camera.rotation.set(pitch, yaw, 0, 'YXZ');
});
RayInteractable entities. DistanceGrabbable, OneHandGrabbable, and TwoHandsGrabbable still model XR manipulation semantics.interaction.select. It should not try to emulate two-hand XR grabbing on desktop unless the app explicitly opts into a custom interaction model.SceneUnderstandingSystem depends on WebXR plane detection, mesh detection, and anchors.EnvironmentRaycastSystem depends on WebXR hit-test sources.