@needle-tools/engine 3.46.0-beta.1 → 3.46.0-beta.2

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.
@@ -75,20 +75,28 @@ export class Camera extends Behaviour implements ICamera {
75
75
  set nearClipPlane(val) {
76
76
  const changed = this._nearClipPlane != val;
77
77
  this._nearClipPlane = val;
78
- if (this._cam && changed) {
78
+ if (this._cam && (changed || this._cam.near != val)) {
79
79
  this._cam.near = val;
80
80
  this._cam.updateProjectionMatrix();
81
81
  }
82
82
  }
83
83
  private _nearClipPlane: number = 0.1;
84
84
 
85
+ applyClippingPlane() {
86
+ if (this._cam) {
87
+ this._cam.near = this._nearClipPlane;
88
+ this._cam.far = this._farClipPlane;
89
+ this._cam.updateProjectionMatrix();
90
+ }
91
+ }
92
+
85
93
  /** The camera's far clipping plane */
86
94
  get farClipPlane(): number { return this._farClipPlane; }
87
95
  @serializable()
88
96
  set farClipPlane(val) {
89
97
  const changed = this._farClipPlane != val;
90
98
  this._farClipPlane = val;
91
- if (this._cam && changed) {
99
+ if (this._cam && (changed || this._cam.far != val)) {
92
100
  this._cam.far = val;
93
101
  this._cam.updateProjectionMatrix();
94
102
  }
@@ -7,7 +7,7 @@ import { destroy, instantiate } from "../../engine/engine_gameobject.js";
7
7
  import { Gizmos } from "../../engine/engine_gizmos.js";
8
8
  import { InputEventQueue, NEPointerEvent } from "../../engine/engine_input.js";
9
9
  import { serializable } from "../../engine/engine_serialization_decorator.js";
10
- import { getBoundingBox } from "../../engine/engine_three_utils.js";
10
+ import { getBoundingBox, getTempVector } from "../../engine/engine_three_utils.js";
11
11
  import type { IComponent, IGameObject } from "../../engine/engine_types.js";
12
12
  import { getParam, isAndroidDevice } from "../../engine/engine_utils.js";
13
13
  import { NeedleXRController, type NeedleXREventArgs, type NeedleXRHitTestResult, NeedleXRSession } from "../../engine/engine_xr.js";
@@ -213,7 +213,8 @@ export class WebARSessionRoot extends Behaviour {
213
213
 
214
214
  // in pass through mode we want to place the scene using an XR controller
215
215
  let controllersDidHit = false;
216
- if (args.xr.isPassThrough && args.xr.controllers.length > 0) {
216
+ // when auto placing we just use the user's view
217
+ if (args.xr.isPassThrough && args.xr.controllers.length > 0 && !this.autoPlace) {
217
218
  for (const ctrl of args.xr.controllers) {
218
219
  // with this we can only place with the left / first controller right now
219
220
  // we also only have one reticle... this should probably be refactored a bit so we can have multiple reticles
@@ -273,7 +274,6 @@ export class WebARSessionRoot extends Behaviour {
273
274
  // save the hit test
274
275
  this._hits[i] = hit.hit;
275
276
  let reticle = this._reticle[i];
276
-
277
277
  if (!reticle) {
278
278
  if (this.customReticle) {
279
279
  if (this.customReticle.asset) {
@@ -300,7 +300,6 @@ export class WebARSessionRoot extends Behaviour {
300
300
  reticle.matrixAutoUpdate = false;
301
301
  reticle.visible = false;
302
302
  }
303
-
304
303
  reticle["lastPos"] = reticle["lastPos"] || hit.position.clone();
305
304
  reticle["lastQuat"] = reticle["lastQuat"] || hit.quaternion.clone();
306
305
  // reticle["targetPos"] = reticle["targetPos"] || hit.position.clone();
@@ -336,8 +335,23 @@ export class WebARSessionRoot extends Behaviour {
336
335
  }
337
336
 
338
337
  if (this.autoPlace) {
339
- reticle.visible = false;
340
- this.onPlaceScene(null);
338
+ this.upVec.set(0, 1, 0).applyQuaternion(reticle.quaternion);
339
+ const isUp = this.upVec.dot(getTempVector(0, 1, 0)) > 0.9;
340
+ if (isUp) {
341
+ // We want the reticle to be at a suitable spot for a moment before we place the scene (not place it immediately)
342
+ let autoplace_timer = reticle["autoplace:timer"] || 0;
343
+ if (autoplace_timer >= 1) {
344
+ reticle.visible = false;
345
+ this.onPlaceScene(null);
346
+ }
347
+ else {
348
+ autoplace_timer += this.context.time.deltaTime;
349
+ reticle["autoplace:timer"] = autoplace_timer;
350
+ }
351
+ }
352
+ else {
353
+ reticle["autoplace:timer"] = 0;
354
+ }
341
355
  }
342
356
  }
343
357
 
@@ -14,6 +14,7 @@ import { NeedleXRController, type NeedleXREventArgs, NeedleXRSession } from "../
14
14
  import { Behaviour, GameObject } from "../../Component.js"
15
15
  import { TeleportTarget } from "../TeleportTarget.js";
16
16
  import type { XRMovementBehaviour } from "../types.js";
17
+ import { hasPointerEventComponent } from "../../ui/PointerEvents.js";
17
18
 
18
19
  const debug = getParam("debugwebxr");
19
20
 
@@ -257,8 +258,12 @@ export class XRControllerMovement extends Behaviour implements XRMovementBehavio
257
258
  continue;
258
259
  }
259
260
 
260
- const hit = this.context.physics.raycastFromRay(ctrl.ray, { testObject: this.hitPointRaycastFilter, precise: false })[0];
261
- this._hitDistances[i] = hit?.distance;
261
+ const hits = this.context.physics.raycastFromRay(ctrl.ray, { testObject: this.hitPointRaycastFilter, precise: false });
262
+ const hit = hits.find(h => {
263
+ // Only render hits on interactable objects
264
+ return hasPointerEventComponent(h.object)
265
+ });
266
+ this._hitDistances[i] = hit?.distance || 0;
262
267
 
263
268
  let disc = this._hitDiscs[i];
264
269
  if (disc) // save the hit object on the disc