Needle Engine

Changes between version 3.20.2 and 3.20.3
Files changed (5) hide show
  1. src/engine-components/AnimatorController.ts +12 -9
  2. src/engine/engine_physics_rapier.ts +31 -4
  3. src/engine/engine_types.ts +4 -0
  4. src/engine-components/ui/EventSystem.ts +2 -2
  5. src/engine-components/RigidBody.ts +25 -1
src/engine-components/AnimatorController.ts CHANGED
@@ -235,11 +235,11 @@
235
235
  // if (!this._activeState) return;
236
236
  const dt = this.animator.context.time.deltaTime;
237
237
  if (this.animator.applyRootMotion) {
238
- this.rootMotionHandler?.onBeforeUpdate();
238
+ this.rootMotionHandler?.onBeforeUpdate(weight);
239
239
  }
240
240
  this._mixer.update(dt);
241
241
  if (this.animator.applyRootMotion) {
242
- this.rootMotionHandler?.onAfterUpdate();
242
+ this.rootMotionHandler?.onAfterUpdate(weight);
243
243
  }
244
244
  }
245
245
 
@@ -881,14 +881,14 @@
881
881
 
882
882
  // private lastPos: Vector3 = new Vector3();
883
883
 
884
- onBeforeUpdate() {
884
+ onBeforeUpdate(_weight: number) {
885
885
  this.positionChange.set(0, 0, 0);
886
886
  this.rotationChange.set(0, 0, 0, 1);
887
887
  }
888
888
 
889
- onAfterUpdate(): boolean {
889
+ onAfterUpdate(weight: number): boolean {
890
890
  if (!this.action) return false;
891
- const weight = this.action.getEffectiveWeight();
891
+ weight *= this.action.getEffectiveWeight();
892
892
  if (weight <= 0) return false;
893
893
  this.positionChange.multiplyScalar(weight);
894
894
  this.rotationChange.slerp(RootMotionAction.identityQuaternion, 1 - weight);
@@ -937,19 +937,22 @@
937
937
 
938
938
  }
939
939
 
940
- onBeforeUpdate() {
940
+ onBeforeUpdate(weight: number) {
941
941
  // capture the position of the object
942
942
  this.basePosition.copy(this.root.position);
943
943
  this.baseQuaternion.copy(this.root.quaternion);
944
944
 
945
945
  for (const hand of this.handler)
946
- hand.onBeforeUpdate();
946
+ hand.onBeforeUpdate(weight);
947
947
  }
948
948
 
949
949
  private summedPosition: Vector3 = new Vector3();
950
950
  private summedRotation: Quaternion = new Quaternion();
951
951
 
952
- onAfterUpdate() {
952
+ onAfterUpdate(weight: number) {
953
+ if (weight <= 0) return;
954
+ // TODO: blend weight properly with root motion (when using timeline blending with animator)
955
+
953
956
  // apply the accumulated changes
954
957
  this.root.position.copy(this.basePosition);
955
958
  this.root.quaternion.copy(this.baseQuaternion);
@@ -957,7 +960,7 @@
957
960
  this.summedPosition.set(0, 0, 0);
958
961
  this.summedRotation.set(0, 0, 0, 1);
959
962
  for (const entry of this.handler) {
960
- if (entry.onAfterUpdate()) {
963
+ if (entry.onAfterUpdate(weight)) {
961
964
  this.summedPosition.add(entry.positionChange);
962
965
  this.summedRotation.multiply(entry.rotationChange);
963
966
  }
src/engine/engine_physics_rapier.ts CHANGED
@@ -229,9 +229,12 @@
229
229
  this._hasCreatedWorld = true;
230
230
  if (RAPIER === undefined) {
231
231
  if (debugPhysics) console.log("Import Rapier");
232
- RAPIER = await import("@dimforge/rapier3d-compat");
232
+ const _rapier = await import("@dimforge/rapier3d-compat");
233
233
  if (debugPhysics) console.log("Init Rapier");
234
- await RAPIER.init()
234
+ await _rapier.init();
235
+ // only assign after all loads are done to avoid a race condition
236
+ // where RAPIER is already set and then used while actually still waiting for initialization.
237
+ RAPIER = _rapier;
235
238
  }
236
239
  if (debugPhysics) console.log("Physics engine initialized, creating world...");
237
240
  this._world = new World(this._gravity);
@@ -668,7 +671,7 @@
668
671
  // otherwise rapier will compute the mass properties based on the collider shape and density
669
672
  // https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
670
673
  if (useExplicitMassProperties) {
671
- // desc.setDensity(0);
674
+ desc.setDensity(0);
672
675
  }
673
676
 
674
677
  const col = this.world.createCollider(desc, rigidBody);
@@ -696,7 +699,7 @@
696
699
 
697
700
  const rb = collider.attachedRigidbody;
698
701
  rigidBody = rb[$bodyKey];
699
- useExplicitMassProperties = true;
702
+ useExplicitMassProperties = rb.autoMass === false;
700
703
  if (!rigidBody) {
701
704
  const kinematic = rb.isKinematic && !debugColliderPlacement;
702
705
  if (debugPhysics)
@@ -744,6 +747,30 @@
744
747
  rigidbody.setAngularDamping(rb.angularDrag);
745
748
  rigidbody.setGravityScale(rb.useGravity ? rb.gravityScale : 0, true);
746
749
 
750
+ // https://rapier.rs/docs/user_guides/javascript/rigid_bodies#dominance
751
+ if (rb.dominanceGroup <= 127 && rb.dominanceGroup >= -127)
752
+ rigidbody.setDominanceGroup(Math.floor(rb.dominanceGroup))
753
+ else rigidbody.setDominanceGroup(0);
754
+
755
+ if (rb.autoMass) {
756
+ rigidbody.setAdditionalMass(0, false);
757
+ for (let i = 0; i < rigidbody.numColliders(); i++) {
758
+ const col = rigidbody.collider(i);
759
+ col.setDensity(1);
760
+ }
761
+ rigidbody.recomputeMassPropertiesFromColliders();
762
+ console.log(rigidbody.mass())
763
+ }
764
+ else {
765
+ rigidbody.setAdditionalMass(rb.mass, false);
766
+ for (let i = 0; i < rigidbody.numColliders(); i++) {
767
+ const col = rigidbody.collider(i);
768
+ col.setDensity(0);
769
+ }
770
+ rigidbody.recomputeMassPropertiesFromColliders();
771
+ console.log(rigidbody.mass())
772
+ }
773
+
747
774
  // https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
748
775
  // rigidbody.setAdditionalMass(rb.mass, true);
749
776
  // for (let i = 0; i < rigidbody.numColliders(); i++) {
src/engine/engine_types.ts CHANGED
@@ -247,11 +247,15 @@
247
247
  export declare interface IRigidbody extends IComponent {
248
248
  constraints: RigidbodyConstraints;
249
249
  isKinematic: boolean;
250
+ /** When true the mass will automatically calculated by attached colliders */
251
+ autoMass: boolean;
250
252
  mass: number;
251
253
  drag: number;
252
254
  angularDrag: number;
253
255
  useGravity: boolean;
254
256
  gravityScale: number;
257
+ dominanceGroup: number;
258
+
255
259
  collisionDetectionMode: CollisionDetectionMode;
256
260
 
257
261
  lockPositionX: boolean;
src/engine-components/ui/EventSystem.ts CHANGED
@@ -97,8 +97,8 @@
97
97
  if (!res) {
98
98
  const rc = GameObject.addNewComponent(this.context.scene, ObjectRaycaster);
99
99
  this.raycaster.push(rc);
100
- if (isDevEnvironment())
101
- console.warn("Added an ObjectRaycaster to the scene because no raycaster was found", this);
100
+ if (isDevEnvironment() || debug)
101
+ console.warn("Added an ObjectRaycaster to the scene because no raycaster was found");
102
102
  }
103
103
  }
104
104
  }
src/engine-components/RigidBody.ts CHANGED
@@ -133,9 +133,26 @@
133
133
 
134
134
  export class Rigidbody extends Behaviour implements IRigidbody {
135
135
 
136
+ /** When true the mass will be automatically calculated by the attached colliders */
136
137
  @validate()
138
+ autoMass: boolean = true;
139
+
137
140
  @serializable()
138
- mass: number = 1;
141
+ set mass(value: number) {
142
+ if (value === this._mass) return;
143
+ this._mass = value;
144
+ this._propertiesChanged = true;
145
+ // When setting the mass manually we disable autoMass
146
+ if (this.__didAwake) {
147
+ this.autoMass = false;
148
+ }
149
+ }
150
+ get mass() {
151
+ if (this.autoMass)
152
+ return this.context.physics.engine?.getBody(this)?.mass() ?? -1;
153
+ return this._mass;
154
+ }
155
+ private _mass: number = 0;
139
156
 
140
157
  @validate()
141
158
  @serializable()
@@ -219,8 +236,15 @@
219
236
  get gravityScale() {
220
237
  return this._gravityScale;
221
238
  }
239
+ @validate()
222
240
  private _gravityScale: number = 1;
223
241
 
242
+ /** Rigidbodies with higher dominance will be immune to forces originating from contacts with rigidbodies of lower dominance.
243
+ * Read more here: https://rapier.rs/docs/user_guides/javascript/rigid_bodies#dominance
244
+ */
245
+ @validate()
246
+ dominanceGroup : number = 0;
247
+
224
248
  private static tempPosition: THREE.Vector3 = new THREE.Vector3();
225
249
  private _propertiesChanged: boolean = false;
226
250
  private _currentVelocity: THREE.Vector3 = new THREE.Vector3();