@needle-tools/engine 2.36.0-pre → 2.38.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.
Files changed (143) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/needle-engine.d.ts +248 -151
  3. package/dist/needle-engine.js +451 -437
  4. package/dist/needle-engine.js.map +4 -4
  5. package/dist/needle-engine.min.js +82 -82
  6. package/dist/needle-engine.min.js.map +4 -4
  7. package/lib/engine/api.d.ts +1 -0
  8. package/lib/engine/api.js +1 -0
  9. package/lib/engine/api.js.map +1 -1
  10. package/lib/engine/debug/debug.d.ts +1 -0
  11. package/lib/engine/debug/debug.js +3 -0
  12. package/lib/engine/debug/debug.js.map +1 -1
  13. package/lib/engine/engine_addressables.d.ts +3 -1
  14. package/lib/engine/engine_addressables.js +12 -5
  15. package/lib/engine/engine_addressables.js.map +1 -1
  16. package/lib/engine/engine_element.js +3 -2
  17. package/lib/engine/engine_element.js.map +1 -1
  18. package/lib/engine/engine_element_overlay.js +4 -3
  19. package/lib/engine/engine_element_overlay.js.map +1 -1
  20. package/lib/engine/engine_gameobject.js +2 -1
  21. package/lib/engine/engine_gameobject.js.map +1 -1
  22. package/lib/engine/engine_input.d.ts +2 -0
  23. package/lib/engine/engine_input.js +14 -3
  24. package/lib/engine/engine_input.js.map +1 -1
  25. package/lib/engine/engine_physics.d.ts +35 -46
  26. package/lib/engine/engine_physics.js +479 -386
  27. package/lib/engine/engine_physics.js.map +1 -1
  28. package/lib/engine/engine_physics.types.d.ts +23 -0
  29. package/lib/engine/engine_physics.types.js +27 -0
  30. package/lib/engine/engine_physics.types.js.map +1 -0
  31. package/lib/engine/engine_serialization_core.d.ts +3 -0
  32. package/lib/engine/engine_serialization_core.js +5 -0
  33. package/lib/engine/engine_serialization_core.js.map +1 -1
  34. package/lib/engine/engine_setup.d.ts +7 -1
  35. package/lib/engine/engine_setup.js +13 -3
  36. package/lib/engine/engine_setup.js.map +1 -1
  37. package/lib/engine/engine_types.d.ts +45 -26
  38. package/lib/engine/engine_types.js +24 -37
  39. package/lib/engine/engine_types.js.map +1 -1
  40. package/lib/engine/engine_util_decorator.d.ts +6 -0
  41. package/lib/engine/engine_util_decorator.js +54 -0
  42. package/lib/engine/engine_util_decorator.js.map +1 -0
  43. package/lib/engine/engine_utils.d.ts +1 -1
  44. package/lib/engine/engine_utils.js +1 -1
  45. package/lib/engine/engine_utils.js.map +1 -1
  46. package/lib/engine/extensions/NEEDLE_gameobject_data.js +2 -0
  47. package/lib/engine/extensions/NEEDLE_gameobject_data.js.map +1 -1
  48. package/lib/engine-components/Animation.d.ts +7 -5
  49. package/lib/engine-components/Animation.js +7 -7
  50. package/lib/engine-components/Animation.js.map +1 -1
  51. package/lib/engine-components/AnimatorController.js +14 -7
  52. package/lib/engine-components/AnimatorController.js.map +1 -1
  53. package/lib/engine-components/BoxHelperComponent.js +1 -0
  54. package/lib/engine-components/BoxHelperComponent.js.map +1 -1
  55. package/lib/engine-components/Camera.d.ts +1 -0
  56. package/lib/engine-components/Camera.js +20 -5
  57. package/lib/engine-components/Camera.js.map +1 -1
  58. package/lib/engine-components/CharacterController.d.ts +31 -0
  59. package/lib/engine-components/CharacterController.js +167 -0
  60. package/lib/engine-components/CharacterController.js.map +1 -0
  61. package/lib/engine-components/Collider.d.ts +16 -5
  62. package/lib/engine-components/Collider.js +45 -23
  63. package/lib/engine-components/Collider.js.map +1 -1
  64. package/lib/engine-components/Component.d.ts +6 -15
  65. package/lib/engine-components/Component.js +7 -112
  66. package/lib/engine-components/Component.js.map +1 -1
  67. package/lib/engine-components/DragControls.js +9 -6
  68. package/lib/engine-components/DragControls.js.map +1 -1
  69. package/lib/engine-components/Light.d.ts +2 -0
  70. package/lib/engine-components/Light.js +13 -2
  71. package/lib/engine-components/Light.js.map +1 -1
  72. package/lib/engine-components/NavMesh.d.ts +0 -5
  73. package/lib/engine-components/NavMesh.js +100 -10
  74. package/lib/engine-components/NavMesh.js.map +1 -1
  75. package/lib/engine-components/NestedGltf.js +2 -0
  76. package/lib/engine-components/NestedGltf.js.map +1 -1
  77. package/lib/engine-components/Renderer.js +4 -0
  78. package/lib/engine-components/Renderer.js.map +1 -1
  79. package/lib/engine-components/RigidBody.d.ts +45 -25
  80. package/lib/engine-components/RigidBody.js +290 -142
  81. package/lib/engine-components/RigidBody.js.map +1 -1
  82. package/lib/engine-components/SmoothFollow.d.ts +2 -1
  83. package/lib/engine-components/SmoothFollow.js +25 -17
  84. package/lib/engine-components/SmoothFollow.js.map +1 -1
  85. package/lib/engine-components/SpatialTrigger.js +1 -1
  86. package/lib/engine-components/SpatialTrigger.js.map +1 -1
  87. package/lib/engine-components/SpectatorCamera.d.ts +1 -0
  88. package/lib/engine-components/SpectatorCamera.js +9 -2
  89. package/lib/engine-components/SpectatorCamera.js.map +1 -1
  90. package/lib/engine-components/SpringJoint.d.ts +0 -13
  91. package/lib/engine-components/SpringJoint.js +42 -41
  92. package/lib/engine-components/SpringJoint.js.map +1 -1
  93. package/lib/engine-components/VideoPlayer.js.map +1 -1
  94. package/lib/engine-components/WebXR.d.ts +1 -0
  95. package/lib/engine-components/WebXR.js +13 -6
  96. package/lib/engine-components/WebXR.js.map +1 -1
  97. package/lib/engine-components/WebXRController.js +12 -6
  98. package/lib/engine-components/WebXRController.js.map +1 -1
  99. package/lib/engine-components/codegen/components.d.ts +4 -3
  100. package/lib/engine-components/codegen/components.js +4 -3
  101. package/lib/engine-components/codegen/components.js.map +1 -1
  102. package/package.json +3 -4
  103. package/src/engine/api.ts +2 -1
  104. package/src/engine/codegen/register_types.js +16 -12
  105. package/src/engine/debug/debug.ts +4 -0
  106. package/src/engine/dist/engine_physics.js +739 -0
  107. package/src/engine/dist/engine_setup.js +777 -0
  108. package/src/engine/engine_addressables.ts +18 -8
  109. package/src/engine/engine_element.ts +3 -2
  110. package/src/engine/engine_element_overlay.ts +4 -3
  111. package/src/engine/engine_gameobject.ts +4 -4
  112. package/src/engine/engine_input.ts +12 -3
  113. package/src/engine/engine_physics.ts +492 -418
  114. package/src/engine/engine_physics.types.ts +28 -0
  115. package/src/engine/engine_serialization_core.ts +8 -1
  116. package/src/engine/engine_setup.ts +31 -18
  117. package/src/engine/engine_types.ts +83 -56
  118. package/src/engine/engine_util_decorator.ts +69 -0
  119. package/src/engine/engine_utils.ts +3 -3
  120. package/src/engine/extensions/NEEDLE_gameobject_data.ts +2 -0
  121. package/src/engine-components/Animation.ts +18 -12
  122. package/src/engine-components/AnimatorController.ts +16 -11
  123. package/src/engine-components/BoxHelperComponent.ts +1 -0
  124. package/src/engine-components/Camera.ts +21 -4
  125. package/src/engine-components/CharacterController.ts +171 -0
  126. package/src/engine-components/Collider.ts +49 -39
  127. package/src/engine-components/Component.ts +15 -130
  128. package/src/engine-components/DragControls.ts +9 -5
  129. package/src/engine-components/Light.ts +17 -3
  130. package/src/engine-components/NavMesh.ts +114 -115
  131. package/src/engine-components/NestedGltf.ts +2 -0
  132. package/src/engine-components/Renderer.ts +5 -1
  133. package/src/engine-components/RigidBody.ts +292 -149
  134. package/src/engine-components/SmoothFollow.ts +21 -18
  135. package/src/engine-components/SpatialTrigger.ts +1 -1
  136. package/src/engine-components/SpectatorCamera.ts +10 -2
  137. package/src/engine-components/SpringJoint.ts +41 -41
  138. package/src/engine-components/VideoPlayer.ts +1 -2
  139. package/src/engine-components/WebXR.ts +15 -6
  140. package/src/engine-components/WebXRController.ts +16 -7
  141. package/src/engine-components/codegen/components.ts +4 -3
  142. package/src/engine-components/dist/CharacterController.js +123 -0
  143. package/src/engine-components/dist/RigidBody.js +458 -0
@@ -1,234 +1,377 @@
1
1
  import { Behaviour } from "./Component";
2
- import { BodyOptions } from '../engine/engine_physics'
3
- import * as CANNON from 'cannon-es'
4
2
  import * as THREE from 'three'
5
3
  import { getWorldPosition } from "../engine/engine_three_utils";
6
4
  import { serializeable } from "../engine/engine_serialization_decorator";
7
5
  import { Watch } from "../engine/engine_utils";
8
- import { Vector3 } from "three";
6
+ import { Object3D, Vector3 } from "three";
9
7
  import { IRigidbody } from "../engine/engine_types";
8
+ import { CollisionDetectionMode, RigidbodyConstraints } from "../engine/engine_physics.types";
9
+ import { validate } from "../engine/engine_util_decorator";
10
+ import { Context, FrameEvent } from "../engine/engine_setup";
11
+
12
+ class TransformWatch {
13
+
14
+ get isDirty(): boolean {
15
+ return this.positionChanged || this.rotationChanged;
16
+ }
17
+ positionChanged: boolean = false;
18
+ rotationChanged: boolean = false;
19
+
20
+ position?: { x?: number, y?: number, z?: number };
21
+ quaternion?: { _x?: number, _y?: number, _z?: number, _w?: number };
22
+
23
+ private _positionKeys: string[] = ["x", "y", "z"];
24
+ private _quaternionKeys: string[] = ["_x", "_y", "_z", "_w"];
25
+
26
+ reset(clearPreviousValues: boolean = false) {
27
+ this.positionChanged = false;
28
+ this.rotationChanged = false;
29
+ this.mute = false;
30
+
31
+ if (clearPreviousValues) {
32
+ if (this.position)
33
+ for (const key of this._positionKeys)
34
+ delete this.position[key];
35
+ if (this.quaternion)
36
+ for (const key of this._quaternionKeys)
37
+ delete this.quaternion[key];
38
+ }
39
+ }
40
+
41
+ mute: boolean = false;
42
+
43
+ applyValues() {
44
+ // only apply the values that actually changed
45
+ // since we want to still control all the other values via physics
46
+ if (this.positionChanged && this.position) {
47
+ for (const key of this._positionKeys) {
48
+ const val = this.position[key];
49
+ if (val !== undefined)
50
+ this.obj.position[key] = val;
51
+ }
52
+ }
53
+ if (this.rotationChanged) {
54
+ if (this.quaternion) {
55
+ for (const key of this._quaternionKeys) {
56
+ const val = this.quaternion[key];
57
+ if (val !== undefined)
58
+ this.obj.quaternion[key] = val;
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ readonly context: Context;
65
+ readonly obj: Object3D;
66
+ private _positionWatch?: Watch;
67
+ private _rotationWatch?: Watch;
68
+
69
+ constructor(obj: Object3D, context: Context) {
70
+ this.context = context;
71
+ this.obj = obj;
72
+ }
73
+
74
+ start(position: boolean, rotation: boolean) {
75
+ this.reset();
76
+ if (position) {
77
+ if (!this._positionWatch)
78
+ this._positionWatch = new Watch(this.obj.position, ["x", "y", "z"]);
79
+ this._positionWatch.apply();
80
+ this.position = {};
81
+ // this.position = this.obj.position.clone();
82
+ this._positionWatch.subscribeWrite((val, prop) => {
83
+ if (this.context.physics.isUpdating || this.mute) return;
84
+ const prev = this.position![prop];
85
+ if (Math.abs(prev - val) < .00001) return;
86
+ this.position![prop] = val;
87
+ this.positionChanged = true;
88
+ })
89
+ }
90
+ if (rotation) {
91
+ if (!this._rotationWatch)
92
+ this._rotationWatch = new Watch(this.obj.quaternion, ["_x", "_y", "_z", "_w"]);
93
+ this._rotationWatch.apply();
94
+ this.quaternion = {};
95
+ // this.quaternion = this.obj.quaternion.clone();
96
+ this._rotationWatch.subscribeWrite((val, prop) => {
97
+ if (this.context.physics.isUpdating || this.mute) return;
98
+ const prev = this.quaternion![prop];
99
+ if (Math.abs(prev - val) < .00001) return;
100
+ this.quaternion![prop] = val;
101
+ this.rotationChanged = true;
102
+ })
103
+ }
104
+ }
105
+
106
+ stop() {
107
+ this._positionWatch?.revoke();
108
+ this._rotationWatch?.revoke();
109
+ }
110
+ }
111
+
10
112
 
11
113
  export class Rigidbody extends Behaviour implements IRigidbody {
12
114
 
115
+ @validate()
13
116
  @serializeable()
14
117
  mass: number = 1;
15
118
 
119
+ @validate()
16
120
  @serializeable()
17
- public set isKinematic(kinematic: boolean) {
18
- this._isKinematic = kinematic;
19
- if (this._body) {
20
- this._body.type = kinematic ? CANNON.Body.KINEMATIC : CANNON.Body.DYNAMIC;
21
- }
22
- }
121
+ useGravity: boolean = true;
23
122
 
24
- public get isKinematic(): boolean {
25
- return this._isKinematic;
26
- }
27
- private _isKinematic: boolean = false;
123
+ @validate()
124
+ @serializeable()
125
+ constraints: RigidbodyConstraints = RigidbodyConstraints.None;
28
126
 
127
+ @validate()
128
+ @serializeable()
129
+ isKinematic: boolean = false;
130
+
131
+ @validate()
29
132
  @serializeable()
30
133
  drag: number = 0;
134
+
135
+ @validate()
31
136
  @serializeable()
32
137
  angularDrag: number = 1;
138
+
139
+ @validate()
33
140
  @serializeable()
34
141
  detectCollisions: boolean = true;
142
+
143
+ @validate()
35
144
  @serializeable()
36
145
  sleepThreshold: number = 0.01;
37
146
 
147
+ @validate()
148
+ @serializeable()
149
+ collisionDetectionMode: CollisionDetectionMode = CollisionDetectionMode.Discrete;
38
150
 
39
- get body(): CANNON.Body | null {
40
- if (this._body === null) {
41
- this.initialize();
42
- }
43
- return this._body;
151
+ get lockPositionX() {
152
+ return (this.constraints & RigidbodyConstraints.FreezePositionX) !== 0;
153
+ }
154
+ get lockPositionY() {
155
+ return (this.constraints & RigidbodyConstraints.FreezePositionY) !== 0;
156
+ }
157
+ get lockPositionZ() {
158
+ return (this.constraints & RigidbodyConstraints.FreezePositionZ) !== 0;
159
+ }
160
+ get lockRotationX() {
161
+ return (this.constraints & RigidbodyConstraints.FreezeRotationX) !== 0;
162
+ }
163
+ get lockRotationY() {
164
+ return (this.constraints & RigidbodyConstraints.FreezeRotationY) !== 0;
165
+ }
166
+ get lockRotationZ() {
167
+ return (this.constraints & RigidbodyConstraints.FreezeRotationZ) !== 0;
168
+ }
169
+
170
+ set lockPositionX(v: boolean) {
171
+ if (v) this.constraints |= RigidbodyConstraints.FreezePositionX;
172
+ else this.constraints &= ~RigidbodyConstraints.FreezePositionX;
173
+ }
174
+ set lockPositionY(v: boolean) {
175
+ if (v) this.constraints |= RigidbodyConstraints.FreezePositionY;
176
+ else this.constraints &= ~RigidbodyConstraints.FreezePositionY;
177
+ }
178
+ set lockPositionZ(v: boolean) {
179
+ if (v) this.constraints |= RigidbodyConstraints.FreezePositionZ;
180
+ else this.constraints &= ~RigidbodyConstraints.FreezePositionZ;
181
+ }
182
+ set lockRotationX(v: boolean) {
183
+ if (v) this.constraints |= RigidbodyConstraints.FreezeRotationX;
184
+ else this.constraints &= ~RigidbodyConstraints.FreezeRotationX;
185
+ }
186
+ set lockRotationY(v: boolean) {
187
+ if (v) this.constraints |= RigidbodyConstraints.FreezeRotationY;
188
+ else this.constraints &= ~RigidbodyConstraints.FreezeRotationY;
189
+ }
190
+ set lockRotationZ(v: boolean) {
191
+ if (v) this.constraints |= RigidbodyConstraints.FreezeRotationZ;
192
+ else this.constraints &= ~RigidbodyConstraints.FreezeRotationZ;
44
193
  }
45
194
 
195
+ private _propertiesChanged: boolean = false;
46
196
  private static tempPosition: THREE.Vector3 = new THREE.Vector3();
47
- private _body: CANNON.Body | null = null;
48
- private currentVelocity!: THREE.Vector3;
197
+ private _currentVelocity!: THREE.Vector3;
49
198
  private _smoothedVelocity!: THREE.Vector3;
50
- private lastWorldPosition!: THREE.Vector3;
199
+ private _smoothedVelocityGetter!: THREE.Vector3;
200
+ private _lastPosition!: THREE.Vector3;
51
201
 
52
- private _ignoreChange: boolean = false;
53
- private _dirty: boolean = false;
202
+ private _watch?: TransformWatch;
54
203
 
55
- private _positionWatch?: Watch;
56
- private _matrixWatch?: Watch;
57
- private _setMatrix: THREE.Matrix4;
58
-
59
- constructor() {
60
- super();
61
- this._setMatrix = new THREE.Matrix4();
62
- }
63
204
 
64
205
  awake() {
65
- this._body = null;
66
- this.currentVelocity = new THREE.Vector3();
206
+ this._watch = undefined;
207
+ this._currentVelocity = new THREE.Vector3();
67
208
  this._smoothedVelocity = new THREE.Vector3();
68
- this.lastWorldPosition = getWorldPosition(this.gameObject).clone();
69
- this._matrixWatch = undefined;
70
- this._positionWatch = undefined;
209
+ this._smoothedVelocityGetter = new THREE.Vector3();
210
+ this._lastPosition = new THREE.Vector3();
71
211
  }
72
212
 
73
- // start() {
74
- // this.setBodyFromGameObject();
75
- // }
76
-
77
213
  onEnable() {
78
- if (this._body) {
79
- this.context.physics.addBody(this.gameObject, this._body);
80
- }
81
- else
82
- this.initialize();
83
-
84
- if (this.body) {
85
- this.body.wakeUp();
86
- this.gameObject.updateWorldMatrix(true, false);
87
- this.setBodyFromGameObject();
214
+ if (!this._watch) {
215
+ this._watch = new TransformWatch(this.gameObject, this.context);
88
216
  }
89
-
90
- if (!this._positionWatch)
91
- this._positionWatch = new Watch(this.gameObject.position, ["x", "y", "z"]);
92
- this._positionWatch.subscribeWrite(_ => {
93
- if (!this.context.physics.isUpdating && !this._ignoreChange) {
94
- this._dirty = true;
95
- this._setMatrix.copy(this.gameObject.matrix);
96
- this._setMatrix.setPosition(this.gameObject.position);
97
- }
98
- })
217
+ this._watch.start(true, true);
218
+ this.startCoroutine(this.beforePhysics(), FrameEvent.LateUpdate);
99
219
  }
100
220
 
101
- onDisable(): void {
102
- if (this._body)
103
- this.context.physics.removeBody(this.gameObject, this._body, false);
221
+ onDisable() {
222
+ this._watch?.stop();
223
+ this.context.physics.removeBody(this);
104
224
  }
105
225
 
106
226
  onDestroy(): void {
107
- if (this._body)
108
- this.context.physics.removeBody(this.gameObject, this._body);
227
+ this.context.physics.removeBody(this);
109
228
  }
110
229
 
111
- onBeforeRender() {
112
- this._ignoreChange = true;
113
- this.updateVelocity();
230
+ onValidate() {
231
+ this._propertiesChanged = true;
232
+ }
114
233
 
115
- if (this._dirty) {
116
- this._dirty = false;
117
- this._setMatrix.decompose(this.gameObject.position, this.gameObject.quaternion, this.gameObject.scale);
118
- this.setBodyFromGameObject();
234
+ // need to do this right before updating physics to prevent rendered object glitching through physical bodies
235
+ *beforePhysics() {
236
+ while (true) {
237
+ if (this._propertiesChanged) {
238
+ this._propertiesChanged = false;
239
+ this.context.physics.updateProperties(this);
240
+ }
241
+ if (this._watch?.isDirty) {
242
+ this._watch.mute = true;
243
+ this._watch.applyValues();
244
+ this.context.physics.updateBody(this, this._watch.positionChanged, this._watch.rotationChanged);
245
+ this._watch.reset();
246
+ }
247
+ this.captureVelocity();
248
+ yield;
119
249
  }
250
+ }
120
251
 
121
- this._ignoreChange = false;
252
+ private get body() {
253
+ return this.context.physics.internal_getRigidbody(this);
122
254
  }
123
255
 
124
- initialize() {
125
- if (this._body) {
126
- return;
127
- }
128
- const options = new BodyOptions();
129
- options.drag = this.drag;
130
- options.angularDrag = this.angularDrag;
131
- options.mass = this.mass;
132
- options.kinematic = this.isKinematic;
133
- options.physicsEvents = this.detectCollisions;
134
- options.sleepThreshold = this.sleepThreshold;
135
- this._body = this.context.physics.createBody(this.gameObject, options);
256
+ public teleport(pt: { x: number, y: number, z: number }, localspace:boolean = true) {
257
+ this._watch?.reset(true);
258
+ if(localspace) this.gameObject.position.set(pt.x, pt.y, pt.z);
259
+ else this.setWorldPosition(pt.x, pt.y, pt.z);
260
+ this.resetForcesAndTorques();
261
+ this.resetVelocities();
262
+ }
263
+
264
+ public resetForces() {
265
+ this.body?.resetForces(true);
136
266
  }
137
267
 
268
+ public resetTorques() {
269
+ this.body?.resetTorques(true);
270
+ }
271
+
272
+ public resetVelocities() {
273
+ this.setVelocity(0, 0, 0);
274
+ this.setAngularVelocity(0, 0, 0);
275
+ }
276
+
277
+ public resetForcesAndTorques() {
278
+ this.resetForces();
279
+ this.resetTorques();
280
+ }
138
281
 
139
282
  public wakeUp() {
140
283
  this.body?.wakeUp();
141
284
  }
142
285
 
143
- public applyForce(vec: THREE.Vector3, rel?: THREE.Vector3) {
144
- const force = new CANNON.Vec3(vec.x, vec.y, vec.z);
145
- force.scale(1 / this.context.time.deltaTime, force);
146
- this.body?.applyForce(force, rel ? new CANNON.Vec3(rel.x, rel.y, rel.z) : undefined);
286
+ public applyForce(vec: Vector3, _rel?: THREE.Vector3) {
287
+ this.body?.addForce(vec, true);
288
+ }
289
+
290
+ public applyImpulse(vec: Vector3) {
291
+ this.body?.applyImpulse(vec, true);
147
292
  }
148
293
 
149
294
  public setForce(x: number, y: number, z: number) {
150
- this.body?.force.set(x, y, z);
295
+ this.body?.resetForces(true);
296
+ this.body?.addForce({ x, y, z }, true);
151
297
  }
152
298
 
153
- public getVelocity(): THREE.Vector3 {
154
- if (this.body)
155
- return Rigidbody.tempPosition.set(this.body?.velocity.x, this.body?.velocity.y, this.body?.velocity.z);
156
- return Rigidbody.tempPosition.set(0, 0, 0);
299
+ public getVelocity(): Vector3 {
300
+ const vel = this.body?.linvel();
301
+ if (!vel) return this._currentVelocity.set(0, 0, 0);
302
+ this._currentVelocity.x = vel.x;
303
+ this._currentVelocity.y = vel.y;
304
+ this._currentVelocity.z = vel.z;
305
+ return this._currentVelocity;
157
306
  }
158
307
 
159
- public setVelocity(x: number | Vector3, y: number, z: number) {
160
- if (!this.body) return;
308
+ public setVelocity(x: number | Vector3, y?: number, z?: number) {
161
309
  if (x instanceof Vector3) {
162
310
  const vec = x;
163
- x = vec.x;
164
- y = vec.y;
165
- z = vec.z;
311
+ this.body?.setLinvel(vec, true);
312
+ return;
166
313
  }
167
- this.body.velocity.x = x / this.context.time.deltaTime;
168
- this.body.velocity.y = y / this.context.time.deltaTime;
169
- this.body.velocity.z = z / this.context.time.deltaTime;
314
+ if (y === undefined || z === undefined) return;
315
+ this.body?.setLinvel({ x: x, y: y, z: z }, true);
170
316
  }
171
317
 
172
- public getTorque(): THREE.Vector3 {
173
- if (this.body)
174
- return Rigidbody.tempPosition.set(this.body?.torque.x, this.body?.torque.y, this.body?.torque.z);
175
- return Rigidbody.tempPosition.set(0, 0, 0);
176
- }
177
-
178
- public setTorque(x: number | Vector3, y: number, z: number) {
179
- if (!this.body) return;
318
+ public setAngularVelocity(x: number | Vector3, y?: number, z?: number) {
180
319
  if (x instanceof Vector3) {
181
320
  const vec = x;
182
- x = vec.x;
183
- y = vec.y;
184
- z = vec.z;
321
+ this.body?.setAngvel(vec, true);
322
+ return;
185
323
  }
186
- this.body.torque.x = x / this.context.time.deltaTime;
187
- this.body.torque.y = y / this.context.time.deltaTime;
188
- this.body.torque.z = z / this.context.time.deltaTime;
189
-
324
+ if (y === undefined || z === undefined) return;
325
+ this.body?.setAngvel({ x: x, y: y, z: z }, true);
190
326
  }
191
327
 
192
- public get smoothedVelocity() { return this._smoothedVelocity; }
193
-
194
- public setAngularVelocity(x: number, y: number, z: number) {
195
- if (!this.body) return;
196
- this.body.angularVelocity.x = x / this.context.time.deltaTime;
197
- this.body.angularVelocity.y = y / this.context.time.deltaTime;
198
- this.body.angularVelocity.z = z / this.context.time.deltaTime;
328
+ public setTorque(x: number | Vector3, y: number, z: number) {
329
+ this.setAngularVelocity(x, y, z);
199
330
  }
200
331
 
201
- private static copyVector3: THREE.Vector3 = new THREE.Vector3();
202
-
203
-
204
- public setBodyFromGameObject(velocity: THREE.Vector3 | null | { x: number, y: number, z: number } = null) {
205
- if (this.body && this.gameObject && !this.destroyed) {
206
- this._ignoreChange = true;
207
- const wp = this.worldPosition;
208
- this.body.position.set(wp.x, wp.y, wp.z);
209
- const wr = this.worldQuaternion;
210
- this.body.quaternion.set(wr.x, wr.y, wr.z, wr.w);
332
+ public get smoothedVelocity(): Vector3 {
333
+ this._smoothedVelocityGetter.copy(this._smoothedVelocity);
334
+ return this._smoothedVelocityGetter.multiplyScalar(1 / this.context.time.deltaTime);
335
+ }
211
336
 
212
- if (velocity) {
213
- Rigidbody.copyVector3.set(velocity.x, velocity.y, velocity.z);
214
- this._smoothedVelocity.lerp(Rigidbody.copyVector3, this.context.time.deltaTime / .1);
215
- const sm = this._smoothedVelocity;
216
- this.body.velocity.x = sm.x;
217
- this.body.velocity.y = sm.y;
218
- this.body.velocity.z = sm.z;
219
- }
220
- this._ignoreChange = false;
337
+ // public get smoothedVelocity() { return this._smoothedVelocity; }
338
+
339
+
340
+
341
+ /**d
342
+ * @deprecated not used anymore
343
+ */
344
+ public setBodyFromGameObject(_velocity: THREE.Vector3 | null | { x: number, y: number, z: number } = null) {
345
+ if (this.gameObject && !this.destroyed) {
346
+ // this.context.physics.updateBody(this);
347
+ // this._ignoreChange = true;
348
+ // const wp = this.worldPosition;
349
+ // this.body.position.set(wp.x, wp.y, wp.z);
350
+ // const wr = this.worldQuaternion;
351
+ // this.body.quaternion.set(wr.x, wr.y, wr.z, wr.w);
352
+
353
+ // if (velocity) {
354
+ // Rigidbody.copyVector3.set(velocity.x, velocity.y, velocity.z);
355
+ // this._smoothedVelocity.lerp(Rigidbody.copyVector3, this.context.time.deltaTime / .1);
356
+ // const sm = this._smoothedVelocity;
357
+ // this.body.velocity.x = sm.x;
358
+ // this.body.velocity.y = sm.y;
359
+ // this.body.velocity.z = sm.z;
360
+ // }
361
+ // this._ignoreChange = false;
221
362
  }
222
363
  }
223
364
 
224
365
 
225
- private updateVelocity() {
226
- if (!this.currentVelocity) return;
227
- if (this.body && this.gameObject) {
366
+
367
+ private captureVelocity() {
368
+ if (this.body) {
228
369
  const wp = getWorldPosition(this.gameObject);
229
- this.currentVelocity.subVectors(wp, this.lastWorldPosition);
230
- this.lastWorldPosition.copy(wp);
231
- this._smoothedVelocity.lerp(this.currentVelocity, this.context.time.deltaTime / .1);
370
+ Rigidbody.tempPosition.copy(wp);
371
+ const vel = wp.sub(this._lastPosition);
372
+ this._lastPosition.copy(Rigidbody.tempPosition);
373
+ this._smoothedVelocity.lerp(vel, this.context.time.deltaTime / .1);
374
+ // this._smoothedVelocity.set(0, 1 / this.context.time.deltaTime, 0);
232
375
  }
233
376
  }
234
377
  }
@@ -1,53 +1,56 @@
1
1
  import { Camera } from "./Camera";
2
2
  import { Behaviour, GameObject } from "./Component";
3
- import * as utils from "../engine/engine_three_utils";
4
3
  import * as THREE from "three";
5
4
  import { Mathf } from "../engine/engine_math";
6
5
  import { serializeable } from "../engine/engine_serialization_decorator";
7
6
  import { Object3D } from "three";
7
+ import { getWorldPosition, getWorldQuaternion } from "../engine/engine_three_utils";
8
+ import { Axes } from "../engine/engine_physics.types";
8
9
 
9
10
  export class SmoothFollow extends Behaviour {
10
11
 
11
12
  @serializeable(Object3D)
12
13
  target: THREE.Object3D | null = null;
13
14
 
15
+ @serializeable()
14
16
  followFactor = .1;
17
+ @serializeable()
15
18
  rotateFactor = .1;
16
19
 
17
- flipForward:boolean = false;
20
+ @serializeable()
21
+ positionAxes : Axes = Axes.All;
18
22
 
19
- private static _invertForward : THREE.Quaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
20
- private _firstUpdate = true;
23
+ // @serializeable()
24
+ // rotationAxes : Axes = Axes.All;
21
25
 
26
+ flipForward: boolean = false;
27
+
28
+ private static _invertForward: THREE.Quaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
29
+ private _firstUpdate = true;
22
30
 
23
- onEnable(): void {
24
- const cam = GameObject.getComponentInChildren(this.gameObject, Camera) as Camera;
25
- if (cam && cam.cam) {
26
- cam.gameObject.position.set(0, 0, 0);
27
- cam.cam.position.set(0, 0, 0);
28
- cam.gameObject.quaternion.identity();
29
- cam.cam.quaternion.setFromEuler(new THREE.Euler(0, Math.PI, 0));
30
- }
31
- }
32
31
 
33
32
  onBeforeRender(): void {
34
- if (this.followFactor <= 0) return;
35
33
  this.updateNow(false);
36
34
  }
37
35
 
38
36
  updateNow(hard: boolean) {
39
37
  if (!this.target || this.target === this.gameObject) return;
40
38
  if (this.followFactor > 0) {
41
- const wp = utils.getWorldPosition(this.target);
39
+ const wp = getWorldPosition(this.target);
42
40
  const fpos = this._firstUpdate || hard ? 1 : Mathf.clamp01(this.context.time.deltaTime * this.followFactor);
43
- this.worldPosition = this.worldPosition.lerp(wp, fpos);
41
+ const currentPosition = this.worldPosition;
42
+ if(this.positionAxes & Axes.X) currentPosition.x = Mathf.lerp(currentPosition.x, wp.x, fpos);
43
+ if(this.positionAxes & Axes.Y) currentPosition.y = Mathf.lerp(currentPosition.y, wp.y, fpos);
44
+ if(this.positionAxes & Axes.Z) currentPosition.z = Mathf.lerp(currentPosition.z, wp.z, fpos);
45
+ this.worldPosition = currentPosition;
44
46
  }
45
47
  if (this.rotateFactor > 0) {
46
- const wr = utils.getWorldQuaternion(this.target);
47
- if(this.flipForward){
48
+ const wr = getWorldQuaternion(this.target);
49
+ if (this.flipForward) {
48
50
  wr.premultiply(SmoothFollow._invertForward);
49
51
  }
50
52
  const frot = this._firstUpdate || hard ? 1 : Mathf.clamp01(this.context.time.deltaTime * this.rotateFactor);
53
+
51
54
  this.worldQuaternion = this.worldQuaternion.slerp(wr, frot);
52
55
  }
53
56
  this._firstUpdate = false;
@@ -95,7 +95,7 @@ export class SpatialTrigger extends Behaviour {
95
95
  SpatialTrigger.triggers.push(this);
96
96
  if (!this.boxHelper) {
97
97
  this.boxHelper = GameObject.addNewComponent(this.gameObject, BoxHelperComponent);
98
- this.boxHelper?.showHelper();
98
+ this.boxHelper?.showHelper(null, debug as boolean);
99
99
  }
100
100
  }
101
101
  onDisable(): void {
@@ -61,6 +61,10 @@ export class SpectatorCamera extends Behaviour {
61
61
  this.target = undefined;
62
62
  }
63
63
 
64
+ private get localId() : string {
65
+ return this.context.connection.connectionId ?? "local";
66
+ }
67
+
64
68
  /** player view to follow */
65
69
  set target(target: PlayerView | undefined) {
66
70
  if (this._handler) {
@@ -74,7 +78,7 @@ export class SpectatorCamera extends Behaviour {
74
78
  // }
75
79
 
76
80
  const prev = this._handler.currentTarget?.userId;
77
- const self = this.context.players.getPlayerView(this.context.connection.connectionId);
81
+ const self = this.context.players.getPlayerView(this.localId);
78
82
 
79
83
  // if user is in XR and sets target to self disable it
80
84
  if (target === undefined || (this.context.isInXR === false && self?.currentObject === target.currentObject)) {
@@ -103,7 +107,7 @@ export class SpectatorCamera extends Behaviour {
103
107
  }
104
108
 
105
109
  private get isSpectatingSelf() {
106
- return this.isSpectating && this.target?.currentObject === this.context.players.getPlayerView(this.context.connection.connectionId)?.currentObject;
110
+ return this.isSpectating && this.target?.currentObject === this.context.players.getPlayerView(this.localId)?.currentObject;
107
111
  }
108
112
 
109
113
  // private currentViewport : THREE.Vector4 = new THREE.Vector4();
@@ -191,6 +195,10 @@ export class SpectatorCamera extends Behaviour {
191
195
 
192
196
  private followSelf() {
193
197
  this.target = this.context.players.getPlayerView(this.context.connection.connectionId);
198
+ if (!this.target) {
199
+ this.context.players.setPlayerView(this.localId, this.context.mainCamera, ViewDevice.Headset);
200
+ this.target = this.context.players.getPlayerView(this.localId);
201
+ }
194
202
  if (debug) console.log("Follow self", this.target);
195
203
  }
196
204