@relu-interactives/spatial-ecs 0.2.5 → 0.2.7
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/{Video-DCMCLInA.d.ts → Video-B-qMljTn.d.ts} +15 -7
- package/dist/{Video-ChVFs9Tl.d.cts → Video-Dj4KBqQ1.d.cts} +15 -7
- package/dist/{chunk-RXCUHGRB.js → chunk-2F6T3BVO.js} +193 -33
- package/dist/chunk-2F6T3BVO.js.map +1 -0
- package/dist/{chunk-4A66FSFT.js → chunk-EIC5B3A7.js} +4 -4
- package/dist/{chunk-4A66FSFT.js.map → chunk-EIC5B3A7.js.map} +1 -1
- package/dist/{chunk-CRP3W2GK.js → chunk-FDWNCXU3.js} +3 -3
- package/dist/{chunk-CRP3W2GK.js.map → chunk-FDWNCXU3.js.map} +1 -1
- package/dist/{chunk-NB6I5JJN.js → chunk-G2DUXNTQ.js} +3 -2
- package/dist/chunk-G2DUXNTQ.js.map +1 -0
- package/dist/{chunk-KRZLEPRI.js → chunk-R5D5PWXV.js} +6 -2
- package/dist/chunk-R5D5PWXV.js.map +1 -0
- package/dist/components/index.cjs +4 -0
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/factories/index.cjs +4 -0
- package/dist/factories/index.cjs.map +1 -1
- package/dist/factories/index.d.cts +1 -1
- package/dist/factories/index.d.ts +1 -1
- package/dist/factories/index.js +3 -3
- package/dist/{index-D1I5L7bA.d.cts → index-B12sx9yF.d.cts} +1 -1
- package/dist/{index-DGZDgt3p.d.ts → index-Cf-PaKyN.d.ts} +1 -1
- package/dist/index.cjs +197 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/dist/systems/index.cjs +193 -29
- package/dist/systems/index.cjs.map +1 -1
- package/dist/systems/index.d.cts +17 -4
- package/dist/systems/index.d.ts +17 -4
- package/dist/systems/index.js +3 -3
- package/dist/worldSnapshotUtils.cjs +1 -0
- package/dist/worldSnapshotUtils.cjs.map +1 -1
- package/dist/worldSnapshotUtils.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-KRZLEPRI.js.map +0 -1
- package/dist/chunk-NB6I5JJN.js.map +0 -1
- package/dist/chunk-RXCUHGRB.js.map +0 -1
package/dist/systems/index.cjs
CHANGED
|
@@ -1325,6 +1325,7 @@ var DEFAULT_INSTANCED_MESH_PARAMETERS = {
|
|
|
1325
1325
|
capsule: DEFAULT_MESH_GEOMETRY_PARAMETERS.capsule,
|
|
1326
1326
|
cube: DEFAULT_MESH_GEOMETRY_PARAMETERS.cube,
|
|
1327
1327
|
cylinder: DEFAULT_MESH_GEOMETRY_PARAMETERS.cylinder,
|
|
1328
|
+
model: DEFAULT_MESH_GEOMETRY_PARAMETERS.cube,
|
|
1328
1329
|
plane: DEFAULT_MESH_GEOMETRY_PARAMETERS.plane,
|
|
1329
1330
|
sphere: DEFAULT_MESH_GEOMETRY_PARAMETERS.sphere
|
|
1330
1331
|
};
|
|
@@ -1332,6 +1333,7 @@ var _InstancedMeshComponent = class _InstancedMeshComponent extends Component {
|
|
|
1332
1333
|
constructor(meshKind = "cube", meshParameters, options) {
|
|
1333
1334
|
super();
|
|
1334
1335
|
this.meshKind = meshKind;
|
|
1336
|
+
this.modelPath = options?.modelPath ?? "";
|
|
1335
1337
|
this.meshParameters = {
|
|
1336
1338
|
...DEFAULT_INSTANCED_MESH_PARAMETERS[meshKind],
|
|
1337
1339
|
...meshParameters ?? {}
|
|
@@ -1374,6 +1376,8 @@ var _InstancedMeshComponent = class _InstancedMeshComponent extends Component {
|
|
|
1374
1376
|
height: sanitize(p.height, MIN_DIM)
|
|
1375
1377
|
};
|
|
1376
1378
|
}
|
|
1379
|
+
case "model":
|
|
1380
|
+
return DEFAULT_MESH_GEOMETRY_PARAMETERS.cube;
|
|
1377
1381
|
}
|
|
1378
1382
|
}
|
|
1379
1383
|
};
|
|
@@ -4133,6 +4137,32 @@ var _MeshGeometrySystem = class _MeshGeometrySystem {
|
|
|
4133
4137
|
};
|
|
4134
4138
|
__name(_MeshGeometrySystem, "MeshGeometrySystem");
|
|
4135
4139
|
var MeshGeometrySystem = _MeshGeometrySystem;
|
|
4140
|
+
var DRACO_DECODER_PATH = resolveDracoDecoderPath();
|
|
4141
|
+
var loadGLTF = /* @__PURE__ */ __name((path) => {
|
|
4142
|
+
return new Promise((resolve, reject) => {
|
|
4143
|
+
const loader = new GLTFLoader_js.GLTFLoader();
|
|
4144
|
+
try {
|
|
4145
|
+
const dracoLoader = new DRACOLoader_js.DRACOLoader();
|
|
4146
|
+
dracoLoader.setDecoderPath(DRACO_DECODER_PATH);
|
|
4147
|
+
loader.setDRACOLoader(dracoLoader);
|
|
4148
|
+
} catch (error) {
|
|
4149
|
+
console.debug("DRACOLoader setup failed or unavailable", error);
|
|
4150
|
+
}
|
|
4151
|
+
loader.load(
|
|
4152
|
+
path,
|
|
4153
|
+
(gltf) => {
|
|
4154
|
+
resolve(gltf);
|
|
4155
|
+
},
|
|
4156
|
+
void 0,
|
|
4157
|
+
(error) => {
|
|
4158
|
+
console.debug("GLTFLoader failed to load", error);
|
|
4159
|
+
reject(error);
|
|
4160
|
+
}
|
|
4161
|
+
);
|
|
4162
|
+
});
|
|
4163
|
+
}, "loadGLTF");
|
|
4164
|
+
|
|
4165
|
+
// core/systems/InstancedMeshSystem.ts
|
|
4136
4166
|
function buildGeometry(component) {
|
|
4137
4167
|
const p = component.getSanitizedParameters();
|
|
4138
4168
|
switch (component.meshKind) {
|
|
@@ -4156,6 +4186,8 @@ function buildGeometry(component) {
|
|
|
4156
4186
|
const params = p;
|
|
4157
4187
|
return new THREE13__namespace.CapsuleGeometry(params.radius, params.height, 4, 8);
|
|
4158
4188
|
}
|
|
4189
|
+
default:
|
|
4190
|
+
return new THREE13__namespace.BoxGeometry(1, 1, 1);
|
|
4159
4191
|
}
|
|
4160
4192
|
}
|
|
4161
4193
|
__name(buildGeometry, "buildGeometry");
|
|
@@ -4164,6 +4196,7 @@ var _quaternion = new THREE13__namespace.Quaternion();
|
|
|
4164
4196
|
var _euler = new THREE13__namespace.Euler();
|
|
4165
4197
|
var _scale = new THREE13__namespace.Vector3();
|
|
4166
4198
|
var _matrix = new THREE13__namespace.Matrix4();
|
|
4199
|
+
var _modelMatrix = new THREE13__namespace.Matrix4();
|
|
4167
4200
|
function instanceTransformToMatrix4(inst, out) {
|
|
4168
4201
|
_position.set(inst.position.x, inst.position.y, inst.position.z);
|
|
4169
4202
|
_euler.set(inst.rotation.x, inst.rotation.y, inst.rotation.z, "XYZ");
|
|
@@ -4172,51 +4205,165 @@ function instanceTransformToMatrix4(inst, out) {
|
|
|
4172
4205
|
out.compose(_position, _quaternion, _scale);
|
|
4173
4206
|
}
|
|
4174
4207
|
__name(instanceTransformToMatrix4, "instanceTransformToMatrix4");
|
|
4208
|
+
function disposePrimitiveInstancedMesh(mesh) {
|
|
4209
|
+
mesh.geometry.dispose();
|
|
4210
|
+
if (Array.isArray(mesh.material)) {
|
|
4211
|
+
for (const m of mesh.material) {
|
|
4212
|
+
m.dispose();
|
|
4213
|
+
}
|
|
4214
|
+
} else {
|
|
4215
|
+
mesh.material.dispose();
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
__name(disposePrimitiveInstancedMesh, "disposePrimitiveInstancedMesh");
|
|
4219
|
+
function disposeModelGroup(group) {
|
|
4220
|
+
group.traverse((child) => {
|
|
4221
|
+
const im = child;
|
|
4222
|
+
if (im.isInstancedMesh) {
|
|
4223
|
+
im.geometry.dispose();
|
|
4224
|
+
if (Array.isArray(im.material)) {
|
|
4225
|
+
for (const m of im.material) {
|
|
4226
|
+
m.dispose();
|
|
4227
|
+
}
|
|
4228
|
+
} else {
|
|
4229
|
+
im.material.dispose();
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
});
|
|
4233
|
+
}
|
|
4234
|
+
__name(disposeModelGroup, "disposeModelGroup");
|
|
4175
4235
|
var _InstancedMeshSystem = class _InstancedMeshSystem {
|
|
4176
4236
|
constructor() {
|
|
4177
4237
|
/** Signature tracking for geometry + instance count changes. */
|
|
4178
4238
|
this.geometrySignatures = /* @__PURE__ */ new Map();
|
|
4239
|
+
/** Signature being loaded per entity. Maps entityId → geometrySignature in-flight.
|
|
4240
|
+
* Prevents re-dispatching a load every frame while comp.instancedMesh is still null. */
|
|
4241
|
+
this.loadingSignatures = /* @__PURE__ */ new Map();
|
|
4242
|
+
/** Per-mesh data for model kind, populated after GLTF load. */
|
|
4243
|
+
this.modelMeshEntries = /* @__PURE__ */ new Map();
|
|
4179
4244
|
}
|
|
4180
4245
|
update(world) {
|
|
4181
4246
|
const entityIds = world.query(InstancedMeshComponent);
|
|
4182
4247
|
const alive = new Set(entityIds);
|
|
4183
4248
|
for (const trackedId of this.geometrySignatures.keys()) {
|
|
4184
|
-
if (!alive.has(trackedId))
|
|
4185
|
-
|
|
4186
|
-
|
|
4249
|
+
if (!alive.has(trackedId)) this.geometrySignatures.delete(trackedId);
|
|
4250
|
+
}
|
|
4251
|
+
for (const trackedId of this.loadingSignatures.keys()) {
|
|
4252
|
+
if (!alive.has(trackedId)) this.loadingSignatures.delete(trackedId);
|
|
4253
|
+
}
|
|
4254
|
+
for (const trackedId of this.modelMeshEntries.keys()) {
|
|
4255
|
+
if (!alive.has(trackedId)) this.modelMeshEntries.delete(trackedId);
|
|
4187
4256
|
}
|
|
4188
4257
|
for (const entityId of entityIds) {
|
|
4189
4258
|
const comp = world.getComponent(
|
|
4190
4259
|
entityId,
|
|
4191
4260
|
InstancedMeshComponent
|
|
4192
4261
|
);
|
|
4193
|
-
if (!comp)
|
|
4194
|
-
continue;
|
|
4195
|
-
}
|
|
4196
|
-
let anchor = null;
|
|
4262
|
+
if (!comp) continue;
|
|
4197
4263
|
const objectRef = world.getComponent(entityId, Object3DRef);
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
}
|
|
4201
|
-
if (!anchor) {
|
|
4202
|
-
continue;
|
|
4203
|
-
}
|
|
4264
|
+
const anchor = objectRef?.object ?? null;
|
|
4265
|
+
if (!anchor) continue;
|
|
4204
4266
|
const instanceCount = comp.instances.length;
|
|
4205
|
-
const geometrySignature = `${comp.meshKind}:${JSON.stringify(comp.meshParameters)}:${instanceCount}`;
|
|
4206
|
-
const
|
|
4267
|
+
const geometrySignature = comp.meshKind === "model" ? `model:${comp.modelPath}:${instanceCount}` : `${comp.meshKind}:${JSON.stringify(comp.meshParameters)}:${instanceCount}`;
|
|
4268
|
+
const pendingLoadSignature = this.loadingSignatures.get(entityId);
|
|
4269
|
+
const needsRebuild = (comp.instancedMesh === null || this.geometrySignatures.get(entityId) !== geometrySignature) && pendingLoadSignature !== geometrySignature;
|
|
4207
4270
|
if (needsRebuild) {
|
|
4208
4271
|
if (comp.instancedMesh) {
|
|
4209
4272
|
anchor.remove(comp.instancedMesh);
|
|
4210
|
-
comp.instancedMesh.
|
|
4211
|
-
|
|
4212
|
-
for (const m of comp.instancedMesh.material) {
|
|
4213
|
-
m.dispose();
|
|
4214
|
-
}
|
|
4273
|
+
if (comp.instancedMesh.isInstancedMesh) {
|
|
4274
|
+
disposePrimitiveInstancedMesh(comp.instancedMesh);
|
|
4215
4275
|
} else {
|
|
4216
|
-
comp.instancedMesh
|
|
4276
|
+
disposeModelGroup(comp.instancedMesh);
|
|
4217
4277
|
}
|
|
4218
4278
|
comp.instancedMesh = null;
|
|
4219
4279
|
}
|
|
4280
|
+
if (pendingLoadSignature !== void 0 && pendingLoadSignature !== geometrySignature) {
|
|
4281
|
+
this.loadingSignatures.delete(entityId);
|
|
4282
|
+
this.modelMeshEntries.delete(entityId);
|
|
4283
|
+
}
|
|
4284
|
+
if (comp.meshKind === "model") {
|
|
4285
|
+
if (comp.modelPath && !this.loadingSignatures.has(entityId)) {
|
|
4286
|
+
this.loadingSignatures.set(entityId, geometrySignature);
|
|
4287
|
+
const targetSignature = geometrySignature;
|
|
4288
|
+
const targetEntityId = entityId;
|
|
4289
|
+
loadGLTF(comp.modelPath).then((gltf) => {
|
|
4290
|
+
if (!world.hasEntity(targetEntityId)) {
|
|
4291
|
+
this.loadingSignatures.delete(targetEntityId);
|
|
4292
|
+
return;
|
|
4293
|
+
}
|
|
4294
|
+
const currentComp = world.getComponent(
|
|
4295
|
+
targetEntityId,
|
|
4296
|
+
InstancedMeshComponent
|
|
4297
|
+
);
|
|
4298
|
+
if (!currentComp) {
|
|
4299
|
+
this.loadingSignatures.delete(targetEntityId);
|
|
4300
|
+
return;
|
|
4301
|
+
}
|
|
4302
|
+
const currentSig = `model:${currentComp.modelPath}:${currentComp.instances.length}`;
|
|
4303
|
+
if (currentSig !== targetSignature) {
|
|
4304
|
+
this.loadingSignatures.delete(targetEntityId);
|
|
4305
|
+
return;
|
|
4306
|
+
}
|
|
4307
|
+
const currentRef = world.getComponent(targetEntityId, Object3DRef);
|
|
4308
|
+
const currentAnchor = currentRef?.object ?? null;
|
|
4309
|
+
if (!currentAnchor) {
|
|
4310
|
+
this.loadingSignatures.delete(targetEntityId);
|
|
4311
|
+
return;
|
|
4312
|
+
}
|
|
4313
|
+
if (currentComp.instancedMesh) {
|
|
4314
|
+
currentAnchor.remove(currentComp.instancedMesh);
|
|
4315
|
+
disposeModelGroup(currentComp.instancedMesh);
|
|
4316
|
+
currentComp.instancedMesh = null;
|
|
4317
|
+
}
|
|
4318
|
+
const count2 = Math.max(1, currentComp.instances.length);
|
|
4319
|
+
const entries = [];
|
|
4320
|
+
gltf.scene.updateWorldMatrix(true, true);
|
|
4321
|
+
gltf.scene.traverse((child) => {
|
|
4322
|
+
const meshChild = child;
|
|
4323
|
+
if (!meshChild.isMesh) return;
|
|
4324
|
+
const geometry2 = meshChild.geometry.clone();
|
|
4325
|
+
const sourceMaterial = Array.isArray(meshChild.material) ? meshChild.material.map((m) => m.clone()) : meshChild.material.clone();
|
|
4326
|
+
meshChild.updateWorldMatrix(true, false);
|
|
4327
|
+
const localMatrix = meshChild.matrixWorld.clone();
|
|
4328
|
+
const instancedMesh2 = new THREE13__namespace.InstancedMesh(
|
|
4329
|
+
geometry2,
|
|
4330
|
+
Array.isArray(sourceMaterial) ? sourceMaterial : sourceMaterial,
|
|
4331
|
+
count2
|
|
4332
|
+
);
|
|
4333
|
+
instancedMesh2.castShadow = currentComp.castShadow;
|
|
4334
|
+
instancedMesh2.receiveShadow = currentComp.receiveShadow;
|
|
4335
|
+
for (let i = 0; i < count2; i++) {
|
|
4336
|
+
const inst = currentComp.instances[i] ?? {
|
|
4337
|
+
position: { x: 0, y: 0, z: 0 },
|
|
4338
|
+
rotation: { x: 0, y: 0, z: 0 },
|
|
4339
|
+
scale: { x: 1, y: 1, z: 1 }
|
|
4340
|
+
};
|
|
4341
|
+
instanceTransformToMatrix4(inst, _matrix);
|
|
4342
|
+
_modelMatrix.multiplyMatrices(_matrix, localMatrix);
|
|
4343
|
+
instancedMesh2.setMatrixAt(i, _modelMatrix);
|
|
4344
|
+
}
|
|
4345
|
+
instancedMesh2.instanceMatrix.needsUpdate = true;
|
|
4346
|
+
entries.push({ localMatrix, instancedMesh: instancedMesh2 });
|
|
4347
|
+
});
|
|
4348
|
+
if (entries.length === 0) {
|
|
4349
|
+
this.loadingSignatures.delete(targetEntityId);
|
|
4350
|
+
return;
|
|
4351
|
+
}
|
|
4352
|
+
const group = new THREE13__namespace.Group();
|
|
4353
|
+
for (const entry of entries) {
|
|
4354
|
+
group.add(entry.instancedMesh);
|
|
4355
|
+
}
|
|
4356
|
+
currentAnchor.add(group);
|
|
4357
|
+
currentComp.instancedMesh = group;
|
|
4358
|
+
this.modelMeshEntries.set(targetEntityId, entries);
|
|
4359
|
+
this.geometrySignatures.set(targetEntityId, targetSignature);
|
|
4360
|
+
this.loadingSignatures.delete(targetEntityId);
|
|
4361
|
+
}).catch(() => {
|
|
4362
|
+
this.loadingSignatures.delete(targetEntityId);
|
|
4363
|
+
});
|
|
4364
|
+
}
|
|
4365
|
+
continue;
|
|
4366
|
+
}
|
|
4220
4367
|
const count = Math.max(1, instanceCount);
|
|
4221
4368
|
const geometry = buildGeometry(comp);
|
|
4222
4369
|
const material = new THREE13__namespace.MeshStandardMaterial({ color: "#ffffff" });
|
|
@@ -4237,15 +4384,32 @@ var _InstancedMeshSystem = class _InstancedMeshSystem {
|
|
|
4237
4384
|
comp.instancedMesh = instancedMesh;
|
|
4238
4385
|
this.geometrySignatures.set(entityId, geometrySignature);
|
|
4239
4386
|
} else {
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4387
|
+
if (comp.meshKind === "model") {
|
|
4388
|
+
const entries = this.modelMeshEntries.get(entityId);
|
|
4389
|
+
if (entries) {
|
|
4390
|
+
const count = comp.instances.length;
|
|
4391
|
+
for (const entry of entries) {
|
|
4392
|
+
for (let i = 0; i < count; i++) {
|
|
4393
|
+
instanceTransformToMatrix4(comp.instances[i], _matrix);
|
|
4394
|
+
_modelMatrix.multiplyMatrices(_matrix, entry.localMatrix);
|
|
4395
|
+
entry.instancedMesh.setMatrixAt(i, _modelMatrix);
|
|
4396
|
+
}
|
|
4397
|
+
entry.instancedMesh.instanceMatrix.needsUpdate = true;
|
|
4398
|
+
entry.instancedMesh.castShadow = comp.castShadow;
|
|
4399
|
+
entry.instancedMesh.receiveShadow = comp.receiveShadow;
|
|
4400
|
+
}
|
|
4401
|
+
}
|
|
4402
|
+
} else {
|
|
4403
|
+
const im = comp.instancedMesh;
|
|
4404
|
+
const count = comp.instances.length;
|
|
4405
|
+
for (let i = 0; i < count; i++) {
|
|
4406
|
+
instanceTransformToMatrix4(comp.instances[i], _matrix);
|
|
4407
|
+
im.setMatrixAt(i, _matrix);
|
|
4408
|
+
}
|
|
4409
|
+
im.instanceMatrix.needsUpdate = true;
|
|
4410
|
+
im.castShadow = comp.castShadow;
|
|
4411
|
+
im.receiveShadow = comp.receiveShadow;
|
|
4245
4412
|
}
|
|
4246
|
-
im.instanceMatrix.needsUpdate = true;
|
|
4247
|
-
im.castShadow = comp.castShadow;
|
|
4248
|
-
im.receiveShadow = comp.receiveShadow;
|
|
4249
4413
|
}
|
|
4250
4414
|
}
|
|
4251
4415
|
}
|