@needle-tools/engine 2.36.0-pre → 2.37.0-pre
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/CHANGELOG.md +12 -0
- package/dist/needle-engine.d.ts +171 -141
- package/dist/needle-engine.js +451 -437
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +82 -82
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/api.d.ts +1 -0
- package/lib/engine/api.js +1 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/debug/debug.d.ts +1 -0
- package/lib/engine/debug/debug.js +3 -0
- package/lib/engine/debug/debug.js.map +1 -1
- package/lib/engine/engine_gameobject.js +2 -1
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +33 -42
- package/lib/engine/engine_physics.js +431 -383
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics.types.d.ts +16 -0
- package/lib/engine/engine_physics.types.js +19 -0
- package/lib/engine/engine_physics.types.js.map +1 -0
- package/lib/engine/engine_serialization_core.d.ts +3 -0
- package/lib/engine/engine_serialization_core.js +5 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.js +3 -1
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_types.d.ts +45 -26
- package/lib/engine/engine_types.js +24 -37
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_util_decorator.d.ts +6 -0
- package/lib/engine/engine_util_decorator.js +54 -0
- package/lib/engine/engine_util_decorator.js.map +1 -0
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +1 -1
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_gameobject_data.js +2 -0
- package/lib/engine/extensions/NEEDLE_gameobject_data.js.map +1 -1
- package/lib/engine-components/Animation.d.ts +6 -5
- package/lib/engine-components/Animation.js +0 -7
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.js +1 -0
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +7 -2
- package/lib/engine-components/Collider.js +27 -15
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/Component.d.ts +6 -15
- package/lib/engine-components/Component.js +7 -112
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/DragControls.js +9 -6
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/NavMesh.d.ts +0 -5
- package/lib/engine-components/NavMesh.js +100 -10
- package/lib/engine-components/NavMesh.js.map +1 -1
- package/lib/engine-components/NestedGltf.js +2 -0
- package/lib/engine-components/NestedGltf.js.map +1 -1
- package/lib/engine-components/RigidBody.d.ts +40 -25
- package/lib/engine-components/RigidBody.js +253 -142
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/SpatialTrigger.js +1 -1
- package/lib/engine-components/SpatialTrigger.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.d.ts +1 -0
- package/lib/engine-components/SpectatorCamera.js +9 -2
- package/lib/engine-components/SpectatorCamera.js.map +1 -1
- package/lib/engine-components/SpringJoint.d.ts +0 -13
- package/lib/engine-components/SpringJoint.js +42 -41
- package/lib/engine-components/SpringJoint.js.map +1 -1
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +1 -0
- package/lib/engine-components/WebXR.js +10 -2
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRController.js +12 -6
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -3
- package/lib/engine-components/codegen/components.js +1 -3
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/package.json +3 -4
- package/src/engine/api.ts +2 -1
- package/src/engine/codegen/register_types.js +4 -12
- package/src/engine/debug/debug.ts +4 -0
- package/src/engine/engine_gameobject.ts +4 -4
- package/src/engine/engine_physics.ts +460 -421
- package/src/engine/engine_physics.types.ts +19 -0
- package/src/engine/engine_serialization_core.ts +8 -1
- package/src/engine/engine_setup.ts +5 -1
- package/src/engine/engine_types.ts +82 -56
- package/src/engine/engine_util_decorator.ts +69 -0
- package/src/engine/engine_utils.ts +3 -3
- package/src/engine/extensions/NEEDLE_gameobject_data.ts +2 -0
- package/src/engine-components/Animation.ts +10 -12
- package/src/engine-components/BoxHelperComponent.ts +1 -0
- package/src/engine-components/Collider.ts +29 -29
- package/src/engine-components/Component.ts +15 -130
- package/src/engine-components/DragControls.ts +9 -5
- package/src/engine-components/NavMesh.ts +114 -115
- package/src/engine-components/NestedGltf.ts +2 -0
- package/src/engine-components/RigidBody.ts +258 -149
- package/src/engine-components/SpatialTrigger.ts +1 -1
- package/src/engine-components/SpectatorCamera.ts +10 -2
- package/src/engine-components/SpringJoint.ts +41 -41
- package/src/engine-components/VideoPlayer.ts +1 -2
- package/src/engine-components/WebXR.ts +12 -2
- package/src/engine-components/WebXRController.ts +16 -7
- package/src/engine-components/codegen/components.ts +1 -3
|
@@ -1,38 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Box3, Layers, Matrix4, Quaternion, Raycaster, Sphere, Vector2, Vector3 } from 'three';
|
|
3
|
-
import cannonDebugger from 'cannon-es-debugger';
|
|
1
|
+
import { Box3, BufferAttribute, BufferGeometry, Layers, LineBasicMaterial, LineSegments, Matrix4, Quaternion, Raycaster, Sphere, Vector2, Vector3 } from 'three';
|
|
4
2
|
import { getParam } from "./engine_utils";
|
|
5
|
-
import { getWorldPosition, getWorldQuaternion, setWorldPositionXYZ, setWorldQuaternionXYZW } from "./engine_three_utils";
|
|
6
|
-
import {
|
|
7
|
-
import { InstancingUtil } from './engine_instancing';
|
|
3
|
+
import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPositionXYZ, setWorldQuaternionXYZW } from "./engine_three_utils";
|
|
4
|
+
import { Collision, ContactPoint } from './engine_types';
|
|
8
5
|
import { foreachComponent } from './engine_gameobject';
|
|
6
|
+
import RAPIER, { ActiveEvents, Collider, ColliderDesc, EventQueue, RigidBody, World } from '@dimforge/rapier3d-compat';
|
|
7
|
+
import { CollisionDetectionMode } from '../engine/engine_physics.types';
|
|
9
8
|
const debugPhysics = getParam("debugphysics");
|
|
9
|
+
const debugColliderPlacement = getParam("debugphysicscolliders");
|
|
10
10
|
const debugCollisions = getParam("debugcollisions");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
kinematic = false;
|
|
14
|
-
physicsEvents = false;
|
|
15
|
-
drag = 0;
|
|
16
|
-
angularDrag = 0.05;
|
|
17
|
-
sleepThreshold = .01;
|
|
18
|
-
}
|
|
19
|
-
// TODO: refactor to return some kind of handle for adding/removing
|
|
20
|
-
class PhysicsObject {
|
|
21
|
-
obj;
|
|
22
|
-
parent;
|
|
23
|
-
body;
|
|
24
|
-
shapes = [];
|
|
25
|
-
collisonCallback = null;
|
|
26
|
-
_hasRigidbody = false;
|
|
27
|
-
_didSleepLastStep = false;
|
|
28
|
-
constructor(obj, body) {
|
|
29
|
-
this.obj = obj;
|
|
30
|
-
this.parent = obj.parent;
|
|
31
|
-
this.body = body;
|
|
32
|
-
if (this.body)
|
|
33
|
-
this.body[$physicsKey] = obj;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
11
|
+
const $componentKey = Symbol("needle component");
|
|
12
|
+
const $bodyKey = Symbol("physics body");
|
|
36
13
|
export class RaycastOptions {
|
|
37
14
|
ray = undefined;
|
|
38
15
|
cam = undefined;
|
|
@@ -196,390 +173,343 @@ export class Physics {
|
|
|
196
173
|
return results;
|
|
197
174
|
}
|
|
198
175
|
// physics simulation
|
|
199
|
-
|
|
176
|
+
_tempPosition = new Vector3();
|
|
177
|
+
_tempQuaternion = new Quaternion();
|
|
178
|
+
_tempMatrix = new Matrix4();
|
|
179
|
+
static _didLoadPhysicsEngine = false;
|
|
200
180
|
_isUpdatingPhysicsWorld = false;
|
|
181
|
+
get isUpdating() { return this._isUpdatingPhysicsWorld; }
|
|
201
182
|
context;
|
|
202
|
-
world
|
|
183
|
+
world;
|
|
184
|
+
_hasCreatedWorld = false;
|
|
185
|
+
eventQueue;
|
|
186
|
+
collisionHandler;
|
|
187
|
+
// private rigidbodies: Array<IRigidbody | null> = [];
|
|
203
188
|
objects = [];
|
|
204
|
-
|
|
205
|
-
|
|
189
|
+
bodies = [];
|
|
190
|
+
// private rigidbodiesLookup: Map<IRigidbody, RigidBody> = new Map<IRigidbody, RigidBody>();
|
|
191
|
+
// private kinematicColliders: Array<IComponent> = [];
|
|
192
|
+
// private rigidbodyLookup: Map<IRigidbody, IComponent[]> = new Map<IRigidbody, IComponent[]>();
|
|
193
|
+
// private objectLookup: Map<Object3D, IRigidbody> = new Map<Object3D, IRigidbody>();
|
|
206
194
|
constructor(context) {
|
|
207
195
|
this.context = context;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
196
|
+
}
|
|
197
|
+
async createWorld() {
|
|
198
|
+
if (this._hasCreatedWorld) {
|
|
199
|
+
console.error("Invalid call to create physics world: world is already created");
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
this._hasCreatedWorld = true;
|
|
203
|
+
if (!Physics._didLoadPhysicsEngine) {
|
|
204
|
+
await RAPIER.init().then(() => RAPIER);
|
|
205
|
+
Physics._didLoadPhysicsEngine = true;
|
|
206
|
+
}
|
|
207
|
+
const gravity = { x: 0.0, y: -9.81, z: 0.0 };
|
|
208
|
+
this.world = new World(gravity);
|
|
209
|
+
}
|
|
210
|
+
addBoxCollider(collider, center, size) {
|
|
211
|
+
const obj = collider.gameObject;
|
|
212
|
+
const scale = getWorldScale(obj, this._tempPosition).multiply(size);
|
|
213
|
+
scale.multiplyScalar(0.5);
|
|
214
|
+
const desc = ColliderDesc.cuboid(scale.x, scale.y, scale.z);
|
|
215
|
+
this.createCollider(collider, desc, center);
|
|
216
|
+
}
|
|
217
|
+
addSphereCollider(collider, center, radius) {
|
|
218
|
+
const obj = collider.gameObject;
|
|
219
|
+
const scale = getWorldScale(obj, this._tempPosition).multiplyScalar(radius);
|
|
220
|
+
const desc = ColliderDesc.ball(scale.x);
|
|
221
|
+
this.createCollider(collider, desc, center);
|
|
222
|
+
}
|
|
223
|
+
addMeshCollider(collider, mesh, convex) {
|
|
224
|
+
const geo = mesh.geometry;
|
|
225
|
+
if (!geo) {
|
|
226
|
+
if (debugPhysics)
|
|
227
|
+
console.warn("Missing mesh geometry", mesh.name);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
let positions = geo.getAttribute("position").array;
|
|
231
|
+
const indices = geo.index?.array;
|
|
232
|
+
// console.log(geo.center())
|
|
233
|
+
// scaling seems not supported yet https://github.com/dimforge/rapier/issues/243
|
|
234
|
+
const scale = getWorldScale(mesh, this._tempPosition);
|
|
235
|
+
if (Math.abs(scale.x - 1) > 0.0001 || Math.abs(scale.y - 1) > 0.0001 || Math.abs(scale.z - 1) > 0.0001) {
|
|
236
|
+
console.warn("Your model is using scaled mesh colliders which is not optimal for performance", mesh.name, Object.assign({}, scale), mesh);
|
|
237
|
+
// showBalloonWarning("Your model is using scaled mesh colliders which is not optimal for performance: " + mesh.name + ", consider using unscaled objects");
|
|
238
|
+
const scaledPositions = new Float32Array(positions.length);
|
|
239
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
240
|
+
scaledPositions[i] = positions[i] * scale.x;
|
|
241
|
+
scaledPositions[i + 1] = positions[i + 1] * scale.y;
|
|
242
|
+
scaledPositions[i + 2] = positions[i + 2] * scale.z;
|
|
244
243
|
}
|
|
244
|
+
positions = scaledPositions;
|
|
245
|
+
}
|
|
246
|
+
const desc = convex ? ColliderDesc.convexMesh(positions) : ColliderDesc.trimesh(positions, indices);
|
|
247
|
+
if (desc) {
|
|
248
|
+
this.createCollider(collider, desc);
|
|
249
|
+
// col.setTranslationWrtParent(new Vector3(0,2,0));
|
|
245
250
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
this.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
251
|
+
}
|
|
252
|
+
createCollider(collider, desc, center) {
|
|
253
|
+
if (!this.world)
|
|
254
|
+
throw new Error("Physics world not initialized");
|
|
255
|
+
const matrix = this._tempMatrix;
|
|
256
|
+
const { rigidBody, useExplicitMassProperties } = this.getRigidbody(collider, this._tempMatrix);
|
|
257
|
+
matrix.decompose(this._tempPosition, this._tempQuaternion, new Vector3());
|
|
258
|
+
if (center)
|
|
259
|
+
this._tempPosition.add(center);
|
|
260
|
+
desc.setTranslation(this._tempPosition.x, this._tempPosition.y, this._tempPosition.z);
|
|
261
|
+
desc.setRotation(this._tempQuaternion);
|
|
262
|
+
desc.setSensor(collider.isTrigger);
|
|
263
|
+
// if we want to use explicit mass properties, we need to set the collider density to 0
|
|
264
|
+
// otherwise rapier will compute the mass properties based on the collider shape and density
|
|
265
|
+
// https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
|
|
266
|
+
if (useExplicitMassProperties) {
|
|
267
|
+
// desc.setDensity(0);
|
|
268
|
+
}
|
|
269
|
+
const col = this.world.createCollider(desc, rigidBody);
|
|
270
|
+
col[$componentKey] = collider;
|
|
271
|
+
collider[$bodyKey] = col;
|
|
272
|
+
col.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
|
|
273
|
+
this.objects.push(collider);
|
|
274
|
+
this.bodies.push(col);
|
|
275
|
+
return col;
|
|
276
|
+
}
|
|
277
|
+
getRigidbody(collider, _matrix) {
|
|
278
|
+
if (!this.world)
|
|
279
|
+
throw new Error("Physics world not initialized");
|
|
280
|
+
let rigidBody = null;
|
|
281
|
+
let useExplicitMassProperties = false;
|
|
282
|
+
if (collider.attachedRigidbody) {
|
|
283
|
+
const rb = collider.attachedRigidbody;
|
|
284
|
+
rigidBody = rb[$bodyKey];
|
|
285
|
+
useExplicitMassProperties = true;
|
|
286
|
+
if (!rigidBody) {
|
|
287
|
+
const kinematic = rb.isKinematic && !debugColliderPlacement;
|
|
288
|
+
if (debugPhysics)
|
|
289
|
+
console.log("Create rigidbody", kinematic);
|
|
290
|
+
const rigidBodyDesc = kinematic ? RAPIER.RigidBodyDesc.kinematicPositionBased() : RAPIER.RigidBodyDesc.dynamic();
|
|
291
|
+
const pos = getWorldPosition(collider.attachedRigidbody.gameObject);
|
|
292
|
+
rigidBodyDesc.setTranslation(pos.x, pos.y, pos.z);
|
|
293
|
+
rigidBodyDesc.setRotation(getWorldQuaternion(collider.attachedRigidbody.gameObject));
|
|
294
|
+
rigidBody = this.world.createRigidBody(rigidBodyDesc);
|
|
295
|
+
this.bodies.push(rigidBody);
|
|
296
|
+
this.objects.push(rb);
|
|
260
297
|
}
|
|
298
|
+
rigidBody[$componentKey] = rb;
|
|
299
|
+
rb[$bodyKey] = rigidBody;
|
|
300
|
+
this.internalUpdateProperties(rb, rigidBody);
|
|
301
|
+
this.getRigidbodyRelativeMatrix(collider.gameObject, rb.gameObject, _matrix);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
const rigidBodyDesc = RAPIER.RigidBodyDesc.kinematicPositionBased();
|
|
305
|
+
const pos = getWorldPosition(collider.gameObject);
|
|
306
|
+
rigidBodyDesc.setTranslation(pos.x, pos.y, pos.z);
|
|
307
|
+
rigidBodyDesc.setRotation(getWorldQuaternion(collider.gameObject));
|
|
308
|
+
rigidBody = this.world.createRigidBody(rigidBodyDesc);
|
|
309
|
+
_matrix.identity();
|
|
310
|
+
rigidBody[$componentKey] = null;
|
|
261
311
|
}
|
|
312
|
+
return { rigidBody: rigidBody, useExplicitMassProperties: useExplicitMassProperties };
|
|
262
313
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
314
|
+
removeBody(obj) {
|
|
315
|
+
const body = obj[$bodyKey];
|
|
316
|
+
obj[$bodyKey] = null;
|
|
317
|
+
if (body) {
|
|
318
|
+
const index = this.objects.findIndex(o => o === obj);
|
|
319
|
+
if (index >= 0) {
|
|
320
|
+
const body = this.bodies[index];
|
|
321
|
+
this.bodies.splice(index, 1);
|
|
322
|
+
this.objects.splice(index, 1);
|
|
323
|
+
if (body instanceof Collider) {
|
|
324
|
+
this.world?.removeCollider(body, true);
|
|
325
|
+
}
|
|
326
|
+
else if (body instanceof RigidBody) {
|
|
327
|
+
this.world?.removeRigidBody(body);
|
|
328
|
+
}
|
|
329
|
+
// check if we need to remove the rigidbody too
|
|
330
|
+
const col = obj;
|
|
331
|
+
if (col.isCollider && col.attachedRigidbody) {
|
|
332
|
+
const rb = col.attachedRigidbody[$bodyKey];
|
|
333
|
+
if (rb && rb.numColliders() <= 0 && rb.world() === this.world) {
|
|
334
|
+
this.world?.removeRigidBody(rb);
|
|
335
|
+
}
|
|
269
336
|
}
|
|
270
|
-
return;
|
|
271
337
|
}
|
|
272
338
|
}
|
|
273
339
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
body
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
this.objects.push(po);
|
|
316
|
-
}
|
|
317
|
-
return shape;
|
|
318
|
-
}
|
|
319
|
-
addSphereCollider(obj, center, radius, rb) {
|
|
320
|
-
const scale = this.tempPosition;
|
|
321
|
-
obj.getWorldScale(scale);
|
|
322
|
-
const factor = Math.max(scale.x, scale.y, scale.z);
|
|
323
|
-
const shape = new PhysicsSphere(radius * factor);
|
|
324
|
-
// shape.collisionResponse = !trigger;
|
|
325
|
-
center = center.clone();
|
|
326
|
-
center.multiply(scale);
|
|
327
|
-
const body = this.addShape(obj, shape, center, rb);
|
|
328
|
-
if (body !== null) {
|
|
329
|
-
this.world.addBody(body);
|
|
330
|
-
if (this.isAlreadyRegistered(body))
|
|
331
|
-
return shape;
|
|
332
|
-
const po = new PhysicsObject(obj, body);
|
|
333
|
-
this.objects.push(po);
|
|
334
|
-
}
|
|
335
|
-
return shape;
|
|
336
|
-
}
|
|
337
|
-
addMeshCollider(_obj) {
|
|
338
|
-
// see https://github.com/schteppe/js/blob/master/demos/bunny.html
|
|
339
|
-
if (debugPhysics)
|
|
340
|
-
console.warn("TODO mesh collider not yet supported");
|
|
341
|
-
// const geometry: BufferGeometry = obj["geometry"];
|
|
342
|
-
// console.log(geometry);
|
|
343
|
-
// const size = geometry.boundingBox.max.clone();
|
|
344
|
-
// size.sub(geometry.boundingBox.min);
|
|
345
|
-
// console.log(size);
|
|
346
|
-
// this.addBoxCollider(obj, size);
|
|
347
|
-
// const verts = geometry.getAttribute("position").array;
|
|
348
|
-
// const faces = new Array<Array<number>>();
|
|
349
|
-
// console.log(geometry);
|
|
350
|
-
// for (let i = 0; i < geometry.index.array.length; i += 3) {
|
|
351
|
-
// const i0 = geometry.index.array[i];
|
|
352
|
-
// const i1 = geometry.index.array[i + 1];
|
|
353
|
-
// const i2 = geometry.index.array[i + 2];
|
|
354
|
-
// const v0 = new Vector3(verts[i0 * 3], verts[i0 * 3 + 1], verts[i0 * 3 + 2]);
|
|
355
|
-
// const v1 = new Vector3(verts[i1 * 3], verts[i1 * 3 + 1], verts[i1 * 3 + 2]);
|
|
356
|
-
// const v2 = new Vector3(verts[i2 * 3], verts[i2 * 3 + 1], verts[i2 * 3 + 2]);
|
|
357
|
-
// const face = [v0, v1, v2];
|
|
358
|
-
// faces.push(face);
|
|
340
|
+
updateBody(comp, translation, rotation) {
|
|
341
|
+
if (comp.destroyed || !comp.gameObject)
|
|
342
|
+
return;
|
|
343
|
+
if (!translation && !rotation)
|
|
344
|
+
return;
|
|
345
|
+
if (comp.isCollider === true) {
|
|
346
|
+
// const collider = comp as ICollider;
|
|
347
|
+
console.warn("TODO: implement updating collider position");
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
const rigidbody = comp;
|
|
351
|
+
const body = rigidbody[$bodyKey];
|
|
352
|
+
if (body) {
|
|
353
|
+
this.syncPhysicsBody(rigidbody.gameObject, body, translation, rotation);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
updateProperties(rigidbody) {
|
|
358
|
+
const physicsBody = rigidbody[$bodyKey];
|
|
359
|
+
if (physicsBody) {
|
|
360
|
+
this.internalUpdateProperties(rigidbody, physicsBody);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
internal_getRigidbody(rb) {
|
|
364
|
+
return rb[$bodyKey];
|
|
365
|
+
}
|
|
366
|
+
internalUpdateProperties(rb, rigidbody) {
|
|
367
|
+
// continuous collision detection
|
|
368
|
+
// https://rapier.rs/docs/user_guides/javascript/rigid_bodies#continuous-collision-detection
|
|
369
|
+
rigidbody.enableCcd(rb.collisionDetectionMode !== CollisionDetectionMode.Discrete);
|
|
370
|
+
rigidbody.setLinearDamping(rb.drag);
|
|
371
|
+
rigidbody.setAngularDamping(rb.angularDrag);
|
|
372
|
+
rigidbody.setGravityScale(rb.useGravity ? 1 : 0, true);
|
|
373
|
+
// https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
|
|
374
|
+
// rigidbody.setAdditionalMass(rb.mass, true);
|
|
375
|
+
// for (let i = 0; i < rigidbody.numColliders(); i++) {
|
|
376
|
+
// const collider = rigidbody.collider(i);
|
|
377
|
+
// if (collider) {
|
|
378
|
+
// collider.setMass(rb.mass);
|
|
379
|
+
// // const density = rb.mass / collider.shape.computeMassProperties().mass;
|
|
380
|
+
// }
|
|
359
381
|
// }
|
|
360
|
-
//
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
for (const obj of this.objects) {
|
|
366
|
-
if (obj.body === body)
|
|
367
|
-
return true;
|
|
368
|
-
}
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
|
-
tempMat1 = new Matrix4();
|
|
372
|
-
tempMat2 = new Matrix4();
|
|
373
|
-
addShape(obj, shape, center, rb) {
|
|
374
|
-
let body = null;
|
|
375
|
-
if (rb) {
|
|
376
|
-
// if (debugPhysics)
|
|
377
|
-
// console.log("get rb body", rb);
|
|
378
|
-
rb.initialize();
|
|
379
|
-
console.assert(rb.body ? true : false, "rigidbody didn't initialize / produce a physics body", rb);
|
|
380
|
-
body = rb.body;
|
|
382
|
+
// lock rotations
|
|
383
|
+
rigidbody.setEnabledRotations(!rb.lockRotationX, !rb.lockRotationY, !rb.lockRotationZ, true);
|
|
384
|
+
rigidbody.setEnabledTranslations(!rb.lockPositionX, !rb.lockPositionY, !rb.lockPositionZ, true);
|
|
385
|
+
if (rb.isKinematic) {
|
|
386
|
+
rigidbody.setBodyType(RAPIER.RigidBodyType.KinematicPositionBased);
|
|
381
387
|
}
|
|
382
388
|
else {
|
|
383
|
-
|
|
384
|
-
body = this.internalCreateBody(obj, null);
|
|
385
|
-
body.type = Body.KINEMATIC;
|
|
389
|
+
rigidbody.setBodyType(RAPIER.RigidBodyType.Dynamic);
|
|
386
390
|
}
|
|
387
|
-
if (body) {
|
|
388
|
-
// console.log(obj.name, obj.position, obj.rotation)
|
|
389
|
-
// the center is serialized from Unity so we need to move it into threejs space
|
|
390
|
-
// this should probably happen on export for colliders
|
|
391
|
-
center.x *= -1;
|
|
392
|
-
let wp = obj.position;
|
|
393
|
-
let wr = obj.quaternion;
|
|
394
|
-
// console.log(obj.name, wp)
|
|
395
|
-
if (rb && rb.gameObject !== obj) {
|
|
396
|
-
this.tempMat1.copy(obj.matrixWorld);
|
|
397
|
-
this.tempMat2.copy(rb.gameObject.matrixWorld).invert();
|
|
398
|
-
this.tempMat1.premultiply(this.tempMat2);
|
|
399
|
-
this.tempMat1.decompose(wp, wr, this.tempPosition);
|
|
400
|
-
}
|
|
401
|
-
else {
|
|
402
|
-
wp = getWorldPosition(obj);
|
|
403
|
-
const bp = body.position;
|
|
404
|
-
wp.x -= bp.x;
|
|
405
|
-
wp.y -= bp.y;
|
|
406
|
-
wp.z -= bp.z;
|
|
407
|
-
wr = getWorldQuaternion(obj);
|
|
408
|
-
const r = new Quaternion(body.quaternion.x, body.quaternion.y, body.quaternion.z, body.quaternion.w);
|
|
409
|
-
wr.multiply(r.invert());
|
|
410
|
-
}
|
|
411
|
-
// get rotation difference
|
|
412
|
-
wp.add(center);
|
|
413
|
-
// if (rb) {
|
|
414
|
-
// this.tempMat.setPosition(wp);
|
|
415
|
-
// this.tempMat.makeRotationFromQuaternion(wr);
|
|
416
|
-
// this.tempMat.multiplyMatrices(this.tempMat, rb?.gameObject.matrix);
|
|
417
|
-
// this.tempMat.decompose(this.tempPosition, this.tempQuaternion, new Vector3());
|
|
418
|
-
// wp.copy(this.tempPosition);
|
|
419
|
-
// }
|
|
420
|
-
// wp.applyQuaternion(wr);
|
|
421
|
-
const pos = new Vec3(wp.x, wp.y, wp.z);
|
|
422
|
-
const rot = new PhysicsQuaternion(wr.x, wr.y, wr.z, wr.w);
|
|
423
|
-
body.addShape(shape, pos, rot);
|
|
424
|
-
body.updateMassProperties();
|
|
425
|
-
this.world.addBody(body);
|
|
426
|
-
}
|
|
427
|
-
return body;
|
|
428
391
|
}
|
|
429
392
|
// private _lastStepTime: number | undefined = 0;
|
|
430
|
-
|
|
393
|
+
lines;
|
|
394
|
+
step(_deltaTime) {
|
|
395
|
+
if (!this.world)
|
|
396
|
+
return;
|
|
431
397
|
this._isUpdatingPhysicsWorld = true;
|
|
432
|
-
|
|
433
|
-
|
|
398
|
+
if (!this.eventQueue) {
|
|
399
|
+
this.eventQueue = new EventQueue(false);
|
|
400
|
+
}
|
|
401
|
+
this.world.step(this.eventQueue);
|
|
434
402
|
this._isUpdatingPhysicsWorld = false;
|
|
435
|
-
|
|
436
|
-
|
|
403
|
+
this.updateDebugRendering(this.world);
|
|
404
|
+
}
|
|
405
|
+
updateDebugRendering(world) {
|
|
406
|
+
if (debugPhysics || debugColliderPlacement) {
|
|
407
|
+
if (!this.lines) {
|
|
408
|
+
let material = new LineBasicMaterial({
|
|
409
|
+
color: 0xffffff,
|
|
410
|
+
// vertexColors: THREE.VertexColors
|
|
411
|
+
});
|
|
412
|
+
let geometry = new BufferGeometry();
|
|
413
|
+
this.lines = new LineSegments(geometry, material);
|
|
414
|
+
this.context.scene.add(this.lines);
|
|
415
|
+
}
|
|
416
|
+
const buffers = world.debugRender();
|
|
417
|
+
this.lines.geometry.setAttribute('position', new BufferAttribute(buffers.vertices, 3));
|
|
418
|
+
this.lines.geometry.setAttribute('color', new BufferAttribute(buffers.colors, 4));
|
|
437
419
|
}
|
|
438
420
|
}
|
|
439
|
-
temp = new Vector3();
|
|
440
|
-
tempQuat = new Quaternion();
|
|
441
421
|
postStep() {
|
|
422
|
+
if (!this.world)
|
|
423
|
+
return;
|
|
442
424
|
this._isUpdatingPhysicsWorld = true;
|
|
443
|
-
|
|
444
|
-
const entry = this.objects[i];
|
|
445
|
-
const body = entry.body;
|
|
446
|
-
if (!body || !body.world)
|
|
447
|
-
continue;
|
|
448
|
-
const obj = entry.obj;
|
|
449
|
-
body.sleepTick(this.context.time.time);
|
|
450
|
-
if (debugPhysics) {
|
|
451
|
-
if (!entry._didSleepLastStep && body.sleepState === Body.SLEEPING) {
|
|
452
|
-
console.log("BODY SLEEPING", body);
|
|
453
|
-
}
|
|
454
|
-
else if (entry._didSleepLastStep && body.sleepState !== Body.SLEEPING) {
|
|
455
|
-
console.log("BODY WOKE UP", body);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
entry._didSleepLastStep = body.sleepState === Body.SLEEPING;
|
|
459
|
-
// if(body.sleepState === Body.SLEEPING) {
|
|
460
|
-
// console.log("SLEEP", body.name);
|
|
461
|
-
// }
|
|
462
|
-
// if (body.type == Body.KINEMATIC) continue;
|
|
463
|
-
if (body.type === Body.KINEMATIC) {
|
|
464
|
-
const wp = getWorldPosition(obj, this.temp);
|
|
465
|
-
body.position.set(wp.x, wp.y, wp.z);
|
|
466
|
-
const rot = getWorldQuaternion(obj, this.tempQuat);
|
|
467
|
-
body.quaternion.set(rot.x, rot.y, rot.z, rot.w);
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
if ((isNaN(body.position.x) || isNaN(body.position.y) || isNaN(body.position.z))) {
|
|
471
|
-
console.error("body position is NaN on", obj.name, "this usually means some colliders are overlapping", body.previousPosition, obj.position);
|
|
472
|
-
this.world.removeBody(body);
|
|
473
|
-
continue;
|
|
474
|
-
}
|
|
475
|
-
// when reparenting (e.g. attached to controller) I think it doesnt work with previous parent? need to test again, to tired now
|
|
476
|
-
if (entry.parent && obj.parent === entry.parent) {
|
|
477
|
-
setWorldQuaternionXYZW(obj, body.quaternion.x, body.quaternion.y, body.quaternion.z, body.quaternion.w);
|
|
478
|
-
const p = body.position;
|
|
479
|
-
setWorldPositionXYZ(obj, p.x, p.y, p.z);
|
|
480
|
-
if (body.velocity.length() > body.sleepSpeedLimit) {
|
|
481
|
-
InstancingUtil.markDirty(obj);
|
|
482
|
-
}
|
|
483
|
-
// this.worldToLocal.x = body.position.x;
|
|
484
|
-
// this.worldToLocal.y = body.position.y;
|
|
485
|
-
// this.worldToLocal.z = body.position.z;
|
|
486
|
-
// const pos = entry.parent.worldToLocal(this.worldToLocal);
|
|
487
|
-
// obj.position.x = pos.x;
|
|
488
|
-
// obj.position.y = pos.y;
|
|
489
|
-
// obj.position.z = pos.z;
|
|
490
|
-
// if (entry.center) {
|
|
491
|
-
// this.rotatedCenter.copy(entry.center);
|
|
492
|
-
// const rot = this.tempQuaternion;
|
|
493
|
-
// rot.copy(obj.quaternion);
|
|
494
|
-
// // obj.getWorldQuaternion(this.tempQuaternion)
|
|
495
|
-
// this.rotatedCenter.applyQuaternion(rot);
|
|
496
|
-
// obj.getWorldScale(this.tempVector);
|
|
497
|
-
// this.rotatedCenter.divide(this.tempVector);
|
|
498
|
-
// obj.position.sub(this.rotatedCenter);
|
|
499
|
-
// }
|
|
500
|
-
}
|
|
501
|
-
}
|
|
425
|
+
this.syncObjects();
|
|
502
426
|
this._isUpdatingPhysicsWorld = false;
|
|
427
|
+
if (this.eventQueue && !this.collisionHandler) {
|
|
428
|
+
this.collisionHandler = new PhysicsCollisionHandler(this.world, this.eventQueue);
|
|
429
|
+
}
|
|
430
|
+
if (this.collisionHandler) {
|
|
431
|
+
this.collisionHandler.handleCollisionEvents();
|
|
432
|
+
this.collisionHandler.update();
|
|
433
|
+
}
|
|
503
434
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
body["_name"] = obj.name;
|
|
508
|
-
obj.getWorldPosition(this.tempPosition);
|
|
509
|
-
const pos = this.tempPosition;
|
|
510
|
-
body.position = new Vec3(pos.x, pos.y, pos.z);
|
|
511
|
-
const quat = this.tempQuaternion;
|
|
512
|
-
obj.getWorldQuaternion(quat);
|
|
513
|
-
body.quaternion = new PhysicsQuaternion(quat.x, quat.y, quat.z, quat.w);
|
|
514
|
-
body.type = Body.KINEMATIC;
|
|
515
|
-
if (shape) {
|
|
516
|
-
body.addShape(shape);
|
|
517
|
-
body.updateMassProperties();
|
|
518
|
-
}
|
|
519
|
-
return body;
|
|
520
|
-
}
|
|
521
|
-
// private findObject(obj: Object3D): PhysicsObject | null {
|
|
522
|
-
// for (let i = 0; i < this.objects.length; i++) {
|
|
523
|
-
// const entry = this.objects[i];
|
|
524
|
-
// if (entry.obj == obj)
|
|
525
|
-
// return entry;
|
|
526
|
-
// }
|
|
527
|
-
// return null;
|
|
528
|
-
// }
|
|
529
|
-
registerCollisionEvents(obj) {
|
|
530
|
-
if (obj.collisonCallback)
|
|
531
|
-
this.unregisterCollisionEvents(obj);
|
|
532
|
-
if (!obj.body)
|
|
533
|
-
return;
|
|
534
|
-
const evt = evt => this.raiseCollisionEvents(obj.obj, evt);
|
|
535
|
-
obj.collisonCallback = evt.bind(this);
|
|
536
|
-
obj.body.addEventListener("collide", obj.collisonCallback);
|
|
537
|
-
}
|
|
538
|
-
unregisterCollisionEvents(obj) {
|
|
539
|
-
if (!obj.collisonCallback)
|
|
540
|
-
return;
|
|
541
|
-
if (!obj.body)
|
|
435
|
+
/** sync rendered objects with physics world (except for colliders without rigidbody) */
|
|
436
|
+
syncObjects() {
|
|
437
|
+
if (debugColliderPlacement)
|
|
542
438
|
return;
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
foreachComponent(collision.gameObject, (c) => {
|
|
561
|
-
c.__internalHandleCollision(collision2, true);
|
|
562
|
-
});
|
|
439
|
+
for (let i = 0; i < this.bodies.length; i++) {
|
|
440
|
+
const obj = this.objects[i];
|
|
441
|
+
const body = this.bodies[i];
|
|
442
|
+
// if the collider is not attached to a rigidbody
|
|
443
|
+
// it means that its kinematic so we need to update its position
|
|
444
|
+
const col = obj;
|
|
445
|
+
if (col?.isCollider === true && !col.attachedRigidbody) {
|
|
446
|
+
const rigidbody = body.parent();
|
|
447
|
+
if (rigidbody)
|
|
448
|
+
this.syncPhysicsBody(obj.gameObject, rigidbody, true, true);
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
// sync
|
|
452
|
+
const pos = body.translation();
|
|
453
|
+
setWorldPositionXYZ(obj.gameObject, pos.x, pos.y, pos.z);
|
|
454
|
+
const rot = body.rotation();
|
|
455
|
+
setWorldQuaternionXYZW(obj.gameObject, rot.x, rot.y, rot.z, rot.w);
|
|
563
456
|
}
|
|
564
457
|
}
|
|
565
|
-
|
|
566
|
-
//
|
|
567
|
-
//
|
|
568
|
-
const
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
458
|
+
syncPhysicsBody(obj, body, translation, rotation) {
|
|
459
|
+
// const bodyType = body.bodyType();
|
|
460
|
+
// const previous = physicsBody.translation();
|
|
461
|
+
// const vel = physicsBody.linvel();
|
|
462
|
+
const worldPosition = getWorldPosition(obj, this._tempPosition);
|
|
463
|
+
const worldQuaternion = getWorldQuaternion(obj, this._tempQuaternion);
|
|
464
|
+
// physicsBody.setBodyType(RAPIER.RigidBodyType.Fixed);
|
|
465
|
+
if (translation)
|
|
466
|
+
body.setTranslation(worldPosition, false);
|
|
467
|
+
if (rotation)
|
|
468
|
+
body.setRotation(worldQuaternion, false);
|
|
469
|
+
// physicsBody.setLinvel(vel, false);
|
|
470
|
+
body.wakeUp();
|
|
471
|
+
// update velocity
|
|
472
|
+
// const pos = physicsBody.translation();
|
|
473
|
+
// pos.x -= previous.x;
|
|
474
|
+
// pos.y -= previous.y;
|
|
475
|
+
// pos.z -= previous.z;
|
|
476
|
+
// // threhold
|
|
477
|
+
// const t = 1;
|
|
478
|
+
// const canUpdateVelocity = Math.abs(pos.x) < t && Math.abs(pos.y) < t && Math.abs(pos.z) < t;
|
|
479
|
+
// if (canUpdateVelocity) {
|
|
480
|
+
// const damping = 1 + this.context.time.deltaTime;
|
|
481
|
+
// vel.x *= damping;
|
|
482
|
+
// vel.y *= damping;
|
|
483
|
+
// vel.z *= damping;
|
|
484
|
+
// vel.x += pos.x;
|
|
485
|
+
// vel.y += pos.y;
|
|
486
|
+
// vel.z += pos.z;
|
|
487
|
+
// console.log(vel);
|
|
488
|
+
// physicsBody.setLinvel(vel, true);
|
|
489
|
+
// }
|
|
490
|
+
// else if(debugPhysics) console.warn("Movement exceeded threshold, not updating velocity", pos);
|
|
491
|
+
// body.setBodyType(bodyType);
|
|
492
|
+
}
|
|
493
|
+
static _matricesBuffer = [];
|
|
494
|
+
getRigidbodyRelativeMatrix(comp, rigidbody, mat, matrices) {
|
|
495
|
+
// collect all matrices to the rigidbody and then build the rigidbody relative matrix
|
|
496
|
+
if (matrices === undefined) {
|
|
497
|
+
matrices = Physics._matricesBuffer;
|
|
498
|
+
matrices.length = 0;
|
|
499
|
+
}
|
|
500
|
+
if (comp === rigidbody) {
|
|
501
|
+
const scale = getWorldScale(comp, this._tempPosition);
|
|
502
|
+
mat.makeScale(scale.x, scale.y, scale.z);
|
|
503
|
+
for (let i = matrices.length - 1; i >= 0; i--) {
|
|
504
|
+
mat.multiply(matrices[i]);
|
|
581
505
|
}
|
|
582
|
-
|
|
506
|
+
return mat;
|
|
507
|
+
}
|
|
508
|
+
matrices.push(comp.matrix);
|
|
509
|
+
if (comp.parent) {
|
|
510
|
+
this.getRigidbodyRelativeMatrix(comp.parent, rigidbody, mat, matrices);
|
|
511
|
+
}
|
|
512
|
+
return mat;
|
|
583
513
|
}
|
|
584
514
|
}
|
|
585
515
|
let colliderProvider = null;
|
|
@@ -591,4 +521,122 @@ class CollisionContext {
|
|
|
591
521
|
return colliderProvider.getCollider(obj);
|
|
592
522
|
}
|
|
593
523
|
}
|
|
524
|
+
/** responsible of processing collision events for the component system */
|
|
525
|
+
class PhysicsCollisionHandler {
|
|
526
|
+
world;
|
|
527
|
+
eventQueue;
|
|
528
|
+
constructor(world, eventQueue) {
|
|
529
|
+
this.world = world;
|
|
530
|
+
this.eventQueue = eventQueue;
|
|
531
|
+
}
|
|
532
|
+
activeCollisions = [];
|
|
533
|
+
activeTriggers = [];
|
|
534
|
+
handleCollisionEvents() {
|
|
535
|
+
if (!this.eventQueue)
|
|
536
|
+
return;
|
|
537
|
+
if (!this.world)
|
|
538
|
+
return;
|
|
539
|
+
this.eventQueue.drainCollisionEvents((handle1, handle2, started) => {
|
|
540
|
+
const col1 = this.world.getCollider(handle1);
|
|
541
|
+
const col2 = this.world.getCollider(handle2);
|
|
542
|
+
const colliderComponent1 = col1[$componentKey];
|
|
543
|
+
const colliderComponent2 = col2[$componentKey];
|
|
544
|
+
// console.log("EVT", colliderComponent1.name, colliderComponent2.name, started);
|
|
545
|
+
if (colliderComponent1 && colliderComponent2) {
|
|
546
|
+
if (started) {
|
|
547
|
+
this.onCollisionStarted(colliderComponent1, col1, colliderComponent2, col2);
|
|
548
|
+
this.onCollisionStarted(colliderComponent2, col2, colliderComponent1, col1);
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
this.onCollisionEnded(colliderComponent1, colliderComponent2);
|
|
552
|
+
this.onCollisionEnded(colliderComponent2, colliderComponent1);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
update() {
|
|
558
|
+
this.onHandleCollisionStay();
|
|
559
|
+
}
|
|
560
|
+
onCollisionStarted(self, selfBody, other, otherBody) {
|
|
561
|
+
let collision = null;
|
|
562
|
+
// if one is a trigger we dont get collisions but want to raise the trigger events
|
|
563
|
+
if (self.isTrigger || other.isTrigger) {
|
|
564
|
+
foreachComponent(self.gameObject, (c) => {
|
|
565
|
+
if (c.onTriggerEnter) {
|
|
566
|
+
c.onTriggerEnter(other);
|
|
567
|
+
}
|
|
568
|
+
this.activeTriggers.push({ collider: self, component: c, otherCollider: other });
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
const object = self.gameObject;
|
|
573
|
+
// TODO: we dont respect the flip value here!
|
|
574
|
+
this.world.contactPair(selfBody, otherBody, (manifold, _flipped) => {
|
|
575
|
+
foreachComponent(object, (c) => {
|
|
576
|
+
if (c.onCollisionEnter) {
|
|
577
|
+
if (!collision) {
|
|
578
|
+
const contacts = [];
|
|
579
|
+
const normal = manifold.normal();
|
|
580
|
+
for (let i = 0; i < manifold.numContacts(); i++) {
|
|
581
|
+
const pt1 = manifold.localContactPoint1(i);
|
|
582
|
+
const dist = manifold.contactDist(i);
|
|
583
|
+
if (pt1) {
|
|
584
|
+
const contact = new ContactPoint(pt1, dist, normal);
|
|
585
|
+
contacts.push(contact);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
collision = new Collision(object, other, contacts);
|
|
589
|
+
}
|
|
590
|
+
c.onCollisionEnter.call(c, collision);
|
|
591
|
+
this.activeCollisions.push({ collider: self, component: c, collision });
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
onHandleCollisionStay() {
|
|
598
|
+
for (const active of this.activeCollisions) {
|
|
599
|
+
const c = active.component;
|
|
600
|
+
if (c.activeAndEnabled && c.onCollisionStay) {
|
|
601
|
+
const arg = active.collision;
|
|
602
|
+
c.onCollisionStay(arg);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
for (const active of this.activeTriggers) {
|
|
606
|
+
const c = active.component;
|
|
607
|
+
if (c.activeAndEnabled && c.onTriggerStay) {
|
|
608
|
+
const arg = active.collider;
|
|
609
|
+
c.onTriggerStay(arg);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
onCollisionEnded(self, other) {
|
|
614
|
+
for (let i = 0; i < this.activeCollisions.length; i++) {
|
|
615
|
+
const active = this.activeCollisions[i];
|
|
616
|
+
const collider = active.collider;
|
|
617
|
+
if (collider === self && active.collision.collider === other) {
|
|
618
|
+
const c = active.component;
|
|
619
|
+
this.activeCollisions.splice(i, 1);
|
|
620
|
+
i--;
|
|
621
|
+
if (c.activeAndEnabled && c.onCollisionExit) {
|
|
622
|
+
const collision = active.collision;
|
|
623
|
+
c.onCollisionExit(collision);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
for (let i = 0; i < this.activeTriggers.length; i++) {
|
|
628
|
+
const active = this.activeTriggers[i];
|
|
629
|
+
const collider = active.collider;
|
|
630
|
+
if (collider === self && active.otherCollider === other) {
|
|
631
|
+
const c = active.component;
|
|
632
|
+
this.activeTriggers.splice(i, 1);
|
|
633
|
+
i--;
|
|
634
|
+
if (c.activeAndEnabled && c.onTriggerExit) {
|
|
635
|
+
const collision = active.otherCollider;
|
|
636
|
+
c.onTriggerExit(collision);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
594
642
|
//# sourceMappingURL=engine_physics.js.map
|