-
Notifications
You must be signed in to change notification settings - Fork 231
Expand file tree
/
Copy pathar.js
More file actions
106 lines (88 loc) · 3.18 KB
/
Copy pathar.js
File metadata and controls
106 lines (88 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
export const closeOverlay = document.createElement("div");
closeOverlay.style.display = "none";
document.body.appendChild(closeOverlay);
let onClose = () => console.log("onClose not set");
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("width", 38);
svg.setAttribute("height", 38);
svg.style.position = "absolute";
svg.style.right = "20px";
svg.style.top = "20px";
svg.addEventListener("click", () => onClose());
closeOverlay.appendChild(svg);
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute("d", "M 12,12 L 28,28 M 28,12 12,28");
path.setAttribute("stroke", "#fff");
path.setAttribute("stroke-width", 2);
svg.appendChild(path);
function setOnClose(fn) {
onClose = fn;
}
function showCloseOverlay(value) {
closeOverlay.style.display = value ? "" : "none";
}
let lastXrTransform = null;
let lastWidth = null;
let lastHeight = null;
export function createController(renderer, scene, onSelect) {
const arController = renderer.xr.getController(0);
arController.addEventListener("select", () => onSelect(lastXrTransform));
scene.add(arController);
return arController;
}
export async function start(renderer, renderFn, onStop) {
if (renderer.xr.getSession() !== null) {
return;
}
renderer.xr.enabled = true;
const sessionInit = {
optionalFeatures: ["dom-overlay", "hit-test"],
domOverlay: { root: closeOverlay }
};
showCloseOverlay(true);
const session = await navigator.xr.requestSession("immersive-ar", sessionInit);
renderer.xr.setReferenceSpaceType("local");
renderer.xr.setSession(session);
const { x, y } = renderer.getSize();
lastWidth = x;
lastHeight = y;
renderer.setSize(window.innerWidth, window.innerHeight);
lastXrTransform = null;
renderer.setAnimationLoop(
await extractHitTransform(
renderer,
renderFn,
(xrTransform) => { lastXrTransform = xrTransform; }));
setOnClose(onStop);
}
export function stop(renderer) {
if (renderer.xr.getSession() === null) {
return;
}
renderer.xr.getSession().end();
renderer.xr.setSession(null);
lastXrTransform = null;
showCloseOverlay(false);
renderer.setAnimationLoop(null);
renderer.setSize(lastWidth, lastHeight);
}
async function extractHitTransform(renderer, renderFn, onXrTransformChange) {
const session = renderer.xr.getSession();
const referenceSpace = await session.requestReferenceSpace("viewer");
const hitTestSource = await session.requestHitTestSource({ space: referenceSpace });
return (time, frame) => {
if (frame) {
// based on https://threejs.org/examples/webxr_ar_hittest.html
const referenceSpace = renderer.xr.getReferenceSpace();
if (hitTestSource) {
const hitTestResults = frame.getHitTestResults(hitTestSource);
if (hitTestResults.length) {
const hit = hitTestResults[0];
const pose = hit.getPose(referenceSpace);
onXrTransformChange(pose.transform);
}
}
}
renderFn(time, frame);
};
}