@@ -75,20 +75,28 @@
|
|
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
|
}
|
@@ -989,10 +989,11 @@
|
|
989
989
|
// apply the clearflags at the beginning of the next frame
|
990
990
|
this.context.pre_update_oneshot_callbacks.push(() => {
|
991
991
|
this.context.mainCameraComponent?.applyClearFlags()
|
992
|
+
this.context.mainCameraComponent?.applyClippingPlane();
|
992
993
|
});
|
993
994
|
|
994
995
|
invokeXRSessionEnd({ session: this });
|
995
|
-
|
996
|
+
|
996
997
|
for (const listener of NeedleXRSession._xrEndListeners) {
|
997
998
|
listener({ xr: this });
|
998
999
|
}
|
@@ -7,7 +7,7 @@
|
|
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 @@
|
|
213
213
|
|
214
214
|
// in pass through mode we want to place the scene using an XR controller
|
215
215
|
let controllersDidHit = false;
|
216
|
-
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
336
335
|
}
|
337
336
|
|
338
337
|
if (this.autoPlace) {
|
339
|
-
|
340
|
-
this.
|
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 @@
|
|
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 @@
|
|
257
258
|
continue;
|
258
259
|
}
|
259
260
|
|
260
|
-
const
|
261
|
-
|
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
|