blob: 3d61acdc19a4371d6f64db282f31b900d2526aef [file] [log] [blame]
<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
<script>
// Can't go in external WPT tests because this test uses MockXRInputSource which
// is not available there.
let testName = "Updating XRReferenceSpace origin offset updates view and input matrices.";
let fakeDeviceInitParams = { supportsImmersive: true };
let requestSessionModes = ['immersive-vr'];
let testFunction =
(session, t, fakeDeviceController) => new Promise((resolve) => {
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
// Need to have a valid pose or input events don't process.
const VIEW_MATRIX_WITH_ROTATION = [
1, 0, 0, 0, // 1st col
0, 0, 1, 0, // 2nd col
0, -1, 0, 0, // 3rd col
4, 3, 2, 1 // 4th col
];
const GRIP_MATRIX_WITH_ROTATION = [
0, 0, -1, 0, // 1st col
0, 1, 0, 0, // 2nd col
1, 0, 0, 0, // 3rd col
1, 2, 3, 1 // 4th col
];
const POINTER_OFFSET_WITH_ROTATION = [
0, 1, 0, 0, // 1st col
-1, 0, 0, 0, // 2nd col
0, 0, 1, 0, // 3rd col
2, 0, 1, 1 // 4th col
]
fakeDeviceController.setXRPresentationFrameData(VALID_POSE_MATRIX, [{
eye:"left",
projectionMatrix: VALID_PROJECTION_MATRIX,
viewMatrix: VIEW_MATRIX_WITH_ROTATION
}, {
eye:"right",
projectionMatrix: VALID_PROJECTION_MATRIX,
viewMatrix: VIEW_MATRIX_WITH_ROTATION
}]);
let input_source = new MockXRInputSource();
input_source.targetRayMode = "tracked-pointer";
input_source.handedness = "right";
input_source.grip = GRIP_MATRIX_WITH_ROTATION;
input_source.pointerOffset = POINTER_OFFSET_WITH_ROTATION;
fakeDeviceController.addInputSource(input_source);
const RADIANS_90D = Math.PI / 2;
const EXPECTED_VIEW_MATRIX_1 = [0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, -1, -1, -1, 1];
const EXPECTED_GRIP_MATRIX_1 = [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 2, 3, 1];
const EXPECTED_RAY_MATRIX_1 = [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 2, 1, 1];
const EXPECTED_VIEW_MATRIX_2 = [0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, -4, 4, 9, 1];
const EXPECTED_GRIP_MATRIX_2 = [0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, -9, -2, -5, 1];
const EXPECTED_RAY_MATRIX_2 = [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, -8, -4, -5, 1];
const EXPECTED_VIEW_MATRIX_3 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -4, 6, 14, 1];
const EXPECTED_GRIP_MATRIX_3 = [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 5, -4, -14, 1];
const EXPECTED_RAY_MATRIX_3 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 5, -6, -13, 1];
// Must have a reference space to get input poses. eye-level doesn't apply
// any transforms to the given matrix.
session.requestReferenceSpace('local').then( (referenceSpace) => {
function OnFrame(time, frame) {
let source = session.inputSources[0];
function CheckState(referenceSpace, expected_view_matrix, expected_grip_matrix, expected_ray_matrix) {
let pose = frame.getViewerPose(referenceSpace);
let grip_pose = frame.getPose(source.gripSpace, referenceSpace);
let input_pose = frame.getPose(source.targetRaySpace, referenceSpace);
let view_matrix = pose.views[0].transform.inverse.matrix;
let grip_matrix = grip_pose.transform.matrix;
let ray_matrix = input_pose.transform.matrix;
assert_matrices_approx_equal(view_matrix, expected_view_matrix);
assert_matrices_approx_equal(grip_matrix, expected_grip_matrix);
assert_matrices_approx_equal(ray_matrix, expected_ray_matrix);
}
CheckState(referenceSpace, EXPECTED_VIEW_MATRIX_1, EXPECTED_GRIP_MATRIX_1, EXPECTED_RAY_MATRIX_1);
const new_position1 = {
x: 10,
y: -3,
z: 5,
};
const new_orientation1 = {
x: Math.sin(RADIANS_90D / 2),
y: 0,
z: 0,
w: Math.cos(RADIANS_90D / 2),
};
referenceSpace = referenceSpace.getOffsetReferenceSpace(new XRRigidTransform(new_position1, new_orientation1));
CheckState(referenceSpace, EXPECTED_VIEW_MATRIX_2, EXPECTED_GRIP_MATRIX_2, EXPECTED_RAY_MATRIX_2);
const new_position2 = {
x: 5,
y: 2,
z: 0,
};
const new_orientation2 = {
x: 0,
y: Math.sin(RADIANS_90D / 2),
z: 0,
w: Math.cos(RADIANS_90D / 2),
};
referenceSpace = referenceSpace.getOffsetReferenceSpace(new XRRigidTransform(new_position2, new_orientation2));
CheckState(referenceSpace, EXPECTED_VIEW_MATRIX_3, EXPECTED_GRIP_MATRIX_3, EXPECTED_RAY_MATRIX_3);
resolve();
}
// Can only request input poses in an xr frame.
session.requestAnimationFrame(OnFrame);
});
});
xr_session_promise_test(
testFunction, fakeDeviceInitParams, requestSessionModes, testName);
</script>