@holoscript/engine 6.0.3 → 6.0.4
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/AutoMesher-CK47F6AV.js +17 -0
- package/dist/GPUBuffers-2LHBCD7X.js +9 -0
- package/dist/WebGPUContext-TNEUYU2Y.js +11 -0
- package/dist/animation/index.cjs +38 -38
- package/dist/animation/index.d.cts +1 -1
- package/dist/animation/index.d.ts +1 -1
- package/dist/animation/index.js +1 -1
- package/dist/audio/index.cjs +16 -6
- package/dist/audio/index.d.cts +1 -1
- package/dist/audio/index.d.ts +1 -1
- package/dist/audio/index.js +1 -1
- package/dist/camera/index.cjs +23 -23
- package/dist/camera/index.d.cts +1 -1
- package/dist/camera/index.d.ts +1 -1
- package/dist/camera/index.js +1 -1
- package/dist/character/index.cjs +6 -4
- package/dist/character/index.js +1 -1
- package/dist/choreography/index.cjs +1194 -0
- package/dist/choreography/index.d.cts +687 -0
- package/dist/choreography/index.d.ts +687 -0
- package/dist/choreography/index.js +1156 -0
- package/dist/chunk-2CSNRI2N.js +217 -0
- package/dist/chunk-33T2WINR.js +266 -0
- package/dist/chunk-35R73OFM.js +1257 -0
- package/dist/chunk-4MMDSUNP.js +1256 -0
- package/dist/chunk-5V6HOU72.js +319 -0
- package/dist/chunk-6QOP6PYF.js +1038 -0
- package/dist/chunk-7KMJVHIL.js +8944 -0
- package/dist/chunk-7VPUC62U.js +1106 -0
- package/dist/chunk-A2Y6RCAT.js +1878 -0
- package/dist/chunk-AHM42MK6.js +8944 -0
- package/dist/chunk-BL7IDTHE.js +218 -0
- package/dist/chunk-CITOMSWL.js +10462 -0
- package/dist/chunk-CXDPKW2K.js +8944 -0
- package/dist/chunk-CXZPLD4S.js +223 -0
- package/dist/chunk-CZYJE7IH.js +5169 -0
- package/dist/chunk-D2OP7YC7.js +6325 -0
- package/dist/chunk-EDRVQHUU.js +1544 -0
- package/dist/chunk-EJSLOOW2.js +3589 -0
- package/dist/chunk-F53SFGW5.js +1878 -0
- package/dist/chunk-HCFPELPY.js +919 -0
- package/dist/chunk-HNEE36PY.js +93 -0
- package/dist/chunk-HYXNV36F.js +1256 -0
- package/dist/chunk-IB7KHVFY.js +821 -0
- package/dist/chunk-IBBO7YYG.js +690 -0
- package/dist/chunk-ILIBGINU.js +5470 -0
- package/dist/chunk-IS4MHLKN.js +5479 -0
- package/dist/chunk-JT2PFKWD.js +5479 -0
- package/dist/chunk-K4CUB4NY.js +1038 -0
- package/dist/chunk-KATDQXRJ.js +10462 -0
- package/dist/chunk-KBQE6ZFJ.js +8944 -0
- package/dist/chunk-KBVD5K7E.js +560 -0
- package/dist/chunk-KCDPVQRY.js +4088 -0
- package/dist/chunk-KN4QJPKN.js +8944 -0
- package/dist/chunk-KWJ3ROSI.js +8944 -0
- package/dist/chunk-L45VF6DD.js +919 -0
- package/dist/chunk-LY4T37YK.js +307 -0
- package/dist/chunk-MDN5WZXA.js +1544 -0
- package/dist/chunk-MGCDP6VU.js +928 -0
- package/dist/chunk-NCX7X6G2.js +8681 -0
- package/dist/chunk-OF54BPVD.js +913 -0
- package/dist/chunk-OWSN2Q3Q.js +690 -0
- package/dist/chunk-PRRB5TTA.js +406 -0
- package/dist/chunk-PXWVQF76.js +4086 -0
- package/dist/chunk-PYCOIDT2.js +812 -0
- package/dist/chunk-PZCSADOV.js +928 -0
- package/dist/chunk-Q2XBVS2K.js +1038 -0
- package/dist/chunk-QDZRXWN5.js +1776 -0
- package/dist/chunk-RNWOZ6WQ.js +913 -0
- package/dist/chunk-ROLFT4CJ.js +1693 -0
- package/dist/chunk-SLTJRZ2N.js +266 -0
- package/dist/chunk-SRUS5XSU.js +4088 -0
- package/dist/chunk-TKCA3WZ5.js +5409 -0
- package/dist/chunk-TNRMXYI2.js +1650 -0
- package/dist/chunk-TQB3GJGM.js +9763 -0
- package/dist/chunk-TUFGXG6K.js +510 -0
- package/dist/chunk-U6KMTGQJ.js +632 -0
- package/dist/chunk-VMGJQST6.js +8681 -0
- package/dist/chunk-X4F4TCG4.js +5470 -0
- package/dist/chunk-ZIFROE75.js +1544 -0
- package/dist/chunk-ZIJQYHSQ.js +1204 -0
- package/dist/combat/index.cjs +4 -4
- package/dist/combat/index.d.cts +1 -1
- package/dist/combat/index.d.ts +1 -1
- package/dist/combat/index.js +1 -1
- package/dist/ecs/index.cjs +1 -1
- package/dist/ecs/index.js +1 -1
- package/dist/environment/index.cjs +14 -14
- package/dist/environment/index.d.cts +1 -1
- package/dist/environment/index.d.ts +1 -1
- package/dist/environment/index.js +1 -1
- package/dist/gpu/index.cjs +4810 -0
- package/dist/gpu/index.js +3714 -0
- package/dist/hologram/index.cjs +27 -1
- package/dist/hologram/index.js +1 -1
- package/dist/index-B2PIsAmR.d.cts +2180 -0
- package/dist/index-B2PIsAmR.d.ts +2180 -0
- package/dist/index-BHySEPX7.d.cts +2921 -0
- package/dist/index-BJV21zuy.d.cts +341 -0
- package/dist/index-BJV21zuy.d.ts +341 -0
- package/dist/index-BQutTphC.d.cts +790 -0
- package/dist/index-ByIq2XrS.d.cts +3910 -0
- package/dist/index-BysHjDSO.d.cts +224 -0
- package/dist/index-BysHjDSO.d.ts +224 -0
- package/dist/index-CKwAJGck.d.ts +455 -0
- package/dist/index-CUl3QstQ.d.cts +3006 -0
- package/dist/index-CUl3QstQ.d.ts +3006 -0
- package/dist/index-CmYtNiI-.d.cts +953 -0
- package/dist/index-CmYtNiI-.d.ts +953 -0
- package/dist/index-CnRzWxi_.d.cts +522 -0
- package/dist/index-CnRzWxi_.d.ts +522 -0
- package/dist/index-CwRWbSC7.d.ts +2921 -0
- package/dist/index-CxKIBstO.d.ts +790 -0
- package/dist/index-DJ6-R8vh.d.cts +455 -0
- package/dist/index-DQKisbcI.d.cts +4968 -0
- package/dist/index-DQKisbcI.d.ts +4968 -0
- package/dist/index-DRT2zJez.d.ts +3910 -0
- package/dist/index-DfNLiAka.d.cts +192 -0
- package/dist/index-DfNLiAka.d.ts +192 -0
- package/dist/index-nMvkoRm8.d.cts +405 -0
- package/dist/index-nMvkoRm8.d.ts +405 -0
- package/dist/index-s9yOFU37.d.cts +604 -0
- package/dist/index-s9yOFU37.d.ts +604 -0
- package/dist/index.cjs +22966 -6960
- package/dist/index.d.cts +864 -20
- package/dist/index.d.ts +864 -20
- package/dist/index.js +3062 -48
- package/dist/input/index.cjs +1 -1
- package/dist/input/index.js +1 -1
- package/dist/orbital/index.cjs +3 -3
- package/dist/orbital/index.d.cts +1 -1
- package/dist/orbital/index.d.ts +1 -1
- package/dist/orbital/index.js +1 -1
- package/dist/particles/index.cjs +16 -16
- package/dist/particles/index.d.cts +1 -1
- package/dist/particles/index.d.ts +1 -1
- package/dist/particles/index.js +1 -1
- package/dist/physics/index.cjs +2377 -21
- package/dist/physics/index.d.cts +1 -1
- package/dist/physics/index.d.ts +1 -1
- package/dist/physics/index.js +35 -1
- package/dist/postfx/index.cjs +3491 -0
- package/dist/postfx/index.js +93 -0
- package/dist/procedural/index.cjs +1 -1
- package/dist/procedural/index.js +1 -1
- package/dist/puppeteer-5VF6KDVO.js +52197 -0
- package/dist/puppeteer-IZVZ3SG4.js +52197 -0
- package/dist/rendering/index.cjs +33 -32
- package/dist/rendering/index.d.cts +1 -1
- package/dist/rendering/index.d.ts +1 -1
- package/dist/rendering/index.js +8 -6
- package/dist/runtime/index.cjs +23 -13
- package/dist/runtime/index.d.cts +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +8 -6
- package/dist/runtime/protocols/index.cjs +349 -0
- package/dist/runtime/protocols/index.js +15 -0
- package/dist/scene/index.cjs +8 -8
- package/dist/scene/index.d.cts +1 -1
- package/dist/scene/index.d.ts +1 -1
- package/dist/scene/index.js +1 -1
- package/dist/shader/index.cjs +3087 -0
- package/dist/shader/index.js +3044 -0
- package/dist/simulation/index.cjs +10680 -0
- package/dist/simulation/index.d.cts +3 -0
- package/dist/simulation/index.d.ts +3 -0
- package/dist/simulation/index.js +307 -0
- package/dist/spatial/index.cjs +2443 -0
- package/dist/spatial/index.d.cts +1545 -0
- package/dist/spatial/index.d.ts +1545 -0
- package/dist/spatial/index.js +2400 -0
- package/dist/terrain/index.cjs +1 -1
- package/dist/terrain/index.d.cts +1 -1
- package/dist/terrain/index.d.ts +1 -1
- package/dist/terrain/index.js +1 -1
- package/dist/transformers.node-4NKAPD5U.js +45620 -0
- package/dist/vm/index.cjs +7 -8
- package/dist/vm/index.d.cts +1 -1
- package/dist/vm/index.d.ts +1 -1
- package/dist/vm/index.js +1 -1
- package/dist/vm-bridge/index.cjs +2 -2
- package/dist/vm-bridge/index.d.cts +2 -2
- package/dist/vm-bridge/index.d.ts +2 -2
- package/dist/vm-bridge/index.js +1 -1
- package/dist/vr/index.cjs +6 -6
- package/dist/vr/index.js +1 -1
- package/dist/world/index.cjs +3 -3
- package/dist/world/index.d.cts +1 -1
- package/dist/world/index.d.ts +1 -1
- package/dist/world/index.js +1 -1
- package/package.json +53 -21
- package/LICENSE +0 -21
|
@@ -0,0 +1,1545 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Spatial Types for Agent Context Awareness
|
|
5
|
+
* Sprint 4 Priority 4 - Spatial Context Awareness
|
|
6
|
+
*
|
|
7
|
+
* Enables agents to understand and reason about spatial relationships
|
|
8
|
+
* in XR environments.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* 3D Vector representation
|
|
12
|
+
*/
|
|
13
|
+
interface Vector3 {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
z: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 2D Vector for screen/UI space
|
|
20
|
+
*/
|
|
21
|
+
interface Vector2 {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Quaternion for rotation
|
|
27
|
+
*/
|
|
28
|
+
interface Quaternion {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
z: number;
|
|
32
|
+
w: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Axis-aligned bounding box
|
|
36
|
+
*/
|
|
37
|
+
interface BoundingBox {
|
|
38
|
+
min: Vector3;
|
|
39
|
+
max: Vector3;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Oriented bounding box with rotation
|
|
43
|
+
*/
|
|
44
|
+
interface OrientedBoundingBox {
|
|
45
|
+
center: Vector3;
|
|
46
|
+
halfExtents: Vector3;
|
|
47
|
+
rotation: Quaternion;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Sphere bounds
|
|
51
|
+
*/
|
|
52
|
+
interface BoundingSphere {
|
|
53
|
+
center: Vector3;
|
|
54
|
+
radius: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Entity that exists in spatial space
|
|
58
|
+
*/
|
|
59
|
+
interface SpatialEntity {
|
|
60
|
+
id: string;
|
|
61
|
+
type: string;
|
|
62
|
+
position: Vector3;
|
|
63
|
+
rotation?: Quaternion;
|
|
64
|
+
bounds?: BoundingBox | BoundingSphere;
|
|
65
|
+
velocity?: Vector3;
|
|
66
|
+
metadata?: Record<string, unknown>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Defined region in space
|
|
70
|
+
*/
|
|
71
|
+
interface Region {
|
|
72
|
+
id: string;
|
|
73
|
+
name: string;
|
|
74
|
+
type: 'box' | 'sphere' | 'polygon' | 'custom';
|
|
75
|
+
bounds: BoundingBox | BoundingSphere;
|
|
76
|
+
properties?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Line of sight between two points
|
|
80
|
+
*/
|
|
81
|
+
interface SightLine {
|
|
82
|
+
from: Vector3;
|
|
83
|
+
to: Vector3;
|
|
84
|
+
blocked: boolean;
|
|
85
|
+
blockingEntity?: string;
|
|
86
|
+
distance: number;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Complete spatial context for an agent
|
|
90
|
+
*/
|
|
91
|
+
interface SpatialContext {
|
|
92
|
+
/** Agent's current position */
|
|
93
|
+
agentPosition: Vector3;
|
|
94
|
+
/** Agent's orientation */
|
|
95
|
+
agentRotation?: Quaternion;
|
|
96
|
+
/** Agent's bounding volume */
|
|
97
|
+
agentBounds?: BoundingBox;
|
|
98
|
+
/** Current velocity */
|
|
99
|
+
agentVelocity?: Vector3;
|
|
100
|
+
/** Entities within perception radius */
|
|
101
|
+
nearbyEntities: SpatialEntity[];
|
|
102
|
+
/** Regions the agent is currently in */
|
|
103
|
+
currentRegions: Region[];
|
|
104
|
+
/** All defined regions in the scene */
|
|
105
|
+
allRegions: Region[];
|
|
106
|
+
/** Computed sight lines to relevant entities */
|
|
107
|
+
sightLines: SightLine[];
|
|
108
|
+
/** Timestamp of context snapshot */
|
|
109
|
+
timestamp: number;
|
|
110
|
+
/** Update rate in Hz */
|
|
111
|
+
updateRate: number;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Event when entity enters perception radius
|
|
115
|
+
*/
|
|
116
|
+
interface EntityEnteredEvent {
|
|
117
|
+
type: 'entity_entered';
|
|
118
|
+
entity: SpatialEntity;
|
|
119
|
+
distance: number;
|
|
120
|
+
timestamp: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Event when entity exits perception radius
|
|
124
|
+
*/
|
|
125
|
+
interface EntityExitedEvent {
|
|
126
|
+
type: 'entity_exited';
|
|
127
|
+
entity: SpatialEntity;
|
|
128
|
+
timestamp: number;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Event when agent enters a region
|
|
132
|
+
*/
|
|
133
|
+
interface RegionEnteredEvent {
|
|
134
|
+
type: 'region_entered';
|
|
135
|
+
region: Region;
|
|
136
|
+
previousRegion?: Region;
|
|
137
|
+
timestamp: number;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Event when agent exits a region
|
|
141
|
+
*/
|
|
142
|
+
interface RegionExitedEvent {
|
|
143
|
+
type: 'region_exited';
|
|
144
|
+
region: Region;
|
|
145
|
+
timestamp: number;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Event when sight line to entity changes
|
|
149
|
+
*/
|
|
150
|
+
interface VisibilityChangedEvent {
|
|
151
|
+
type: 'visibility_changed';
|
|
152
|
+
entityId: string;
|
|
153
|
+
visible: boolean;
|
|
154
|
+
sightLine: SightLine;
|
|
155
|
+
timestamp: number;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Union of all spatial events
|
|
159
|
+
*/
|
|
160
|
+
type SpatialEvent = EntityEnteredEvent | EntityExitedEvent | RegionEnteredEvent | RegionExitedEvent | VisibilityChangedEvent;
|
|
161
|
+
/**
|
|
162
|
+
* Configuration for spatial awareness
|
|
163
|
+
*/
|
|
164
|
+
interface SpatialAwarenessConfig {
|
|
165
|
+
/** How often to update spatial context (Hz) */
|
|
166
|
+
updateRate: number;
|
|
167
|
+
/** Maximum distance for entity perception (meters) */
|
|
168
|
+
perceptionRadius: number;
|
|
169
|
+
/** Maximum distance for visibility checks (meters) */
|
|
170
|
+
visibilityRadius: number;
|
|
171
|
+
/** Enable region tracking */
|
|
172
|
+
trackRegions: boolean;
|
|
173
|
+
/** Enable sight line computation */
|
|
174
|
+
computeSightLines: boolean;
|
|
175
|
+
/** Entity types to track (empty = all) */
|
|
176
|
+
entityTypeFilter: string[];
|
|
177
|
+
/** Minimum movement to trigger update (meters) */
|
|
178
|
+
movementThreshold: number;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Default spatial awareness configuration
|
|
182
|
+
*/
|
|
183
|
+
declare const DEFAULT_SPATIAL_CONFIG: SpatialAwarenessConfig;
|
|
184
|
+
/**
|
|
185
|
+
* Calculate distance between two points
|
|
186
|
+
*/
|
|
187
|
+
declare function distance(a: Vector3, b: Vector3): number;
|
|
188
|
+
/**
|
|
189
|
+
* Calculate squared distance (faster when comparing)
|
|
190
|
+
*/
|
|
191
|
+
declare function distanceSquared(a: Vector3, b: Vector3): number;
|
|
192
|
+
/**
|
|
193
|
+
* Check if point is inside bounding box
|
|
194
|
+
*/
|
|
195
|
+
declare function isPointInBox(point: Vector3, box: BoundingBox): boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Check if point is inside sphere
|
|
198
|
+
*/
|
|
199
|
+
declare function isPointInSphere(point: Vector3, sphere: BoundingSphere): boolean;
|
|
200
|
+
/**
|
|
201
|
+
* Get center of bounding box
|
|
202
|
+
*/
|
|
203
|
+
declare function getBoxCenter(box: BoundingBox): Vector3;
|
|
204
|
+
/**
|
|
205
|
+
* Check if two bounding boxes overlap
|
|
206
|
+
*/
|
|
207
|
+
declare function boxesOverlap(a: BoundingBox, b: BoundingBox): boolean;
|
|
208
|
+
/**
|
|
209
|
+
* Normalize a vector
|
|
210
|
+
*/
|
|
211
|
+
declare function normalize(v: Vector3): Vector3;
|
|
212
|
+
/**
|
|
213
|
+
* Subtract two vectors
|
|
214
|
+
*/
|
|
215
|
+
declare function subtract(a: Vector3, b: Vector3): Vector3;
|
|
216
|
+
/**
|
|
217
|
+
* Add two vectors
|
|
218
|
+
*/
|
|
219
|
+
declare function add(a: Vector3, b: Vector3): Vector3;
|
|
220
|
+
/**
|
|
221
|
+
* Scale a vector
|
|
222
|
+
*/
|
|
223
|
+
declare function scale(v: Vector3, s: number): Vector3;
|
|
224
|
+
/**
|
|
225
|
+
* Dot product of two vectors
|
|
226
|
+
*/
|
|
227
|
+
declare function dot(a: Vector3, b: Vector3): number;
|
|
228
|
+
/**
|
|
229
|
+
* Cross product of two vectors
|
|
230
|
+
*/
|
|
231
|
+
declare function cross(a: Vector3, b: Vector3): Vector3;
|
|
232
|
+
/**
|
|
233
|
+
* Linear interpolation between two vectors
|
|
234
|
+
*/
|
|
235
|
+
declare function lerp(a: Vector3, b: Vector3, t: number): Vector3;
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Spatial Query System
|
|
239
|
+
* Sprint 4 Priority 4 - Spatial Context Awareness
|
|
240
|
+
*
|
|
241
|
+
* Provides efficient spatial queries for finding entities based on
|
|
242
|
+
* distance, visibility, reachability, and region containment.
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Types of spatial queries
|
|
247
|
+
*/
|
|
248
|
+
type SpatialQueryType = 'nearest' | 'within' | 'visible' | 'reachable' | 'in_region' | 'by_type' | 'raycast';
|
|
249
|
+
/**
|
|
250
|
+
* Base query interface
|
|
251
|
+
*/
|
|
252
|
+
interface SpatialQueryBase {
|
|
253
|
+
type: SpatialQueryType;
|
|
254
|
+
from: Vector3;
|
|
255
|
+
entityTypeFilter?: string[];
|
|
256
|
+
maxResults?: number;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Find nearest entities
|
|
260
|
+
*/
|
|
261
|
+
interface NearestQuery extends SpatialQueryBase {
|
|
262
|
+
type: 'nearest';
|
|
263
|
+
count?: number;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Find entities within radius
|
|
267
|
+
*/
|
|
268
|
+
interface WithinQuery extends SpatialQueryBase {
|
|
269
|
+
type: 'within';
|
|
270
|
+
radius: number;
|
|
271
|
+
includePartial?: boolean;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Find visible entities
|
|
275
|
+
*/
|
|
276
|
+
interface VisibleQuery extends SpatialQueryBase {
|
|
277
|
+
type: 'visible';
|
|
278
|
+
direction?: Vector3;
|
|
279
|
+
fov?: number;
|
|
280
|
+
maxDistance?: number;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Find reachable entities (pathfinding)
|
|
284
|
+
*/
|
|
285
|
+
interface ReachableQuery extends SpatialQueryBase {
|
|
286
|
+
type: 'reachable';
|
|
287
|
+
maxDistance?: number;
|
|
288
|
+
obstacles?: SpatialEntity[];
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Find entities in a region
|
|
292
|
+
*/
|
|
293
|
+
interface InRegionQuery extends SpatialQueryBase {
|
|
294
|
+
type: 'in_region';
|
|
295
|
+
region: Region;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Find entities by type
|
|
299
|
+
*/
|
|
300
|
+
interface ByTypeQuery extends SpatialQueryBase {
|
|
301
|
+
type: 'by_type';
|
|
302
|
+
entityTypes: string[];
|
|
303
|
+
radius?: number;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Raycast query
|
|
307
|
+
*/
|
|
308
|
+
interface RaycastQuery extends SpatialQueryBase {
|
|
309
|
+
type: 'raycast';
|
|
310
|
+
direction: Vector3;
|
|
311
|
+
maxDistance: number;
|
|
312
|
+
hitFirst?: boolean;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Union of all query types
|
|
316
|
+
*/
|
|
317
|
+
type SpatialQuery = NearestQuery | WithinQuery | VisibleQuery | ReachableQuery | InRegionQuery | ByTypeQuery | RaycastQuery;
|
|
318
|
+
/**
|
|
319
|
+
* Single query result with distance
|
|
320
|
+
*/
|
|
321
|
+
interface QueryResult {
|
|
322
|
+
entity: SpatialEntity;
|
|
323
|
+
distance: number;
|
|
324
|
+
direction?: Vector3;
|
|
325
|
+
sightLine?: SightLine;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Raycast hit result
|
|
329
|
+
*/
|
|
330
|
+
interface RaycastHit {
|
|
331
|
+
entity: SpatialEntity;
|
|
332
|
+
point: Vector3;
|
|
333
|
+
distance: number;
|
|
334
|
+
normal?: Vector3;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Executes spatial queries against a set of entities
|
|
338
|
+
*/
|
|
339
|
+
declare class SpatialQueryExecutor {
|
|
340
|
+
private entities;
|
|
341
|
+
private regions;
|
|
342
|
+
private spatialIndex;
|
|
343
|
+
constructor();
|
|
344
|
+
/**
|
|
345
|
+
* Update the entity set
|
|
346
|
+
*/
|
|
347
|
+
updateEntities(entities: SpatialEntity[]): void;
|
|
348
|
+
/**
|
|
349
|
+
* Update regions
|
|
350
|
+
*/
|
|
351
|
+
updateRegions(regions: Region[]): void;
|
|
352
|
+
/**
|
|
353
|
+
* Execute a spatial query
|
|
354
|
+
*/
|
|
355
|
+
execute(query: SpatialQuery): QueryResult[];
|
|
356
|
+
/**
|
|
357
|
+
* Find nearest entities
|
|
358
|
+
*/
|
|
359
|
+
private executeNearest;
|
|
360
|
+
/**
|
|
361
|
+
* Find entities within radius
|
|
362
|
+
*/
|
|
363
|
+
private executeWithin;
|
|
364
|
+
/**
|
|
365
|
+
* Find visible entities
|
|
366
|
+
*/
|
|
367
|
+
private executeVisible;
|
|
368
|
+
/**
|
|
369
|
+
* Find reachable entities (simplified - no full pathfinding)
|
|
370
|
+
*/
|
|
371
|
+
private executeReachable;
|
|
372
|
+
/**
|
|
373
|
+
* Find entities in a region
|
|
374
|
+
*/
|
|
375
|
+
private executeInRegion;
|
|
376
|
+
/**
|
|
377
|
+
* Find entities by type
|
|
378
|
+
*/
|
|
379
|
+
private executeByType;
|
|
380
|
+
/**
|
|
381
|
+
* Execute raycast
|
|
382
|
+
*/
|
|
383
|
+
private executeRaycast;
|
|
384
|
+
/**
|
|
385
|
+
* Check line of sight between two points
|
|
386
|
+
*/
|
|
387
|
+
private checkSightLine;
|
|
388
|
+
/**
|
|
389
|
+
* Raycast against a single entity
|
|
390
|
+
*/
|
|
391
|
+
private raycastEntity;
|
|
392
|
+
/**
|
|
393
|
+
* Get approximate radius of an entity
|
|
394
|
+
*/
|
|
395
|
+
private getEntityRadius;
|
|
396
|
+
/**
|
|
397
|
+
* Check if point is in region
|
|
398
|
+
*/
|
|
399
|
+
private isInRegion;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Spatial Context Provider
|
|
404
|
+
* Sprint 4 Priority 4 - Spatial Context Awareness
|
|
405
|
+
*
|
|
406
|
+
* Manages spatial context for agents, providing real-time updates about
|
|
407
|
+
* nearby entities, regions, and visibility.
|
|
408
|
+
*/
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Events emitted by the spatial context provider
|
|
412
|
+
*/
|
|
413
|
+
interface SpatialContextProviderEvents {
|
|
414
|
+
'entity:entered': (agentId: string, event: SpatialEvent) => void;
|
|
415
|
+
'entity:exited': (agentId: string, event: SpatialEvent) => void;
|
|
416
|
+
'region:entered': (agentId: string, event: SpatialEvent) => void;
|
|
417
|
+
'region:exited': (agentId: string, event: SpatialEvent) => void;
|
|
418
|
+
'visibility:changed': (agentId: string, event: SpatialEvent) => void;
|
|
419
|
+
'context:updated': (agentId: string, context: SpatialContext) => void;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Provides spatial context to agents
|
|
423
|
+
*/
|
|
424
|
+
declare class SpatialContextProvider extends EventEmitter {
|
|
425
|
+
private agents;
|
|
426
|
+
private entities;
|
|
427
|
+
private regions;
|
|
428
|
+
private queryExecutor;
|
|
429
|
+
private updateInterval;
|
|
430
|
+
private isRunning;
|
|
431
|
+
constructor();
|
|
432
|
+
/**
|
|
433
|
+
* Start the spatial context provider
|
|
434
|
+
*/
|
|
435
|
+
start(): void;
|
|
436
|
+
/**
|
|
437
|
+
* Stop the spatial context provider
|
|
438
|
+
*/
|
|
439
|
+
stop(): void;
|
|
440
|
+
/**
|
|
441
|
+
* Manual update (for testing or custom update loops)
|
|
442
|
+
*/
|
|
443
|
+
update(): void;
|
|
444
|
+
/**
|
|
445
|
+
* Register an agent for spatial awareness
|
|
446
|
+
*/
|
|
447
|
+
registerAgent(agentId: string, position: Vector3, config?: Partial<SpatialAwarenessConfig>): void;
|
|
448
|
+
/**
|
|
449
|
+
* Unregister an agent
|
|
450
|
+
*/
|
|
451
|
+
unregisterAgent(agentId: string): void;
|
|
452
|
+
/**
|
|
453
|
+
* Update agent position
|
|
454
|
+
*/
|
|
455
|
+
updateAgentPosition(agentId: string, position: Vector3, velocity?: Vector3): void;
|
|
456
|
+
/**
|
|
457
|
+
* Get agent's current spatial context
|
|
458
|
+
*/
|
|
459
|
+
getContext(agentId: string): SpatialContext | null;
|
|
460
|
+
/**
|
|
461
|
+
* Add or update an entity
|
|
462
|
+
*/
|
|
463
|
+
setEntity(entity: SpatialEntity): void;
|
|
464
|
+
/**
|
|
465
|
+
* Remove an entity
|
|
466
|
+
*/
|
|
467
|
+
removeEntity(entityId: string): void;
|
|
468
|
+
/**
|
|
469
|
+
* Batch update entities
|
|
470
|
+
*/
|
|
471
|
+
setEntities(entities: SpatialEntity[]): void;
|
|
472
|
+
/**
|
|
473
|
+
* Get all entities
|
|
474
|
+
*/
|
|
475
|
+
getEntities(): SpatialEntity[];
|
|
476
|
+
/**
|
|
477
|
+
* Add or update a region
|
|
478
|
+
*/
|
|
479
|
+
setRegion(region: Region): void;
|
|
480
|
+
/**
|
|
481
|
+
* Remove a region
|
|
482
|
+
*/
|
|
483
|
+
removeRegion(regionId: string): void;
|
|
484
|
+
/**
|
|
485
|
+
* Subscribe to region events for an agent
|
|
486
|
+
*/
|
|
487
|
+
subscribeToRegion(agentId: string, regionId: string, callback: (event: SpatialEvent) => void): void;
|
|
488
|
+
/**
|
|
489
|
+
* Unsubscribe from region events
|
|
490
|
+
*/
|
|
491
|
+
unsubscribeFromRegion(agentId: string, regionId: string): void;
|
|
492
|
+
/**
|
|
493
|
+
* Execute a spatial query
|
|
494
|
+
*/
|
|
495
|
+
query(query: SpatialQuery): QueryResult[];
|
|
496
|
+
/**
|
|
497
|
+
* Find nearest entities to position
|
|
498
|
+
*/
|
|
499
|
+
findNearest(from: Vector3, count?: number, typeFilter?: string[]): QueryResult[];
|
|
500
|
+
/**
|
|
501
|
+
* Find entities within radius
|
|
502
|
+
*/
|
|
503
|
+
findWithin(from: Vector3, radius: number, typeFilter?: string[]): QueryResult[];
|
|
504
|
+
/**
|
|
505
|
+
* Find visible entities from position
|
|
506
|
+
*/
|
|
507
|
+
findVisible(from: Vector3, direction?: Vector3, fov?: number, maxDistance?: number): QueryResult[];
|
|
508
|
+
/**
|
|
509
|
+
* Update context for a single agent
|
|
510
|
+
*/
|
|
511
|
+
private updateAgentContext;
|
|
512
|
+
/**
|
|
513
|
+
* Find entities within radius of position
|
|
514
|
+
*/
|
|
515
|
+
private findEntitiesInRadius;
|
|
516
|
+
/**
|
|
517
|
+
* Find regions containing position
|
|
518
|
+
*/
|
|
519
|
+
private findRegionsContaining;
|
|
520
|
+
/**
|
|
521
|
+
* Check if position is in region
|
|
522
|
+
*/
|
|
523
|
+
private isInRegion;
|
|
524
|
+
/**
|
|
525
|
+
* Check for entity enter/exit events
|
|
526
|
+
*/
|
|
527
|
+
private checkEntityEvents;
|
|
528
|
+
/**
|
|
529
|
+
* Check for region enter/exit events
|
|
530
|
+
*/
|
|
531
|
+
private checkRegionEvents;
|
|
532
|
+
/**
|
|
533
|
+
* Compute sight lines to entities
|
|
534
|
+
*/
|
|
535
|
+
private computeSightLines;
|
|
536
|
+
/**
|
|
537
|
+
* Check if line between two points is blocked
|
|
538
|
+
*/
|
|
539
|
+
private isLineBlocked;
|
|
540
|
+
/**
|
|
541
|
+
* Get entity radius
|
|
542
|
+
*/
|
|
543
|
+
private getEntityRadius;
|
|
544
|
+
/**
|
|
545
|
+
* Dot product
|
|
546
|
+
*/
|
|
547
|
+
private dot3;
|
|
548
|
+
/**
|
|
549
|
+
* Rebuild the query executor index
|
|
550
|
+
*/
|
|
551
|
+
private rebuildQueryIndex;
|
|
552
|
+
/**
|
|
553
|
+
* Get minimum update interval
|
|
554
|
+
*/
|
|
555
|
+
private getMinUpdateInterval;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Spatial Constraint Types for HoloScript Type System
|
|
560
|
+
*
|
|
561
|
+
* Defines compile-time spatial constraint trait extensions:
|
|
562
|
+
* - spatial_adjacent: Two entities must be within a given distance threshold
|
|
563
|
+
* - spatial_contains: One entity's bounds must fully enclose another
|
|
564
|
+
* - spatial_reachable: An unobstructed path must exist between entities
|
|
565
|
+
* - spatial_temporal_adjacent: Adjacency that must hold for N seconds (duration constraint)
|
|
566
|
+
* - spatial_temporal_reachable: Reachability with moving obstacle velocity prediction
|
|
567
|
+
* - spatial_trajectory: Path-based constraints over predicted entity motion
|
|
568
|
+
*
|
|
569
|
+
* These constraints are verified at compile time (static analysis of spatial
|
|
570
|
+
* declarations) and optionally enforced at runtime via the trait handlers.
|
|
571
|
+
*
|
|
572
|
+
* @module spatial/SpatialConstraintTypes
|
|
573
|
+
*/
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Discriminant for the spatial constraint families.
|
|
577
|
+
*
|
|
578
|
+
* Includes the original three plus the spatiotemporal extensions:
|
|
579
|
+
* - spatial_temporal_adjacent: adjacency that must hold for a duration
|
|
580
|
+
* - spatial_temporal_reachable: reachability accounting for moving obstacles
|
|
581
|
+
* - spatial_trajectory: path-based constraints over predicted motion
|
|
582
|
+
*/
|
|
583
|
+
type SpatialConstraintKind = 'spatial_adjacent' | 'spatial_contains' | 'spatial_reachable' | 'spatial_temporal_adjacent' | 'spatial_temporal_reachable' | 'spatial_trajectory';
|
|
584
|
+
/**
|
|
585
|
+
* Adjacency constraint: entities A and B must remain within `maxDistance`
|
|
586
|
+
* of each other. If `minDistance` is specified they must also be at least
|
|
587
|
+
* that far apart (useful for preventing overlap).
|
|
588
|
+
*
|
|
589
|
+
* HoloScript syntax:
|
|
590
|
+
* ```holoscript
|
|
591
|
+
* orb#shelf {
|
|
592
|
+
* @spatial_adjacent(target: "book", maxDistance: 1.5m, axis: "xz")
|
|
593
|
+
* }
|
|
594
|
+
* ```
|
|
595
|
+
*/
|
|
596
|
+
interface SpatialAdjacentConstraint {
|
|
597
|
+
kind: 'spatial_adjacent';
|
|
598
|
+
/** Source entity that declares the constraint */
|
|
599
|
+
sourceId: string;
|
|
600
|
+
/** Target entity or entity type that must be adjacent */
|
|
601
|
+
targetId: string;
|
|
602
|
+
/** Maximum allowable distance (meters). Required. */
|
|
603
|
+
maxDistance: number;
|
|
604
|
+
/** Minimum allowable distance (meters). Defaults to 0. */
|
|
605
|
+
minDistance?: number;
|
|
606
|
+
/**
|
|
607
|
+
* Axis restriction for distance calculation.
|
|
608
|
+
* - 'xyz' full 3D distance (default)
|
|
609
|
+
* - 'xz' horizontal plane only (ignores y)
|
|
610
|
+
* - 'xy' vertical plane only (ignores z)
|
|
611
|
+
* - 'x'|'y'|'z' single axis
|
|
612
|
+
*/
|
|
613
|
+
axis?: SpatialAxis;
|
|
614
|
+
/** Whether the constraint is bidirectional (default true) */
|
|
615
|
+
bidirectional?: boolean;
|
|
616
|
+
/** Human-readable label for error messages */
|
|
617
|
+
label?: string;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Configuration for the spatial_adjacent trait (parsed from HoloScript source).
|
|
621
|
+
*/
|
|
622
|
+
interface SpatialAdjacentConfig {
|
|
623
|
+
target: string;
|
|
624
|
+
maxDistance: number;
|
|
625
|
+
minDistance?: number;
|
|
626
|
+
axis?: SpatialAxis;
|
|
627
|
+
bidirectional?: boolean;
|
|
628
|
+
/** When true, emit warnings instead of errors at compile time */
|
|
629
|
+
soft?: boolean;
|
|
630
|
+
/** Runtime enforcement mode */
|
|
631
|
+
enforcement?: SpatialEnforcementMode;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Containment constraint: entity A's bounding volume must fully enclose
|
|
635
|
+
* entity B. Useful for zones, rooms, inventories, and UI containers.
|
|
636
|
+
*
|
|
637
|
+
* HoloScript syntax:
|
|
638
|
+
* ```holoscript
|
|
639
|
+
* orb#room {
|
|
640
|
+
* @spatial_contains(target: "furniture", margin: 0.1m, strict: true)
|
|
641
|
+
* }
|
|
642
|
+
* ```
|
|
643
|
+
*/
|
|
644
|
+
interface SpatialContainsConstraint {
|
|
645
|
+
kind: 'spatial_contains';
|
|
646
|
+
/** The container entity */
|
|
647
|
+
containerId: string;
|
|
648
|
+
/** The entity that must be fully inside the container */
|
|
649
|
+
containedId: string;
|
|
650
|
+
/**
|
|
651
|
+
* Extra margin (meters) that must exist between the contained entity's
|
|
652
|
+
* bounds and the container's bounds. Defaults to 0.
|
|
653
|
+
*/
|
|
654
|
+
margin?: number;
|
|
655
|
+
/**
|
|
656
|
+
* Strict mode: if true, the contained entity's full bounding volume
|
|
657
|
+
* must be inside. If false (default), only the center point is checked.
|
|
658
|
+
*/
|
|
659
|
+
strict?: boolean;
|
|
660
|
+
/** Whether to also check child entities recursively */
|
|
661
|
+
recursive?: boolean;
|
|
662
|
+
/** Human-readable label for error messages */
|
|
663
|
+
label?: string;
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Configuration for the spatial_contains trait.
|
|
667
|
+
*/
|
|
668
|
+
interface SpatialContainsConfig {
|
|
669
|
+
target: string;
|
|
670
|
+
margin?: number;
|
|
671
|
+
strict?: boolean;
|
|
672
|
+
recursive?: boolean;
|
|
673
|
+
/** When true, emit warnings instead of errors at compile time */
|
|
674
|
+
soft?: boolean;
|
|
675
|
+
/** Runtime enforcement mode */
|
|
676
|
+
enforcement?: SpatialEnforcementMode;
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Reachability constraint: a clear (unobstructed) path must exist from
|
|
680
|
+
* entity A to entity B, considering obstacles and navigation meshes.
|
|
681
|
+
*
|
|
682
|
+
* HoloScript syntax:
|
|
683
|
+
* ```holoscript
|
|
684
|
+
* orb#npc {
|
|
685
|
+
* @spatial_reachable(
|
|
686
|
+
* target: "exit_door",
|
|
687
|
+
* maxPathLength: 50m,
|
|
688
|
+
* obstacles: ["wall", "barrier"],
|
|
689
|
+
* algorithm: "navmesh"
|
|
690
|
+
* )
|
|
691
|
+
* }
|
|
692
|
+
* ```
|
|
693
|
+
*/
|
|
694
|
+
interface SpatialReachableConstraint {
|
|
695
|
+
kind: 'spatial_reachable';
|
|
696
|
+
/** The starting entity */
|
|
697
|
+
sourceId: string;
|
|
698
|
+
/** The destination entity */
|
|
699
|
+
targetId: string;
|
|
700
|
+
/**
|
|
701
|
+
* Maximum allowable path length in meters.
|
|
702
|
+
* If the shortest unobstructed path exceeds this, the constraint fails.
|
|
703
|
+
*/
|
|
704
|
+
maxPathLength?: number;
|
|
705
|
+
/**
|
|
706
|
+
* Entity types (or specific IDs) that are considered obstacles.
|
|
707
|
+
* If empty, only static colliders block reachability.
|
|
708
|
+
*/
|
|
709
|
+
obstacleTypes?: string[];
|
|
710
|
+
/**
|
|
711
|
+
* Pathfinding algorithm hint.
|
|
712
|
+
* - 'line_of_sight' simple raycast (fast, conservative)
|
|
713
|
+
* - 'navmesh' navigation mesh query (accurate)
|
|
714
|
+
* - 'astar' grid-based A* (general purpose)
|
|
715
|
+
*/
|
|
716
|
+
algorithm?: SpatialReachableAlgorithm;
|
|
717
|
+
/** Agent radius for path clearance (meters). Defaults to 0.5 */
|
|
718
|
+
agentRadius?: number;
|
|
719
|
+
/** Whether the constraint is bidirectional (default true) */
|
|
720
|
+
bidirectional?: boolean;
|
|
721
|
+
/** Human-readable label for error messages */
|
|
722
|
+
label?: string;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Configuration for the spatial_reachable trait.
|
|
726
|
+
*/
|
|
727
|
+
interface SpatialReachableConfig {
|
|
728
|
+
target: string;
|
|
729
|
+
maxPathLength?: number;
|
|
730
|
+
obstacleTypes?: string[];
|
|
731
|
+
algorithm?: SpatialReachableAlgorithm;
|
|
732
|
+
agentRadius?: number;
|
|
733
|
+
bidirectional?: boolean;
|
|
734
|
+
/** When true, emit warnings instead of errors at compile time */
|
|
735
|
+
soft?: boolean;
|
|
736
|
+
/** Runtime enforcement mode */
|
|
737
|
+
enforcement?: SpatialEnforcementMode;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Temporal adjacency constraint: entities A and B must remain within
|
|
741
|
+
* `maxDistance` for at least `minDuration` seconds. Optionally, the
|
|
742
|
+
* constraint only triggers a violation after the condition has been
|
|
743
|
+
* broken for `gracePeriod` seconds (hysteresis).
|
|
744
|
+
*
|
|
745
|
+
* HoloScript syntax:
|
|
746
|
+
* ```holoscript
|
|
747
|
+
* orb#guard {
|
|
748
|
+
* @spatial_temporal_adjacent(
|
|
749
|
+
* target: "prisoner",
|
|
750
|
+
* maxDistance: 3m,
|
|
751
|
+
* minDuration: 5s,
|
|
752
|
+
* gracePeriod: 1s,
|
|
753
|
+
* axis: "xz"
|
|
754
|
+
* )
|
|
755
|
+
* }
|
|
756
|
+
* ```
|
|
757
|
+
*/
|
|
758
|
+
interface SpatialTemporalAdjacentConstraint {
|
|
759
|
+
kind: 'spatial_temporal_adjacent';
|
|
760
|
+
/** Source entity that declares the constraint */
|
|
761
|
+
sourceId: string;
|
|
762
|
+
/** Target entity or entity type that must be adjacent */
|
|
763
|
+
targetId: string;
|
|
764
|
+
/** Maximum allowable distance (meters). Required. */
|
|
765
|
+
maxDistance: number;
|
|
766
|
+
/** Minimum allowable distance (meters). Defaults to 0. */
|
|
767
|
+
minDistance?: number;
|
|
768
|
+
/**
|
|
769
|
+
* Minimum duration (seconds) the adjacency condition must hold
|
|
770
|
+
* continuously before the constraint is considered satisfied.
|
|
771
|
+
*/
|
|
772
|
+
minDuration: number;
|
|
773
|
+
/**
|
|
774
|
+
* Grace period (seconds). After the adjacency condition breaks,
|
|
775
|
+
* wait this long before emitting a violation. Provides hysteresis
|
|
776
|
+
* to prevent flickering. Defaults to 0.
|
|
777
|
+
*/
|
|
778
|
+
gracePeriod?: number;
|
|
779
|
+
/** Axis restriction for distance calculation. */
|
|
780
|
+
axis?: SpatialAxis;
|
|
781
|
+
/** Whether the constraint is bidirectional (default true) */
|
|
782
|
+
bidirectional?: boolean;
|
|
783
|
+
/** Human-readable label for error messages */
|
|
784
|
+
label?: string;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Configuration for the spatial_temporal_adjacent trait (parsed from HoloScript).
|
|
788
|
+
*/
|
|
789
|
+
interface SpatialTemporalAdjacentConfig {
|
|
790
|
+
target: string;
|
|
791
|
+
maxDistance: number;
|
|
792
|
+
minDistance?: number;
|
|
793
|
+
minDuration: number;
|
|
794
|
+
gracePeriod?: number;
|
|
795
|
+
axis?: SpatialAxis;
|
|
796
|
+
bidirectional?: boolean;
|
|
797
|
+
/** When true, emit warnings instead of errors at compile time */
|
|
798
|
+
soft?: boolean;
|
|
799
|
+
/** Runtime enforcement mode */
|
|
800
|
+
enforcement?: SpatialEnforcementMode;
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Velocity-aware reachability constraint: checks whether a path exists
|
|
804
|
+
* from entity A to entity B, accounting for moving obstacles by predicting
|
|
805
|
+
* their positions `predictionHorizon` seconds into the future based on
|
|
806
|
+
* their current velocity vectors.
|
|
807
|
+
*
|
|
808
|
+
* HoloScript syntax:
|
|
809
|
+
* ```holoscript
|
|
810
|
+
* orb#drone {
|
|
811
|
+
* @spatial_temporal_reachable(
|
|
812
|
+
* target: "landing_pad",
|
|
813
|
+
* maxPathLength: 100m,
|
|
814
|
+
* predictionHorizon: 3s,
|
|
815
|
+
* movingObstacles: ["vehicle", "drone"],
|
|
816
|
+
* safetyMargin: 1.5m
|
|
817
|
+
* )
|
|
818
|
+
* }
|
|
819
|
+
* ```
|
|
820
|
+
*/
|
|
821
|
+
interface SpatialTemporalReachableConstraint {
|
|
822
|
+
kind: 'spatial_temporal_reachable';
|
|
823
|
+
/** The starting entity */
|
|
824
|
+
sourceId: string;
|
|
825
|
+
/** The destination entity */
|
|
826
|
+
targetId: string;
|
|
827
|
+
/** Maximum allowable path length in meters. */
|
|
828
|
+
maxPathLength?: number;
|
|
829
|
+
/**
|
|
830
|
+
* How far into the future (seconds) to predict obstacle positions.
|
|
831
|
+
* Obstacle positions are extrapolated via position + velocity * t.
|
|
832
|
+
*/
|
|
833
|
+
predictionHorizon: number;
|
|
834
|
+
/**
|
|
835
|
+
* Entity types (or specific IDs) treated as moving obstacles.
|
|
836
|
+
* Their velocity vectors are read from the spatial context.
|
|
837
|
+
*/
|
|
838
|
+
movingObstacles?: string[];
|
|
839
|
+
/**
|
|
840
|
+
* Static obstacle types (no velocity prediction applied).
|
|
841
|
+
*/
|
|
842
|
+
staticObstacles?: string[];
|
|
843
|
+
/**
|
|
844
|
+
* Safety margin (meters) to add around predicted obstacle positions.
|
|
845
|
+
* Accounts for velocity uncertainty. Defaults to 0.5.
|
|
846
|
+
*/
|
|
847
|
+
safetyMargin?: number;
|
|
848
|
+
/** Pathfinding algorithm hint. */
|
|
849
|
+
algorithm?: SpatialReachableAlgorithm;
|
|
850
|
+
/** Agent radius for path clearance (meters). Defaults to 0.5 */
|
|
851
|
+
agentRadius?: number;
|
|
852
|
+
/** Whether the constraint is bidirectional (default true) */
|
|
853
|
+
bidirectional?: boolean;
|
|
854
|
+
/** Human-readable label for error messages */
|
|
855
|
+
label?: string;
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Configuration for the spatial_temporal_reachable trait.
|
|
859
|
+
*/
|
|
860
|
+
interface SpatialTemporalReachableConfig {
|
|
861
|
+
target: string;
|
|
862
|
+
maxPathLength?: number;
|
|
863
|
+
predictionHorizon: number;
|
|
864
|
+
movingObstacles?: string[];
|
|
865
|
+
staticObstacles?: string[];
|
|
866
|
+
safetyMargin?: number;
|
|
867
|
+
algorithm?: SpatialReachableAlgorithm;
|
|
868
|
+
agentRadius?: number;
|
|
869
|
+
bidirectional?: boolean;
|
|
870
|
+
/** When true, emit warnings instead of errors at compile time */
|
|
871
|
+
soft?: boolean;
|
|
872
|
+
/** Runtime enforcement mode */
|
|
873
|
+
enforcement?: SpatialEnforcementMode;
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Trajectory constraint: verifies that the predicted motion path of an
|
|
877
|
+
* entity satisfies spatial constraints. The trajectory is computed from
|
|
878
|
+
* position + velocity (and optional acceleration) over a time horizon,
|
|
879
|
+
* and can be checked against keep-in zones, keep-out zones, waypoints,
|
|
880
|
+
* and maximum deviation from a reference path.
|
|
881
|
+
*
|
|
882
|
+
* HoloScript syntax:
|
|
883
|
+
* ```holoscript
|
|
884
|
+
* orb#missile {
|
|
885
|
+
* @spatial_trajectory(
|
|
886
|
+
* mode: "keep_in",
|
|
887
|
+
* region: "safe_corridor",
|
|
888
|
+
* horizon: 5s,
|
|
889
|
+
* sampleCount: 20,
|
|
890
|
+
* maxDeviation: 2m
|
|
891
|
+
* )
|
|
892
|
+
* }
|
|
893
|
+
* ```
|
|
894
|
+
*/
|
|
895
|
+
interface SpatialTrajectoryConstraint {
|
|
896
|
+
kind: 'spatial_trajectory';
|
|
897
|
+
/** The entity whose trajectory is being constrained */
|
|
898
|
+
sourceId: string;
|
|
899
|
+
/**
|
|
900
|
+
* Constraint mode:
|
|
901
|
+
* - 'keep_in': trajectory must stay inside the region
|
|
902
|
+
* - 'keep_out': trajectory must avoid the region
|
|
903
|
+
* - 'follow': trajectory must stay within maxDeviation of a reference path
|
|
904
|
+
* - 'waypoint': trajectory must pass through specified waypoints
|
|
905
|
+
*/
|
|
906
|
+
mode: SpatialTrajectoryMode;
|
|
907
|
+
/**
|
|
908
|
+
* Region ID or entity ID that defines the spatial boundary
|
|
909
|
+
* (for keep_in and keep_out modes).
|
|
910
|
+
*/
|
|
911
|
+
regionId?: string;
|
|
912
|
+
/**
|
|
913
|
+
* Time horizon (seconds) over which to predict the trajectory.
|
|
914
|
+
*/
|
|
915
|
+
horizon: number;
|
|
916
|
+
/**
|
|
917
|
+
* Number of sample points along the trajectory to check.
|
|
918
|
+
* Higher values increase accuracy but cost more. Defaults to 10.
|
|
919
|
+
*/
|
|
920
|
+
sampleCount?: number;
|
|
921
|
+
/**
|
|
922
|
+
* Maximum allowed deviation (meters) from a reference path
|
|
923
|
+
* (for 'follow' mode).
|
|
924
|
+
*/
|
|
925
|
+
maxDeviation?: number;
|
|
926
|
+
/**
|
|
927
|
+
* Waypoints the trajectory must pass through (for 'waypoint' mode).
|
|
928
|
+
* Each waypoint has a position and an acceptance radius.
|
|
929
|
+
*/
|
|
930
|
+
waypoints?: TrajectoryWaypoint[];
|
|
931
|
+
/**
|
|
932
|
+
* Reference path for 'follow' mode. An ordered list of points
|
|
933
|
+
* defining the ideal trajectory.
|
|
934
|
+
*/
|
|
935
|
+
referencePath?: Vector3[];
|
|
936
|
+
/**
|
|
937
|
+
* Whether to account for acceleration (quadratic prediction)
|
|
938
|
+
* instead of linear velocity extrapolation. Defaults to false.
|
|
939
|
+
*/
|
|
940
|
+
useAcceleration?: boolean;
|
|
941
|
+
/** Human-readable label for error messages */
|
|
942
|
+
label?: string;
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* A waypoint along a trajectory, with an acceptance radius.
|
|
946
|
+
*/
|
|
947
|
+
interface TrajectoryWaypoint {
|
|
948
|
+
position: Vector3;
|
|
949
|
+
/** Radius (meters) within which the trajectory is considered to pass through */
|
|
950
|
+
radius: number;
|
|
951
|
+
/** Optional label for diagnostics */
|
|
952
|
+
label?: string;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Trajectory constraint mode.
|
|
956
|
+
*/
|
|
957
|
+
type SpatialTrajectoryMode = 'keep_in' | 'keep_out' | 'follow' | 'waypoint';
|
|
958
|
+
/**
|
|
959
|
+
* Configuration for the spatial_trajectory trait.
|
|
960
|
+
*/
|
|
961
|
+
interface SpatialTrajectoryConfig {
|
|
962
|
+
mode: SpatialTrajectoryMode;
|
|
963
|
+
regionId?: string;
|
|
964
|
+
horizon: number;
|
|
965
|
+
sampleCount?: number;
|
|
966
|
+
maxDeviation?: number;
|
|
967
|
+
waypoints?: TrajectoryWaypoint[];
|
|
968
|
+
referencePath?: Vector3[];
|
|
969
|
+
useAcceleration?: boolean;
|
|
970
|
+
/** When true, emit warnings instead of errors at compile time */
|
|
971
|
+
soft?: boolean;
|
|
972
|
+
/** Runtime enforcement mode */
|
|
973
|
+
enforcement?: SpatialEnforcementMode;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Axis filter for distance calculations.
|
|
977
|
+
*/
|
|
978
|
+
type SpatialAxis = 'xyz' | 'xz' | 'xy' | 'x' | 'y' | 'z';
|
|
979
|
+
/**
|
|
980
|
+
* Pathfinding algorithm for reachability.
|
|
981
|
+
*/
|
|
982
|
+
type SpatialReachableAlgorithm = 'line_of_sight' | 'navmesh' | 'astar';
|
|
983
|
+
/**
|
|
984
|
+
* How the constraint is enforced at runtime.
|
|
985
|
+
* - 'prevent' block the violating action (e.g., prevent entity from moving out of range)
|
|
986
|
+
* - 'correct' snap entity back to valid state
|
|
987
|
+
* - 'warn' emit a runtime warning but allow the violation
|
|
988
|
+
* - 'none' compile-time only, no runtime checks
|
|
989
|
+
*/
|
|
990
|
+
type SpatialEnforcementMode = 'prevent' | 'correct' | 'warn' | 'none';
|
|
991
|
+
/**
|
|
992
|
+
* Union of all spatial constraints (including spatiotemporal extensions).
|
|
993
|
+
*/
|
|
994
|
+
type SpatialConstraint = SpatialAdjacentConstraint | SpatialContainsConstraint | SpatialReachableConstraint | SpatialTemporalAdjacentConstraint | SpatialTemporalReachableConstraint | SpatialTrajectoryConstraint;
|
|
995
|
+
/**
|
|
996
|
+
* Severity level for spatial constraint diagnostics.
|
|
997
|
+
*/
|
|
998
|
+
type SpatialDiagnosticSeverity = 'error' | 'warning' | 'info';
|
|
999
|
+
/**
|
|
1000
|
+
* A single diagnostic produced by compile-time spatial constraint verification.
|
|
1001
|
+
*/
|
|
1002
|
+
interface SpatialConstraintDiagnostic {
|
|
1003
|
+
/** Severity of the diagnostic */
|
|
1004
|
+
severity: SpatialDiagnosticSeverity;
|
|
1005
|
+
/** Diagnostic code (e.g., 'HSP030', 'HSP031', 'HSP032') */
|
|
1006
|
+
code: string;
|
|
1007
|
+
/** Human-readable error/warning message */
|
|
1008
|
+
message: string;
|
|
1009
|
+
/** Source line (1-indexed) where the constraint is declared */
|
|
1010
|
+
line: number;
|
|
1011
|
+
/** Source column (0-indexed) */
|
|
1012
|
+
column: number;
|
|
1013
|
+
/** The constraint kind that produced this diagnostic */
|
|
1014
|
+
constraintKind: SpatialConstraintKind;
|
|
1015
|
+
/** Source entity ID */
|
|
1016
|
+
sourceId: string;
|
|
1017
|
+
/** Target entity ID */
|
|
1018
|
+
targetId: string;
|
|
1019
|
+
/** Suggested fix(es) */
|
|
1020
|
+
suggestions?: string[];
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Result of compile-time spatial constraint verification.
|
|
1024
|
+
*/
|
|
1025
|
+
interface SpatialConstraintCheckResult {
|
|
1026
|
+
/** Whether all constraints passed */
|
|
1027
|
+
valid: boolean;
|
|
1028
|
+
/** All diagnostics produced */
|
|
1029
|
+
diagnostics: SpatialConstraintDiagnostic[];
|
|
1030
|
+
/** Map of entity ID -> resolved spatial constraints */
|
|
1031
|
+
constraintMap: Map<string, SpatialConstraint[]>;
|
|
1032
|
+
/** Statistics */
|
|
1033
|
+
stats: {
|
|
1034
|
+
totalConstraints: number;
|
|
1035
|
+
adjacentCount: number;
|
|
1036
|
+
containsCount: number;
|
|
1037
|
+
reachableCount: number;
|
|
1038
|
+
temporalAdjacentCount: number;
|
|
1039
|
+
temporalReachableCount: number;
|
|
1040
|
+
trajectoryCount: number;
|
|
1041
|
+
errorsCount: number;
|
|
1042
|
+
warningsCount: number;
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* A spatial declaration extracted from HoloScript source during parsing.
|
|
1047
|
+
* These are the "facts" the compile-time verifier reasons about.
|
|
1048
|
+
*/
|
|
1049
|
+
interface SpatialDeclaration {
|
|
1050
|
+
/** Entity ID */
|
|
1051
|
+
entityId: string;
|
|
1052
|
+
/** Entity type (e.g., 'orb', 'agent', 'zone') */
|
|
1053
|
+
entityType: string;
|
|
1054
|
+
/** Declared static position (if known at compile time) */
|
|
1055
|
+
position?: Vector3;
|
|
1056
|
+
/** Declared bounds (if known at compile time) */
|
|
1057
|
+
bounds?: BoundingBox | BoundingSphere;
|
|
1058
|
+
/** Parent entity ID (for containment hierarchy) */
|
|
1059
|
+
parentId?: string;
|
|
1060
|
+
/** Region the entity is declared in */
|
|
1061
|
+
regionId?: string;
|
|
1062
|
+
/** All spatial constraints declared on this entity */
|
|
1063
|
+
constraints: SpatialConstraint[];
|
|
1064
|
+
/** Source line for error reporting */
|
|
1065
|
+
line?: number;
|
|
1066
|
+
/** Source column for error reporting */
|
|
1067
|
+
column?: number;
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Event emitted when a spatial constraint is violated at runtime.
|
|
1071
|
+
*/
|
|
1072
|
+
interface SpatialConstraintViolationEvent {
|
|
1073
|
+
type: 'spatial_constraint_violation';
|
|
1074
|
+
constraintKind: SpatialConstraintKind;
|
|
1075
|
+
sourceId: string;
|
|
1076
|
+
targetId: string;
|
|
1077
|
+
message: string;
|
|
1078
|
+
/** Current measured value (distance, overlap percentage, path length) */
|
|
1079
|
+
currentValue: number;
|
|
1080
|
+
/** Required threshold */
|
|
1081
|
+
requiredValue: number;
|
|
1082
|
+
timestamp: number;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Event emitted when a violated spatial constraint returns to valid state.
|
|
1086
|
+
*/
|
|
1087
|
+
interface SpatialConstraintResolvedEvent {
|
|
1088
|
+
type: 'spatial_constraint_resolved';
|
|
1089
|
+
constraintKind: SpatialConstraintKind;
|
|
1090
|
+
sourceId: string;
|
|
1091
|
+
targetId: string;
|
|
1092
|
+
timestamp: number;
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Union of all spatial constraint events.
|
|
1096
|
+
*/
|
|
1097
|
+
type SpatialConstraintEvent = SpatialConstraintViolationEvent | SpatialConstraintResolvedEvent;
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* Spatial Constraint Validator
|
|
1101
|
+
*
|
|
1102
|
+
* Performs compile-time verification of spatial constraints declared in
|
|
1103
|
+
* HoloScript source. Analyzes spatial declarations (positions, bounds,
|
|
1104
|
+
* hierarchy) to detect constraint violations before runtime.
|
|
1105
|
+
*
|
|
1106
|
+
* Diagnostic codes:
|
|
1107
|
+
* HSP030 — spatial_adjacent violation
|
|
1108
|
+
* HSP031 — spatial_contains violation
|
|
1109
|
+
* HSP032 — spatial_reachable violation
|
|
1110
|
+
* HSP033 — spatial constraint target not found
|
|
1111
|
+
* HSP034 — spatial constraint circular reference
|
|
1112
|
+
* HSP035 — spatial constraint incompatible configuration
|
|
1113
|
+
* HSP036 — spatial_temporal_adjacent violation
|
|
1114
|
+
* HSP037 — spatial_temporal_reachable violation
|
|
1115
|
+
* HSP038 — spatial_trajectory violation
|
|
1116
|
+
*
|
|
1117
|
+
* @module spatial/SpatialConstraintValidator
|
|
1118
|
+
*/
|
|
1119
|
+
|
|
1120
|
+
/**
|
|
1121
|
+
* Compile-time spatial constraint validator.
|
|
1122
|
+
*
|
|
1123
|
+
* Given a set of spatial declarations (extracted from parsed HoloScript AST),
|
|
1124
|
+
* validates all declared spatial constraints and reports diagnostics.
|
|
1125
|
+
*
|
|
1126
|
+
* @example
|
|
1127
|
+
* ```typescript
|
|
1128
|
+
* const validator = new SpatialConstraintValidator();
|
|
1129
|
+
* const result = validator.validate(declarations);
|
|
1130
|
+
* if (!result.valid) {
|
|
1131
|
+
* for (const diag of result.diagnostics) {
|
|
1132
|
+
* console.error(`[${diag.code}] ${diag.message}`);
|
|
1133
|
+
* }
|
|
1134
|
+
* }
|
|
1135
|
+
* ```
|
|
1136
|
+
*/
|
|
1137
|
+
declare class SpatialConstraintValidator {
|
|
1138
|
+
private declarations;
|
|
1139
|
+
private diagnostics;
|
|
1140
|
+
private constraintMap;
|
|
1141
|
+
/**
|
|
1142
|
+
* Validate all spatial constraints across a set of declarations.
|
|
1143
|
+
*/
|
|
1144
|
+
validate(declarations: SpatialDeclaration[]): SpatialConstraintCheckResult;
|
|
1145
|
+
/**
|
|
1146
|
+
* Validate a single constraint in isolation (useful for incremental checks).
|
|
1147
|
+
*/
|
|
1148
|
+
validateSingle(source: SpatialDeclaration, constraint: SpatialConstraint, allDeclarations: SpatialDeclaration[]): SpatialConstraintDiagnostic[];
|
|
1149
|
+
private resolveReferences;
|
|
1150
|
+
private detectCircularReferences;
|
|
1151
|
+
private validateAdjacent;
|
|
1152
|
+
private validateContains;
|
|
1153
|
+
/**
|
|
1154
|
+
* Check that a point is inside the container bounds (with margin).
|
|
1155
|
+
*/
|
|
1156
|
+
private validatePointContainment;
|
|
1157
|
+
/**
|
|
1158
|
+
* Strict containment: contained entity's full bounds must be inside container.
|
|
1159
|
+
*/
|
|
1160
|
+
private validateStrictContainment;
|
|
1161
|
+
/**
|
|
1162
|
+
* Recursively check containment for child entities.
|
|
1163
|
+
*/
|
|
1164
|
+
private validateRecursiveContainment;
|
|
1165
|
+
private validateReachable;
|
|
1166
|
+
/**
|
|
1167
|
+
* Check line-of-sight between two points through known obstacles.
|
|
1168
|
+
* Returns the ID of the first blocking obstacle, or null if clear.
|
|
1169
|
+
*/
|
|
1170
|
+
private checkLineOfSight;
|
|
1171
|
+
private validateTemporalAdjacent;
|
|
1172
|
+
private validateTemporalReachable;
|
|
1173
|
+
private validateTrajectory;
|
|
1174
|
+
private validateCrossConstraintConsistency;
|
|
1175
|
+
/**
|
|
1176
|
+
* Reset all internal state for a new validation run.
|
|
1177
|
+
*/
|
|
1178
|
+
private reset;
|
|
1179
|
+
/**
|
|
1180
|
+
* Add a diagnostic to the list.
|
|
1181
|
+
*/
|
|
1182
|
+
private addDiagnostic;
|
|
1183
|
+
/**
|
|
1184
|
+
* Resolve a target ID to a declaration, including type-based matching.
|
|
1185
|
+
*/
|
|
1186
|
+
private resolveTarget;
|
|
1187
|
+
/**
|
|
1188
|
+
* Get the target ID from any spatial constraint.
|
|
1189
|
+
*/
|
|
1190
|
+
private getTargetId;
|
|
1191
|
+
/**
|
|
1192
|
+
* Compute distance along a specific axis filter.
|
|
1193
|
+
*/
|
|
1194
|
+
computeAxisDistance(a: Vector3, b: Vector3, axis: SpatialAxis): number;
|
|
1195
|
+
/**
|
|
1196
|
+
* Convert any bounds type to a BoundingBox, optionally offset by position.
|
|
1197
|
+
*/
|
|
1198
|
+
private toBoundingBox;
|
|
1199
|
+
/**
|
|
1200
|
+
* Ray-AABB intersection test.
|
|
1201
|
+
*/
|
|
1202
|
+
private rayIntersectsBox;
|
|
1203
|
+
/**
|
|
1204
|
+
* Check if a point is within `extraRadius` of a bounding volume.
|
|
1205
|
+
*/
|
|
1206
|
+
private isPointNearBounds;
|
|
1207
|
+
/**
|
|
1208
|
+
* Find all containers that declare spatial_contains with a given entity.
|
|
1209
|
+
*/
|
|
1210
|
+
private findContainers;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* OctreeSystem.ts
|
|
1215
|
+
*
|
|
1216
|
+
* Octree spatial partitioning: insert/remove objects,
|
|
1217
|
+
* range queries, ray queries, and automatic subdivision.
|
|
1218
|
+
*
|
|
1219
|
+
* @module spatial
|
|
1220
|
+
*/
|
|
1221
|
+
interface OctreeEntry {
|
|
1222
|
+
id: string;
|
|
1223
|
+
x: number;
|
|
1224
|
+
y: number;
|
|
1225
|
+
z: number;
|
|
1226
|
+
radius: number;
|
|
1227
|
+
}
|
|
1228
|
+
declare class OctreeSystem {
|
|
1229
|
+
private root;
|
|
1230
|
+
private maxEntriesPerNode;
|
|
1231
|
+
private maxDepth;
|
|
1232
|
+
private entryCount;
|
|
1233
|
+
constructor(centerX: number, centerY: number, centerZ: number, halfSize: number);
|
|
1234
|
+
insert(entry: OctreeEntry): boolean;
|
|
1235
|
+
private insertIntoNode;
|
|
1236
|
+
remove(id: string): boolean;
|
|
1237
|
+
private removeFromNode;
|
|
1238
|
+
queryRadius(x: number, y: number, z: number, radius: number): OctreeEntry[];
|
|
1239
|
+
private queryRadiusNode;
|
|
1240
|
+
private sphereOverlapsNode;
|
|
1241
|
+
private subdivide;
|
|
1242
|
+
private containsPoint;
|
|
1243
|
+
getEntryCount(): number;
|
|
1244
|
+
clear(): void;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* OctreeLODSystem.ts
|
|
1249
|
+
*
|
|
1250
|
+
* Octree-based Level-of-Detail system for Gaussian Splatting scenes.
|
|
1251
|
+
* Implements the Octree-GS approach (TPAMI 2025): anchor Gaussians assigned
|
|
1252
|
+
* to octree levels with camera-distance LOD selection and budget-aware capping.
|
|
1253
|
+
*
|
|
1254
|
+
* Key design decisions:
|
|
1255
|
+
* - Anchor Gaussians are stored at the octree level matching their detail scale
|
|
1256
|
+
* - Camera distance determines which LOD levels contribute to rendering
|
|
1257
|
+
* - Power-law (Levy flight) transition thresholds replace linear spacing
|
|
1258
|
+
* - Budget enforcement drops deepest LOD levels first when over cap
|
|
1259
|
+
* - VR mode reserves fixed budget per avatar (W.034: 60K each, max 3)
|
|
1260
|
+
*
|
|
1261
|
+
* Research references:
|
|
1262
|
+
* W.032 - Octree-GS LOD (anchor-based level selection, TPAMI 2025)
|
|
1263
|
+
* W.034 - VR Gaussian budget (~180K total on Quest 3 at 72fps)
|
|
1264
|
+
* P.030.01 - Hierarchical LOD Gaussian Architecture pattern
|
|
1265
|
+
* P.030.05 - VR Gaussian Budget Management pattern
|
|
1266
|
+
*
|
|
1267
|
+
* @module spatial
|
|
1268
|
+
*/
|
|
1269
|
+
/**
|
|
1270
|
+
* Gaussian anchor: a representative Gaussian at a specific octree level.
|
|
1271
|
+
* At rendering time, only anchors from selected LOD levels are drawn.
|
|
1272
|
+
*/
|
|
1273
|
+
interface GaussianAnchor {
|
|
1274
|
+
/** Unique identifier for this anchor Gaussian */
|
|
1275
|
+
id: string;
|
|
1276
|
+
/** World-space position (center of the Gaussian) */
|
|
1277
|
+
x: number;
|
|
1278
|
+
y: number;
|
|
1279
|
+
z: number;
|
|
1280
|
+
/** Gaussian scale (max axis determines effective radius for octree insertion) */
|
|
1281
|
+
scale: number;
|
|
1282
|
+
/** LOD level this anchor belongs to (0 = coarsest/root, higher = finer detail) */
|
|
1283
|
+
lodLevel: number;
|
|
1284
|
+
/** Number of Gaussians this anchor represents (for budget accounting) */
|
|
1285
|
+
gaussianCount: number;
|
|
1286
|
+
/** Optional: index into the original splat array for rendering */
|
|
1287
|
+
splatIndex?: number;
|
|
1288
|
+
/** V11: Perceptual importance (0-1, default 0.5). Higher = kept under budget pressure */
|
|
1289
|
+
importance?: number;
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Configuration for the octree LOD system.
|
|
1293
|
+
*/
|
|
1294
|
+
interface OctreeLODConfig {
|
|
1295
|
+
/** Maximum octree depth (number of LOD levels). 4-8 typical for city-scale. */
|
|
1296
|
+
maxDepth: number;
|
|
1297
|
+
/**
|
|
1298
|
+
* Power-law exponent for transition threshold spacing.
|
|
1299
|
+
* Controls how distance thresholds grow with LOD level.
|
|
1300
|
+
* - 1.0 = linear spacing (uniform)
|
|
1301
|
+
* - 1.5 = moderate power-law (recommended for indoor/room-scale)
|
|
1302
|
+
* - 2.0 = aggressive power-law (recommended for outdoor/city-scale)
|
|
1303
|
+
* Levy flight research (W.030) suggests power-law distributions match
|
|
1304
|
+
* natural depth trajectory patterns in camera movement.
|
|
1305
|
+
*/
|
|
1306
|
+
powerLawExponent: number;
|
|
1307
|
+
/** Base distance for LOD level 0 transition (in world units) */
|
|
1308
|
+
baseDistance: number;
|
|
1309
|
+
/** Maximum distance for the outermost LOD level (in world units) */
|
|
1310
|
+
maxDistance: number;
|
|
1311
|
+
/** VR mode: enable hard budget enforcement */
|
|
1312
|
+
vrMode: boolean;
|
|
1313
|
+
/** Total Gaussian budget (0 = unlimited). VR default: 180000 (Quest 3 at 72fps) */
|
|
1314
|
+
gaussianBudget: number;
|
|
1315
|
+
/** Per-avatar Gaussian reservation (0 = no avatar reservations) */
|
|
1316
|
+
perAvatarReservation: number;
|
|
1317
|
+
/** Maximum number of avatars with reserved budgets */
|
|
1318
|
+
maxAvatars: number;
|
|
1319
|
+
/** Maximum anchors per node before subdivision */
|
|
1320
|
+
maxAnchorsPerNode: number;
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Result of an LOD selection query: which levels and anchors to render.
|
|
1324
|
+
*/
|
|
1325
|
+
interface LODSelectionResult {
|
|
1326
|
+
/** LOD levels selected for rendering (0 = coarsest, higher = finer) */
|
|
1327
|
+
selectedLevels: number[];
|
|
1328
|
+
/** Total Gaussians selected across all levels */
|
|
1329
|
+
totalGaussians: number;
|
|
1330
|
+
/** Whether the budget cap was applied (some levels were dropped) */
|
|
1331
|
+
budgetCapped: boolean;
|
|
1332
|
+
/** Number of LOD levels dropped due to budget cap */
|
|
1333
|
+
levelsDropped: number;
|
|
1334
|
+
/** Anchor Gaussians to render (flattened from selected levels) */
|
|
1335
|
+
anchors: GaussianAnchor[];
|
|
1336
|
+
/** Camera distance to scene center */
|
|
1337
|
+
cameraDistance: number;
|
|
1338
|
+
/** Computed transition thresholds (for debugging/visualization) */
|
|
1339
|
+
thresholds: number[];
|
|
1340
|
+
/** Available Gaussian budget after avatar reservations */
|
|
1341
|
+
availableBudget: number;
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1344
|
+
* Per-level statistics for the octree.
|
|
1345
|
+
*/
|
|
1346
|
+
interface LODLevelStats {
|
|
1347
|
+
level: number;
|
|
1348
|
+
anchorCount: number;
|
|
1349
|
+
gaussianCount: number;
|
|
1350
|
+
nodeCount: number;
|
|
1351
|
+
}
|
|
1352
|
+
/**
|
|
1353
|
+
* Metrics snapshot for the entire OctreeLOD system.
|
|
1354
|
+
*/
|
|
1355
|
+
interface OctreeLODMetrics {
|
|
1356
|
+
/** Total anchor count across all levels */
|
|
1357
|
+
totalAnchors: number;
|
|
1358
|
+
/** Total Gaussian count across all levels */
|
|
1359
|
+
totalGaussians: number;
|
|
1360
|
+
/** Per-level breakdown */
|
|
1361
|
+
levels: LODLevelStats[];
|
|
1362
|
+
/** Octree depth (actual, may be less than maxDepth) */
|
|
1363
|
+
actualDepth: number;
|
|
1364
|
+
/** Number of active avatar reservations */
|
|
1365
|
+
activeAvatarReservations: number;
|
|
1366
|
+
/** Total nodes in the octree */
|
|
1367
|
+
totalNodes: number;
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Octree-based Level-of-Detail system for Gaussian Splatting scenes.
|
|
1371
|
+
*
|
|
1372
|
+
* Architecture (based on Octree-GS, TPAMI 2025):
|
|
1373
|
+
*
|
|
1374
|
+
* 1. **Octree Construction**: Scene bounding box is recursively subdivided
|
|
1375
|
+
* into 8 children up to maxDepth levels. Each level corresponds to an
|
|
1376
|
+
* LOD level (depth 0 = coarsest overview, depth N = finest detail).
|
|
1377
|
+
*
|
|
1378
|
+
* 2. **Anchor Assignment**: Gaussian splats are assigned to the octree level
|
|
1379
|
+
* matching their detail scale. Coarse/large Gaussians go to shallow levels;
|
|
1380
|
+
* fine/small Gaussians go to deep levels. This is the "anchor" concept
|
|
1381
|
+
* from Octree-GS.
|
|
1382
|
+
*
|
|
1383
|
+
* 3. **LOD Selection**: Given a camera position, compute distance to each
|
|
1384
|
+
* octree voxel. Use power-law transition thresholds to determine which
|
|
1385
|
+
* LOD levels are active. Closer voxels activate deeper (finer) levels.
|
|
1386
|
+
*
|
|
1387
|
+
* 4. **Budget Enforcement**: Sum Gaussian counts across selected levels.
|
|
1388
|
+
* If total exceeds the budget, drop the deepest (finest) levels first.
|
|
1389
|
+
* This preserves scene overview while sacrificing fine detail under pressure.
|
|
1390
|
+
*
|
|
1391
|
+
* 5. **VR Mode**: Reserves fixed Gaussian budget per avatar (e.g., 60K each),
|
|
1392
|
+
* then allocates remaining budget to scene LOD selection.
|
|
1393
|
+
*
|
|
1394
|
+
* Usage:
|
|
1395
|
+
* ```typescript
|
|
1396
|
+
* const lod = new OctreeLODSystem({
|
|
1397
|
+
* maxDepth: 6,
|
|
1398
|
+
* powerLawExponent: 1.5,
|
|
1399
|
+
* baseDistance: 2.0,
|
|
1400
|
+
* maxDistance: 200.0,
|
|
1401
|
+
* vrMode: true,
|
|
1402
|
+
* gaussianBudget: 180000,
|
|
1403
|
+
* perAvatarReservation: 60000,
|
|
1404
|
+
* maxAvatars: 3,
|
|
1405
|
+
* });
|
|
1406
|
+
*
|
|
1407
|
+
* // Build octree from scene bounds
|
|
1408
|
+
* lod.initialize(0, 0, 0, 100); // center + halfSize
|
|
1409
|
+
*
|
|
1410
|
+
* // Insert anchor Gaussians at appropriate LOD levels
|
|
1411
|
+
* lod.insertAnchor({ id: 'a0', x: 10, y: 0, z: 5, scale: 2.0, lodLevel: 0, gaussianCount: 500 });
|
|
1412
|
+
* lod.insertAnchor({ id: 'a1', x: 10, y: 0, z: 5, scale: 0.1, lodLevel: 4, gaussianCount: 50 });
|
|
1413
|
+
*
|
|
1414
|
+
* // Select LOD levels for current camera
|
|
1415
|
+
* const selection = lod.selectLOD(cameraX, cameraY, cameraZ);
|
|
1416
|
+
* // selection.anchors contains the Gaussians to render this frame
|
|
1417
|
+
* ```
|
|
1418
|
+
*/
|
|
1419
|
+
declare class OctreeLODSystem {
|
|
1420
|
+
private root;
|
|
1421
|
+
private config;
|
|
1422
|
+
private thresholds;
|
|
1423
|
+
private anchorCount;
|
|
1424
|
+
private totalGaussianCount;
|
|
1425
|
+
private activeAvatars;
|
|
1426
|
+
private nodeCount;
|
|
1427
|
+
/** Scene center for distance calculations */
|
|
1428
|
+
private sceneCX;
|
|
1429
|
+
private sceneCY;
|
|
1430
|
+
private sceneCZ;
|
|
1431
|
+
constructor(config?: Partial<OctreeLODConfig>);
|
|
1432
|
+
/**
|
|
1433
|
+
* Initialize the octree with scene bounds.
|
|
1434
|
+
* Must be called before inserting anchors.
|
|
1435
|
+
*/
|
|
1436
|
+
initialize(centerX: number, centerY: number, centerZ: number, halfSize: number): void;
|
|
1437
|
+
/**
|
|
1438
|
+
* Initialize from a bounding box (min/max corners).
|
|
1439
|
+
*/
|
|
1440
|
+
initializeFromBounds(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): void;
|
|
1441
|
+
/**
|
|
1442
|
+
* Compute power-law transition thresholds for LOD level selection.
|
|
1443
|
+
*
|
|
1444
|
+
* Power-law spacing (Levy flight-inspired, W.030):
|
|
1445
|
+
* threshold[i] = baseDistance * ((i + 1) / maxDepth) ^ exponent * (maxDistance / baseDistance)
|
|
1446
|
+
*
|
|
1447
|
+
* This produces thresholds that are tightly spaced near the camera
|
|
1448
|
+
* (where detail matters most) and widely spaced at far distances
|
|
1449
|
+
* (where coarse LOD suffices).
|
|
1450
|
+
*/
|
|
1451
|
+
private computeThresholds;
|
|
1452
|
+
/**
|
|
1453
|
+
* Get the computed transition thresholds (read-only).
|
|
1454
|
+
*/
|
|
1455
|
+
getThresholds(): readonly number[];
|
|
1456
|
+
/**
|
|
1457
|
+
* Insert an anchor Gaussian into the octree at its designated LOD level.
|
|
1458
|
+
* Returns true if successfully inserted.
|
|
1459
|
+
*/
|
|
1460
|
+
insertAnchor(anchor: GaussianAnchor): boolean;
|
|
1461
|
+
private insertIntoNode;
|
|
1462
|
+
/**
|
|
1463
|
+
* Remove an anchor by ID.
|
|
1464
|
+
*/
|
|
1465
|
+
removeAnchor(id: string): boolean;
|
|
1466
|
+
private removeFromNode;
|
|
1467
|
+
/**
|
|
1468
|
+
* Bulk-insert anchors (more efficient than individual inserts for large scenes).
|
|
1469
|
+
* Anchors are sorted by LOD level for efficient tree traversal.
|
|
1470
|
+
*/
|
|
1471
|
+
bulkInsert(anchors: GaussianAnchor[]): number;
|
|
1472
|
+
/**
|
|
1473
|
+
* Select LOD levels and anchors to render based on camera position.
|
|
1474
|
+
*
|
|
1475
|
+
* Algorithm:
|
|
1476
|
+
* 1. Compute camera distance to scene center
|
|
1477
|
+
* 2. Walk thresholds to find the deepest (finest) LOD level visible
|
|
1478
|
+
* 3. Select all levels from 0 (coarsest) through the deepest visible level
|
|
1479
|
+
* 4. Collect anchors from selected levels
|
|
1480
|
+
* 5. If budget mode, drop deepest levels until under budget
|
|
1481
|
+
* 6. In VR mode, subtract avatar reservations from available budget
|
|
1482
|
+
*/
|
|
1483
|
+
selectLOD(cameraX: number, cameraY: number, cameraZ: number, avatarCount?: number): LODSelectionResult;
|
|
1484
|
+
/**
|
|
1485
|
+
* Recursively collect anchors from the octree that belong to the selected levels.
|
|
1486
|
+
*/
|
|
1487
|
+
private collectAnchors;
|
|
1488
|
+
/**
|
|
1489
|
+
* Set the number of active avatars (for VR budget reservation).
|
|
1490
|
+
*/
|
|
1491
|
+
setActiveAvatars(count: number): void;
|
|
1492
|
+
/**
|
|
1493
|
+
* Get the number of active avatar reservations.
|
|
1494
|
+
*/
|
|
1495
|
+
getActiveAvatars(): number;
|
|
1496
|
+
/**
|
|
1497
|
+
* Get the scene-available Gaussian budget after avatar reservations.
|
|
1498
|
+
*/
|
|
1499
|
+
getAvailableSceneBudget(): number;
|
|
1500
|
+
/**
|
|
1501
|
+
* Compute the appropriate LOD level for a Gaussian based on its scale.
|
|
1502
|
+
*
|
|
1503
|
+
* Larger Gaussians (coarse detail) -> lower LOD levels (shallow octree nodes)
|
|
1504
|
+
* Smaller Gaussians (fine detail) -> higher LOD levels (deep octree nodes)
|
|
1505
|
+
*
|
|
1506
|
+
* Uses logarithmic mapping: level = floor(log2(maxScale / scale))
|
|
1507
|
+
* Clamped to [0, maxDepth-1].
|
|
1508
|
+
*/
|
|
1509
|
+
computeLODLevelFromScale(scale: number, maxScaleInScene: number): number;
|
|
1510
|
+
private createNode;
|
|
1511
|
+
private subdivideNode;
|
|
1512
|
+
private containsPoint;
|
|
1513
|
+
/**
|
|
1514
|
+
* Get comprehensive metrics about the octree state.
|
|
1515
|
+
*/
|
|
1516
|
+
getMetrics(): OctreeLODMetrics;
|
|
1517
|
+
private collectMetrics;
|
|
1518
|
+
/**
|
|
1519
|
+
* Get the total number of anchors.
|
|
1520
|
+
*/
|
|
1521
|
+
getAnchorCount(): number;
|
|
1522
|
+
/**
|
|
1523
|
+
* Get the total Gaussian count across all anchors.
|
|
1524
|
+
*/
|
|
1525
|
+
getTotalGaussianCount(): number;
|
|
1526
|
+
/**
|
|
1527
|
+
* Get the current configuration.
|
|
1528
|
+
*/
|
|
1529
|
+
getConfig(): Readonly<OctreeLODConfig>;
|
|
1530
|
+
/**
|
|
1531
|
+
* Update configuration (recomputes thresholds).
|
|
1532
|
+
*/
|
|
1533
|
+
updateConfig(config: Partial<OctreeLODConfig>): void;
|
|
1534
|
+
/**
|
|
1535
|
+
* Clear all anchors and reset the octree.
|
|
1536
|
+
* Preserves configuration.
|
|
1537
|
+
*/
|
|
1538
|
+
clear(): void;
|
|
1539
|
+
/**
|
|
1540
|
+
* Check if the system has been initialized.
|
|
1541
|
+
*/
|
|
1542
|
+
isInitialized(): boolean;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
export { type BoundingBox, type BoundingSphere, type ByTypeQuery, DEFAULT_SPATIAL_CONFIG, type EntityEnteredEvent, type EntityExitedEvent, type GaussianAnchor, type InRegionQuery, type LODLevelStats, type LODSelectionResult, type NearestQuery, type OctreeEntry, type OctreeLODConfig, type OctreeLODMetrics, OctreeLODSystem, OctreeSystem, type OrientedBoundingBox, type Quaternion, type QueryResult, type RaycastHit, type RaycastQuery, type ReachableQuery, type Region, type RegionEnteredEvent, type RegionExitedEvent, type SightLine, type SpatialAdjacentConfig, type SpatialAdjacentConstraint, type SpatialAwarenessConfig, type SpatialAxis, type SpatialConstraint, type SpatialConstraintCheckResult, type SpatialConstraintDiagnostic, type SpatialConstraintEvent, type SpatialConstraintKind, type SpatialConstraintResolvedEvent, SpatialConstraintValidator, type SpatialConstraintViolationEvent, type SpatialContainsConfig, type SpatialContainsConstraint, type SpatialContext, SpatialContextProvider, type SpatialContextProviderEvents, type SpatialDeclaration, type SpatialDiagnosticSeverity, type SpatialEnforcementMode, type SpatialEntity, type SpatialEvent, type SpatialQuery, type SpatialQueryBase, SpatialQueryExecutor, type SpatialQueryType, type SpatialReachableAlgorithm, type SpatialReachableConfig, type SpatialReachableConstraint, type SpatialTemporalAdjacentConfig, type SpatialTemporalAdjacentConstraint, type SpatialTemporalReachableConfig, type SpatialTemporalReachableConstraint, type SpatialTrajectoryConfig, type SpatialTrajectoryConstraint, type SpatialTrajectoryMode, type TrajectoryWaypoint, type Vector2, type Vector3, type VisibilityChangedEvent, type VisibleQuery, type WithinQuery, add, boxesOverlap, cross, distance, distanceSquared, dot, getBoxCenter, isPointInBox, isPointInSphere, lerp, normalize, scale, subtract };
|