@needle-tools/engine 2.37.0-pre → 2.38.0-pre.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.
Files changed (101) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/needle-engine.d.ts +118 -19
  3. package/dist/needle-engine.js +352 -352
  4. package/dist/needle-engine.js.map +4 -4
  5. package/dist/needle-engine.min.js +25 -25
  6. package/dist/needle-engine.min.js.map +4 -4
  7. package/lib/engine/engine_addressables.d.ts +3 -1
  8. package/lib/engine/engine_addressables.js +12 -5
  9. package/lib/engine/engine_addressables.js.map +1 -1
  10. package/lib/engine/engine_element.js +3 -2
  11. package/lib/engine/engine_element.js.map +1 -1
  12. package/lib/engine/engine_element_overlay.js +4 -3
  13. package/lib/engine/engine_element_overlay.js.map +1 -1
  14. package/lib/engine/engine_input.d.ts +2 -0
  15. package/lib/engine/engine_input.js +14 -3
  16. package/lib/engine/engine_input.js.map +1 -1
  17. package/lib/engine/engine_physics.d.ts +11 -4
  18. package/lib/engine/engine_physics.js +107 -42
  19. package/lib/engine/engine_physics.js.map +1 -1
  20. package/lib/engine/engine_physics.types.d.ts +7 -0
  21. package/lib/engine/engine_physics.types.js +8 -0
  22. package/lib/engine/engine_physics.types.js.map +1 -1
  23. package/lib/engine/engine_setup.d.ts +12 -6
  24. package/lib/engine/engine_setup.js +30 -22
  25. package/lib/engine/engine_setup.js.map +1 -1
  26. package/lib/engine/engine_types.d.ts +3 -1
  27. package/lib/engine/engine_types.js.map +1 -1
  28. package/lib/engine-components/Animation.d.ts +1 -0
  29. package/lib/engine-components/Animation.js +7 -0
  30. package/lib/engine-components/Animation.js.map +1 -1
  31. package/lib/engine-components/AnimatorController.js +14 -7
  32. package/lib/engine-components/AnimatorController.js.map +1 -1
  33. package/lib/engine-components/Camera.d.ts +2 -0
  34. package/lib/engine-components/Camera.js +24 -6
  35. package/lib/engine-components/Camera.js.map +1 -1
  36. package/lib/engine-components/CharacterController.d.ts +34 -0
  37. package/lib/engine-components/CharacterController.js +179 -0
  38. package/lib/engine-components/CharacterController.js.map +1 -0
  39. package/lib/engine-components/Collider.d.ts +10 -5
  40. package/lib/engine-components/Collider.js +18 -11
  41. package/lib/engine-components/Collider.js.map +1 -1
  42. package/lib/engine-components/Joints.d.ts +15 -0
  43. package/lib/engine-components/Joints.js +42 -0
  44. package/lib/engine-components/Joints.js.map +1 -0
  45. package/lib/engine-components/Light.d.ts +2 -0
  46. package/lib/engine-components/Light.js +13 -2
  47. package/lib/engine-components/Light.js.map +1 -1
  48. package/lib/engine-components/OrbitControls.js +1 -1
  49. package/lib/engine-components/OrbitControls.js.map +1 -1
  50. package/lib/engine-components/Renderer.js +4 -0
  51. package/lib/engine-components/Renderer.js.map +1 -1
  52. package/lib/engine-components/RigidBody.d.ts +6 -1
  53. package/lib/engine-components/RigidBody.js +62 -25
  54. package/lib/engine-components/RigidBody.js.map +1 -1
  55. package/lib/engine-components/SmoothFollow.d.ts +2 -1
  56. package/lib/engine-components/SmoothFollow.js +25 -17
  57. package/lib/engine-components/SmoothFollow.js.map +1 -1
  58. package/lib/engine-components/WebXR.js +3 -4
  59. package/lib/engine-components/WebXR.js.map +1 -1
  60. package/lib/engine-components/codegen/components.d.ts +4 -0
  61. package/lib/engine-components/codegen/components.js +4 -0
  62. package/lib/engine-components/codegen/components.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/engine/codegen/register_types.js +16 -0
  65. package/src/engine/dist/engine_physics.js +739 -0
  66. package/src/engine/dist/engine_setup.js +777 -0
  67. package/src/engine/engine_addressables.ts +18 -8
  68. package/src/engine/engine_element.ts +3 -2
  69. package/src/engine/engine_element_overlay.ts +4 -3
  70. package/src/engine/engine_input.ts +12 -3
  71. package/src/engine/engine_physics.ts +119 -57
  72. package/src/engine/engine_physics.types.ts +9 -0
  73. package/src/engine/engine_setup.ts +53 -45
  74. package/src/engine/engine_types.ts +4 -1
  75. package/src/engine-components/Animation.ts +8 -0
  76. package/src/engine-components/AnimatorController.ts +16 -11
  77. package/src/engine-components/Camera.ts +25 -5
  78. package/src/engine-components/CharacterController.ts +185 -0
  79. package/src/engine-components/Collider.ts +21 -15
  80. package/src/engine-components/Joints.ts +40 -0
  81. package/src/engine-components/Light.ts +17 -3
  82. package/src/engine-components/OrbitControls.ts +1 -1
  83. package/src/engine-components/Renderer.ts +5 -1
  84. package/src/engine-components/RigidBody.ts +63 -29
  85. package/src/engine-components/SmoothFollow.ts +21 -18
  86. package/src/engine-components/WebXR.ts +3 -4
  87. package/src/engine-components/codegen/components.ts +4 -0
  88. package/src/engine-components/dist/CharacterController.js +123 -0
  89. package/src/engine-components/dist/RigidBody.js +458 -0
  90. package/src/include/console/ConsoleReroute.js +79 -0
  91. package/src/include/draco/draco_decoder.js +48 -0
  92. package/src/include/draco/draco_decoder.wasm +0 -0
  93. package/src/include/ktx2/basis_transcoder.js +21 -0
  94. package/src/include/ktx2/basis_transcoder.wasm +0 -0
  95. package/src/include/three/ARButton.js +208 -0
  96. package/src/include/three/DragControls.js +232 -0
  97. package/src/include/three/EXT_mesh_gpu_instancing_exporter.js +67 -0
  98. package/src/include/three/VRButton.js +196 -0
  99. package/src/include/three-mesh-ui-assets/backspace.png +0 -0
  100. package/src/include/three-mesh-ui-assets/enter.png +0 -0
  101. package/src/include/three-mesh-ui-assets/shift.png +0 -0
@@ -5,7 +5,7 @@ import { Context } from "./engine_setup";
5
5
  import { Group, Object3D, Scene } from "three";
6
6
  import { processNewScripts } from "./engine_mainloop_utils";
7
7
  import { InstantiateEvent, registerPrefabProvider, syncInstantiate } from "./engine_networking_instantiate";
8
- import { download } from "./engine_web_api";
8
+ import { download, hash } from "./engine_web_api";
9
9
  import { getLoader } from "./engine_gltf";
10
10
  import { SourceIdentifier } from "./engine_types";
11
11
  import { destroy, instantiate, InstantiateOptions } from "./engine_gameobject";
@@ -51,11 +51,11 @@ export class AssetReference {
51
51
 
52
52
  static getOrCreate(sourceId: SourceIdentifier, uri: string, context: Context): AssetReference {
53
53
  const fullPath = getPath(sourceId, uri);
54
- if(debug) console.log("GetOrCreate Addressable from", sourceId, uri, "FinalPath=", fullPath);
54
+ if (debug) console.log("GetOrCreate Addressable from", sourceId, uri, "FinalPath=", fullPath);
55
55
  const addressables = context.addressables;
56
56
  const existing = addressables.findAssetReference(fullPath);
57
57
  if (existing) return existing;
58
- const ref = new AssetReference(fullPath);
58
+ const ref = new AssetReference(fullPath, context.hash);
59
59
  addressables.registerAssetReference(ref);
60
60
  return ref;
61
61
  }
@@ -63,6 +63,7 @@ export class AssetReference {
63
63
  get asset(): any {
64
64
  return this._glbRoot ?? this._asset;
65
65
  }
66
+
66
67
  protected set asset(val: any) {
67
68
  this._asset = val;
68
69
  }
@@ -70,7 +71,7 @@ export class AssetReference {
70
71
  private _loading?: PromiseLike<any>;
71
72
 
72
73
  get uri(): string {
73
- return this._uri!;
74
+ return this._uri;
74
75
  }
75
76
 
76
77
  get rawAsset(): any { return this._asset; }
@@ -80,11 +81,20 @@ export class AssetReference {
80
81
  private _uri: string;
81
82
  private _progressListeners: ProgressCallback[] = [];
82
83
 
84
+ private _hash?: string;
85
+ private _hashedUri: string;
86
+
83
87
  private _isLoadingRawBinary: boolean = false;
84
88
  private _rawBinary?: ArrayBuffer | null;
85
89
 
86
- constructor(uri: string) {
90
+ constructor(uri: string, hash?: string) {
87
91
  this._uri = uri;
92
+ this._hash = hash;
93
+ if (uri.includes("?v="))
94
+ this._hashedUri = uri;
95
+ else
96
+ this._hashedUri = hash ? uri + "?v=" + hash : uri;
97
+
88
98
  registerPrefabProvider(this._uri, this.onResolvePrefab.bind(this));
89
99
  }
90
100
 
@@ -120,8 +130,8 @@ export class AssetReference {
120
130
  if (this._isLoadingRawBinary) return null;
121
131
  if (this._rawBinary !== undefined) return this._rawBinary;
122
132
  this._isLoadingRawBinary = true;
123
- if (debug) console.log("Preload", this.uri);
124
- const res = await download(this.uri, p => {
133
+ if (debug) console.log("Preload", this._hashedUri);
134
+ const res = await download(this._hashedUri, p => {
125
135
  this.raiseProgressEvent(p);
126
136
  });
127
137
  this._rawBinary = res?.buffer ?? null;
@@ -148,7 +158,7 @@ export class AssetReference {
148
158
  }
149
159
  else {
150
160
  if (debug) console.log("Load async", this.uri);
151
- this._loading = getLoader().loadSync(context, this.uri, null, true, prog => {
161
+ this._loading = getLoader().loadSync(context, this._hashedUri, null, true, prog => {
152
162
  this.raiseProgressEvent(prog);
153
163
  });
154
164
  }
@@ -133,7 +133,8 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
133
133
  if (srcAttributeValue) src = srcAttributeValue;
134
134
 
135
135
  const alias = this.getAttribute("alias");
136
- this._context = new Context({ name: src, domElement: this, alias: alias });
136
+ const hash = this.getAttribute("hash");
137
+ this._context = new Context({ name: src, domElement: this, alias: alias, hash: hash ?? undefined });
137
138
  this._watcher = new EngineElementSourceFileWatcher(this.getAttribute("id") ?? alias ?? "", this._context);
138
139
 
139
140
  if (src && src.length > 0) {
@@ -234,7 +235,7 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
234
235
  }
235
236
 
236
237
  static get observedAttributes() {
237
- return ["src", "loadstart", "progress", "loadfinished", "dracoDecoderPath", "dracoDecoderType", "ktx2DecoderPath"];
238
+ return ["hash", "src", "loadstart", "progress", "loadfinished", "dracoDecoderPath", "dracoDecoderType", "ktx2DecoderPath"];
238
239
  }
239
240
 
240
241
  attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
@@ -73,11 +73,12 @@ export class AROverlayHandler {
73
73
  return element;
74
74
  }
75
75
  if (element.children) {
76
- // @ts-ignore
77
- for (const ch of element.children) {
76
+ for (let i = 0; i < element.children.length; i++) {
77
+ const ch = element.children[i] as HTMLElement;
78
78
  if (!ch || !ch.classList) continue;
79
- if (ch.classList.contains(arContainerClassName))
79
+ if (ch.classList.contains(arContainerClassName)) {
80
80
  return ch;
81
+ }
81
82
  }
82
83
  }
83
84
 
@@ -147,6 +147,10 @@ export class Input extends EventTarget {
147
147
  if (i >= this._mouseWheelChanged.length) return false;
148
148
  return this._mouseWheelChanged[i];
149
149
  }
150
+ getMouseWheelDeltaY(i: number = 0): number {
151
+ if (i >= this._mouseWheelDeltaY.length) return 0;
152
+ return this._mouseWheelDeltaY[i];
153
+ }
150
154
  getPointerEvent(i: number): Event | undefined {
151
155
  if (i >= this._pointerEvent.length) return undefined;
152
156
  return this._pointerEvent[i] ?? undefined;
@@ -169,6 +173,7 @@ export class Input extends EventTarget {
169
173
  private _pointerIds: number[] = [];
170
174
  private _pointerTypes: string[] = [""];
171
175
  private _mouseWheelChanged: boolean[] = [false];
176
+ private _mouseWheelDeltaY: number[] = [0];
172
177
  private _pointerEvent: Event[] = [];
173
178
 
174
179
  getKeyDown(): string | null {
@@ -269,11 +274,12 @@ export class Input extends EventTarget {
269
274
  this._pointerClick[i] = false;
270
275
  for (let i = 0; i < this._pointerDoubleClick.length; i++)
271
276
  this._pointerDoubleClick[i] = false;
272
- for (const pt of this._pointerPositionsDelta) {
277
+ for (const pt of this._pointerPositionsDelta)
273
278
  pt.set(0, 0);
274
- }
275
279
  for (let i = 0; i < this._mouseWheelChanged.length; i++)
276
280
  this._mouseWheelChanged[i] = false;
281
+ for (let i = 0; i < this._mouseWheelDeltaY.length; i++)
282
+ this._mouseWheelDeltaY[i] = 0;
277
283
  }
278
284
 
279
285
 
@@ -307,9 +313,12 @@ export class Input extends EventTarget {
307
313
  this.onDispatchEvent(InputEvents.KeyUp, new KeyEventArgs(evt));
308
314
  }
309
315
 
310
- private onMouseWheel(_evt) {
316
+ private onMouseWheel(evt: WheelEvent) {
317
+ if (this._mouseWheelDeltaY.length <= 0) this._mouseWheelDeltaY.push(0);
311
318
  if (this._mouseWheelChanged.length <= 0) this._mouseWheelChanged.push(false);
312
319
  this._mouseWheelChanged[0] = true;
320
+ const current = this._mouseWheelDeltaY[0];
321
+ this._mouseWheelDeltaY[0] = current + evt.deltaY;
313
322
  }
314
323
 
315
324
  private onTouchMove(_evt) {
@@ -1,23 +1,20 @@
1
- import { BasicDepthPacking, Box3, BufferAttribute, BufferGeometry, Camera, Intersection, Layers, LineBasicMaterial, LineSegments, Matrix4, Mesh, NormalAnimationBlendMode, Object3D, Quaternion, Ray, Raycaster, Sphere, Vector2, Vector3 } from 'three'
1
+ import { BasicDepthPacking, Box3, BufferAttribute, BufferGeometry, Camera, Intersection, Layers, LineBasicMaterial, LineSegments, Matrix4, Mesh, NormalAnimationBlendMode, NumberKeyframeTrack, Object3D, Quaternion, Ray, Raycaster, Sphere, Vector2, Vector3 } from 'three'
2
2
  import { Context } from './engine_setup';
3
3
  import { getParam } from "./engine_utils"
4
- import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPosition, setWorldPositionXYZ, setWorldQuaternionXYZW } from "./engine_three_utils"
4
+ import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPositionXYZ, setWorldQuaternionXYZW } from "./engine_three_utils"
5
5
  import {
6
6
  IComponent,
7
- IGameObject,
8
7
  ICollider,
9
8
  IRigidbody,
10
9
  Collision,
11
- ICollisionContext,
12
10
  ContactPoint,
13
11
  Vec3
14
12
  } from './engine_types';
15
13
  import { InstancingUtil } from './engine_instancing';
16
14
  import { foreachComponent } from './engine_gameobject';
17
15
 
18
- import RAPIER, { ActiveEvents, Collider, ColliderDesc, EventQueue, RigidBody, TempContactManifold, World } from '@dimforge/rapier3d-compat';
19
- import { CollisionDetectionMode, RigidbodyConstraints } from '../engine/engine_physics.types';
20
- import { showBalloonWarning } from './debug/debug';
16
+ import RAPIER, { ActiveEvents, Collider, ColliderDesc, EventQueue, JointData, RigidBody, RigidBodyType, World } from '@dimforge/rapier3d-compat';
17
+ import { CollisionDetectionMode } from '../engine/engine_physics.types';
21
18
  export type Rapier = typeof RAPIER;
22
19
 
23
20
 
@@ -33,6 +30,8 @@ declare type PhysicsBody = {
33
30
 
34
31
  const $componentKey = Symbol("needle component");
35
32
  const $bodyKey = Symbol("physics body");
33
+ const $colliderRigidbody = Symbol("rigidbody");
34
+ // const $removed = Symbol("removed");
36
35
 
37
36
  export class RaycastOptions {
38
37
  ray: Ray | undefined = undefined;
@@ -209,6 +208,7 @@ export class Physics {
209
208
 
210
209
  private _tempPosition: Vector3 = new Vector3();
211
210
  private _tempQuaternion: Quaternion = new Quaternion();
211
+ private _tempScale: Vector3 = new Vector3();
212
212
  private _tempMatrix: Matrix4 = new Matrix4();
213
213
 
214
214
  private static _didLoadPhysicsEngine: boolean = false;
@@ -224,13 +224,10 @@ export class Physics {
224
224
  private collisionHandler?: PhysicsCollisionHandler;
225
225
 
226
226
 
227
- // private rigidbodies: Array<IRigidbody | null> = [];
228
227
  private objects: IComponent[] = [];
229
228
  private bodies: PhysicsBody[] = [];
230
- // private rigidbodiesLookup: Map<IRigidbody, RigidBody> = new Map<IRigidbody, RigidBody>();
231
- // private kinematicColliders: Array<IComponent> = [];
232
- // private rigidbodyLookup: Map<IRigidbody, IComponent[]> = new Map<IRigidbody, IComponent[]>();
233
- // private objectLookup: Map<Object3D, IRigidbody> = new Map<Object3D, IRigidbody>();
229
+
230
+ private _meshCache: Map<string, Float32Array> = new Map<string, Float32Array>();
234
231
 
235
232
 
236
233
  constructor(context: Context) {
@@ -251,6 +248,10 @@ export class Physics {
251
248
  this.world = new World(gravity);
252
249
  }
253
250
 
251
+ clearCaches() {
252
+ this._meshCache.clear();
253
+ }
254
+
254
255
  addBoxCollider(collider: ICollider, center: Vector3, size: Vector3) {
255
256
  const obj = collider.gameObject;
256
257
  const scale = getWorldScale(obj, this._tempPosition).multiply(size);
@@ -266,6 +267,14 @@ export class Physics {
266
267
  this.createCollider(collider, desc, center);
267
268
  }
268
269
 
270
+ addCapsuleCollider(collider: ICollider, center: Vector3, height: number, radius: number) {
271
+ const obj = collider.gameObject;
272
+ const scale = getWorldScale(obj, this._tempPosition);
273
+ if (debugPhysics) console.log("capsule scale", scale, height, radius);
274
+ const desc = ColliderDesc.capsule(height * .5 * scale.y - radius, radius * scale.x);
275
+ this.createCollider(collider, desc, center);
276
+ }
277
+
269
278
  addMeshCollider(collider: ICollider, mesh: Mesh, convex: boolean) {
270
279
  const geo = mesh.geometry;
271
280
  if (!geo) {
@@ -281,15 +290,22 @@ export class Physics {
281
290
  // scaling seems not supported yet https://github.com/dimforge/rapier/issues/243
282
291
  const scale = getWorldScale(mesh, this._tempPosition)
283
292
  if (Math.abs(scale.x - 1) > 0.0001 || Math.abs(scale.y - 1) > 0.0001 || Math.abs(scale.z - 1) > 0.0001) {
284
- console.warn("Your model is using scaled mesh colliders which is not optimal for performance", mesh.name, Object.assign({}, scale), mesh);
285
- // showBalloonWarning("Your model is using scaled mesh colliders which is not optimal for performance: " + mesh.name + ", consider using unscaled objects");
286
- const scaledPositions = new Float32Array(positions.length);
287
- for (let i = 0; i < positions.length; i += 3) {
288
- scaledPositions[i] = positions[i] * scale.x;
289
- scaledPositions[i + 1] = positions[i + 1] * scale.y;
290
- scaledPositions[i + 2] = positions[i + 2] * scale.z;
293
+ const key = geo.uuid + "_" + scale.x + "_" + scale.y + "_" + scale.z + "_" + convex;
294
+ if (this._meshCache.has(key)) {
295
+ positions = this._meshCache.get(key)!;
296
+ }
297
+ else {
298
+ console.warn("Your model is using scaled mesh colliders which is not optimal for performance", mesh.name, Object.assign({}, scale), mesh);
299
+ // showBalloonWarning("Your model is using scaled mesh colliders which is not optimal for performance: " + mesh.name + ", consider using unscaled objects");
300
+ const scaledPositions = new Float32Array(positions.length);
301
+ for (let i = 0; i < positions.length; i += 3) {
302
+ scaledPositions[i] = positions[i] * scale.x;
303
+ scaledPositions[i + 1] = positions[i + 1] * scale.y;
304
+ scaledPositions[i + 2] = positions[i + 2] * scale.z;
305
+ }
306
+ positions = scaledPositions;
307
+ this._meshCache.set(key, scaledPositions);
291
308
  }
292
- positions = scaledPositions;
293
309
  }
294
310
 
295
311
  const desc = convex ? ColliderDesc.convexMesh(positions) : ColliderDesc.trimesh(positions, indices);
@@ -308,9 +324,10 @@ export class Physics {
308
324
  useExplicitMassProperties
309
325
  } = this.getRigidbody(collider, this._tempMatrix);
310
326
 
311
- matrix.decompose(this._tempPosition, this._tempQuaternion, new Vector3());
327
+ matrix.decompose(this._tempPosition, this._tempQuaternion, this._tempScale);
328
+ getWorldScale(collider.gameObject, this._tempScale);
312
329
  if (center)
313
- this._tempPosition.add(center);
330
+ this._tempPosition.add(center).multiply(this._tempScale);
314
331
  desc.setTranslation(this._tempPosition.x, this._tempPosition.y, this._tempPosition.z);
315
332
  desc.setRotation(this._tempQuaternion);
316
333
 
@@ -373,13 +390,15 @@ export class Physics {
373
390
 
374
391
  }
375
392
 
393
+ collider[$colliderRigidbody] = rigidBody;
394
+
376
395
  return { rigidBody: rigidBody, useExplicitMassProperties: useExplicitMassProperties };
377
396
  }
378
397
 
379
398
  removeBody(obj: IComponent) {
380
399
  const body = obj[$bodyKey];
381
400
  obj[$bodyKey] = null;
382
- if (body) {
401
+ if (body && this.world) {
383
402
  const index = this.objects.findIndex(o => o === obj);
384
403
  if (index >= 0) {
385
404
  const body = this.bodies[index];
@@ -387,20 +406,37 @@ export class Physics {
387
406
  this.objects.splice(index, 1);
388
407
 
389
408
  if (body instanceof Collider) {
390
- this.world?.removeCollider(body as Collider, true);
409
+ const collider = body as Collider;
410
+ this.world?.removeCollider(collider, true);
411
+
412
+ // remove the rigidbody if it doesnt have colliders anymore
413
+ const rb = collider.parent();
414
+ if (rb && rb.numColliders() <= 0) {
415
+ this.world?.removeRigidBody(rb);
416
+ }
391
417
  }
392
418
  else if (body instanceof RigidBody) {
393
- this.world?.removeRigidBody(body as RigidBody);
419
+ // TODO: running this code below causes a crash in rapier
420
+ // const rb = body as RigidBody;
421
+ // console.log("colliders", rb.numColliders())
422
+ // for (let i = 0; i < rb.numColliders(); i++) {
423
+ // const col = rb.collider(i);
424
+ // this.world?.removeCollider(col, true);
425
+ // }
426
+ // console.log("colliders", rb.numColliders(), rb)
427
+ // console.log(rb.handle, rb.userData);
428
+ // if (rb.userData === undefined)
429
+ // this.world?.removeRigidBody(rb);
394
430
  }
395
431
 
396
432
  // check if we need to remove the rigidbody too
397
- const col = obj as ICollider;
398
- if (col.isCollider && col.attachedRigidbody) {
399
- const rb = col.attachedRigidbody[$bodyKey];
400
- if (rb && rb.numColliders() <= 0 && rb.world() === this.world) {
401
- this.world?.removeRigidBody(rb);
402
- }
403
- }
433
+ // const col = obj as ICollider;
434
+ // if (col.isCollider && col.attachedRigidbody) {
435
+ // const rb = col.attachedRigidbody[$bodyKey] as RigidBody;
436
+ // if (rb && rb.numColliders() <= 0) {
437
+ // // this.world?.removeRigidBody(rb);
438
+ // }
439
+ // }
404
440
  }
405
441
  }
406
442
  }
@@ -526,10 +562,22 @@ export class Physics {
526
562
  continue;
527
563
  }
528
564
 
565
+
529
566
  // sync
530
567
  const pos = body.translation();
531
- setWorldPositionXYZ(obj.gameObject, pos.x, pos.y, pos.z);
532
568
  const rot = body.rotation();
569
+ // make sure to keep the collider offset
570
+ const center = obj["center"] as Vector3;
571
+ if (center && center.isVector3) {
572
+ this._tempQuaternion.set(rot.x, rot.y, rot.z, rot.w);
573
+ const offset = this._tempPosition.copy(center).applyQuaternion(this._tempQuaternion);
574
+ const scale = getWorldScale(obj.gameObject);
575
+ offset.multiply(scale);
576
+ pos.x -= offset.x;
577
+ pos.y -= offset.y;
578
+ pos.z -= offset.z;
579
+ }
580
+ setWorldPositionXYZ(obj.gameObject, pos.x, pos.y, pos.z);
533
581
  setWorldQuaternionXYZW(obj.gameObject, rot.x, rot.y, rot.z, rot.w);
534
582
  }
535
583
  }
@@ -542,13 +590,27 @@ export class Physics {
542
590
 
543
591
  const worldPosition = getWorldPosition(obj, this._tempPosition);
544
592
  const worldQuaternion = getWorldQuaternion(obj, this._tempQuaternion);
593
+ const type = body.bodyType();
594
+ switch (type) {
595
+ case RigidBodyType.Fixed:
596
+ case RigidBodyType.KinematicPositionBased:
597
+ case RigidBodyType.KinematicVelocityBased:
598
+ if (translation)
599
+ body.setNextKinematicTranslation(worldPosition);
600
+ if (rotation)
601
+ body.setNextKinematicRotation(worldQuaternion);
602
+ break;
603
+ default:
604
+ if (translation)
605
+ body.setTranslation(worldPosition, false);
606
+ if (rotation)
607
+ body.setRotation(worldQuaternion, false);
608
+ break;
609
+
610
+ }
611
+ body.wakeUp();
545
612
  // physicsBody.setBodyType(RAPIER.RigidBodyType.Fixed);
546
- if (translation)
547
- body.setTranslation(worldPosition, false);
548
- if (rotation)
549
- body.setRotation(worldQuaternion, false);
550
613
  // physicsBody.setLinvel(vel, false);
551
- body.wakeUp();
552
614
 
553
615
  // update velocity
554
616
  // const pos = physicsBody.translation();
@@ -596,30 +658,29 @@ export class Physics {
596
658
  return mat;
597
659
  }
598
660
 
661
+ private static centerConnectionPos = { x: 0, y: 0, z: 0 };
662
+ private static centerConnectionRot = { x: 0, y: 0, z: 0, w: 1 };
599
663
 
600
- }
601
-
602
-
603
- export interface IColliderProvider {
604
- getCollider(obj: Object3D): ICollider;
605
- }
606
-
607
- let colliderProvider: IColliderProvider | null = null;
608
- export function registerColliderProvider(prov: IColliderProvider) {
609
- colliderProvider = prov;
610
- }
611
-
612
- class CollisionContext implements ICollisionContext {
613
-
614
- getCollider(obj: Object3D<Event>): ICollider {
615
- return colliderProvider!.getCollider(obj);
664
+ addFixedJoint(body1: IRigidbody, body2: IRigidbody, rel: { x: number, y: number, z: number }) {
665
+ if (!this.world) {
666
+ console.error("Physics world not initialized");
667
+ return;
668
+ }
669
+ const b1 = body1[$bodyKey] as RigidBody;
670
+ const b2 = body2[$bodyKey] as RigidBody;
671
+ const rot = body1.worldQuaternion.multiply(body2.worldQuaternion.invert());
672
+ const params = JointData.fixed(
673
+ Physics.centerConnectionPos, Physics.centerConnectionRot,
674
+ rel, rot
675
+ );
676
+ const joint = this.world.createImpulseJoint(params, b1, b2, true);
677
+ console.log("ADD JOINT", joint)
616
678
  }
617
679
 
618
680
  }
619
681
 
620
682
 
621
683
 
622
-
623
684
  /** responsible of processing collision events for the component system */
624
685
  class PhysicsCollisionHandler {
625
686
 
@@ -642,7 +703,8 @@ class PhysicsCollisionHandler {
642
703
  const col2 = this.world!.getCollider(handle2);
643
704
  const colliderComponent1 = col1[$componentKey];
644
705
  const colliderComponent2 = col2[$componentKey];
645
- // console.log("EVT", colliderComponent1.name, colliderComponent2.name, started);
706
+ if (debugCollisions)
707
+ console.log("EVT", colliderComponent1.name, colliderComponent2.name, started, col1, col2);
646
708
  if (colliderComponent1 && colliderComponent2) {
647
709
  if (started) {
648
710
  this.onCollisionStarted(colliderComponent1, col1, colliderComponent2, col2);
@@ -710,7 +772,7 @@ class PhysicsCollisionHandler {
710
772
  for (const active of this.activeTriggers) {
711
773
  const c = active.component;
712
774
  if (c.activeAndEnabled && c.onTriggerStay) {
713
- const arg = active.collider;
775
+ const arg = active.otherCollider;
714
776
  c.onTriggerStay(arg);
715
777
  }
716
778
  }
@@ -16,4 +16,13 @@ export enum RigidbodyConstraints {
16
16
  FreezeRotationZ = 64,
17
17
  FreezeRotation = 112,
18
18
  FreezeAll = 126,
19
+ }
20
+
21
+
22
+ export enum Axes {
23
+ None = 0,
24
+ X = 2,
25
+ Y = 4,
26
+ Z = 8,
27
+ All = ~0,
19
28
  }