@spatial-engine/three 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.cjs +126 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +54 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +97 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Francisco Rueda Esquivel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ThreeSynchronizer: () => ThreeSynchronizer,
|
|
24
|
+
box3ToAABB: () => box3ToAABB,
|
|
25
|
+
rayBox3Intersect: () => rayBox3Intersect,
|
|
26
|
+
rayToFlatArray: () => rayToFlatArray,
|
|
27
|
+
threeRayToPool: () => threeRayToPool
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
var import_core = require("@spatial-engine/core");
|
|
31
|
+
|
|
32
|
+
// src/synchronizer.ts
|
|
33
|
+
var import_three = require("three");
|
|
34
|
+
var ThreeSynchronizer = class {
|
|
35
|
+
/** The AABBPool index used to identify this object in the core engine. */
|
|
36
|
+
id;
|
|
37
|
+
object;
|
|
38
|
+
octree;
|
|
39
|
+
aabbPool;
|
|
40
|
+
_box = new import_three.Box3();
|
|
41
|
+
_inserted = false;
|
|
42
|
+
constructor(object, octree, aabbPool) {
|
|
43
|
+
this.object = object;
|
|
44
|
+
this.octree = octree;
|
|
45
|
+
this.aabbPool = aabbPool;
|
|
46
|
+
this.id = aabbPool.allocate();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Recompute the object's world-space bounding box and sync it to the
|
|
50
|
+
* Octree. Call this whenever the object may have moved or changed shape.
|
|
51
|
+
*/
|
|
52
|
+
sync() {
|
|
53
|
+
this._box.setFromObject(this.object);
|
|
54
|
+
const { min, max } = this._box;
|
|
55
|
+
if (!this._inserted) {
|
|
56
|
+
this.aabbPool.set(this.id, min.x, min.y, min.z, max.x, max.y, max.z);
|
|
57
|
+
this.octree.insert(this.id);
|
|
58
|
+
this._inserted = true;
|
|
59
|
+
} else {
|
|
60
|
+
this.octree.update(this.id, min.x, min.y, min.z, max.x, max.y, max.z);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// src/index.ts
|
|
66
|
+
function box3ToAABB(pool, box) {
|
|
67
|
+
const index = pool.allocate();
|
|
68
|
+
pool.set(
|
|
69
|
+
index,
|
|
70
|
+
box.min.x,
|
|
71
|
+
box.min.y,
|
|
72
|
+
box.min.z,
|
|
73
|
+
box.max.x,
|
|
74
|
+
box.max.y,
|
|
75
|
+
box.max.z
|
|
76
|
+
);
|
|
77
|
+
return index;
|
|
78
|
+
}
|
|
79
|
+
function threeRayToPool(pool, ray) {
|
|
80
|
+
const index = pool.allocate();
|
|
81
|
+
pool.set(
|
|
82
|
+
index,
|
|
83
|
+
ray.origin.x,
|
|
84
|
+
ray.origin.y,
|
|
85
|
+
ray.origin.z,
|
|
86
|
+
ray.direction.x,
|
|
87
|
+
ray.direction.y,
|
|
88
|
+
ray.direction.z
|
|
89
|
+
);
|
|
90
|
+
return index;
|
|
91
|
+
}
|
|
92
|
+
function rayToFlatArray(ray, buf = new Float32Array(import_core.RAY_STRIDE)) {
|
|
93
|
+
buf[0] = ray.origin.x;
|
|
94
|
+
buf[1] = ray.origin.y;
|
|
95
|
+
buf[2] = ray.origin.z;
|
|
96
|
+
buf[3] = ray.direction.x;
|
|
97
|
+
buf[4] = ray.direction.y;
|
|
98
|
+
buf[5] = ray.direction.z;
|
|
99
|
+
return buf;
|
|
100
|
+
}
|
|
101
|
+
var _rayBuf = new Float32Array(import_core.RAY_STRIDE);
|
|
102
|
+
var _aabbBuf = new Float32Array(6);
|
|
103
|
+
function rayBox3Intersect(ray, box) {
|
|
104
|
+
_rayBuf[0] = ray.origin.x;
|
|
105
|
+
_rayBuf[1] = ray.origin.y;
|
|
106
|
+
_rayBuf[2] = ray.origin.z;
|
|
107
|
+
_rayBuf[3] = ray.direction.x;
|
|
108
|
+
_rayBuf[4] = ray.direction.y;
|
|
109
|
+
_rayBuf[5] = ray.direction.z;
|
|
110
|
+
_aabbBuf[0] = box.min.x;
|
|
111
|
+
_aabbBuf[1] = box.min.y;
|
|
112
|
+
_aabbBuf[2] = box.min.z;
|
|
113
|
+
_aabbBuf[3] = box.max.x;
|
|
114
|
+
_aabbBuf[4] = box.max.y;
|
|
115
|
+
_aabbBuf[5] = box.max.z;
|
|
116
|
+
return (0, import_core.rayIntersectsAABB)(_rayBuf, 0, _aabbBuf, 0);
|
|
117
|
+
}
|
|
118
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
119
|
+
0 && (module.exports = {
|
|
120
|
+
ThreeSynchronizer,
|
|
121
|
+
box3ToAABB,
|
|
122
|
+
rayBox3Intersect,
|
|
123
|
+
rayToFlatArray,
|
|
124
|
+
threeRayToPool
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/synchronizer.ts"],"sourcesContent":["import type { Box3, Ray } from 'three';\nimport { AABBPool, RayPool, rayIntersectsAABB, RAY_STRIDE } from '@spatial-engine/core';\n\nexport { ThreeSynchronizer } from './synchronizer.js';\n\n/**\n * Convert a Three.js Box3 into an AABB slot in the pool.\n * Returns the allocated index.\n */\nexport function box3ToAABB(pool: AABBPool, box: Box3): number {\n const index = pool.allocate();\n pool.set(\n index,\n box.min.x,\n box.min.y,\n box.min.z,\n box.max.x,\n box.max.y,\n box.max.z,\n );\n return index;\n}\n\n/**\n * Convert a Three.js Ray into a Ray slot in the pool.\n * Returns the allocated index.\n */\nexport function threeRayToPool(pool: RayPool, ray: Ray): number {\n const index = pool.allocate();\n pool.set(\n index,\n ray.origin.x,\n ray.origin.y,\n ray.origin.z,\n ray.direction.x,\n ray.direction.y,\n ray.direction.z,\n );\n return index;\n}\n\n/**\n * Fill a pre-allocated (or newly created) Float32Array with the ray data in\n * the flat format `[ox, oy, oz, dx, dy, dz]` expected by the core query engine.\n *\n * @param ray The Three.js Ray to convert.\n * @param buf Optional pre-allocated Float32Array of length RAY_STRIDE (6).\n * If omitted a new buffer is created. Pass a cached buffer to\n * avoid allocation and stay zero-GC.\n * @returns The filled buffer (same reference as `buf` when provided).\n */\nexport function rayToFlatArray(ray: Ray, buf: Float32Array = new Float32Array(RAY_STRIDE)): Float32Array {\n buf[0] = ray.origin.x;\n buf[1] = ray.origin.y;\n buf[2] = ray.origin.z;\n buf[3] = ray.direction.x;\n buf[4] = ray.direction.y;\n buf[5] = ray.direction.z;\n return buf;\n}\n\n/**\n * Test whether a Three.js Ray intersects a Three.js Box3.\n * Returns the parametric hit distance `t` or -1 on miss.\n * Uses pre-allocated Float32Array buffers to stay zero-GC.\n */\nconst _rayBuf = new Float32Array(RAY_STRIDE);\nconst _aabbBuf = new Float32Array(6);\n\nexport function rayBox3Intersect(ray: Ray, box: Box3): number {\n _rayBuf[0] = ray.origin.x;\n _rayBuf[1] = ray.origin.y;\n _rayBuf[2] = ray.origin.z;\n _rayBuf[3] = ray.direction.x;\n _rayBuf[4] = ray.direction.y;\n _rayBuf[5] = ray.direction.z;\n\n _aabbBuf[0] = box.min.x;\n _aabbBuf[1] = box.min.y;\n _aabbBuf[2] = box.min.z;\n _aabbBuf[3] = box.max.x;\n _aabbBuf[4] = box.max.y;\n _aabbBuf[5] = box.max.z;\n\n return rayIntersectsAABB(_rayBuf, 0, _aabbBuf, 0);\n}\n","import type { Mesh, Group } from 'three';\nimport { Box3 } from 'three';\nimport { AABBPool, Octree } from '@spatial-engine/core';\n\n/**\n * Synchronizes a THREE.Mesh or THREE.Group with a spatial-engine Octree.\n *\n * On the first call to `sync()` the object's world-space bounding box is\n * computed, stored in the AABBPool, and inserted into the Octree.\n * Subsequent calls to `sync()` recompute the bounding box and call\n * `Octree.update()` to reposition the entry without a full reinsertion.\n *\n * Each synchronizer occupies exactly one slot in the supplied AABBPool;\n * that slot's index is exposed as the read-only `id` property.\n */\nexport class ThreeSynchronizer {\n /** The AABBPool index used to identify this object in the core engine. */\n readonly id: number;\n\n private readonly object: Mesh | Group;\n private readonly octree: Octree;\n private readonly aabbPool: AABBPool;\n private readonly _box: Box3 = new Box3();\n private _inserted: boolean = false;\n\n constructor(object: Mesh | Group, octree: Octree, aabbPool: AABBPool) {\n this.object = object;\n this.octree = octree;\n this.aabbPool = aabbPool;\n this.id = aabbPool.allocate();\n }\n\n /**\n * Recompute the object's world-space bounding box and sync it to the\n * Octree. Call this whenever the object may have moved or changed shape.\n */\n sync(): void {\n this._box.setFromObject(this.object);\n const { min, max } = this._box;\n\n if (!this._inserted) {\n this.aabbPool.set(this.id, min.x, min.y, min.z, max.x, max.y, max.z);\n this.octree.insert(this.id);\n this._inserted = true;\n } else {\n this.octree.update(this.id, min.x, min.y, min.z, max.x, max.y, max.z);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAiE;;;ACAjE,mBAAqB;AAcd,IAAM,oBAAN,MAAwB;AAAA;AAAA,EAEpB;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAa,IAAI,kBAAK;AAAA,EAC/B,YAAqB;AAAA,EAE7B,YAAY,QAAsB,QAAgB,UAAoB;AACpE,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,KAAK,SAAS,SAAS;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAa;AACX,SAAK,KAAK,cAAc,KAAK,MAAM;AACnC,UAAM,EAAE,KAAK,IAAI,IAAI,KAAK;AAE1B,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,SAAS,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACnE,WAAK,OAAO,OAAO,KAAK,EAAE;AAC1B,WAAK,YAAY;AAAA,IACnB,OAAO;AACL,WAAK,OAAO,OAAO,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAAA,IACtE;AAAA,EACF;AACF;;;ADvCO,SAAS,WAAW,MAAgB,KAAmB;AAC5D,QAAM,QAAQ,KAAK,SAAS;AAC5B,OAAK;AAAA,IACH;AAAA,IACA,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,EACV;AACA,SAAO;AACT;AAMO,SAAS,eAAe,MAAe,KAAkB;AAC9D,QAAM,QAAQ,KAAK,SAAS;AAC5B,OAAK;AAAA,IACH;AAAA,IACA,IAAI,OAAO;AAAA,IACX,IAAI,OAAO;AAAA,IACX,IAAI,OAAO;AAAA,IACX,IAAI,UAAU;AAAA,IACd,IAAI,UAAU;AAAA,IACd,IAAI,UAAU;AAAA,EAChB;AACA,SAAO;AACT;AAYO,SAAS,eAAe,KAAU,MAAoB,IAAI,aAAa,sBAAU,GAAiB;AACvG,MAAI,CAAC,IAAI,IAAI,OAAO;AACpB,MAAI,CAAC,IAAI,IAAI,OAAO;AACpB,MAAI,CAAC,IAAI,IAAI,OAAO;AACpB,MAAI,CAAC,IAAI,IAAI,UAAU;AACvB,MAAI,CAAC,IAAI,IAAI,UAAU;AACvB,MAAI,CAAC,IAAI,IAAI,UAAU;AACvB,SAAO;AACT;AAOA,IAAM,UAAU,IAAI,aAAa,sBAAU;AAC3C,IAAM,WAAW,IAAI,aAAa,CAAC;AAE5B,SAAS,iBAAiB,KAAU,KAAmB;AAC5D,UAAQ,CAAC,IAAI,IAAI,OAAO;AACxB,UAAQ,CAAC,IAAI,IAAI,OAAO;AACxB,UAAQ,CAAC,IAAI,IAAI,OAAO;AACxB,UAAQ,CAAC,IAAI,IAAI,UAAU;AAC3B,UAAQ,CAAC,IAAI,IAAI,UAAU;AAC3B,UAAQ,CAAC,IAAI,IAAI,UAAU;AAE3B,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AAEtB,aAAO,+BAAkB,SAAS,GAAG,UAAU,CAAC;AAClD;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Mesh, Group, Box3, Ray } from 'three';
|
|
2
|
+
import { Octree, AABBPool, RayPool } from '@spatial-engine/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Synchronizes a THREE.Mesh or THREE.Group with a spatial-engine Octree.
|
|
6
|
+
*
|
|
7
|
+
* On the first call to `sync()` the object's world-space bounding box is
|
|
8
|
+
* computed, stored in the AABBPool, and inserted into the Octree.
|
|
9
|
+
* Subsequent calls to `sync()` recompute the bounding box and call
|
|
10
|
+
* `Octree.update()` to reposition the entry without a full reinsertion.
|
|
11
|
+
*
|
|
12
|
+
* Each synchronizer occupies exactly one slot in the supplied AABBPool;
|
|
13
|
+
* that slot's index is exposed as the read-only `id` property.
|
|
14
|
+
*/
|
|
15
|
+
declare class ThreeSynchronizer {
|
|
16
|
+
/** The AABBPool index used to identify this object in the core engine. */
|
|
17
|
+
readonly id: number;
|
|
18
|
+
private readonly object;
|
|
19
|
+
private readonly octree;
|
|
20
|
+
private readonly aabbPool;
|
|
21
|
+
private readonly _box;
|
|
22
|
+
private _inserted;
|
|
23
|
+
constructor(object: Mesh | Group, octree: Octree, aabbPool: AABBPool);
|
|
24
|
+
/**
|
|
25
|
+
* Recompute the object's world-space bounding box and sync it to the
|
|
26
|
+
* Octree. Call this whenever the object may have moved or changed shape.
|
|
27
|
+
*/
|
|
28
|
+
sync(): void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Convert a Three.js Box3 into an AABB slot in the pool.
|
|
33
|
+
* Returns the allocated index.
|
|
34
|
+
*/
|
|
35
|
+
declare function box3ToAABB(pool: AABBPool, box: Box3): number;
|
|
36
|
+
/**
|
|
37
|
+
* Convert a Three.js Ray into a Ray slot in the pool.
|
|
38
|
+
* Returns the allocated index.
|
|
39
|
+
*/
|
|
40
|
+
declare function threeRayToPool(pool: RayPool, ray: Ray): number;
|
|
41
|
+
/**
|
|
42
|
+
* Fill a pre-allocated (or newly created) Float32Array with the ray data in
|
|
43
|
+
* the flat format `[ox, oy, oz, dx, dy, dz]` expected by the core query engine.
|
|
44
|
+
*
|
|
45
|
+
* @param ray The Three.js Ray to convert.
|
|
46
|
+
* @param buf Optional pre-allocated Float32Array of length RAY_STRIDE (6).
|
|
47
|
+
* If omitted a new buffer is created. Pass a cached buffer to
|
|
48
|
+
* avoid allocation and stay zero-GC.
|
|
49
|
+
* @returns The filled buffer (same reference as `buf` when provided).
|
|
50
|
+
*/
|
|
51
|
+
declare function rayToFlatArray(ray: Ray, buf?: Float32Array): Float32Array;
|
|
52
|
+
declare function rayBox3Intersect(ray: Ray, box: Box3): number;
|
|
53
|
+
|
|
54
|
+
export { ThreeSynchronizer, box3ToAABB, rayBox3Intersect, rayToFlatArray, threeRayToPool };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Mesh, Group, Box3, Ray } from 'three';
|
|
2
|
+
import { Octree, AABBPool, RayPool } from '@spatial-engine/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Synchronizes a THREE.Mesh or THREE.Group with a spatial-engine Octree.
|
|
6
|
+
*
|
|
7
|
+
* On the first call to `sync()` the object's world-space bounding box is
|
|
8
|
+
* computed, stored in the AABBPool, and inserted into the Octree.
|
|
9
|
+
* Subsequent calls to `sync()` recompute the bounding box and call
|
|
10
|
+
* `Octree.update()` to reposition the entry without a full reinsertion.
|
|
11
|
+
*
|
|
12
|
+
* Each synchronizer occupies exactly one slot in the supplied AABBPool;
|
|
13
|
+
* that slot's index is exposed as the read-only `id` property.
|
|
14
|
+
*/
|
|
15
|
+
declare class ThreeSynchronizer {
|
|
16
|
+
/** The AABBPool index used to identify this object in the core engine. */
|
|
17
|
+
readonly id: number;
|
|
18
|
+
private readonly object;
|
|
19
|
+
private readonly octree;
|
|
20
|
+
private readonly aabbPool;
|
|
21
|
+
private readonly _box;
|
|
22
|
+
private _inserted;
|
|
23
|
+
constructor(object: Mesh | Group, octree: Octree, aabbPool: AABBPool);
|
|
24
|
+
/**
|
|
25
|
+
* Recompute the object's world-space bounding box and sync it to the
|
|
26
|
+
* Octree. Call this whenever the object may have moved or changed shape.
|
|
27
|
+
*/
|
|
28
|
+
sync(): void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Convert a Three.js Box3 into an AABB slot in the pool.
|
|
33
|
+
* Returns the allocated index.
|
|
34
|
+
*/
|
|
35
|
+
declare function box3ToAABB(pool: AABBPool, box: Box3): number;
|
|
36
|
+
/**
|
|
37
|
+
* Convert a Three.js Ray into a Ray slot in the pool.
|
|
38
|
+
* Returns the allocated index.
|
|
39
|
+
*/
|
|
40
|
+
declare function threeRayToPool(pool: RayPool, ray: Ray): number;
|
|
41
|
+
/**
|
|
42
|
+
* Fill a pre-allocated (or newly created) Float32Array with the ray data in
|
|
43
|
+
* the flat format `[ox, oy, oz, dx, dy, dz]` expected by the core query engine.
|
|
44
|
+
*
|
|
45
|
+
* @param ray The Three.js Ray to convert.
|
|
46
|
+
* @param buf Optional pre-allocated Float32Array of length RAY_STRIDE (6).
|
|
47
|
+
* If omitted a new buffer is created. Pass a cached buffer to
|
|
48
|
+
* avoid allocation and stay zero-GC.
|
|
49
|
+
* @returns The filled buffer (same reference as `buf` when provided).
|
|
50
|
+
*/
|
|
51
|
+
declare function rayToFlatArray(ray: Ray, buf?: Float32Array): Float32Array;
|
|
52
|
+
declare function rayBox3Intersect(ray: Ray, box: Box3): number;
|
|
53
|
+
|
|
54
|
+
export { ThreeSynchronizer, box3ToAABB, rayBox3Intersect, rayToFlatArray, threeRayToPool };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { rayIntersectsAABB, RAY_STRIDE } from "@spatial-engine/core";
|
|
3
|
+
|
|
4
|
+
// src/synchronizer.ts
|
|
5
|
+
import { Box3 } from "three";
|
|
6
|
+
var ThreeSynchronizer = class {
|
|
7
|
+
/** The AABBPool index used to identify this object in the core engine. */
|
|
8
|
+
id;
|
|
9
|
+
object;
|
|
10
|
+
octree;
|
|
11
|
+
aabbPool;
|
|
12
|
+
_box = new Box3();
|
|
13
|
+
_inserted = false;
|
|
14
|
+
constructor(object, octree, aabbPool) {
|
|
15
|
+
this.object = object;
|
|
16
|
+
this.octree = octree;
|
|
17
|
+
this.aabbPool = aabbPool;
|
|
18
|
+
this.id = aabbPool.allocate();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Recompute the object's world-space bounding box and sync it to the
|
|
22
|
+
* Octree. Call this whenever the object may have moved or changed shape.
|
|
23
|
+
*/
|
|
24
|
+
sync() {
|
|
25
|
+
this._box.setFromObject(this.object);
|
|
26
|
+
const { min, max } = this._box;
|
|
27
|
+
if (!this._inserted) {
|
|
28
|
+
this.aabbPool.set(this.id, min.x, min.y, min.z, max.x, max.y, max.z);
|
|
29
|
+
this.octree.insert(this.id);
|
|
30
|
+
this._inserted = true;
|
|
31
|
+
} else {
|
|
32
|
+
this.octree.update(this.id, min.x, min.y, min.z, max.x, max.y, max.z);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/index.ts
|
|
38
|
+
function box3ToAABB(pool, box) {
|
|
39
|
+
const index = pool.allocate();
|
|
40
|
+
pool.set(
|
|
41
|
+
index,
|
|
42
|
+
box.min.x,
|
|
43
|
+
box.min.y,
|
|
44
|
+
box.min.z,
|
|
45
|
+
box.max.x,
|
|
46
|
+
box.max.y,
|
|
47
|
+
box.max.z
|
|
48
|
+
);
|
|
49
|
+
return index;
|
|
50
|
+
}
|
|
51
|
+
function threeRayToPool(pool, ray) {
|
|
52
|
+
const index = pool.allocate();
|
|
53
|
+
pool.set(
|
|
54
|
+
index,
|
|
55
|
+
ray.origin.x,
|
|
56
|
+
ray.origin.y,
|
|
57
|
+
ray.origin.z,
|
|
58
|
+
ray.direction.x,
|
|
59
|
+
ray.direction.y,
|
|
60
|
+
ray.direction.z
|
|
61
|
+
);
|
|
62
|
+
return index;
|
|
63
|
+
}
|
|
64
|
+
function rayToFlatArray(ray, buf = new Float32Array(RAY_STRIDE)) {
|
|
65
|
+
buf[0] = ray.origin.x;
|
|
66
|
+
buf[1] = ray.origin.y;
|
|
67
|
+
buf[2] = ray.origin.z;
|
|
68
|
+
buf[3] = ray.direction.x;
|
|
69
|
+
buf[4] = ray.direction.y;
|
|
70
|
+
buf[5] = ray.direction.z;
|
|
71
|
+
return buf;
|
|
72
|
+
}
|
|
73
|
+
var _rayBuf = new Float32Array(RAY_STRIDE);
|
|
74
|
+
var _aabbBuf = new Float32Array(6);
|
|
75
|
+
function rayBox3Intersect(ray, box) {
|
|
76
|
+
_rayBuf[0] = ray.origin.x;
|
|
77
|
+
_rayBuf[1] = ray.origin.y;
|
|
78
|
+
_rayBuf[2] = ray.origin.z;
|
|
79
|
+
_rayBuf[3] = ray.direction.x;
|
|
80
|
+
_rayBuf[4] = ray.direction.y;
|
|
81
|
+
_rayBuf[5] = ray.direction.z;
|
|
82
|
+
_aabbBuf[0] = box.min.x;
|
|
83
|
+
_aabbBuf[1] = box.min.y;
|
|
84
|
+
_aabbBuf[2] = box.min.z;
|
|
85
|
+
_aabbBuf[3] = box.max.x;
|
|
86
|
+
_aabbBuf[4] = box.max.y;
|
|
87
|
+
_aabbBuf[5] = box.max.z;
|
|
88
|
+
return rayIntersectsAABB(_rayBuf, 0, _aabbBuf, 0);
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
ThreeSynchronizer,
|
|
92
|
+
box3ToAABB,
|
|
93
|
+
rayBox3Intersect,
|
|
94
|
+
rayToFlatArray,
|
|
95
|
+
threeRayToPool
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/synchronizer.ts"],"sourcesContent":["import type { Box3, Ray } from 'three';\nimport { AABBPool, RayPool, rayIntersectsAABB, RAY_STRIDE } from '@spatial-engine/core';\n\nexport { ThreeSynchronizer } from './synchronizer.js';\n\n/**\n * Convert a Three.js Box3 into an AABB slot in the pool.\n * Returns the allocated index.\n */\nexport function box3ToAABB(pool: AABBPool, box: Box3): number {\n const index = pool.allocate();\n pool.set(\n index,\n box.min.x,\n box.min.y,\n box.min.z,\n box.max.x,\n box.max.y,\n box.max.z,\n );\n return index;\n}\n\n/**\n * Convert a Three.js Ray into a Ray slot in the pool.\n * Returns the allocated index.\n */\nexport function threeRayToPool(pool: RayPool, ray: Ray): number {\n const index = pool.allocate();\n pool.set(\n index,\n ray.origin.x,\n ray.origin.y,\n ray.origin.z,\n ray.direction.x,\n ray.direction.y,\n ray.direction.z,\n );\n return index;\n}\n\n/**\n * Fill a pre-allocated (or newly created) Float32Array with the ray data in\n * the flat format `[ox, oy, oz, dx, dy, dz]` expected by the core query engine.\n *\n * @param ray The Three.js Ray to convert.\n * @param buf Optional pre-allocated Float32Array of length RAY_STRIDE (6).\n * If omitted a new buffer is created. Pass a cached buffer to\n * avoid allocation and stay zero-GC.\n * @returns The filled buffer (same reference as `buf` when provided).\n */\nexport function rayToFlatArray(ray: Ray, buf: Float32Array = new Float32Array(RAY_STRIDE)): Float32Array {\n buf[0] = ray.origin.x;\n buf[1] = ray.origin.y;\n buf[2] = ray.origin.z;\n buf[3] = ray.direction.x;\n buf[4] = ray.direction.y;\n buf[5] = ray.direction.z;\n return buf;\n}\n\n/**\n * Test whether a Three.js Ray intersects a Three.js Box3.\n * Returns the parametric hit distance `t` or -1 on miss.\n * Uses pre-allocated Float32Array buffers to stay zero-GC.\n */\nconst _rayBuf = new Float32Array(RAY_STRIDE);\nconst _aabbBuf = new Float32Array(6);\n\nexport function rayBox3Intersect(ray: Ray, box: Box3): number {\n _rayBuf[0] = ray.origin.x;\n _rayBuf[1] = ray.origin.y;\n _rayBuf[2] = ray.origin.z;\n _rayBuf[3] = ray.direction.x;\n _rayBuf[4] = ray.direction.y;\n _rayBuf[5] = ray.direction.z;\n\n _aabbBuf[0] = box.min.x;\n _aabbBuf[1] = box.min.y;\n _aabbBuf[2] = box.min.z;\n _aabbBuf[3] = box.max.x;\n _aabbBuf[4] = box.max.y;\n _aabbBuf[5] = box.max.z;\n\n return rayIntersectsAABB(_rayBuf, 0, _aabbBuf, 0);\n}\n","import type { Mesh, Group } from 'three';\nimport { Box3 } from 'three';\nimport { AABBPool, Octree } from '@spatial-engine/core';\n\n/**\n * Synchronizes a THREE.Mesh or THREE.Group with a spatial-engine Octree.\n *\n * On the first call to `sync()` the object's world-space bounding box is\n * computed, stored in the AABBPool, and inserted into the Octree.\n * Subsequent calls to `sync()` recompute the bounding box and call\n * `Octree.update()` to reposition the entry without a full reinsertion.\n *\n * Each synchronizer occupies exactly one slot in the supplied AABBPool;\n * that slot's index is exposed as the read-only `id` property.\n */\nexport class ThreeSynchronizer {\n /** The AABBPool index used to identify this object in the core engine. */\n readonly id: number;\n\n private readonly object: Mesh | Group;\n private readonly octree: Octree;\n private readonly aabbPool: AABBPool;\n private readonly _box: Box3 = new Box3();\n private _inserted: boolean = false;\n\n constructor(object: Mesh | Group, octree: Octree, aabbPool: AABBPool) {\n this.object = object;\n this.octree = octree;\n this.aabbPool = aabbPool;\n this.id = aabbPool.allocate();\n }\n\n /**\n * Recompute the object's world-space bounding box and sync it to the\n * Octree. Call this whenever the object may have moved or changed shape.\n */\n sync(): void {\n this._box.setFromObject(this.object);\n const { min, max } = this._box;\n\n if (!this._inserted) {\n this.aabbPool.set(this.id, min.x, min.y, min.z, max.x, max.y, max.z);\n this.octree.insert(this.id);\n this._inserted = true;\n } else {\n this.octree.update(this.id, min.x, min.y, min.z, max.x, max.y, max.z);\n }\n }\n}\n"],"mappings":";AACA,SAA4B,mBAAmB,kBAAkB;;;ACAjE,SAAS,YAAY;AAcd,IAAM,oBAAN,MAAwB;AAAA;AAAA,EAEpB;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAa,IAAI,KAAK;AAAA,EAC/B,YAAqB;AAAA,EAE7B,YAAY,QAAsB,QAAgB,UAAoB;AACpE,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,KAAK,SAAS,SAAS;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAa;AACX,SAAK,KAAK,cAAc,KAAK,MAAM;AACnC,UAAM,EAAE,KAAK,IAAI,IAAI,KAAK;AAE1B,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,SAAS,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACnE,WAAK,OAAO,OAAO,KAAK,EAAE;AAC1B,WAAK,YAAY;AAAA,IACnB,OAAO;AACL,WAAK,OAAO,OAAO,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAAA,IACtE;AAAA,EACF;AACF;;;ADvCO,SAAS,WAAW,MAAgB,KAAmB;AAC5D,QAAM,QAAQ,KAAK,SAAS;AAC5B,OAAK;AAAA,IACH;AAAA,IACA,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,IACR,IAAI,IAAI;AAAA,EACV;AACA,SAAO;AACT;AAMO,SAAS,eAAe,MAAe,KAAkB;AAC9D,QAAM,QAAQ,KAAK,SAAS;AAC5B,OAAK;AAAA,IACH;AAAA,IACA,IAAI,OAAO;AAAA,IACX,IAAI,OAAO;AAAA,IACX,IAAI,OAAO;AAAA,IACX,IAAI,UAAU;AAAA,IACd,IAAI,UAAU;AAAA,IACd,IAAI,UAAU;AAAA,EAChB;AACA,SAAO;AACT;AAYO,SAAS,eAAe,KAAU,MAAoB,IAAI,aAAa,UAAU,GAAiB;AACvG,MAAI,CAAC,IAAI,IAAI,OAAO;AACpB,MAAI,CAAC,IAAI,IAAI,OAAO;AACpB,MAAI,CAAC,IAAI,IAAI,OAAO;AACpB,MAAI,CAAC,IAAI,IAAI,UAAU;AACvB,MAAI,CAAC,IAAI,IAAI,UAAU;AACvB,MAAI,CAAC,IAAI,IAAI,UAAU;AACvB,SAAO;AACT;AAOA,IAAM,UAAU,IAAI,aAAa,UAAU;AAC3C,IAAM,WAAW,IAAI,aAAa,CAAC;AAE5B,SAAS,iBAAiB,KAAU,KAAmB;AAC5D,UAAQ,CAAC,IAAI,IAAI,OAAO;AACxB,UAAQ,CAAC,IAAI,IAAI,OAAO;AACxB,UAAQ,CAAC,IAAI,IAAI,OAAO;AACxB,UAAQ,CAAC,IAAI,IAAI,UAAU;AAC3B,UAAQ,CAAC,IAAI,IAAI,UAAU;AAC3B,UAAQ,CAAC,IAAI,IAAI,UAAU;AAE3B,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AACtB,WAAS,CAAC,IAAI,IAAI,IAAI;AAEtB,SAAO,kBAAkB,SAAS,GAAG,UAAU,CAAC;AAClD;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spatial-engine/three",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Three.js adapter for @spatial-engine/core",
|
|
5
|
+
"author": "Francisco Rueda Esquivel",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/franruedaesq/spatial-engine.git",
|
|
10
|
+
"directory": "packages/three"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"three",
|
|
14
|
+
"threejs",
|
|
15
|
+
"octree",
|
|
16
|
+
"spatial",
|
|
17
|
+
"aabb",
|
|
18
|
+
"3d",
|
|
19
|
+
"data-oriented-design",
|
|
20
|
+
"zero-gc"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "./dist/index.cjs",
|
|
24
|
+
"module": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js",
|
|
30
|
+
"require": "./dist/index.cjs"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist"
|
|
35
|
+
],
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@spatial-engine/core": "0.0.1"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"three": ">=0.150.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"three": "^0.166.1",
|
|
44
|
+
"@types/three": "^0.166.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsup",
|
|
48
|
+
"typecheck": "tsc --noEmit"
|
|
49
|
+
}
|
|
50
|
+
}
|