<!--
Tests that AR hit test results are available in rAF as soon as hit test source is available.
-->
<html>
<head>
<link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css">
</head>
<body>
<canvas id="webgl-canvas"></canvas>
<script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script>
<script src="../resources/webxr_e2e.js"></script>
<script>var shouldAutoCreateNonImmersiveSession = false;</script>
<script src="../resources/webxr_boilerplate.js"></script>
<script>
const TestState = Object.freeze({
"Initial": 0,
"RequestHitTestSource": 1,
"HitTestSourceRequested": 2,
"HitTestSourceAvailable": 3, // hitTestSource variable is guaranteed to be non-null in this state
"Done": 4,
});
let testState = null;
let hitTestSource = null;
function stepStartHitTesting() {
const sessionInfo = sessionInfos[sessionTypes.AR];
const referenceSpace = sessionInfo.currentRefSpace;
testState = TestState.Initial;
// There is no way we can guarantee that the recording starts with a plane detected - the
// recording only contains sensors stream and camera images, not the ARCore session state
// itself. ARCore should work in exactly the same way as if it is a brand new session, so
// it will go through "camera not tracking" state at the beginning, on to detecting some
// feature points, and then to actually finding the plane. Given that, we should allow
// for retry logic in the test - the initial hit tests may return empty results until
// ARCore detects a plane.
// Since we try every frame and we currently run at 30FPS, it should mean we'll retry for
// 5 seconds.
let retries_left = 30 * 5;
onARFrameCallback = (session, frame) => {
console.log('Got AR frame, test state: ' + testState);
switch(testState) {
case TestState.Initial: {
const pose = frame.getViewerPose(referenceSpace);
if(!pose || pose.emulatedPosition) {
// Wait for session to stabilize.
return;
}
testState = TestState.RequestHitTestSource;
return;
}
case TestState.RequestHitTestSource: {
// Try to create a hit test source from within a frame.
console.log('Requesting hit test source');
sessionInfo.currentSession.requestHitTestSource({
space: referenceSpace,
offsetRay: new XRRay()
}).then((hts) => {
console.log('Got hit test source');
hitTestSource = hts;
testState = TestState.HitTestSourceAvailable;
}).catch((err) => {
assert_unreached("XRSession.requestHitTestSource() promise rejected.");
testState = TestState.Done;
});
testState = TestState.HitTestSourceRequested;
return;
}
case TestState.HitTestSourceAvailable: {
const results = frame.getHitTestResults(hitTestSource);
if(results.length) {
testState = TestState.Done;
done();
} else {
--retries_left;
if(retries_left > 0) {
// Retry.
testState = TestState.RequestHitTestSource;
} else {
assert_unreached("Hit test results were not available right after the hit test source was created.");
testState = TestState.Done;
}
}
// Irrespective of the results, we won't need this hit test source anymore.
hitTestSource.cancel();
hitTestSource = null;
return;
}
default:
return;
}
};
}
</script>
</body>
</html>