Skip to content

Commit e5fb75c

Browse files
committed
Basic WebXR Hit-Test - Viewer center only
1 parent c29abe5 commit e5fb75c

File tree

14 files changed

+779
-19
lines changed

14 files changed

+779
-19
lines changed

Assets/WebGLTemplates/WebXR/webxr.js

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
this.controllerB = new XRControllerData();
1313
this.handLeft = new XRHandData();
1414
this.handRight = new XRHandData();
15+
this.viewerHitTestPose = new XRHitPoseData();
1516
this.frameNumber = 0;
1617
this.xrData = null;
1718
}
@@ -60,9 +61,18 @@
6061
this.radius = 0;
6162
}
6263

64+
function XRHitPoseData() {
65+
this.frame = 0;
66+
this.available = 0;
67+
this.position = [0, 0, 0];
68+
this.rotation = [0, 0, 0, 1];
69+
}
70+
6371
function XRManager() {
6472
this.xrSession = null;
6573
this.inlineSession = null;
74+
this.viewerSpace = null;
75+
this.viewerHitTestSource = null;
6676
this.xrData = new XRData();
6777
this.canvas = null;
6878
this.ctx = null;
@@ -108,12 +118,15 @@
108118
var onToggleAr = this.toggleAr.bind(this);
109119
var onToggleVr = this.toggleVr.bind(this);
110120
var onUnityLoaded = this.unityLoaded.bind(this);
121+
var onToggleHitTest = this.toggleHitTest.bind(this);
111122

112123
// dispatched by index.html
113124
document.addEventListener('UnityLoaded', onUnityLoaded, false);
114125

115126
document.addEventListener('toggleAR', onToggleAr, false);
116127
document.addEventListener('toggleVR', onToggleVr, false);
128+
129+
document.addEventListener('toggleHitTest', onToggleHitTest, false);
117130
}
118131

119132
XRManager.prototype.onRequestARSession = function () {
@@ -134,7 +147,7 @@
134147
window.requestAnimationFrame( tempRender );
135148
navigator.xr.requestSession('immersive-ar', {
136149
requiredFeatures: ['local-floor'], // TODO: Get this value from Unity
137-
optionalFeatures: ['dom-overlay', 'hand-tracking'],
150+
optionalFeatures: ['dom-overlay', 'hand-tracking', 'hit-test'],
138151
domOverlay: {root: this.canvas.parentElement}
139152
}).then(async (session) => {
140153
this.waitingHandheldARHack = false;
@@ -181,6 +194,11 @@
181194
xrSessionEvent.session.removeEventListener('squeezestart', this.onInputEvent);
182195
xrSessionEvent.session.removeEventListener('squeezeend', this.onInputEvent);
183196
}
197+
198+
if (this.viewerHitTestSource) {
199+
this.viewerHitTestSource.cancel();
200+
this.viewerHitTestSource = null;
201+
}
184202

185203
this.gameInstance.Module.WebXR.OnEndXR();
186204
this.didNotifyUnity = false;
@@ -262,6 +280,26 @@
262280
}
263281
}
264282

283+
XRManager.prototype.toggleHitTest = function () {
284+
if (!this.gameInstance)
285+
{
286+
return;
287+
}
288+
if (this.xrSession && this.xrSession.isInSession && this.xrSession.isAR) {
289+
if (this.viewerHitTestSource) {
290+
this.viewerHitTestSource.cancel();
291+
this.viewerHitTestSource = null;
292+
} else {
293+
this.xrSession.requestReferenceSpace('viewer').then((refSpace) => {
294+
this.viewerSpace = refSpace;
295+
this.xrSession.requestHitTestSource({space: this.viewerSpace}).then((hitTestSource) => {
296+
this.viewerHitTestSource = hitTestSource;
297+
});
298+
});
299+
}
300+
}
301+
}
302+
265303
XRManager.prototype.setGameInstance = function (gameInstance) {
266304
if (!this.gameInstance) {
267305
this.gameInstance = gameInstance;
@@ -580,16 +618,35 @@
580618
}
581619

582620
this.getXRControllersData(frame, session.inputSources, session.refSpace, xrData);
621+
622+
if (session.isAR && this.viewerHitTestSource) {
623+
xrData.viewerHitTestPose.frame = xrData.frameNumber;
624+
let viewerHitTestResults = frame.getHitTestResults(this.viewerHitTestSource);
625+
if (viewerHitTestResults.length > 0) {
626+
let hitTestPose = viewerHitTestResults[0].getPose(session.refSpace);
627+
xrData.viewerHitTestPose.available = 1;
628+
xrData.viewerHitTestPose.position[0] = hitTestPose.transform.position.x;
629+
xrData.viewerHitTestPose.position[1] = hitTestPose.transform.position.y;
630+
xrData.viewerHitTestPose.position[2] = -hitTestPose.transform.position.z;
631+
xrData.viewerHitTestPose.rotation[0] = -hitTestPose.transform.orientation.x;
632+
xrData.viewerHitTestPose.rotation[1] = -hitTestPose.transform.orientation.y;
633+
xrData.viewerHitTestPose.rotation[2] = hitTestPose.transform.orientation.z;
634+
xrData.viewerHitTestPose.rotation[3] = hitTestPose.transform.orientation.w;
635+
} else {
636+
xrData.viewerHitTestPose.available = 0;
637+
}
638+
document.dispatchEvent(new CustomEvent('XRViewerHitTestPose', { detail: {
639+
viewerHitTestPose: xrData.viewerHitTestPose
640+
}}));
641+
}
583642

584643
// Dispatch event with headset data to be handled in webxr.jslib
585644
document.dispatchEvent(new CustomEvent('XRData', { detail: {
586645
leftProjectionMatrix: xrData.leftProjectionMatrix,
587646
rightProjectionMatrix: xrData.rightProjectionMatrix,
588647
leftViewMatrix: xrData.leftViewMatrix,
589648
rightViewMatrix: xrData.rightViewMatrix,
590-
sitStandMatrix: xrData.sitStandMatrix,
591-
controllerA: xrData.controllerA,
592-
controllerB: xrData.controllerB
649+
sitStandMatrix: xrData.sitStandMatrix
593650
}}));
594651

595652
document.dispatchEvent(new CustomEvent('XRControllersData', { detail: {

Assets/WebGLTemplates/WebXRFullView/webxr.js

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
this.controllerB = new XRControllerData();
1313
this.handLeft = new XRHandData();
1414
this.handRight = new XRHandData();
15+
this.viewerHitTestPose = new XRHitPoseData();
1516
this.frameNumber = 0;
1617
this.xrData = null;
1718
}
@@ -60,9 +61,18 @@
6061
this.radius = 0;
6162
}
6263

64+
function XRHitPoseData() {
65+
this.frame = 0;
66+
this.available = 0;
67+
this.position = [0, 0, 0];
68+
this.rotation = [0, 0, 0, 1];
69+
}
70+
6371
function XRManager() {
6472
this.xrSession = null;
6573
this.inlineSession = null;
74+
this.viewerSpace = null;
75+
this.viewerHitTestSource = null;
6676
this.xrData = new XRData();
6777
this.canvas = null;
6878
this.ctx = null;
@@ -108,12 +118,15 @@
108118
var onToggleAr = this.toggleAr.bind(this);
109119
var onToggleVr = this.toggleVr.bind(this);
110120
var onUnityLoaded = this.unityLoaded.bind(this);
121+
var onToggleHitTest = this.toggleHitTest.bind(this);
111122

112123
// dispatched by index.html
113124
document.addEventListener('UnityLoaded', onUnityLoaded, false);
114125

115126
document.addEventListener('toggleAR', onToggleAr, false);
116127
document.addEventListener('toggleVR', onToggleVr, false);
128+
129+
document.addEventListener('toggleHitTest', onToggleHitTest, false);
117130
}
118131

119132
XRManager.prototype.onRequestARSession = function () {
@@ -134,7 +147,7 @@
134147
window.requestAnimationFrame( tempRender );
135148
navigator.xr.requestSession('immersive-ar', {
136149
requiredFeatures: ['local-floor'], // TODO: Get this value from Unity
137-
optionalFeatures: ['dom-overlay', 'hand-tracking'],
150+
optionalFeatures: ['dom-overlay', 'hand-tracking', 'hit-test'],
138151
domOverlay: {root: this.canvas.parentElement}
139152
}).then(async (session) => {
140153
this.waitingHandheldARHack = false;
@@ -181,6 +194,11 @@
181194
xrSessionEvent.session.removeEventListener('squeezestart', this.onInputEvent);
182195
xrSessionEvent.session.removeEventListener('squeezeend', this.onInputEvent);
183196
}
197+
198+
if (this.viewerHitTestSource) {
199+
this.viewerHitTestSource.cancel();
200+
this.viewerHitTestSource = null;
201+
}
184202

185203
this.gameInstance.Module.WebXR.OnEndXR();
186204
this.didNotifyUnity = false;
@@ -262,6 +280,26 @@
262280
}
263281
}
264282

283+
XRManager.prototype.toggleHitTest = function () {
284+
if (!this.gameInstance)
285+
{
286+
return;
287+
}
288+
if (this.xrSession && this.xrSession.isInSession && this.xrSession.isAR) {
289+
if (this.viewerHitTestSource) {
290+
this.viewerHitTestSource.cancel();
291+
this.viewerHitTestSource = null;
292+
} else {
293+
this.xrSession.requestReferenceSpace('viewer').then((refSpace) => {
294+
this.viewerSpace = refSpace;
295+
this.xrSession.requestHitTestSource({space: this.viewerSpace}).then((hitTestSource) => {
296+
this.viewerHitTestSource = hitTestSource;
297+
});
298+
});
299+
}
300+
}
301+
}
302+
265303
XRManager.prototype.setGameInstance = function (gameInstance) {
266304
if (!this.gameInstance) {
267305
this.gameInstance = gameInstance;
@@ -580,16 +618,35 @@
580618
}
581619

582620
this.getXRControllersData(frame, session.inputSources, session.refSpace, xrData);
621+
622+
if (session.isAR && this.viewerHitTestSource) {
623+
xrData.viewerHitTestPose.frame = xrData.frameNumber;
624+
let viewerHitTestResults = frame.getHitTestResults(this.viewerHitTestSource);
625+
if (viewerHitTestResults.length > 0) {
626+
let hitTestPose = viewerHitTestResults[0].getPose(session.refSpace);
627+
xrData.viewerHitTestPose.available = 1;
628+
xrData.viewerHitTestPose.position[0] = hitTestPose.transform.position.x;
629+
xrData.viewerHitTestPose.position[1] = hitTestPose.transform.position.y;
630+
xrData.viewerHitTestPose.position[2] = -hitTestPose.transform.position.z;
631+
xrData.viewerHitTestPose.rotation[0] = -hitTestPose.transform.orientation.x;
632+
xrData.viewerHitTestPose.rotation[1] = -hitTestPose.transform.orientation.y;
633+
xrData.viewerHitTestPose.rotation[2] = hitTestPose.transform.orientation.z;
634+
xrData.viewerHitTestPose.rotation[3] = hitTestPose.transform.orientation.w;
635+
} else {
636+
xrData.viewerHitTestPose.available = 0;
637+
}
638+
document.dispatchEvent(new CustomEvent('XRViewerHitTestPose', { detail: {
639+
viewerHitTestPose: xrData.viewerHitTestPose
640+
}}));
641+
}
583642

584643
// Dispatch event with headset data to be handled in webxr.jslib
585644
document.dispatchEvent(new CustomEvent('XRData', { detail: {
586645
leftProjectionMatrix: xrData.leftProjectionMatrix,
587646
rightProjectionMatrix: xrData.rightProjectionMatrix,
588647
leftViewMatrix: xrData.leftViewMatrix,
589648
rightViewMatrix: xrData.rightViewMatrix,
590-
sitStandMatrix: xrData.sitStandMatrix,
591-
controllerA: xrData.controllerA,
592-
controllerB: xrData.controllerB
649+
sitStandMatrix: xrData.sitStandMatrix
593650
}}));
594651

595652
document.dispatchEvent(new CustomEvent('XRControllersData', { detail: {

Assets/WebXR/Plugins/WebGL/webxr.jslib

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ mergeInto(LibraryManager.library, {
1313
HandsArray = new Float32Array(buffer, byteOffset, length);
1414
},
1515

16+
InitViewerHitTestPoseArray: function(byteOffset, length) {
17+
ViewerHitTestPoseArray = new Float32Array(buffer, byteOffset, length);
18+
},
19+
20+
ToggleViewerHitTest: function() {
21+
document.dispatchEvent(new CustomEvent('toggleHitTest', {}));
22+
},
23+
1624
ListenWebXRData: function() {
1725
// Listen for headset updates from webxr.jspre and load data into shared Array which we pick up in Unity.
1826
document.addEventListener('XRData', function(evt) {
@@ -75,5 +83,18 @@ mergeInto(LibraryManager.library, {
7583
}
7684
});
7785
});
86+
document.addEventListener('XRViewerHitTestPose', function(evt) {
87+
var data = evt.detail;
88+
var index = 0;
89+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.frame;
90+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.available;
91+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.position[0];
92+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.position[1];
93+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.position[2];
94+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.rotation[0];
95+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.rotation[1];
96+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.rotation[2];
97+
ViewerHitTestPoseArray[index++] = data.viewerHitTestPose.rotation[3];
98+
});
7899
}
79100
});

Assets/WebXR/Samples/Desert/Prefabs/WebXRCameraSet.prefab

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,11 @@ MonoBehaviour:
734734
m_Script: {fileID: 11500000, guid: 9f6b70cf8d6f4f94f931699457ea09a0, type: 3}
735735
m_Name:
736736
m_EditorClassIdentifier:
737+
cameraMain: {fileID: 20092747195267750}
738+
cameraL: {fileID: 20930522213222284}
739+
cameraR: {fileID: 20572450475250664}
740+
cameraARL: {fileID: 8992034749185188121}
741+
cameraARR: {fileID: 3431978019681743018}
737742
--- !u!81 &81178167226133646
738743
AudioListener:
739744
m_ObjectHideFlags: 0

0 commit comments

Comments
 (0)