| <!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 requestSessionOptions = ['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 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.7419161200523376, 0.6434604525566101, -0.1884651929140091, 0, -0.1884651929140091, -0.06961867958307266, -0.9796091318130493, 0, -0.6434604525566101, 0.7623069882392883, 0.06961867958307266, 0, -4, 4, 9, 1]; |
| const EXPECTED_GRIP_MATRIX_2 = [-0.6434604525566101, 0.06961867958307266, -0.7623069882392883, 0, 0.7419161200523376, -0.1884651929140091, -0.6434604525566101, 0, -0.1884651929140091, -0.9796091318130493, 0.06961867958307266, 0, 4.118846416473389, 8.01339340209961, -5.368484020233154, 1]; |
| const EXPECTED_RAY_MATRIX_2 = [0.7419161200523376, -0.1884651929140091, -0.6434604525566101, 0, 0.6434604525566101, -0.06961867958307266, 0.7623069882392883, 0, -0.1884651929140091, -0.9796091318130493, 0.06961867958307266, 0, 2.643460512161255, 7.1730217933654785, -6.823479652404785, 1]; |
| |
| // Must have a reference space to get input poses. eye-level doesn't apply |
| // any transforms to the given matrix. |
| session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }).then( (referenceSpace) => { |
| function OnFrame(time, frame) { |
| let source = session.getInputSources()[0]; |
| |
| function CheckState(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(EXPECTED_VIEW_MATRIX_1, EXPECTED_GRIP_MATRIX_1, EXPECTED_RAY_MATRIX_1); |
| |
| const new_position = { |
| x : 10, |
| y : -3, |
| z : 5 |
| }; |
| |
| const degrees_45 = Math.PI / 4; |
| const rotation = Math.sin(degrees_45 / 2); |
| const new_orientation = { |
| x : rotation, |
| y : rotation * -1, |
| z : rotation * 3, |
| w : Math.cos(degrees_45 / 2) |
| }; |
| |
| referenceSpace.originOffset = new XRRigidTransform(new_position, new_orientation); |
| CheckState(EXPECTED_VIEW_MATRIX_2, EXPECTED_GRIP_MATRIX_2, EXPECTED_RAY_MATRIX_2); |
| resolve(); |
| } |
| |
| // Can only request input poses in an xr frame. |
| session.requestAnimationFrame(OnFrame); |
| }); |
| }); |
| |
| xr_session_promise_test( |
| testFunction, fakeDeviceInitParams, requestSessionOptions, testName); |
| |
| </script> |