@drawcall/acta 0.1.21 → 0.1.23

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.
@@ -28,6 +28,9 @@ export declare class CharacterBehavior extends EventDispatcher<CharacterBehavior
28
28
  private readonly computedProperties;
29
29
  worldHeadDirection: Vector3 | undefined;
30
30
  worldAimDirection: Vector3 | undefined;
31
+ /**
32
+ * vector representing the movement velocity in world space with meter per second as unit
33
+ */
31
34
  readonly worldMoveVelocity: Vector3;
32
35
  private abortController;
33
36
  private updateTimeline?;
package/dist/behavior.js CHANGED
@@ -18,6 +18,28 @@ const localQuaternionHelper = new Quaternion();
18
18
  const eulerHelper = new Euler();
19
19
  const directionHelper = new Vector3();
20
20
  const vectorHelper = new Vector3();
21
+ const worldQuaternionHelper = new Quaternion();
22
+ const parentWorldQuaternionHelper = new Quaternion();
23
+ const parentWorldQuaternionInvHelper = new Quaternion();
24
+ const worldEulerHelper = new Euler(0, 0, 0, 'YXZ');
25
+ const worldYawDirectionHelper = new Vector3();
26
+ const getWorldYaw = (object) => {
27
+ object.getWorldQuaternion(worldQuaternionHelper);
28
+ worldEulerHelper.setFromQuaternion(worldQuaternionHelper, 'YXZ');
29
+ return worldEulerHelper.y;
30
+ };
31
+ const setWorldYaw = (object, desiredWorldYaw) => {
32
+ if (object.parent == null) {
33
+ object.rotation.y = desiredWorldYaw;
34
+ return;
35
+ }
36
+ worldYawDirectionHelper.set(Math.sin(desiredWorldYaw), 0, Math.cos(desiredWorldYaw));
37
+ object.parent.getWorldQuaternion(parentWorldQuaternionHelper);
38
+ parentWorldQuaternionInvHelper.copy(parentWorldQuaternionHelper).invert();
39
+ worldYawDirectionHelper.applyQuaternion(parentWorldQuaternionInvHelper);
40
+ const localYaw = Math.atan2(worldYawDirectionHelper.x, worldYawDirectionHelper.z);
41
+ object.rotation.y = localYaw;
42
+ };
21
43
  //TODO: support direction AND position targets for head and aim
22
44
  export class CharacterBehavior extends EventDispatcher {
23
45
  model;
@@ -25,11 +47,15 @@ export class CharacterBehavior extends EventDispatcher {
25
47
  applyJump;
26
48
  properties = {};
27
49
  computedProperties = {
28
- isMoving: () => this.worldMoveVelocity.length() > 0,
50
+ // < 0.02 m/s (2 cm per second) is generally imperceptible to the human eye
51
+ isMoving: () => this.worldMoveVelocity.length() > 0.05,
29
52
  };
30
53
  // Direction and movement properties
31
54
  worldHeadDirection;
32
55
  worldAimDirection;
56
+ /**
57
+ * vector representing the movement velocity in world space with meter per second as unit
58
+ */
33
59
  worldMoveVelocity = new Vector3(0, 0, 0);
34
60
  abortController = new AbortController();
35
61
  updateTimeline;
@@ -145,14 +171,14 @@ export class CharacterBehavior extends EventDispatcher {
145
171
  }
146
172
  // Lerp body yaw with angle wrapping
147
173
  this.currentBodyYaw = lerpAngle(this.currentBodyYaw, targetBodyYaw, BodyRotationSpeed * delta);
148
- this.model.scene.rotation.y = this.currentBodyYaw;
174
+ setWorldYaw(this.model.scene, this.currentBodyYaw);
149
175
  this.updateTimeline?.(undefined, delta);
150
176
  this.model.mixer.update(delta);
151
177
  // Stabilize spine during aiming to face the aim direction
152
178
  if (this.isAiming) {
153
179
  const spineBone = this.model.scene.getObjectByName('spine');
154
180
  // Extract yaw from aim direction and add PI offset for model facing
155
- const aimYaw = this.model.scene.rotation.y + Math.PI + SpineAimYawOffset;
181
+ const aimYaw = getWorldYaw(this.model.scene) + Math.PI + SpineAimYawOffset;
156
182
  // Create target quaternion with just the yaw (no pitch/roll)
157
183
  eulerHelper.set(0, aimYaw, 0, 'YXZ');
158
184
  quaternionHelper.setFromEuler(eulerHelper);
@@ -260,7 +286,7 @@ export class CharacterBehavior extends EventDispatcher {
260
286
  return () => parallel('all', action({
261
287
  update: () => {
262
288
  // Transform world velocity to model's local space by rotating by inverse of model's Y rotation
263
- vectorHelper.copy(this.worldMoveVelocity).applyAxisAngle(UpVector, -this.model.scene.rotation.y);
289
+ vectorHelper.copy(this.worldMoveVelocity).applyAxisAngle(UpVector, -getWorldYaw(this.model.scene));
264
290
  const speed = normalizedLocalMoveDirection.set(vectorHelper.x, -vectorHelper.z).length();
265
291
  normalizedLocalMoveDirection.divideScalar(speed);
266
292
  jogFwdAction.timeScale = 0.222 * speed;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@drawcall/acta",
3
3
  "type": "module",
4
4
  "main": "dist/index.js",
5
- "version": "0.1.21",
5
+ "version": "0.1.23",
6
6
  "author": "Bela Bohlender",
7
7
  "license": "SEE LICENSE IN LICENSE",
8
8
  "homepage": "https://drawcall.ai",