@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.
- package/dist/{chunk-Z6ZMR3CS.js → chunk-Q52ADLF7.js} +69 -3
- package/dist/chunk-Q52ADLF7.js.map +1 -0
- package/dist/{index-CppKDxbu.d.ts → index-D2Jt_JzH.d.ts} +11 -0
- package/dist/{index-I2IsocYW.d.cts → index-DaG03vyN.d.cts} +11 -0
- package/dist/index.cjs +67 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/systems/index.cjs +67 -1
- package/dist/systems/index.cjs.map +1 -1
- package/dist/systems/index.d.cts +1 -1
- package/dist/systems/index.d.ts +1 -1
- package/dist/systems/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-Z6ZMR3CS.js.map +0 -1
|
@@ -736,6 +736,10 @@ declare class XREnvironmentSystem implements EcsSystem {
|
|
|
736
736
|
private roomCaptureRequested;
|
|
737
737
|
/** This frame's inverse viewer matrix, or null when unavailable. */
|
|
738
738
|
private viewerInverse;
|
|
739
|
+
/** This frame's viewer position in reference space, for room election. */
|
|
740
|
+
private viewerPos;
|
|
741
|
+
/** The ONE global room mesh currently allowed to spawn. */
|
|
742
|
+
private electedGlobalMesh;
|
|
739
743
|
private readonly tmpViewerMatrix;
|
|
740
744
|
private readonly tmpViewPos;
|
|
741
745
|
update(world: World, deltaTime?: number): void;
|
|
@@ -786,6 +790,13 @@ declare class XREnvironmentSystem implements EcsSystem {
|
|
|
786
790
|
private findRig;
|
|
787
791
|
private syncPlanes;
|
|
788
792
|
private syncMeshes;
|
|
793
|
+
/**
|
|
794
|
+
* Pick THE room's global mesh: the one whose scan origin is nearest the
|
|
795
|
+
* viewer, sticky to the current choice within a margin so origin jitter
|
|
796
|
+
* can't flap the room. Without a viewer pose (or with a single candidate)
|
|
797
|
+
* the first candidate stands; ties are impossible to break anyway.
|
|
798
|
+
*/
|
|
799
|
+
private electGlobalMesh;
|
|
789
800
|
/**
|
|
790
801
|
* Admission control for a NOT-yet-spawned surface. With a viewer pose
|
|
791
802
|
* available, the surface must behave world-anchored for a few frames before
|
|
@@ -736,6 +736,10 @@ declare class XREnvironmentSystem implements EcsSystem {
|
|
|
736
736
|
private roomCaptureRequested;
|
|
737
737
|
/** This frame's inverse viewer matrix, or null when unavailable. */
|
|
738
738
|
private viewerInverse;
|
|
739
|
+
/** This frame's viewer position in reference space, for room election. */
|
|
740
|
+
private viewerPos;
|
|
741
|
+
/** The ONE global room mesh currently allowed to spawn. */
|
|
742
|
+
private electedGlobalMesh;
|
|
739
743
|
private readonly tmpViewerMatrix;
|
|
740
744
|
private readonly tmpViewPos;
|
|
741
745
|
update(world: World, deltaTime?: number): void;
|
|
@@ -786,6 +790,13 @@ declare class XREnvironmentSystem implements EcsSystem {
|
|
|
786
790
|
private findRig;
|
|
787
791
|
private syncPlanes;
|
|
788
792
|
private syncMeshes;
|
|
793
|
+
/**
|
|
794
|
+
* Pick THE room's global mesh: the one whose scan origin is nearest the
|
|
795
|
+
* viewer, sticky to the current choice within a margin so origin jitter
|
|
796
|
+
* can't flap the room. Without a viewer pose (or with a single candidate)
|
|
797
|
+
* the first candidate stands; ties are impossible to break anyway.
|
|
798
|
+
*/
|
|
799
|
+
private electGlobalMesh;
|
|
789
800
|
/**
|
|
790
801
|
* Admission control for a NOT-yet-spawned surface. With a viewer pose
|
|
791
802
|
* available, the surface must behave world-anchored for a few frames before
|
package/dist/index.cjs
CHANGED
|
@@ -12978,6 +12978,11 @@ function debugColorFor(kind, semanticLabel) {
|
|
|
12978
12978
|
}
|
|
12979
12979
|
__name(debugColorFor, "debugColorFor");
|
|
12980
12980
|
var GLOBAL_MESH_DEBUG_OPACITY = 0.35;
|
|
12981
|
+
var GLOBAL_MESH_SWITCH_MARGIN = 1.5;
|
|
12982
|
+
function isGlobalMeshSurface(mesh) {
|
|
12983
|
+
return (mesh.semanticLabel ?? null) === "global mesh";
|
|
12984
|
+
}
|
|
12985
|
+
__name(isGlobalMeshSurface, "isGlobalMeshSurface");
|
|
12981
12986
|
var DEBUG_RENDER_ORDER = 900;
|
|
12982
12987
|
var ROOM_CAPTURE_DELAY_SECONDS = 3;
|
|
12983
12988
|
var SYNTHETIC_FLOOR_EXTENT = 50;
|
|
@@ -13016,6 +13021,10 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
|
|
|
13016
13021
|
this.roomCaptureRequested = false;
|
|
13017
13022
|
/** This frame's inverse viewer matrix, or null when unavailable. */
|
|
13018
13023
|
this.viewerInverse = null;
|
|
13024
|
+
/** This frame's viewer position in reference space, for room election. */
|
|
13025
|
+
this.viewerPos = null;
|
|
13026
|
+
/** The ONE global room mesh currently allowed to spawn. */
|
|
13027
|
+
this.electedGlobalMesh = null;
|
|
13019
13028
|
this.tmpViewerMatrix = new THREE56__namespace.Matrix4();
|
|
13020
13029
|
this.tmpViewPos = new THREE56__namespace.Vector3();
|
|
13021
13030
|
}
|
|
@@ -13056,7 +13065,14 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
|
|
|
13056
13065
|
const useMesh = (mode === "mesh" || mode === "auto") && meshesAvailable;
|
|
13057
13066
|
const usePlanes = mode === "planes" || mode === "auto" && !useMesh;
|
|
13058
13067
|
const viewer = frame.getViewerPose?.(referenceSpace);
|
|
13059
|
-
|
|
13068
|
+
if (viewer) {
|
|
13069
|
+
const vm = viewer.transform.matrix;
|
|
13070
|
+
this.viewerPos = { x: vm[12], y: vm[13], z: vm[14] };
|
|
13071
|
+
this.viewerInverse = this.tmpViewerMatrix.fromArray(vm).invert();
|
|
13072
|
+
} else {
|
|
13073
|
+
this.viewerPos = null;
|
|
13074
|
+
this.viewerInverse = null;
|
|
13075
|
+
}
|
|
13060
13076
|
if (usePlanes) {
|
|
13061
13077
|
this.syncPlanes(world, frame, referenceSpace, deltaTime);
|
|
13062
13078
|
} else if (this.planes.size > 0) {
|
|
@@ -13211,7 +13227,17 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
|
|
|
13211
13227
|
for (const mesh of this.pendingMeshes.keys()) {
|
|
13212
13228
|
if (!detected.has(mesh)) this.pendingMeshes.delete(mesh);
|
|
13213
13229
|
}
|
|
13230
|
+
const electedGlobal = this.electGlobalMesh(frame, detected, referenceSpace);
|
|
13214
13231
|
for (const mesh of detected) {
|
|
13232
|
+
if (isGlobalMeshSurface(mesh) && mesh !== electedGlobal) {
|
|
13233
|
+
const stale = this.meshes.get(mesh);
|
|
13234
|
+
if (stale) {
|
|
13235
|
+
this.destroyEntry(world, stale);
|
|
13236
|
+
this.meshes.delete(mesh);
|
|
13237
|
+
}
|
|
13238
|
+
this.pendingMeshes.delete(mesh);
|
|
13239
|
+
continue;
|
|
13240
|
+
}
|
|
13215
13241
|
const pose = frame.getPose(mesh.meshSpace, referenceSpace);
|
|
13216
13242
|
if (!pose) continue;
|
|
13217
13243
|
const emulated = pose.emulatedPosition === true;
|
|
@@ -13235,6 +13261,45 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
|
|
|
13235
13261
|
if (allowed) this.applyPose(world, entry.entityId, pose);
|
|
13236
13262
|
}
|
|
13237
13263
|
}
|
|
13264
|
+
/**
|
|
13265
|
+
* Pick THE room's global mesh: the one whose scan origin is nearest the
|
|
13266
|
+
* viewer, sticky to the current choice within a margin so origin jitter
|
|
13267
|
+
* can't flap the room. Without a viewer pose (or with a single candidate)
|
|
13268
|
+
* the first candidate stands; ties are impossible to break anyway.
|
|
13269
|
+
*/
|
|
13270
|
+
electGlobalMesh(frame, detected, referenceSpace) {
|
|
13271
|
+
let nearest = null;
|
|
13272
|
+
let nearestDist = Number.POSITIVE_INFINITY;
|
|
13273
|
+
let currentDist = Number.POSITIVE_INFINITY;
|
|
13274
|
+
let currentStillDetected = false;
|
|
13275
|
+
for (const mesh of detected) {
|
|
13276
|
+
if (!isGlobalMeshSurface(mesh)) continue;
|
|
13277
|
+
if (!this.viewerPos) {
|
|
13278
|
+
return this.electedGlobalMesh && detected.has(this.electedGlobalMesh) ? this.electedGlobalMesh : mesh;
|
|
13279
|
+
}
|
|
13280
|
+
const pose = frame.getPose(mesh.meshSpace, referenceSpace);
|
|
13281
|
+
if (!pose) continue;
|
|
13282
|
+
const m = pose.transform.matrix;
|
|
13283
|
+
const d = Math.hypot(
|
|
13284
|
+
m[12] - this.viewerPos.x,
|
|
13285
|
+
m[13] - this.viewerPos.y,
|
|
13286
|
+
m[14] - this.viewerPos.z
|
|
13287
|
+
);
|
|
13288
|
+
if (mesh === this.electedGlobalMesh) {
|
|
13289
|
+
currentDist = d;
|
|
13290
|
+
currentStillDetected = true;
|
|
13291
|
+
}
|
|
13292
|
+
if (d < nearestDist) {
|
|
13293
|
+
nearestDist = d;
|
|
13294
|
+
nearest = mesh;
|
|
13295
|
+
}
|
|
13296
|
+
}
|
|
13297
|
+
if (currentStillDetected && currentDist < nearestDist + GLOBAL_MESH_SWITCH_MARGIN) {
|
|
13298
|
+
return this.electedGlobalMesh;
|
|
13299
|
+
}
|
|
13300
|
+
this.electedGlobalMesh = nearest;
|
|
13301
|
+
return nearest;
|
|
13302
|
+
}
|
|
13238
13303
|
/**
|
|
13239
13304
|
* Admission control for a NOT-yet-spawned surface. With a viewer pose
|
|
13240
13305
|
* available, the surface must behave world-anchored for a few frames before
|
|
@@ -13446,6 +13511,7 @@ var _XREnvironmentSystem = class _XREnvironmentSystem {
|
|
|
13446
13511
|
this.clearMap(world, this.meshes);
|
|
13447
13512
|
this.pendingPlanes.clear();
|
|
13448
13513
|
this.pendingMeshes.clear();
|
|
13514
|
+
this.electedGlobalMesh = null;
|
|
13449
13515
|
}
|
|
13450
13516
|
dispose(world) {
|
|
13451
13517
|
this.clearAll(world);
|