| <!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. |
| const testName = "Updating XRBoundedReferenceSpace origin offset updates view, input matrices, and bounds geometry."; |
| const fakeDeviceInitParams = { supportsImmersive: true }; |
| const requestSessionModes = ['immersive-vr']; |
| |
| function testFunction(session, t, fakeDeviceController) { |
| // Session must have a baseLayer or frame requests will be ignored. |
| session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) }); |
| |
| const INITIAL_VIEW_MATRIX = [ |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 0, 0, 1, 0, |
| 1, 2, 3, 1, |
| ]; |
| const INITIAL_GRIP_MATRIX = [ |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 0, 0, 1, 0, |
| 1, 2, 3, 1, |
| ]; |
| const LOCAL_POINTER_OFFSET = [ |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 0, 0, 1, 0, |
| 0.01, 0.02, 0.03, 1, |
| ]; |
| |
| const STAGE_TRANSFORM = [ |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 0, 0, 1, 0, |
| 0.1, 0.2, 0.3, 1, |
| ]; |
| |
| fakeDeviceController.setStageTransform(STAGE_TRANSFORM); |
| fakeDeviceController.setStageSize(2.0, 3.0); |
| fakeDeviceController.setXRPresentationFrameData(IDENTITY_MATRIX, [{ |
| eye:"left", |
| projectionMatrix: VALID_PROJECTION_MATRIX, |
| viewMatrix: INITIAL_VIEW_MATRIX, |
| }, { |
| eye:"right", |
| projectionMatrix: VALID_PROJECTION_MATRIX, |
| viewMatrix: INITIAL_VIEW_MATRIX, |
| }]); |
| |
| let input_source = new MockXRInputSource(); |
| input_source.targetRayMode = "tracked-pointer"; |
| input_source.handedness = "right"; |
| input_source.grip = INITIAL_GRIP_MATRIX; |
| input_source.pointerOffset = LOCAL_POINTER_OFFSET; |
| fakeDeviceController.addInputSource(input_source); |
| |
| return new Promise((resolve, reject) => { |
| session.requestAnimationFrame((time, frame) => { |
| let input_source = session.inputSources[0]; |
| |
| session.requestReferenceSpace('bounded-floor').then((referenceSpace) => { |
| |
| function CheckState( |
| reference_space, |
| expected_view_matrix, |
| expected_grip_matrix, |
| expected_ray_matrix, |
| expected_bounds_geometry |
| ) { |
| let pose = frame.getViewerPose(reference_space); |
| let grip_pose = frame.getPose(input_source.gripSpace, reference_space); |
| let input_pose = frame.getPose(input_source.targetRaySpace, reference_space); |
| |
| 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(expected_view_matrix, view_matrix); |
| assert_matrices_approx_equal(expected_grip_matrix, grip_matrix); |
| assert_matrices_approx_equal(expected_ray_matrix, ray_matrix); |
| |
| assert_equals(reference_space.boundsGeometry.length, expected_bounds_geometry.length); |
| for (var i = 0; i < reference_space.boundsGeometry.length; ++i) { |
| assert_points_approx_equal(reference_space.boundsGeometry[i], expected_bounds_geometry[i]); |
| } |
| } |
| |
| const EXPECTED_VIEW_MATRIX_1 = [ |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 0, 0, 1, 0, |
| -0.1, -0.2, -0.3, 1, |
| ]; |
| const EXPECTED_GRIP_MATRIX_1 = [ |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 0, 0, 1, 0, |
| 1.1, 2.2, 3.3, 1, |
| ]; |
| const EXPECTED_RAY_MATRIX_1 = [ |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 0, 0, 1, 0, |
| 1.11, 2.22, 3.33, 1, |
| ]; |
| |
| const EXPECTED_BOUNDS_GEOMETRY_1 = [ |
| {x: 1, y: 0, z: -1.5, w: 1}, |
| {x: 1, y: 0, z: 1.5, w: 1}, |
| {x: -1, y: 0, z: 1.5, w: 1}, |
| {x: -1, y: 0, z: -1.5, w: 1}, |
| ]; |
| |
| // Check state after initialization |
| CheckState( |
| referenceSpace, |
| EXPECTED_VIEW_MATRIX_1, |
| EXPECTED_GRIP_MATRIX_1, |
| EXPECTED_RAY_MATRIX_1, |
| EXPECTED_BOUNDS_GEOMETRY_1 |
| ); |
| |
| const RADIANS_90D = Math.PI / 2; |
| |
| // Perform arbitrary transformation to reference space originOffset |
| const new_position1 = { |
| x: 10, // Translate 10 units along the x-axis |
| y: -3, // Translate -3 units along the y-axis |
| z: 5, // Translate 5 units along the z-axis |
| }; |
| const new_orientation1 = { |
| x: Math.sin(RADIANS_90D / 2), // Rotate 90 degrees around the x-axis |
| y: 0, |
| z: 0, |
| w: Math.cos(RADIANS_90D / 2), |
| }; |
| referenceSpace = referenceSpace.getOffsetReferenceSpace(new XRRigidTransform(new_position1, new_orientation1)); |
| |
| const EXPECTED_VIEW_MATRIX_2 = [ |
| 1, 0, 0, 0, |
| 0, 0, 1, 0, |
| 0, -1, 0, 0, |
| 9.9, -3.2, 4.7, 1, |
| ]; |
| const EXPECTED_GRIP_MATRIX_2 = [ |
| 1, 0, 0, 0, |
| 0, 0, -1, 0, |
| 0, 1, 0, 0, |
| -8.9, -1.7, -5.2, 1, |
| ]; |
| const EXPECTED_RAY_MATRIX_2 = [ |
| 1, 0, 0, 0, |
| 0, 0, -1, 0, |
| 0, 1, 0, 0, |
| -8.89, -1.67, -5.22, 1, |
| ]; |
| |
| const EXPECTED_BOUNDS_GEOMETRY_2 = [ |
| {x: -9, y: -6.5, z: -3, w: 1}, |
| {x: -9, y: -3.5, z: -3, w: 1}, |
| {x: -11, y: -3.5, z: -3, w: 1}, |
| {x: -11, y: -6.5, z: -3, w: 1}, |
| ]; |
| |
| // Check state after transformation |
| CheckState( |
| referenceSpace, |
| EXPECTED_VIEW_MATRIX_2, |
| EXPECTED_GRIP_MATRIX_2, |
| EXPECTED_RAY_MATRIX_2, |
| EXPECTED_BOUNDS_GEOMETRY_2 |
| ); |
| |
| // Perform arbitrary transformation to reference space originOffset |
| const new_position2 = { |
| x: 5, // Translate 5 units along the x-axis |
| y: 2, // Translate 2 units along the y-axis |
| z: 0, |
| }; |
| const new_orientation2 = { |
| x: 0, |
| y: Math.sin(RADIANS_90D / 2), // Rotate 90 degrees about the y-axis |
| z: 0, |
| w: Math.cos(RADIANS_90D / 2), |
| }; |
| referenceSpace = referenceSpace.getOffsetReferenceSpace(new XRRigidTransform(new_position2, new_orientation2)); |
| |
| const EXPECTED_VIEW_MATRIX_3 = [ |
| 0, 1, 0, 0, |
| 0, 0, 1, 0, |
| 1, 0, 0, 0, |
| 14.9, -3.2, 6.7, 1, |
| ]; |
| const EXPECTED_GRIP_MATRIX_3 = [ |
| 0, 0, 1, 0, |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 5.2, -3.7, -13.9, 1, |
| ]; |
| const EXPECTED_RAY_MATRIX_3 = [ |
| 0, 0, 1, 0, |
| 1, 0, 0, 0, |
| 0, 1, 0, 0, |
| 5.22, -3.67, -13.89, 1, |
| ]; |
| |
| const EXPECTED_BOUNDS_GEOMETRY_3 = [ |
| {x: 3, y: -8.5, z: -14, w: 1}, |
| {x: 3, y: -5.5, z: -14, w: 1}, |
| {x: 3, y: -5.5, z: -16, w: 1}, |
| {x: 3, y: -8.5, z: -16, w: 1}, |
| ]; |
| |
| // Check state after transformation |
| CheckState( |
| referenceSpace, |
| EXPECTED_VIEW_MATRIX_3, |
| EXPECTED_GRIP_MATRIX_3, |
| EXPECTED_RAY_MATRIX_3, |
| EXPECTED_BOUNDS_GEOMETRY_3 |
| ); |
| |
| resolve(); |
| }); |
| }); |
| }); |
| }; |
| |
| xr_session_promise_test(testFunction, fakeDeviceInitParams, requestSessionModes, testName); |
| |
| </script> |