@relu-interactives/spatial-ecs 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8125,6 +8125,11 @@ function debugColorFor(kind, semanticLabel) {
8125
8125
  }
8126
8126
  __name(debugColorFor, "debugColorFor");
8127
8127
  var GLOBAL_MESH_DEBUG_OPACITY = 0.35;
8128
+ var GLOBAL_MESH_SWITCH_MARGIN = 1.5;
8129
+ function isGlobalMeshSurface(mesh) {
8130
+ return (mesh.semanticLabel ?? null) === "global mesh";
8131
+ }
8132
+ __name(isGlobalMeshSurface, "isGlobalMeshSurface");
8128
8133
  var DEBUG_RENDER_ORDER = 900;
8129
8134
  var ROOM_CAPTURE_DELAY_SECONDS = 3;
8130
8135
  var SYNTHETIC_FLOOR_EXTENT = 50;
@@ -8163,6 +8168,10 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
8163
8168
  this.roomCaptureRequested = false;
8164
8169
  /** This frame's inverse viewer matrix, or null when unavailable. */
8165
8170
  this.viewerInverse = null;
8171
+ /** This frame's viewer position in reference space, for room election. */
8172
+ this.viewerPos = null;
8173
+ /** The ONE global room mesh currently allowed to spawn. */
8174
+ this.electedGlobalMesh = null;
8166
8175
  this.tmpViewerMatrix = new THREE19.Matrix4();
8167
8176
  this.tmpViewPos = new THREE19.Vector3();
8168
8177
  }
@@ -8203,7 +8212,14 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
8203
8212
  const useMesh = (mode === "mesh" || mode === "auto") && meshesAvailable;
8204
8213
  const usePlanes = mode === "planes" || mode === "auto" && !useMesh;
8205
8214
  const viewer = frame.getViewerPose?.(referenceSpace);
8206
- this.viewerInverse = viewer ? this.tmpViewerMatrix.fromArray(viewer.transform.matrix).invert() : null;
8215
+ if (viewer) {
8216
+ const vm = viewer.transform.matrix;
8217
+ this.viewerPos = { x: vm[12], y: vm[13], z: vm[14] };
8218
+ this.viewerInverse = this.tmpViewerMatrix.fromArray(vm).invert();
8219
+ } else {
8220
+ this.viewerPos = null;
8221
+ this.viewerInverse = null;
8222
+ }
8207
8223
  if (usePlanes) {
8208
8224
  this.syncPlanes(world, frame, referenceSpace, deltaTime);
8209
8225
  } else if (this.planes.size > 0) {
@@ -8358,7 +8374,17 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
8358
8374
  for (const mesh of this.pendingMeshes.keys()) {
8359
8375
  if (!detected.has(mesh)) this.pendingMeshes.delete(mesh);
8360
8376
  }
8377
+ const electedGlobal = this.electGlobalMesh(frame, detected, referenceSpace);
8361
8378
  for (const mesh of detected) {
8379
+ if (isGlobalMeshSurface(mesh) && mesh !== electedGlobal) {
8380
+ const stale = this.meshes.get(mesh);
8381
+ if (stale) {
8382
+ this.destroyEntry(world, stale);
8383
+ this.meshes.delete(mesh);
8384
+ }
8385
+ this.pendingMeshes.delete(mesh);
8386
+ continue;
8387
+ }
8362
8388
  const pose = frame.getPose(mesh.meshSpace, referenceSpace);
8363
8389
  if (!pose) continue;
8364
8390
  const emulated = pose.emulatedPosition === true;
@@ -8382,6 +8408,45 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
8382
8408
  if (allowed) this.applyPose(world, entry.entityId, pose);
8383
8409
  }
8384
8410
  }
8411
+ /**
8412
+ * Pick THE room's global mesh: the one whose scan origin is nearest the
8413
+ * viewer, sticky to the current choice within a margin so origin jitter
8414
+ * can't flap the room. Without a viewer pose (or with a single candidate)
8415
+ * the first candidate stands; ties are impossible to break anyway.
8416
+ */
8417
+ electGlobalMesh(frame, detected, referenceSpace) {
8418
+ let nearest = null;
8419
+ let nearestDist = Number.POSITIVE_INFINITY;
8420
+ let currentDist = Number.POSITIVE_INFINITY;
8421
+ let currentStillDetected = false;
8422
+ for (const mesh of detected) {
8423
+ if (!isGlobalMeshSurface(mesh)) continue;
8424
+ if (!this.viewerPos) {
8425
+ return this.electedGlobalMesh && detected.has(this.electedGlobalMesh) ? this.electedGlobalMesh : mesh;
8426
+ }
8427
+ const pose = frame.getPose(mesh.meshSpace, referenceSpace);
8428
+ if (!pose) continue;
8429
+ const m = pose.transform.matrix;
8430
+ const d = Math.hypot(
8431
+ m[12] - this.viewerPos.x,
8432
+ m[13] - this.viewerPos.y,
8433
+ m[14] - this.viewerPos.z
8434
+ );
8435
+ if (mesh === this.electedGlobalMesh) {
8436
+ currentDist = d;
8437
+ currentStillDetected = true;
8438
+ }
8439
+ if (d < nearestDist) {
8440
+ nearestDist = d;
8441
+ nearest = mesh;
8442
+ }
8443
+ }
8444
+ if (currentStillDetected && currentDist < nearestDist + GLOBAL_MESH_SWITCH_MARGIN) {
8445
+ return this.electedGlobalMesh;
8446
+ }
8447
+ this.electedGlobalMesh = nearest;
8448
+ return nearest;
8449
+ }
8385
8450
  /**
8386
8451
  * Admission control for a NOT-yet-spawned surface. With a viewer pose
8387
8452
  * available, the surface must behave world-anchored for a few frames before
@@ -8593,6 +8658,7 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
8593
8658
  this.clearMap(world, this.meshes);
8594
8659
  this.pendingPlanes.clear();
8595
8660
  this.pendingMeshes.clear();
8661
+ this.electedGlobalMesh = null;
8596
8662
  }
8597
8663
  dispose(world) {
8598
8664
  this.clearAll(world);
@@ -10985,5 +11051,5 @@ __name(_XRHoverVisualSystem, "XRHoverVisualSystem");
10985
11051
  var XRHoverVisualSystem = _XRHoverVisualSystem;
10986
11052
 
10987
11053
  export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CURLED_COS, CameraSyncSystem, DEFAULT_DIRECTION_TOLERANCE, DEFAULT_ENTER_CONFIDENCE, DEFAULT_EXIT_CONFIDENCE, DEFAULT_LOST_GRACE_SECONDS, DEFAULT_MIN_HOLD_SECONDS, EnvironmentSyncSystem, FALLBACK_HAND_SCALE, HYDRATABLE_ENTITY_KINDS, HandPoseTracker, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MATCH_FALLOFF, MAX_PLAUSIBLE_SPEED, MAX_SAMPLE_AGE_SECONDS, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PINCH_FINGERS, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, STRAIGHT_COS, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, TeleportAimGate, ThrowVelocityTracker, TransformSyncSystem, UIInteractionSystem, UIPanelSystem, VELOCITY_SAMPLES, VRTeleportAreaSystem, VideoSystem, XRAnchorSystem, XRControllerVisualSystem, XREnvironmentSystem, XRHandPoseSystem, XRHitTestSystem, XRHoverVisualSystem, XRInputSystem, XRInteractionSystem, XRLocomotionSystem, XRSessionSystem, XRTeleportVisualSystem, XR_FINGERS, XR_HOVER_SHELL_FLAG, angularVelocityFrom, applyHandMaterial, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeFingerCurl, computeHandShape, computeInstanceOverrides, computePalmPose, computePalmWidth, computePinch, computeSpread, createHandMaterial, decanonicalizeComponentValue, despawnPrefab, encodeOverride, estimateHandScale, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, matchHandPose, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, readXrCapabilities, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, setPrefabAssetUrlResolver, spawnPrefab };
10988
- //# sourceMappingURL=chunk-Z6ZMR3CS.js.map
10989
- //# sourceMappingURL=chunk-Z6ZMR3CS.js.map
11054
+ //# sourceMappingURL=chunk-Q52ADLF7.js.map
11055
+ //# sourceMappingURL=chunk-Q52ADLF7.js.map