@series-inc/rundot-3d-engine 0.5.20 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/systems/index.d.ts +17 -6
- package/dist/systems/index.js +85 -61
- package/dist/systems/index.js.map +1 -1
- package/package.json +2 -2
package/dist/systems/index.d.ts
CHANGED
|
@@ -299,24 +299,34 @@ declare class SphereColliderComponent extends Component {
|
|
|
299
299
|
type MeshColliderType = "bounding_box" | "convex_hull";
|
|
300
300
|
interface MeshColliderJSON extends ComponentJSON {
|
|
301
301
|
type: "mesh_collider";
|
|
302
|
-
colliderType
|
|
302
|
+
colliderType?: MeshColliderType;
|
|
303
303
|
bodyType?: "static" | "kinematic" | "dynamic";
|
|
304
304
|
isSensor?: boolean;
|
|
305
305
|
enableCollisionEvents?: boolean;
|
|
306
|
+
excludeChildren?: boolean;
|
|
307
|
+
/** nodeOverrides wraps properties inside a `data` object */
|
|
308
|
+
data?: {
|
|
309
|
+
colliderType?: MeshColliderType;
|
|
310
|
+
bodyType?: "static" | "kinematic" | "dynamic";
|
|
311
|
+
isSensor?: boolean;
|
|
312
|
+
enableCollisionEvents?: boolean;
|
|
313
|
+
excludeChildren?: boolean;
|
|
314
|
+
};
|
|
306
315
|
}
|
|
307
316
|
declare class MeshColliderComponent extends Component {
|
|
308
|
-
static fromPrefabJSON(json: MeshColliderJSON, node: PrefabNode): MeshColliderComponent | null;
|
|
317
|
+
static fromPrefabJSON(json: MeshColliderJSON, node: PrefabNode | null): MeshColliderComponent | null;
|
|
309
318
|
private rigidBody;
|
|
310
319
|
private readonly meshName;
|
|
311
320
|
private readonly colliderType;
|
|
312
321
|
private readonly bodyType;
|
|
313
322
|
private readonly isSensor?;
|
|
314
323
|
private readonly enableCollisionEvents?;
|
|
315
|
-
|
|
324
|
+
private readonly excludeChildren;
|
|
325
|
+
constructor(meshName: string | null, colliderType?: MeshColliderType, bodyType?: RigidBodyType, isSensor?: boolean, enableCollisionEvents?: boolean, excludeChildren?: boolean);
|
|
326
|
+
/** Iterate meshes, optionally only direct children */
|
|
327
|
+
private static forEachMesh;
|
|
316
328
|
/**
|
|
317
|
-
* Collect all vertex positions from a mesh group
|
|
318
|
-
* Matches the editor's getAllVerticesFromStowMesh which uses parentWorldMatrixInverse
|
|
319
|
-
* (for a detached group, that's identity — so we just use child.matrixWorld directly).
|
|
329
|
+
* Collect all vertex positions from a mesh group.
|
|
320
330
|
* Returns a flat Float32Array of [x,y,z, x,y,z, ...].
|
|
321
331
|
*/
|
|
322
332
|
private static collectVertices;
|
|
@@ -328,6 +338,7 @@ declare class MeshColliderComponent extends Component {
|
|
|
328
338
|
*/
|
|
329
339
|
private static computeBounds;
|
|
330
340
|
protected onCreate(): void;
|
|
341
|
+
private createCollider;
|
|
331
342
|
getRigidBody(): RigidBodyComponentThree | null;
|
|
332
343
|
}
|
|
333
344
|
|
package/dist/systems/index.js
CHANGED
|
@@ -158,18 +158,25 @@ SphereColliderComponent = __decorateClass([
|
|
|
158
158
|
import * as THREE3 from "three";
|
|
159
159
|
var MeshColliderComponent = class extends Component {
|
|
160
160
|
static fromPrefabJSON(json, node) {
|
|
161
|
-
const
|
|
161
|
+
const props = json.data ?? json;
|
|
162
|
+
const colliderType = props.colliderType ?? "bounding_box";
|
|
162
163
|
if (colliderType !== "bounding_box" && colliderType !== "convex_hull") {
|
|
163
|
-
console.warn(`Unknown mesh collider type: ${
|
|
164
|
+
console.warn(`Unknown mesh collider type: ${props.colliderType}`);
|
|
164
165
|
return null;
|
|
165
166
|
}
|
|
167
|
+
const bodyType = props.bodyType ?? "static" /* STATIC */;
|
|
168
|
+
const isSensor = props.isSensor;
|
|
169
|
+
const enableCollisionEvents = props.enableCollisionEvents;
|
|
170
|
+
const excludeChildren = props.excludeChildren ?? false;
|
|
171
|
+
if (!node) {
|
|
172
|
+
return new MeshColliderComponent(null, colliderType, bodyType, isSensor, enableCollisionEvents, excludeChildren);
|
|
173
|
+
}
|
|
166
174
|
const stowMeshComponent = node.components.find((c) => c.type === "stow_mesh");
|
|
167
175
|
if (!stowMeshComponent) {
|
|
168
176
|
console.warn("MeshColliderComponent requires a stow_mesh component on the same node");
|
|
169
177
|
return null;
|
|
170
178
|
}
|
|
171
|
-
|
|
172
|
-
return new MeshColliderComponent(stowMeshComponent.mesh.assetId, colliderType, bodyType, json.isSensor, json.enableCollisionEvents);
|
|
179
|
+
return new MeshColliderComponent(stowMeshComponent.mesh.assetId, colliderType, bodyType, isSensor, enableCollisionEvents, excludeChildren);
|
|
173
180
|
}
|
|
174
181
|
rigidBody = null;
|
|
175
182
|
meshName;
|
|
@@ -177,37 +184,48 @@ var MeshColliderComponent = class extends Component {
|
|
|
177
184
|
bodyType;
|
|
178
185
|
isSensor;
|
|
179
186
|
enableCollisionEvents;
|
|
180
|
-
|
|
187
|
+
excludeChildren;
|
|
188
|
+
constructor(meshName, colliderType = "bounding_box", bodyType = "static" /* STATIC */, isSensor, enableCollisionEvents, excludeChildren = false) {
|
|
181
189
|
super();
|
|
182
190
|
this.meshName = meshName;
|
|
183
191
|
this.colliderType = colliderType;
|
|
184
192
|
this.bodyType = bodyType;
|
|
185
193
|
this.isSensor = isSensor;
|
|
186
194
|
this.enableCollisionEvents = enableCollisionEvents;
|
|
195
|
+
this.excludeChildren = excludeChildren;
|
|
196
|
+
}
|
|
197
|
+
/** Iterate meshes, optionally only direct children */
|
|
198
|
+
static forEachMesh(root, excludeChildren, fn) {
|
|
199
|
+
if (excludeChildren) {
|
|
200
|
+
for (const child of root.children) {
|
|
201
|
+
if (child.isMesh) fn(child);
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
root.traverse((child) => {
|
|
205
|
+
if (child.isMesh) fn(child);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
187
208
|
}
|
|
188
209
|
/**
|
|
189
|
-
* Collect all vertex positions from a mesh group
|
|
190
|
-
* Matches the editor's getAllVerticesFromStowMesh which uses parentWorldMatrixInverse
|
|
191
|
-
* (for a detached group, that's identity — so we just use child.matrixWorld directly).
|
|
210
|
+
* Collect all vertex positions from a mesh group.
|
|
192
211
|
* Returns a flat Float32Array of [x,y,z, x,y,z, ...].
|
|
193
212
|
*/
|
|
194
|
-
static collectVertices(meshGroup, scale) {
|
|
213
|
+
static collectVertices(meshGroup, scale, excludeChildren = false) {
|
|
195
214
|
meshGroup.updateMatrixWorld(true);
|
|
196
215
|
const allVertices = [];
|
|
197
216
|
const vertex = new THREE3.Vector3();
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
217
|
+
MeshColliderComponent.forEachMesh(meshGroup, excludeChildren, (mesh) => {
|
|
218
|
+
if (!mesh.geometry) return;
|
|
219
|
+
const posAttr = mesh.geometry.getAttribute("position");
|
|
220
|
+
if (!posAttr) return;
|
|
221
|
+
for (let i = 0; i < posAttr.count; i++) {
|
|
222
|
+
vertex.fromBufferAttribute(posAttr, i);
|
|
223
|
+
vertex.applyMatrix4(mesh.matrixWorld);
|
|
224
|
+
allVertices.push(
|
|
225
|
+
vertex.x * scale.x,
|
|
226
|
+
vertex.y * scale.y,
|
|
227
|
+
vertex.z * scale.z
|
|
228
|
+
);
|
|
211
229
|
}
|
|
212
230
|
});
|
|
213
231
|
return new Float32Array(allVertices);
|
|
@@ -218,21 +236,20 @@ var MeshColliderComponent = class extends Component {
|
|
|
218
236
|
* detached cached mesh group is equivalent to identity. So we use child.matrixWorld
|
|
219
237
|
* directly, which includes the mesh group root's own transform — exactly as the editor does.
|
|
220
238
|
*/
|
|
221
|
-
static computeBounds(meshGroup, scale) {
|
|
239
|
+
static computeBounds(meshGroup, scale, excludeChildren = false) {
|
|
222
240
|
meshGroup.updateMatrixWorld(true);
|
|
223
241
|
const box = new THREE3.Box3();
|
|
224
242
|
let foundMesh = false;
|
|
225
|
-
|
|
226
|
-
if (
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
243
|
+
MeshColliderComponent.forEachMesh(meshGroup, excludeChildren, (mesh) => {
|
|
244
|
+
if (!mesh.geometry) return;
|
|
245
|
+
foundMesh = true;
|
|
246
|
+
if (!mesh.geometry.boundingBox) {
|
|
247
|
+
mesh.geometry.computeBoundingBox();
|
|
248
|
+
}
|
|
249
|
+
if (mesh.geometry.boundingBox) {
|
|
250
|
+
const tempBox = mesh.geometry.boundingBox.clone();
|
|
251
|
+
tempBox.applyMatrix4(mesh.matrixWorld);
|
|
252
|
+
box.union(tempBox);
|
|
236
253
|
}
|
|
237
254
|
});
|
|
238
255
|
if (!foundMesh || box.isEmpty()) return null;
|
|
@@ -245,40 +262,47 @@ var MeshColliderComponent = class extends Component {
|
|
|
245
262
|
return { size, center };
|
|
246
263
|
}
|
|
247
264
|
onCreate() {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
265
|
+
if (this.meshName) {
|
|
266
|
+
const stowkit = StowKitSystem.getInstance();
|
|
267
|
+
stowkit.getMesh(this.meshName).then((meshGroup) => {
|
|
268
|
+
if (!this.isAttached()) return;
|
|
269
|
+
this.createCollider(meshGroup);
|
|
270
|
+
});
|
|
271
|
+
} else {
|
|
272
|
+
this.createCollider(this.gameObject);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
createCollider(meshRoot) {
|
|
276
|
+
const scale = this.gameObject.scale.clone();
|
|
277
|
+
if (this.colliderType === "convex_hull") {
|
|
278
|
+
const vertices = MeshColliderComponent.collectVertices(meshRoot, scale, this.excludeChildren);
|
|
279
|
+
if (vertices.length < 9) {
|
|
280
|
+
console.warn("MeshColliderComponent: Not enough vertices for convex hull");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
this.rigidBody = new RigidBodyComponentThree({
|
|
284
|
+
type: this.bodyType,
|
|
285
|
+
shape: "convex_hull" /* CONVEX_HULL */,
|
|
286
|
+
vertices,
|
|
287
|
+
centerOffset: new THREE3.Vector3(0, 0, 0),
|
|
288
|
+
isSensor: this.isSensor,
|
|
289
|
+
enableCollisionEvents: this.enableCollisionEvents
|
|
290
|
+
});
|
|
291
|
+
this.gameObject.addComponent(this.rigidBody);
|
|
292
|
+
} else {
|
|
293
|
+
const bounds = MeshColliderComponent.computeBounds(meshRoot, scale, this.excludeChildren);
|
|
294
|
+
if (bounds) {
|
|
258
295
|
this.rigidBody = new RigidBodyComponentThree({
|
|
259
296
|
type: this.bodyType,
|
|
260
|
-
shape: "
|
|
261
|
-
|
|
262
|
-
centerOffset:
|
|
297
|
+
shape: "box" /* BOX */,
|
|
298
|
+
size: bounds.size,
|
|
299
|
+
centerOffset: bounds.center,
|
|
263
300
|
isSensor: this.isSensor,
|
|
264
301
|
enableCollisionEvents: this.enableCollisionEvents
|
|
265
302
|
});
|
|
266
303
|
this.gameObject.addComponent(this.rigidBody);
|
|
267
|
-
} else {
|
|
268
|
-
const bounds = MeshColliderComponent.computeBounds(meshGroup, scale);
|
|
269
|
-
if (bounds) {
|
|
270
|
-
this.rigidBody = new RigidBodyComponentThree({
|
|
271
|
-
type: this.bodyType,
|
|
272
|
-
shape: "box" /* BOX */,
|
|
273
|
-
size: bounds.size,
|
|
274
|
-
centerOffset: bounds.center,
|
|
275
|
-
isSensor: this.isSensor,
|
|
276
|
-
enableCollisionEvents: this.enableCollisionEvents
|
|
277
|
-
});
|
|
278
|
-
this.gameObject.addComponent(this.rigidBody);
|
|
279
|
-
}
|
|
280
304
|
}
|
|
281
|
-
}
|
|
305
|
+
}
|
|
282
306
|
}
|
|
283
307
|
getRigidBody() {
|
|
284
308
|
return this.rigidBody;
|