@flighthq/spatial 0.3.1-next.975.01aea94 → 0.4.0-edge.1908.751021c
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/bvh3D.d.ts +3 -0
- package/dist/bvh3D.d.ts.map +1 -0
- package/dist/bvh3D.js +575 -0
- package/dist/bvh3D.js.map +1 -0
- package/dist/contract.d.ts +6 -1
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +6 -1
- package/dist/contract.js.map +1 -1
- package/dist/explainSpatialIndexing2D.d.ts +3 -0
- package/dist/explainSpatialIndexing2D.d.ts.map +1 -0
- package/dist/{explainSpatialIndexing.js → explainSpatialIndexing2D.js} +2 -2
- package/dist/explainSpatialIndexing2D.js.map +1 -0
- package/dist/explainSpatialIndexing3D.d.ts +3 -0
- package/dist/explainSpatialIndexing3D.d.ts.map +1 -0
- package/dist/explainSpatialIndexing3D.js +15 -0
- package/dist/explainSpatialIndexing3D.js.map +1 -0
- package/dist/formatSpatialIndexingNotice.d.ts.map +1 -1
- package/dist/formatSpatialIndexingNotice.js +8 -2
- package/dist/formatSpatialIndexingNotice.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/spatialIndex.d.ts +10 -10
- package/dist/spatialIndex.d.ts.map +1 -1
- package/dist/spatialIndex.js +14 -14
- package/dist/spatialIndex.js.map +1 -1
- package/dist/spatialIndex3D.d.ts +13 -0
- package/dist/spatialIndex3D.d.ts.map +1 -0
- package/dist/spatialIndex3D.js +166 -0
- package/dist/spatialIndex3D.js.map +1 -0
- package/dist/spatialIndexingGuard.d.ts +4 -0
- package/dist/spatialIndexingGuard.d.ts.map +1 -0
- package/dist/spatialIndexingGuard.js +23 -0
- package/dist/spatialIndexingGuard.js.map +1 -0
- package/dist/uniformGrid.d.ts +2 -3
- package/dist/uniformGrid.d.ts.map +1 -1
- package/dist/uniformGrid.js +5 -15
- package/dist/uniformGrid.js.map +1 -1
- package/dist/uniformGrid3D.d.ts +3 -0
- package/dist/uniformGrid3D.d.ts.map +1 -0
- package/dist/uniformGrid3D.js +627 -0
- package/dist/uniformGrid3D.js.map +1 -0
- package/package.json +3 -3
- package/src/bvh3D.test.ts +294 -0
- package/src/explainSpatialIndexing2D.test.ts +81 -0
- package/src/explainSpatialIndexing3D.test.ts +59 -0
- package/src/formatSpatialIndexingNotice.test.ts +30 -4
- package/src/spatialIndex.test.ts +65 -65
- package/src/spatialIndex3D.test.ts +273 -0
- package/src/spatialIndexingGuard.test.ts +188 -0
- package/src/uniformGrid.test.ts +54 -182
- package/src/uniformGrid3D.test.ts +358 -0
- package/dist/explainSpatialIndexing.d.ts +0 -3
- package/dist/explainSpatialIndexing.d.ts.map +0 -1
- package/dist/explainSpatialIndexing.js.map +0 -1
- package/src/explainSpatialIndexing.test.ts +0 -76
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { SpatialIndex2D, SpatialIndexingExplanation, SpatialObjectId } from '@flighthq/types/contract';
|
|
2
|
+
export declare function explainSpatialIndexing2D(index: Readonly<SpatialIndex2D>, id: SpatialObjectId): SpatialIndexingExplanation;
|
|
3
|
+
//# sourceMappingURL=explainSpatialIndexing2D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainSpatialIndexing2D.d.ts","sourceRoot":"","sources":["../src/explainSpatialIndexing2D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAY5G,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,EAAE,EAAE,eAAe,GAClB,0BAA0B,CAE5B"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// This is the pull half of the diagnostics convention, and the measurement seam a regression test
|
|
9
9
|
// asserts the cost bound against: `bucketCount` is the number that goes unbounded when the bound is
|
|
10
10
|
// removed, so a test can pin it without timing anything.
|
|
11
|
-
export function
|
|
11
|
+
export function explainSpatialIndexing2D(index, id) {
|
|
12
12
|
return index.runtime.backend.explainSpatialIndexing(id);
|
|
13
13
|
}
|
|
14
|
-
//# sourceMappingURL=
|
|
14
|
+
//# sourceMappingURL=explainSpatialIndexing2D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainSpatialIndexing2D.js","sourceRoot":"","sources":["../src/explainSpatialIndexing2D.ts"],"names":[],"mappings":"AAEA,qGAAqG;AACrG,sGAAsG;AACtG,+FAA+F;AAC/F,sGAAsG;AACtG,6FAA6F;AAC7F,yBAAyB;AACzB,EAAE;AACF,kGAAkG;AAClG,oGAAoG;AACpG,yDAAyD;AACzD,MAAM,UAAU,wBAAwB,CACtC,KAA+B,EAC/B,EAAmB;IAEnB,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { SpatialIndex3D, SpatialIndexingExplanation, SpatialObjectId } from '@flighthq/types/contract';
|
|
2
|
+
export declare function explainSpatialIndexing3D(index: Readonly<SpatialIndex3D>, id: SpatialObjectId): SpatialIndexingExplanation;
|
|
3
|
+
//# sourceMappingURL=explainSpatialIndexing3D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainSpatialIndexing3D.d.ts","sourceRoot":"","sources":["../src/explainSpatialIndexing3D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAa5G,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,EAAE,EAAE,eAAe,GAClB,0BAA0B,CAE5B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Reports how the index is currently holding `id`, as plain data. Pure: reads only, indexes nothing,
|
|
2
|
+
// never throws on an unknown id, and retains no reference to the backend. Import it to answer "why is
|
|
3
|
+
// this object not in my query results?" — `absent` means it was never inserted or was removed,
|
|
4
|
+
// `declined` means its bounds were non-finite or inverted and it is deliberately not held, `overflow`
|
|
5
|
+
// means it is held but cannot be usefully bucketed, and `cells` reports the bucket count the
|
|
6
|
+
// per-object bound caps.
|
|
7
|
+
//
|
|
8
|
+
// This is the pull half of the diagnostics convention, and the measurement seam a regression test
|
|
9
|
+
// asserts the cost bound against: `bucketCount` is the number that goes unbounded when the bound is
|
|
10
|
+
// removed, so a test can pin it without timing anything. It matters more here than in 2D — the span
|
|
11
|
+
// a missing bound would walk grows with the cube of an object's extent rather than the square.
|
|
12
|
+
export function explainSpatialIndexing3D(index, id) {
|
|
13
|
+
return index.runtime.backend.explainSpatialIndexing(id);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=explainSpatialIndexing3D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainSpatialIndexing3D.js","sourceRoot":"","sources":["../src/explainSpatialIndexing3D.ts"],"names":[],"mappings":"AAEA,qGAAqG;AACrG,sGAAsG;AACtG,+FAA+F;AAC/F,sGAAsG;AACtG,6FAA6F;AAC7F,yBAAyB;AACzB,EAAE;AACF,kGAAkG;AAClG,oGAAoG;AACpG,oGAAoG;AACpG,+FAA+F;AAC/F,MAAM,UAAU,wBAAwB,CACtC,KAA+B,EAC/B,EAAmB;IAEnB,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatSpatialIndexingNotice.d.ts","sourceRoot":"","sources":["../src/formatSpatialIndexingNotice.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"formatSpatialIndexingNotice.d.ts","sourceRoot":"","sources":["../src/formatSpatialIndexingNotice.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAuBtE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,MAAM,CAsB3F"}
|
|
@@ -3,6 +3,12 @@ import { MAX_INDEXED_CELLS_PER_OBJECT } from './uniformGrid';
|
|
|
3
3
|
// holds one. Import it to turn the structured record a SpatialIndexingGuard receives into something a
|
|
4
4
|
// developer reads; leave it unimported and neither the text nor its cost reaches a bundle.
|
|
5
5
|
//
|
|
6
|
+
// The sentences name the UNSUFFIXED backend methods (`removeSpatialObject`), never the dimensioned
|
|
7
|
+
// free-function wrappers. A notice carries no axis — one guard serves both dimensions — so there is
|
|
8
|
+
// nothing here from which to pick 2D or 3D, and naming one would misdescribe every notice from the
|
|
9
|
+
// other. The unsuffixed names are also the ones a caller greps: they are what the backend seam
|
|
10
|
+
// declares and what a consumer like physics3d actually calls.
|
|
11
|
+
//
|
|
6
12
|
// This package deliberately stops at the structured guard seam plus this optional formatter rather
|
|
7
13
|
// than adding an `enableSpatialGuards` that chooses reporting policy. A caller can send the record to
|
|
8
14
|
// tests, telemetry, a host sink, or `@flighthq/log`, choosing its own channel and deduplication. An
|
|
@@ -14,10 +20,10 @@ import { MAX_INDEXED_CELLS_PER_OBJECT } from './uniformGrid';
|
|
|
14
20
|
// setSpatialIndexingGuard((notice) => logWarn({ message: formatSpatialIndexingNotice(notice) }, 'spatial'));
|
|
15
21
|
export function formatSpatialIndexingNotice(notice) {
|
|
16
22
|
if (notice.reason === 'invalid-cell-size') {
|
|
17
|
-
return `
|
|
23
|
+
return `the uniform grid's cellSize (${notice.cellSize}) must be a positive finite number. ${notice.operation}SpatialObject(${notice.id}) used the bounded overflow path instead, so results remain correct but queries scan this object.`;
|
|
18
24
|
}
|
|
19
25
|
if (notice.reason === 'inverted-bounds') {
|
|
20
|
-
return `${notice.operation}SpatialObject(${notice.id}):
|
|
26
|
+
return `${notice.operation}SpatialObject(${notice.id}): no minimum may exceed its matching maximum, so the object was not indexed and no query will return it. The operation returns false for this — normalize or correct the bounds upstream.`;
|
|
21
27
|
}
|
|
22
28
|
if (notice.reason === 'missing-id') {
|
|
23
29
|
if (notice.operation === 'remove') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatSpatialIndexingNotice.js","sourceRoot":"","sources":["../src/formatSpatialIndexingNotice.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAE7D,qGAAqG;AACrG,sGAAsG;AACtG,2FAA2F;AAC3F,EAAE;AACF,mGAAmG;AACnG,sGAAsG;AACtG,oGAAoG;AACpG,sGAAsG;AACtG,wGAAwG;AACxG,wGAAwG;AACxG,2CAA2C;AAC3C,EAAE;AACF,+GAA+G;AAC/G,MAAM,UAAU,2BAA2B,CAAC,MAAuC;IACjF,IAAI,MAAM,CAAC,MAAM,KAAK,mBAAmB,EAAE,CAAC;QAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"formatSpatialIndexingNotice.js","sourceRoot":"","sources":["../src/formatSpatialIndexingNotice.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAE7D,qGAAqG;AACrG,sGAAsG;AACtG,2FAA2F;AAC3F,EAAE;AACF,mGAAmG;AACnG,oGAAoG;AACpG,mGAAmG;AACnG,+FAA+F;AAC/F,8DAA8D;AAC9D,EAAE;AACF,mGAAmG;AACnG,sGAAsG;AACtG,oGAAoG;AACpG,sGAAsG;AACtG,wGAAwG;AACxG,wGAAwG;AACxG,2CAA2C;AAC3C,EAAE;AACF,+GAA+G;AAC/G,MAAM,UAAU,2BAA2B,CAAC,MAAuC;IACjF,IAAI,MAAM,CAAC,MAAM,KAAK,mBAAmB,EAAE,CAAC;QAC1C,OAAO,gCAAgC,MAAM,CAAC,QAAQ,uCAAuC,MAAM,CAAC,SAAS,iBAAiB,MAAM,CAAC,EAAE,mGAAmG,CAAC;IAC7O,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;QACxC,OAAO,GAAG,MAAM,CAAC,SAAS,iBAAiB,MAAM,CAAC,EAAE,4LAA4L,CAAC;IACnP,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QACnC,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO,uBAAuB,MAAM,CAAC,EAAE,kHAAkH,CAAC;QAC5J,CAAC;QACD,OAAO,uBAAuB,MAAM,CAAC,EAAE,oGAAoG,MAAM,CAAC,IAAI,yFAAyF,CAAC;IAClP,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,MAAM,CAAC,SAAS,iBAAiB,MAAM,CAAC,EAAE,2MAA2M,CAAC;IAClQ,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,MAAM,CAAC,SAAS,iBAAiB,MAAM,CAAC,EAAE,sBAAsB,MAAM,CAAC,sBAAsB,oBAAoB,4BAA4B,kPAAkP,CAAC;IAC5Y,CAAC;IACD,gGAAgG;IAChG,oGAAoG;IACpG,OAAO,GAAG,MAAM,CAAC,SAAS,iBAAiB,MAAM,CAAC,EAAE,kBAAkB,MAAM,CAAC,IAAI,2CAA2C,CAAC;AAC/H,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { MAX_INDEXED_CELLS_PER_OBJECT,
|
|
1
|
+
export { MAX_INDEXED_CELLS_PER_OBJECT, clearSpatialIndex2D, clearSpatialIndex3D, createSpatialIndex2D, createSpatialIndex3D, createUniformGridSpatialBackend2D, createBvhSpatialBackend3D, createUniformGridSpatialBackend3D, explainSpatialIndexing2D, explainSpatialIndexing3D, formatSpatialIndexingNotice, insertSpatialObject2D, insertSpatialObject3D, querySpatialPairs2D, querySpatialPairs3D, querySpatialPoint2D, querySpatialPoint3D, querySpatialRay2D, querySpatialRay3D, querySpatialRegion2D, querySpatialFrustum3D, querySpatialRegion3D, querySpatialSphere3D, removeSpatialObject2D, removeSpatialObject3D, setSpatialIndexingGuard, updateSpatialObject2D, updateSpatialObject3D, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,iCAAiC,EACjC,yBAAyB,EACzB,iCAAiC,EACjC,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { MAX_INDEXED_CELLS_PER_OBJECT,
|
|
1
|
+
export { MAX_INDEXED_CELLS_PER_OBJECT, clearSpatialIndex2D, clearSpatialIndex3D, createSpatialIndex2D, createSpatialIndex3D, createUniformGridSpatialBackend2D, createBvhSpatialBackend3D, createUniformGridSpatialBackend3D, explainSpatialIndexing2D, explainSpatialIndexing3D, formatSpatialIndexingNotice, insertSpatialObject2D, insertSpatialObject3D, querySpatialPairs2D, querySpatialPairs3D, querySpatialPoint2D, querySpatialPoint3D, querySpatialRay2D, querySpatialRay3D, querySpatialRegion2D, querySpatialFrustum3D, querySpatialRegion3D, querySpatialSphere3D, removeSpatialObject2D, removeSpatialObject3D, setSpatialIndexingGuard, updateSpatialObject2D, updateSpatialObject3D, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,iCAAiC,EACjC,yBAAyB,EACzB,iCAAiC,EACjC,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
|
package/dist/spatialIndex.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
1
|
+
import type { SpatialAabb2D, SpatialIndex2D, SpatialIndexBackend2D, SpatialObjectId, SpatialPair } from '@flighthq/types/contract';
|
|
2
|
+
export declare function clearSpatialIndex2D(index: Readonly<SpatialIndex2D>): void;
|
|
3
|
+
export declare function createSpatialIndex2D(backend?: SpatialIndexBackend2D): SpatialIndex2D;
|
|
4
|
+
export declare function insertSpatialObject2D(index: Readonly<SpatialIndex2D>, id: SpatialObjectId, bounds: Readonly<SpatialAabb2D>): boolean;
|
|
5
|
+
export declare function querySpatialPairs2D(index: Readonly<SpatialIndex2D>, out: SpatialPair[]): void;
|
|
6
|
+
export declare function querySpatialPoint2D(index: Readonly<SpatialIndex2D>, x: number, y: number, out: SpatialObjectId[]): void;
|
|
7
|
+
export declare function querySpatialRay2D(index: Readonly<SpatialIndex2D>, x: number, y: number, dx: number, dy: number, out: SpatialObjectId[]): void;
|
|
8
|
+
export declare function querySpatialRegion2D(index: Readonly<SpatialIndex2D>, region: Readonly<SpatialAabb2D>, out: SpatialObjectId[]): void;
|
|
9
|
+
export declare function removeSpatialObject2D(index: Readonly<SpatialIndex2D>, id: SpatialObjectId): void;
|
|
10
|
+
export declare function updateSpatialObject2D(index: Readonly<SpatialIndex2D>, id: SpatialObjectId, bounds: Readonly<SpatialAabb2D>): boolean;
|
|
11
11
|
//# sourceMappingURL=spatialIndex.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spatialIndex.d.ts","sourceRoot":"","sources":["../src/spatialIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"spatialIndex.d.ts","sourceRoot":"","sources":["../src/spatialIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAKlC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,IAAI,CAEzE;AAMD,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,cAAc,CAMpF;AAOD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAC9B,OAAO,CAET;AAKD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,IAAI,CAE7F;AAGD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,eAAe,EAAE,GACrB,IAAI,CAEN;AAID,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,eAAe,EAAE,GACrB,IAAI,CAEN;AAGD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,GAAG,EAAE,eAAe,EAAE,GACrB,IAAI,CAEN;AAGD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,eAAe,GAAG,IAAI,CAEhG;AAMD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAC9B,OAAO,CAET"}
|
package/dist/spatialIndex.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createUniformGridSpatialBackend2D } from './uniformGrid';
|
|
2
2
|
// Empties the index of all objects while keeping it (and its backend) reusable.
|
|
3
|
-
export function
|
|
3
|
+
export function clearSpatialIndex2D(index) {
|
|
4
4
|
index.runtime.backend.clearSpatialIndex();
|
|
5
5
|
}
|
|
6
6
|
// Creates a 2D broadphase index. With no backend it defaults to a uniform grid sized for
|
|
7
7
|
// medium-scale scenes; pass an explicit backend (a differently-sized grid, or a future quadtree /
|
|
8
8
|
// sweep-and-prune) to select the structure for the workload. Constructing the default grid happens
|
|
9
9
|
// here, on call — importing the package has no side effect.
|
|
10
|
-
export function
|
|
10
|
+
export function createSpatialIndex2D(backend) {
|
|
11
11
|
return {
|
|
12
12
|
runtime: {
|
|
13
|
-
backend: backend ??
|
|
13
|
+
backend: backend ?? createUniformGridSpatialBackend2D(DEFAULT_SPATIAL_CELL_SIZE),
|
|
14
14
|
},
|
|
15
15
|
};
|
|
16
16
|
}
|
|
@@ -18,41 +18,41 @@ export function createSpatialIndex(backend) {
|
|
|
18
18
|
// may reuse its own value afterward. Returns false when the bounds cannot be indexed at all
|
|
19
19
|
// (non-finite or inverted) — the object is then absent from every query rather than present at a
|
|
20
20
|
// nonsense position. Oversized-but-valid bounds return true and stay fully queryable; the backend
|
|
21
|
-
// decides how to hold them.
|
|
22
|
-
export function
|
|
21
|
+
// decides how to hold them. explainSpatialIndexing2D reports which happened.
|
|
22
|
+
export function insertSpatialObject2D(index, id, bounds) {
|
|
23
23
|
return index.runtime.backend.insertSpatialObject(id, bounds);
|
|
24
24
|
}
|
|
25
25
|
// Fills `out` (cleared first) with every deduplicated candidate pair — each unordered pair at most
|
|
26
26
|
// once, never an object with itself. A pair is a broadphase candidate: the two objects are close
|
|
27
27
|
// enough to be worth a narrow-phase test, which the caller (or @flighthq/collision) performs.
|
|
28
|
-
export function
|
|
28
|
+
export function querySpatialPairs2D(index, out) {
|
|
29
29
|
index.runtime.backend.querySpatialPairs(out);
|
|
30
30
|
}
|
|
31
31
|
// Fills `out` (cleared first) with the ids whose bounds contain the point (`x`,`y`).
|
|
32
|
-
export function
|
|
32
|
+
export function querySpatialPoint2D(index, x, y, out) {
|
|
33
33
|
index.runtime.backend.querySpatialPoint(x, y, out);
|
|
34
34
|
}
|
|
35
35
|
// Fills `out` (cleared first) with the ids whose bounds the ray from (`x`,`y`) along (`dx`,`dy`)
|
|
36
36
|
// intersects. The direction need not be normalized; the ray is treated as extending forward only.
|
|
37
|
-
export function
|
|
37
|
+
export function querySpatialRay2D(index, x, y, dx, dy, out) {
|
|
38
38
|
index.runtime.backend.querySpatialRay(x, y, dx, dy, out);
|
|
39
39
|
}
|
|
40
40
|
// Fills `out` (cleared first) with the ids whose bounds overlap `region`.
|
|
41
|
-
export function
|
|
41
|
+
export function querySpatialRegion2D(index, region, out) {
|
|
42
42
|
index.runtime.backend.querySpatialRegion(region, out);
|
|
43
43
|
}
|
|
44
44
|
// Removes an object from the index. A no-op if the id is not present.
|
|
45
|
-
export function
|
|
45
|
+
export function removeSpatialObject2D(index, id) {
|
|
46
46
|
index.runtime.backend.removeSpatialObject(id);
|
|
47
47
|
}
|
|
48
48
|
// Moves an already-inserted object to new bounds. Inserting a not-yet-present id behaves as insert.
|
|
49
|
-
// Returns the same sentinel as
|
|
49
|
+
// Returns the same sentinel as insertSpatialObject2D. A declined update removes the object rather than
|
|
50
50
|
// leaving it at its old bounds, so a caller that ignores the sentinel can never read a stale position
|
|
51
51
|
// as a current one.
|
|
52
|
-
export function
|
|
52
|
+
export function updateSpatialObject2D(index, id, bounds) {
|
|
53
53
|
return index.runtime.backend.updateSpatialObject(id, bounds);
|
|
54
54
|
}
|
|
55
|
-
// The default uniform-grid cell size when
|
|
55
|
+
// The default uniform-grid cell size when createSpatialIndex2D is called without an explicit backend —
|
|
56
56
|
// a middle-of-the-road choice; a workload with a known typical object size should pass its own grid.
|
|
57
57
|
const DEFAULT_SPATIAL_CELL_SIZE = 128;
|
|
58
58
|
//# sourceMappingURL=spatialIndex.js.map
|
package/dist/spatialIndex.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spatialIndex.js","sourceRoot":"","sources":["../src/spatialIndex.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"spatialIndex.js","sourceRoot":"","sources":["../src/spatialIndex.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAElE,gFAAgF;AAChF,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;AAC5C,CAAC;AAED,yFAAyF;AACzF,kGAAkG;AAClG,mGAAmG;AACnG,4DAA4D;AAC5D,MAAM,UAAU,oBAAoB,CAAC,OAA+B;IAClE,OAAO;QACL,OAAO,EAAE;YACP,OAAO,EAAE,OAAO,IAAI,iCAAiC,CAAC,yBAAyB,CAAC;SACjF;KACF,CAAC;AACJ,CAAC;AAED,oGAAoG;AACpG,4FAA4F;AAC5F,iGAAiG;AACjG,kGAAkG;AAClG,6EAA6E;AAC7E,MAAM,UAAU,qBAAqB,CACnC,KAA+B,EAC/B,EAAmB,EACnB,MAA+B;IAE/B,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED,mGAAmG;AACnG,iGAAiG;AACjG,8FAA8F;AAC9F,MAAM,UAAU,mBAAmB,CAAC,KAA+B,EAAE,GAAkB;IACrF,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,mBAAmB,CACjC,KAA+B,EAC/B,CAAS,EACT,CAAS,EACT,GAAsB;IAEtB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;AACrD,CAAC;AAED,iGAAiG;AACjG,kGAAkG;AAClG,MAAM,UAAU,iBAAiB,CAC/B,KAA+B,EAC/B,CAAS,EACT,CAAS,EACT,EAAU,EACV,EAAU,EACV,GAAsB;IAEtB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,oBAAoB,CAClC,KAA+B,EAC/B,MAA+B,EAC/B,GAAsB;IAEtB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACxD,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,qBAAqB,CAAC,KAA+B,EAAE,EAAmB;IACxF,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,oGAAoG;AACpG,uGAAuG;AACvG,sGAAsG;AACtG,oBAAoB;AACpB,MAAM,UAAU,qBAAqB,CACnC,KAA+B,EAC/B,EAAmB,EACnB,MAA+B;IAE/B,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED,uGAAuG;AACvG,qGAAqG;AACrG,MAAM,yBAAyB,GAAG,GAAG,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SpatialAabb3D, SpatialFrustum3D, SpatialIndex3D, SpatialIndexBackend3D, SpatialObjectId, SpatialPair } from '@flighthq/types/contract';
|
|
2
|
+
export declare function clearSpatialIndex3D(index: Readonly<SpatialIndex3D>): void;
|
|
3
|
+
export declare function createSpatialIndex3D(backend?: SpatialIndexBackend3D): SpatialIndex3D;
|
|
4
|
+
export declare function insertSpatialObject3D(index: Readonly<SpatialIndex3D>, id: SpatialObjectId, bounds: Readonly<SpatialAabb3D>): boolean;
|
|
5
|
+
export declare function querySpatialFrustum3D(index: Readonly<SpatialIndex3D>, frustum: Readonly<SpatialFrustum3D>, out: SpatialObjectId[], slices?: number): void;
|
|
6
|
+
export declare function querySpatialPairs3D(index: Readonly<SpatialIndex3D>, out: SpatialPair[]): void;
|
|
7
|
+
export declare function querySpatialPoint3D(index: Readonly<SpatialIndex3D>, x: number, y: number, z: number, out: SpatialObjectId[]): void;
|
|
8
|
+
export declare function querySpatialRay3D(index: Readonly<SpatialIndex3D>, x: number, y: number, z: number, dx: number, dy: number, dz: number, out: SpatialObjectId[]): void;
|
|
9
|
+
export declare function querySpatialRegion3D(index: Readonly<SpatialIndex3D>, region: Readonly<SpatialAabb3D>, out: SpatialObjectId[]): void;
|
|
10
|
+
export declare function querySpatialSphere3D(index: Readonly<SpatialIndex3D>, x: number, y: number, z: number, radius: number, out: SpatialObjectId[]): void;
|
|
11
|
+
export declare function removeSpatialObject3D(index: Readonly<SpatialIndex3D>, id: SpatialObjectId): void;
|
|
12
|
+
export declare function updateSpatialObject3D(index: Readonly<SpatialIndex3D>, id: SpatialObjectId, bounds: Readonly<SpatialAabb3D>): boolean;
|
|
13
|
+
//# sourceMappingURL=spatialIndex3D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spatialIndex3D.d.ts","sourceRoot":"","sources":["../src/spatialIndex3D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAKlC,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,IAAI,CAEzE;AAMD,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,cAAc,CAMpF;AAOD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAC9B,OAAO,CAET;AAmBD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,OAAO,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EACnC,GAAG,EAAE,eAAe,EAAE,EACtB,MAAM,SAAyB,GAC9B,IAAI,CAqDN;AAKD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,IAAI,CAE7F;AAGD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,eAAe,EAAE,GACrB,IAAI,CAEN;AAKD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,eAAe,EAAE,GACrB,IAAI,CAEN;AAGD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,GAAG,EAAE,eAAe,EAAE,GACrB,IAAI,CAEN;AASD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,eAAe,EAAE,GACrB,IAAI,CAUN;AAGD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,eAAe,GAAG,IAAI,CAEhG;AAMD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAC9B,OAAO,CAET"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { createUniformGridSpatialBackend3D } from './uniformGrid3D';
|
|
2
|
+
// Empties the index of all objects while keeping it (and its backend) reusable.
|
|
3
|
+
export function clearSpatialIndex3D(index) {
|
|
4
|
+
index.runtime.backend.clearSpatialIndex();
|
|
5
|
+
}
|
|
6
|
+
// Creates a 3D broadphase index. With no backend it defaults to a uniform grid sized for
|
|
7
|
+
// medium-scale scenes; pass an explicit backend (a differently-sized grid, or a future octree / BVH)
|
|
8
|
+
// to select the structure for the workload. Constructing the default grid happens here, on call —
|
|
9
|
+
// importing the package has no side effect.
|
|
10
|
+
export function createSpatialIndex3D(backend) {
|
|
11
|
+
return {
|
|
12
|
+
runtime: {
|
|
13
|
+
backend: backend ?? createUniformGridSpatialBackend3D(DEFAULT_SPATIAL_CELL_SIZE_3D),
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
// Adds an object to the index under `id` with its current bounds. The bounds are copied; the caller
|
|
18
|
+
// may reuse its own value afterward. Returns false when the bounds cannot be indexed at all
|
|
19
|
+
// (non-finite or inverted) — the object is then absent from every query rather than present at a
|
|
20
|
+
// nonsense position. Oversized-but-valid bounds return true and stay fully queryable; the backend
|
|
21
|
+
// decides how to hold them. explainSpatialIndexing3D reports which happened.
|
|
22
|
+
export function insertSpatialObject3D(index, id, bounds) {
|
|
23
|
+
return index.runtime.backend.insertSpatialObject(id, bounds);
|
|
24
|
+
}
|
|
25
|
+
// Fills `out` (cleared first) with the ids whose bounds may lie inside the view volume — the candidate
|
|
26
|
+
// set for view culling.
|
|
27
|
+
//
|
|
28
|
+
// Built on the region query rather than on a new backend method, so every present and future backend
|
|
29
|
+
// answers it without implementing anything, and the ratified eight-method seam does not widen for a
|
|
30
|
+
// query that needs no structural knowledge.
|
|
31
|
+
//
|
|
32
|
+
// The volume is covered by `slices` axis-aligned boxes taken along its DEPTH rather than by one box
|
|
33
|
+
// around the whole thing. A single AABB is correct but nearly useless for culling: a long perspective
|
|
34
|
+
// frustum's bounding box approaches the whole world, so the query would hand back almost every object
|
|
35
|
+
// and cull nothing. Slicing costs one region query per slice and shrinks the covered volume toward the
|
|
36
|
+
// frustum itself — eight slices is a good default, and more is a straight trade of query time against
|
|
37
|
+
// candidates the caller would otherwise reject.
|
|
38
|
+
//
|
|
39
|
+
// The result is a CANDIDATE set, in the same sense as `querySpatialPairs3D`: every id whose bounds the
|
|
40
|
+
// covering boxes touch, which is a superset of what is truly visible. The caller applies the exact
|
|
41
|
+
// plane test to what comes back.
|
|
42
|
+
export function querySpatialFrustum3D(index, frustum, out, slices = DEFAULT_FRUSTUM_SLICES) {
|
|
43
|
+
out.length = 0;
|
|
44
|
+
const corners = frustum.corners;
|
|
45
|
+
if (corners.length < 24 || !(slices >= 1))
|
|
46
|
+
return;
|
|
47
|
+
const steps = Math.floor(slices);
|
|
48
|
+
frustumSeen.clear();
|
|
49
|
+
for (let slice = 0; slice < steps; slice += 1) {
|
|
50
|
+
const nearT = slice / steps;
|
|
51
|
+
const farT = (slice + 1) / steps;
|
|
52
|
+
let minX = Infinity;
|
|
53
|
+
let minY = Infinity;
|
|
54
|
+
let minZ = Infinity;
|
|
55
|
+
let maxX = -Infinity;
|
|
56
|
+
let maxY = -Infinity;
|
|
57
|
+
let maxZ = -Infinity;
|
|
58
|
+
// Both ends of the slice, for all four edges: the volume between two depths is bounded by the eight
|
|
59
|
+
// points at those depths. Taking only the far end would clip the slice's own near face away.
|
|
60
|
+
for (let corner = 0; corner < 4; corner += 1) {
|
|
61
|
+
const near = corner * 3;
|
|
62
|
+
const far = 12 + corner * 3;
|
|
63
|
+
for (const t of [nearT, farT]) {
|
|
64
|
+
const x = corners[near] + (corners[far] - corners[near]) * t;
|
|
65
|
+
const y = corners[near + 1] + (corners[far + 1] - corners[near + 1]) * t;
|
|
66
|
+
const z = corners[near + 2] + (corners[far + 2] - corners[near + 2]) * t;
|
|
67
|
+
if (x < minX)
|
|
68
|
+
minX = x;
|
|
69
|
+
if (x > maxX)
|
|
70
|
+
maxX = x;
|
|
71
|
+
if (y < minY)
|
|
72
|
+
minY = y;
|
|
73
|
+
if (y > maxY)
|
|
74
|
+
maxY = y;
|
|
75
|
+
if (z < minZ)
|
|
76
|
+
minZ = z;
|
|
77
|
+
if (z > maxZ)
|
|
78
|
+
maxZ = z;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!Number.isFinite(minX) || !Number.isFinite(maxZ))
|
|
82
|
+
return;
|
|
83
|
+
queryRegionScratch.minX = minX;
|
|
84
|
+
queryRegionScratch.minY = minY;
|
|
85
|
+
queryRegionScratch.minZ = minZ;
|
|
86
|
+
queryRegionScratch.maxX = maxX;
|
|
87
|
+
queryRegionScratch.maxY = maxY;
|
|
88
|
+
queryRegionScratch.maxZ = maxZ;
|
|
89
|
+
index.runtime.backend.querySpatialRegion(queryRegionScratch, frustumSlice);
|
|
90
|
+
// Slices share objects that straddle their boundary, so the union has to be deduplicated — without
|
|
91
|
+
// this the same id appears once per slice it touches, and a caller counting results would over-count
|
|
92
|
+
// a large object exactly in proportion to how large it is.
|
|
93
|
+
for (const id of frustumSlice) {
|
|
94
|
+
if (frustumSeen.has(id))
|
|
95
|
+
continue;
|
|
96
|
+
frustumSeen.add(id);
|
|
97
|
+
out.push(id);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Fills `out` (cleared first) with every deduplicated candidate pair — each unordered pair at most
|
|
102
|
+
// once, never an object with itself. A pair is a broadphase candidate: the two objects are close
|
|
103
|
+
// enough to be worth a narrow-phase test, which the caller (or @flighthq/collision) performs.
|
|
104
|
+
export function querySpatialPairs3D(index, out) {
|
|
105
|
+
index.runtime.backend.querySpatialPairs(out);
|
|
106
|
+
}
|
|
107
|
+
// Fills `out` (cleared first) with the ids whose bounds contain the point (`x`,`y`,`z`).
|
|
108
|
+
export function querySpatialPoint3D(index, x, y, z, out) {
|
|
109
|
+
index.runtime.backend.querySpatialPoint(x, y, z, out);
|
|
110
|
+
}
|
|
111
|
+
// Fills `out` (cleared first) with the ids whose bounds the ray from (`x`,`y`,`z`) along
|
|
112
|
+
// (`dx`,`dy`,`dz`) intersects. The direction need not be normalized; the ray is treated as extending
|
|
113
|
+
// forward only.
|
|
114
|
+
export function querySpatialRay3D(index, x, y, z, dx, dy, dz, out) {
|
|
115
|
+
index.runtime.backend.querySpatialRay(x, y, z, dx, dy, dz, out);
|
|
116
|
+
}
|
|
117
|
+
// Fills `out` (cleared first) with the ids whose bounds overlap `region`.
|
|
118
|
+
export function querySpatialRegion3D(index, region, out) {
|
|
119
|
+
index.runtime.backend.querySpatialRegion(region, out);
|
|
120
|
+
}
|
|
121
|
+
// Fills `out` (cleared first) with the ids whose bounds may lie within `radius` of (`x`,`y`,`z`).
|
|
122
|
+
//
|
|
123
|
+
// A CANDIDATE set over the sphere's bounding cube, not an exact sphere test — the index stores bounds
|
|
124
|
+
// and answers box questions, and the corners of that cube reach past the sphere by a factor of the
|
|
125
|
+
// square root of three. That is the same contract every other query here keeps, and the caller that
|
|
126
|
+
// needs exactness applies the distance test to what comes back. The value of the export is that the
|
|
127
|
+
// cube is derived once, correctly, instead of at every callsite.
|
|
128
|
+
export function querySpatialSphere3D(index, x, y, z, radius, out) {
|
|
129
|
+
out.length = 0;
|
|
130
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z) || !(radius >= 0))
|
|
131
|
+
return;
|
|
132
|
+
queryRegionScratch.minX = x - radius;
|
|
133
|
+
queryRegionScratch.minY = y - radius;
|
|
134
|
+
queryRegionScratch.minZ = z - radius;
|
|
135
|
+
queryRegionScratch.maxX = x + radius;
|
|
136
|
+
queryRegionScratch.maxY = y + radius;
|
|
137
|
+
queryRegionScratch.maxZ = z + radius;
|
|
138
|
+
index.runtime.backend.querySpatialRegion(queryRegionScratch, out);
|
|
139
|
+
}
|
|
140
|
+
// Removes an object from the index. A no-op if the id is not present.
|
|
141
|
+
export function removeSpatialObject3D(index, id) {
|
|
142
|
+
index.runtime.backend.removeSpatialObject(id);
|
|
143
|
+
}
|
|
144
|
+
// Moves an already-inserted object to new bounds. Inserting a not-yet-present id behaves as insert.
|
|
145
|
+
// Returns the same sentinel as insertSpatialObject3D. A declined update removes the object rather than
|
|
146
|
+
// leaving it at its old bounds, so a caller that ignores the sentinel can never read a stale position
|
|
147
|
+
// as a current one.
|
|
148
|
+
export function updateSpatialObject3D(index, id, bounds) {
|
|
149
|
+
return index.runtime.backend.updateSpatialObject(id, bounds);
|
|
150
|
+
}
|
|
151
|
+
// The default uniform-grid cell size when createSpatialIndex3D is called without an explicit backend.
|
|
152
|
+
// Deliberately the same middle-of-the-road number as the 2D default: a cell is a world-space length,
|
|
153
|
+
// not a volume, so "roughly the size of a typical object" means the same thing in both dimensions. A
|
|
154
|
+
// workload with a known typical object size should pass its own grid — and in 3D it pays off sooner,
|
|
155
|
+
// since the per-object cell budget is a ~10-cell cube rather than a 32-cell square.
|
|
156
|
+
const DEFAULT_SPATIAL_CELL_SIZE_3D = 128;
|
|
157
|
+
// How many depth slices cover a frustum when the caller does not choose. Eight brings a typical
|
|
158
|
+
// perspective volume's covered bounds close to the volume itself while keeping the query to eight
|
|
159
|
+
// region calls; one slice degenerates to the single-AABB behaviour that makes frustum culling pointless.
|
|
160
|
+
const DEFAULT_FRUSTUM_SLICES = 8;
|
|
161
|
+
// Reused across calls: a culling pass runs every frame, and these would otherwise be three allocations
|
|
162
|
+
// per frame in the hot path. Never held beyond the call that fills them.
|
|
163
|
+
const queryRegionScratch = { maxX: 0, maxY: 0, maxZ: 0, minX: 0, minY: 0, minZ: 0 };
|
|
164
|
+
const frustumSeen = new Set();
|
|
165
|
+
const frustumSlice = [];
|
|
166
|
+
//# sourceMappingURL=spatialIndex3D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spatialIndex3D.js","sourceRoot":"","sources":["../src/spatialIndex3D.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SpatialIndexingGuard, SpatialIndexingNotice } from '@flighthq/types/contract';
|
|
2
|
+
export declare function reportSpatialIndexing(notice: Readonly<SpatialIndexingNotice>): void;
|
|
3
|
+
export declare function setSpatialIndexingGuard(guard: SpatialIndexingGuard | null): void;
|
|
4
|
+
//# sourceMappingURL=spatialIndexingGuard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spatialIndexingGuard.d.ts","sourceRoot":"","sources":["../src/spatialIndexingGuard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAU5F,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,IAAI,CAGnF;AAMD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,GAAG,IAAI,CAEhF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Hands a notice to the installed guard, or does nothing when none is installed. The null check is
|
|
2
|
+
// all production pays at a noteworthy site; the caller-facing text lives in the separately-importable
|
|
3
|
+
// formatSpatialIndexingNotice, per the diagnostics inversion rule.
|
|
4
|
+
//
|
|
5
|
+
// Shared by both dimensions' grids on purpose. The guard is a development diagnostic keyed to the
|
|
6
|
+
// question "why is this object not in my query results?", which is dimension-free — the notice's own
|
|
7
|
+
// vocabulary (mode, operation, reason, bucketCount) carries no axis. Giving 2D and 3D separate guards
|
|
8
|
+
// would mean an application debugging an index had to install two.
|
|
9
|
+
export function reportSpatialIndexing(notice) {
|
|
10
|
+
if (_indexingGuard === null)
|
|
11
|
+
return;
|
|
12
|
+
_indexingGuard(notice);
|
|
13
|
+
}
|
|
14
|
+
// Installs the indexing guard consulted for invalid configuration or bounds, missing-id operations,
|
|
15
|
+
// and overflow routing; null uninstalls it. Module-scoped rather than per-grid: it is a development
|
|
16
|
+
// diagnostic, and an application debugging an index wants it on for every grid at once — in either
|
|
17
|
+
// dimension.
|
|
18
|
+
export function setSpatialIndexingGuard(guard) {
|
|
19
|
+
_indexingGuard = guard;
|
|
20
|
+
}
|
|
21
|
+
// Diagnostics seam filled by setSpatialIndexingGuard.
|
|
22
|
+
let _indexingGuard = null;
|
|
23
|
+
//# sourceMappingURL=spatialIndexingGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spatialIndexingGuard.js","sourceRoot":"","sources":["../src/spatialIndexingGuard.ts"],"names":[],"mappings":"AAEA,mGAAmG;AACnG,sGAAsG;AACtG,mEAAmE;AACnE,EAAE;AACF,kGAAkG;AAClG,qGAAqG;AACrG,sGAAsG;AACtG,mEAAmE;AACnE,MAAM,UAAU,qBAAqB,CAAC,MAAuC;IAC3E,IAAI,cAAc,KAAK,IAAI;QAAE,OAAO;IACpC,cAAc,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC;AAED,oGAAoG;AACpG,oGAAoG;AACpG,mGAAmG;AACnG,aAAa;AACb,MAAM,UAAU,uBAAuB,CAAC,KAAkC;IACxE,cAAc,GAAG,KAAK,CAAC;AACzB,CAAC;AAED,sDAAsD;AACtD,IAAI,cAAc,GAAgC,IAAI,CAAC"}
|
package/dist/uniformGrid.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SpatialIndexBackend2D } from '@flighthq/types/contract';
|
|
2
2
|
export declare const MAX_INDEXED_CELLS_PER_OBJECT = 1024;
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function setSpatialIndexingGuard(guard: SpatialIndexingGuard | null): void;
|
|
3
|
+
export declare function createUniformGridSpatialBackend2D(cellSize: number): SpatialIndexBackend2D;
|
|
5
4
|
//# sourceMappingURL=uniformGrid.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uniformGrid.d.ts","sourceRoot":"","sources":["../src/uniformGrid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,
|
|
1
|
+
{"version":3,"file":"uniformGrid.d.ts","sourceRoot":"","sources":["../src/uniformGrid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,qBAAqB,EAQtB,MAAM,0BAA0B,CAAC;AAmBlC,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAejD,wBAAgB,iCAAiC,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAkDzF"}
|
package/dist/uniformGrid.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { reportSpatialIndexing } from './spatialIndexingGuard';
|
|
1
2
|
// The per-object cell budget. An object whose AABB covers more cells than this is held in the flat
|
|
2
3
|
// overflow list instead of being written into every cell it spans.
|
|
3
4
|
//
|
|
@@ -21,13 +22,13 @@ export const MAX_INDEXED_CELLS_PER_OBJECT = 1024;
|
|
|
21
22
|
// good value is a positive finite number roughly the size of a typical object (too small over-spans
|
|
22
23
|
// large objects across many cells, too large lumps unrelated objects together). An invalid size uses
|
|
23
24
|
// the bounded overflow path to keep results correct and reports through the indexing guard. No
|
|
24
|
-
// import-time side effect — the caller constructs a grid explicitly, and
|
|
25
|
+
// import-time side effect — the caller constructs a grid explicitly, and createSpatialIndex2D uses
|
|
25
26
|
// this as its default index.
|
|
26
27
|
//
|
|
27
28
|
// Object size does not set the cost: an AABB spanning more than MAX_INDEXED_CELLS_PER_OBJECT cells
|
|
28
29
|
// goes to a flat overflow list that every query scans, and non-finite or inverted bounds are declined
|
|
29
|
-
// outright with a false sentinel. Both are visible through
|
|
30
|
-
export function
|
|
30
|
+
// outright with a false sentinel. Both are visible through explainSpatialIndexing2D.
|
|
31
|
+
export function createUniformGridSpatialBackend2D(cellSize) {
|
|
31
32
|
const grid = {
|
|
32
33
|
cellSize,
|
|
33
34
|
cells: new Map(),
|
|
@@ -79,12 +80,6 @@ export function createUniformGridSpatialBackend(cellSize) {
|
|
|
79
80
|
},
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
|
-
// Installs the indexing guard consulted for invalid configuration or bounds, missing-id operations,
|
|
83
|
-
// and overflow routing; null uninstalls it. Module-scoped rather than per-grid: it is a development
|
|
84
|
-
// diagnostic, and an application debugging an index wants it on for every grid at once.
|
|
85
|
-
export function setSpatialIndexingGuard(guard) {
|
|
86
|
-
_indexingGuard = guard;
|
|
87
|
-
}
|
|
88
83
|
// Maps a world coordinate to its cell index along one axis. Uses floor so negative coordinates map
|
|
89
84
|
// to consistently decreasing cell indices (world 0 is the boundary between cell -1 and cell 0).
|
|
90
85
|
function _cellIndex(coord, cellSize) {
|
|
@@ -387,9 +382,7 @@ function _queryGridPairs(grid, out) {
|
|
|
387
382
|
_queryGridOverflowPairs(grid, out);
|
|
388
383
|
}
|
|
389
384
|
function _reportGridIndexing(grid, id, mode, operation, reason, wouldOccupyBucketCount) {
|
|
390
|
-
|
|
391
|
-
return;
|
|
392
|
-
_indexingGuard({ cellSize: grid.cellSize, id, mode, operation, reason, wouldOccupyBucketCount });
|
|
385
|
+
reportSpatialIndexing({ cellSize: grid.cellSize, id, mode, operation, reason, wouldOccupyBucketCount });
|
|
393
386
|
}
|
|
394
387
|
// Gathers the ids in the cell containing the point, then confirms each against its real bounds. A
|
|
395
388
|
// single cell holds each id at most once, so no dedup pass is needed. Overflowed objects hold no cell
|
|
@@ -560,7 +553,4 @@ function _spannedCellCount(cellSize, aabb) {
|
|
|
560
553
|
const cy1 = _cellIndex(aabb.maxY, cellSize);
|
|
561
554
|
return (cx1 - cx0 + 1) * (cy1 - cy0 + 1);
|
|
562
555
|
}
|
|
563
|
-
// Diagnostics seam filled by setSpatialIndexingGuard. Caller-facing text stays in the separate
|
|
564
|
-
// formatSpatialIndexingNotice module, so production pays only the null checks at noteworthy sites.
|
|
565
|
-
let _indexingGuard = null;
|
|
566
556
|
//# sourceMappingURL=uniformGrid.js.map
|