From ce66ef1e7bf20d3f3dfd4f8d037846bd482c420c Mon Sep 17 00:00:00 2001 From: Tom Birdsong Date: Wed, 1 Dec 2021 12:04:14 -0500 Subject: [PATCH 1/3] feat(XR): Remap OpenVR gamepad for OpenXR gamepad support --- .../InteractorStyleTrackballCamera/index.js | 13 +++-- .../Core/RenderWindowInteractor/Constants.js | 14 ++++- .../Core/RenderWindowInteractor/index.js | 53 ++++++++++--------- .../Rendering/OpenGL/RenderWindow/index.js | 4 ++ 4 files changed, 55 insertions(+), 29 deletions(-) diff --git a/Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js b/Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js index c07be922153..b918e2fc6c6 100644 --- a/Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js +++ b/Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js @@ -58,7 +58,7 @@ function vtkInteractorStyleTrackballCamera(publicAPI, model) { ed && ed.pressed && ed.device === Device.RightController && - ed.input === Input.TrackPad + (ed.input === Input.Trigger || ed.input === Input.TrackPad) ) { publicAPI.startCameraPose(); return; @@ -67,7 +67,7 @@ function vtkInteractorStyleTrackballCamera(publicAPI, model) { ed && !ed.pressed && ed.device === Device.RightController && - ed.input === Input.TrackPad && + (ed.input === Input.Trigger || ed.input === Input.TrackPad) && model.state === States.IS_CAMERA_POSE ) { publicAPI.endCameraPose(); @@ -91,13 +91,18 @@ function vtkInteractorStyleTrackballCamera(publicAPI, model) { const oldTrans = camera.getPhysicalTranslation(); // look at the y axis to determine how fast / what direction to move - const speed = ed.gamepad.axes[1]; + const speed = 0.5; // ed.gamepad.axes[1]; // 0.05 meters / frame movement const pscale = speed * 0.05 * camera.getPhysicalScale(); // convert orientation to world coordinate direction - const dir = camera.physicalOrientationToWorldDirection(ed.orientation); + const dir = camera.physicalOrientationToWorldDirection([ + ed.orientation.x, + ed.orientation.y, + ed.orientation.z, + ed.orientation.w, + ]); camera.setPhysicalTranslation( oldTrans[0] + dir[0] * pscale, diff --git a/Sources/Rendering/Core/RenderWindowInteractor/Constants.js b/Sources/Rendering/Core/RenderWindowInteractor/Constants.js index 79a4de2fd8a..546bdc42522 100644 --- a/Sources/Rendering/Core/RenderWindowInteractor/Constants.js +++ b/Sources/Rendering/Core/RenderWindowInteractor/Constants.js @@ -9,10 +9,22 @@ export const Input = { Trigger: 1, TrackPad: 2, Grip: 3, - ApplicationMenu: 4, + Thumbstick: 4, + A: 5, + B: 6, + ApplicationMenu: 7, // Not exposed in WebXR API +}; + +export const Axis = { + Unknown: 0, + TouchpadX: 1, + TouchpadY: 2, + ThumbstickX: 3, + ThumbstickY: 4, }; export default { Device, Input, + Axis, }; diff --git a/Sources/Rendering/Core/RenderWindowInteractor/index.js b/Sources/Rendering/Core/RenderWindowInteractor/index.js index b5ec257e2f8..26581e9ec9c 100644 --- a/Sources/Rendering/Core/RenderWindowInteractor/index.js +++ b/Sources/Rendering/Core/RenderWindowInteractor/index.js @@ -12,11 +12,13 @@ const { vtkWarningMacro, vtkErrorMacro, normalizeWheel, vtkOnceErrorMacro } = // ---------------------------------------------------------------------------- const deviceInputMap = { - 'OpenVR Gamepad': [ - Input.TrackPad, + 'xr-standard': [ Input.Trigger, Input.Grip, - Input.ApplicationMenu, + Input.TrackPad, + Input.Thumbstick, + Input.A, + Input.B, ], }; @@ -415,55 +417,58 @@ function vtkRenderWindowInteractor(publicAPI, model) { } }; - publicAPI.updateGamepads = (displayId) => { - const gamepads = navigator.getGamepads(); - + publicAPI.updateXRGamepads = (xrSession, xrFrame, xrRefSpace) => { // watch for when buttons change state and fire events - for (let i = 0; i < gamepads.length; ++i) { - const gp = gamepads[i]; - if (gp && gp.displayId === displayId) { + xrSession.inputSources.forEach((inputSource) => { + const pose = xrFrame.getPose(inputSource.gripSpace, xrRefSpace); + const gp = inputSource.gamepad; + const hand = inputSource.handedness; + if (gp) { if (!(gp.index in model.lastGamepadValues)) { - model.lastGamepadValues[gp.index] = { buttons: {} }; + model.lastGamepadValues[gp.index] = { + left: { buttons: {} }, + right: { buttons: {} }, + }; } for (let b = 0; b < gp.buttons.length; ++b) { - if (!(b in model.lastGamepadValues[gp.index].buttons)) { - model.lastGamepadValues[gp.index].buttons[b] = false; + if (!(b in model.lastGamepadValues[gp.index][hand].buttons)) { + model.lastGamepadValues[gp.index][hand].buttons[b] = false; } if ( - model.lastGamepadValues[gp.index].buttons[b] !== + model.lastGamepadValues[gp.index][hand].buttons[b] !== gp.buttons[b].pressed ) { publicAPI.button3DEvent({ gamepad: gp, - position: gp.pose.position, - orientation: gp.pose.orientation, + position: pose.transform.position, + orientation: pose.transform.orientation, pressed: gp.buttons[b].pressed, device: - gp.hand === 'left' + inputSource.handedness === 'left' ? Device.LeftController : Device.RightController, input: - deviceInputMap[gp.id] && deviceInputMap[gp.id][b] - ? deviceInputMap[gp.id][b] + deviceInputMap[gp.mapping] && deviceInputMap[gp.mapping][b] + ? deviceInputMap[gp.mapping][b] : Input.Trigger, }); - model.lastGamepadValues[gp.index].buttons[b] = + model.lastGamepadValues[gp.index][hand].buttons[b] = gp.buttons[b].pressed; } - if (model.lastGamepadValues[gp.index].buttons[b]) { + if (model.lastGamepadValues[gp.index][hand].buttons[b]) { publicAPI.move3DEvent({ gamepad: gp, - position: gp.pose.position, - orientation: gp.pose.orientation, + position: pose.transform.position, + orientation: pose.transform.orientation, device: - gp.hand === 'left' + inputSource.handedness === 'left' ? Device.LeftController : Device.RightController, }); } } } - } + }); }; publicAPI.handleMouseMove = (event) => { diff --git a/Sources/Rendering/OpenGL/RenderWindow/index.js b/Sources/Rendering/OpenGL/RenderWindow/index.js index ed6d87ed230..36897d8dc2f 100644 --- a/Sources/Rendering/OpenGL/RenderWindow/index.js +++ b/Sources/Rendering/OpenGL/RenderWindow/index.js @@ -354,6 +354,10 @@ function vtkOpenGLRenderWindow(publicAPI, model) { publicAPI.xrRender = async (t, frame) => { const xrSession = frame.session; + model.renderable + .getInteractor() + .updateXRGamepads(xrSession, frame, model.xrReferenceSpace); + model.xrSceneFrame = model.xrSession.requestAnimationFrame( publicAPI.xrRender ); From 765259f033cede42a3c0ee9e5e1777e1f07734ed Mon Sep 17 00:00:00 2001 From: Tom Birdsong Date: Mon, 13 Dec 2021 07:45:40 -0500 Subject: [PATCH 2/3] test(XR): WIP snap rotation --- Examples/Geometry/VR/index.js | 4 +- .../InteractorStyleTrackballCamera/index.js | 31 +++- Sources/Rendering/Core/Camera/index.js | 138 +++++++++++++++- .../Core/RenderWindowInteractor/index.js | 156 ++++++++++++------ .../Rendering/OpenGL/RenderWindow/index.js | 10 +- 5 files changed, 275 insertions(+), 64 deletions(-) diff --git a/Examples/Geometry/VR/index.js b/Examples/Geometry/VR/index.js index 332bd11401a..71164aa23be 100644 --- a/Examples/Geometry/VR/index.js +++ b/Examples/Geometry/VR/index.js @@ -36,7 +36,7 @@ const renderWindow = fullScreenRenderer.getRenderWindow(); // this // ---------------------------------------------------------------------------- -const coneSource = vtkConeSource.newInstance({ height: 100.0, radius: 50 }); +const coneSource = vtkConeSource.newInstance({ height: 1.0, radius: 0.5 }); const filter = vtkCalculator.newInstance(); filter.setInputConnection(coneSource.getOutputPort()); @@ -66,7 +66,7 @@ mapper.setInputConnection(filter.getOutputPort()); const actor = vtkActor.newInstance(); actor.setMapper(mapper); -actor.setPosition(0.0, 0.0, -20.0); +actor.setPosition(0.0, 0.0, -1.0); renderer.addActor(actor); renderer.resetCamera(); diff --git a/Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js b/Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js index b918e2fc6c6..b73c78380f5 100644 --- a/Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js +++ b/Sources/Interaction/Style/InteractorStyleTrackballCamera/index.js @@ -3,6 +3,7 @@ import vtkInteractorStyle from 'vtk.js/Sources/Rendering/Core/InteractorStyle'; import vtkInteractorStyleConstants from 'vtk.js/Sources/Rendering/Core/InteractorStyle/Constants'; import * as vtkMath from 'vtk.js/Sources/Common/Core/Math'; import { + Axis, Device, Input, } from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor/Constants'; @@ -58,7 +59,7 @@ function vtkInteractorStyleTrackballCamera(publicAPI, model) { ed && ed.pressed && ed.device === Device.RightController && - (ed.input === Input.Trigger || ed.input === Input.TrackPad) + ed.input === Input.Trigger // || ed.input === Input.TrackPad) ) { publicAPI.startCameraPose(); return; @@ -67,24 +68,46 @@ function vtkInteractorStyleTrackballCamera(publicAPI, model) { ed && !ed.pressed && ed.device === Device.RightController && - (ed.input === Input.Trigger || ed.input === Input.TrackPad) && + ed.input === Input.Trigger && // || ed.input === Input.TrackPad) && model.state === States.IS_CAMERA_POSE ) { publicAPI.endCameraPose(); // return; } + if ( + ed && + ed.device === Device.RightController && + ed.input && + (ed.input === Axis.ThumbstickX || Input.TrackPad) + ) { + publicAPI.updateCameraOrientation(ed); + } + if (ed && ed.input && (ed.input === Axis.ThumbstickX || Input.TrackPad)) { + publicAPI.updateCameraOrientation(ed); + } }; publicAPI.handleMove3D = (ed) => { switch (model.state) { case States.IS_CAMERA_POSE: - publicAPI.updateCameraPose(ed); + publicAPI.updateCameraPosition(ed); break; default: } }; - publicAPI.updateCameraPose = (ed) => { + publicAPI.updateCameraOrientation = (ed) => { + // rotate the world in the direction + // of the controller + const camera = ed.pokedRenderer.getActiveCamera(); + let worldMatrix = new Float64Array(16); + camera.getWorldToPhysicalMatrix(worldMatrix); + + const angle = ed.device === Device.LeftController ? -22.5 : 22.5; + camera.applyPhysicalYaw(angle); + }; + + publicAPI.updateCameraPosition = (ed) => { // move the world in the direction of the // controller const camera = ed.pokedRenderer.getActiveCamera(); diff --git a/Sources/Rendering/Core/Camera/index.js b/Sources/Rendering/Core/Camera/index.js index 0fa32b74d3d..070058c11d0 100644 --- a/Sources/Rendering/Core/Camera/index.js +++ b/Sources/Rendering/Core/Camera/index.js @@ -397,11 +397,124 @@ function vtkCamera(publicAPI, model) { mat4.scale(result, result, tmpvec1); mat4.translate(result, result, model.physicalTranslation); + + // let rot = mat4.identity(new Float64Array(16)); + //mat4.fromRotation(rot, model.physicalYawAngle / 180 * 3.14, model.physicalViewUp); + //// mat4.invert(rot, rot); + //mat4.mul(result, rot, result); + + //let tmpRot = mat4.identity(new Float64Array(16)); + //let matInv = mat4.identity(new Float64Array(16)); + //mat4.rotateY(tmpRot, tmpRot, model.physicalYawAngle / 180 * 3.14); + //mat4.transpose(tmpRot, tmpRot); + //mat4.invert(matInv, ) + // mat4.mul(result, tmpRot, result); + }; + + publicAPI.applyPhysicalYaw = (angle) => { + model.physicalYawAngle += angle; + if (model.physicalYawAngle > 360) { + model.physicalYawAngle -= 360; + } else if (model.physicalYawAngle < 0) { + model.physicalYawAngle += 360; + } }; publicAPI.computeViewParametersFromViewMatrix = (vmat) => { // invert to get view to world - mat4.invert(tmpMatrix, vmat); + let worldToViewPos = new Float64Array(4); + let viewToWorldPos = new Float64Array(4); + let v2wMatrix = new Float64Array(16); + worldToViewPos[0] = vmat[12]; + worldToViewPos[1] = vmat[13]; + worldToViewPos[2] = vmat[14]; + worldToViewPos[3] = 1; + mat4.invert(v2wMatrix, vmat); + viewToWorldPos[0] = v2wMatrix[12]; + viewToWorldPos[1] = v2wMatrix[13]; + viewToWorldPos[2] = v2wMatrix[14]; + viewToWorldPos[3] = 1; + mat4.copy(tmpMatrix, v2wMatrix); + //console.log('View -> World'); + //console.log(v2wMatrix); + //mat4.copy(tmpMatrix, vmat); + //v[0] = tmpMatrix[12]; //tmpMatrix[12] = 0; + //tmpMatrix[13] = 0; + //tmpMatrix[14] = 0; + //mat4.invert(tmpMatrix, tmpMatrix); + + //// + //// + //// mat4.invert(tmpMatrix, tmpMatrix); + //// mat4.rotateY(tmpMatrix, tmpMatrix, model.physicalYawAngle / 180 * 3.14); + //// mat4.translate(tmpMatrix, tmpMatrix, [-v[0], -v[1], -v[2]]); + + ////// Correct center of rotation, incorrect view translation + ////mat4.invert(tmpMatrix, tmpMatrix); + ////mat4.rotateY(tmpMatrix, tmpMatrix, model.physicalYawAngle / 180 * 3.14); + + //// Correct view translation, incorrect center of rotation + //// mat4.invert(tmpMatrix, tmpMatrix);); + ////let tmp = mat4.identity(new Float64Array(16)); + ////tmpMatrix[12] = 0; + ////tmpMatrix[14] = 0; + //mat4.invert(tmpMatrix, tmpMatrix); + + let w2vTranslate = mat4.identity(new Float64Array(16)); + let rotate = mat4.identity(new Float64Array(16)); + let rotateRev = mat4.identity(new Float64Array(16)); + let w2vTranslateReverse = mat4.identity(new Float64Array(16)); + let v2wTranslate = mat4.identity(new Float64Array(16)); + let v2wTranslateReverse = mat4.identity(new Float64Array(16)); + + mat4.translate(v2wTranslate, v2wTranslate, [ + -viewToWorldPos[0], + -viewToWorldPos[1], + -viewToWorldPos[2], + ]); + mat4.rotateY(rotate, rotate, (model.physicalYawAngle / 180) * 3.14); + mat4.rotateY( + rotateRev, + rotateRev, + ((-1 * model.physicalYawAngle) / 180) * 3.14 + ); + mat4.translate(v2wTranslateReverse, v2wTranslateReverse, viewToWorldPos); + mat4.translate(w2vTranslate, w2vTranslate, [ + -worldToViewPos[0], + -worldToViewPos[1], + -worldToViewPos[2], + ]); + mat4.translate(w2vTranslateReverse, w2vTranslateReverse, worldToViewPos); + + //mat4.mul(tmpMatrix, w2vTranslate, vmat); + //mat4.mul(tmpMatrix, rotate, tmpMatrix); + //mat4.mul(tmpMatrix, w2vTranslateReverse, tmpMatrix); + //mat4.invert(tmpMatrix, tmpMatrix); + + // FIXME works post-snap? mat4.mul(v2wTranslateReverse, v2wTranslate, rotate); + // mat4.mul(v2wTranslate, v2wTranslate, rotate); + //mat4.mul(v2wTranslateReverse, v2wTranslateReverse, rotate); + mat4.mul(v2wTranslateReverse, v2wTranslate, rotate); + mat4.mul(tmpMatrix, v2wTranslateReverse, v2wMatrix); + mat4.mul(tmpMatrix, tmpMatrix, rotate); + mat4.mul(tmpMatrix, v2wTranslate, tmpMatrix); + + //mat4.rotateY(tmpMatrix, tmpMatrix, -1 * model.physicalYawAngle / 180 * 3.14); + //mat4.translate(tmpMatrix, tmpMatrix, [0, 0, 0.01 * model.physicalYawAngle]); + //mat4.translate(tmpMatrix, tmpMatrix, v); + //mat4.invert(tmpMatrix, tmpMatrix); + //// + //mat4.invert(tmpMatrix, tmpMatrix); + //tmpMatrix[12] = v[0]; + //tmpMatrix[13] = v[1]; + //tmpMatrix[14] = v[2]; + + // FIXME try pushing through the cone position at <0,0,-1> + //v[0] = 0; + //v[1] = 0; + //v[1] = -1; + //vec3.transformMat4(tmpvec1, v, tmpMatrix); + // console.log(v); // note with glmatrix operations happen in // the reverse order @@ -443,6 +556,27 @@ function vtkCamera(publicAPI, model) { // world -> view mat4.multiply(tmpMatrix, mat, tmpMatrix); + console.log('orig'); + console.log(tmpMatrix); + let rot = mat4.identity(new Float64Array(16)); + let v = new Float64Array(3); + v[0] = tmpMatrix[12]; + v[1] = tmpMatrix[13]; + v[2] = tmpMatrix[14]; + //mat4.rotateY(rot, rot, model.physicalYawAngle / 180 * 3.14); + // mat4.transpose(rot, rot); + //mat4.translate(tmpMatrix, tmpMatrix, [-v[0], -v[1], -v[2]]); + mat4.mul(tmpMatrix, tmpMatrix, rot); + tmpMatrix[12] = v[0]; + tmpMatrix[13] = v[1]; + tmpMatrix[14] = v[2]; + //mat4.mul(tmpMatrix, rot, tmpMatrix); + //mat4.translate(tmpMatrix, tmpMatrix, v); + + console.log(tmpMatrix); + let tmp = tmpMatrix[12]; + //tmpMatrix[12] = tmpMatrix[14]; + //tmpMatrix[14] = tmp; publicAPI.computeViewParametersFromViewMatrix(tmpMatrix); }; @@ -721,6 +855,8 @@ export const DEFAULT_VALUES = { physicalScale: 1.0, physicalViewUp: [0, 1, 0], physicalViewNorth: [0, 0, -1], + + physicalYawAngle: 0, }; // ---------------------------------------------------------------------------- diff --git a/Sources/Rendering/Core/RenderWindowInteractor/index.js b/Sources/Rendering/Core/RenderWindowInteractor/index.js index 26581e9ec9c..8907750a3ce 100644 --- a/Sources/Rendering/Core/RenderWindowInteractor/index.js +++ b/Sources/Rendering/Core/RenderWindowInteractor/index.js @@ -3,7 +3,7 @@ import * as vtkMath from 'vtk.js/Sources/Common/Core/Math'; import Constants from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor/Constants'; -const { Device, Input } = Constants; +const { Axis, Device, Input } = Constants; const { vtkWarningMacro, vtkErrorMacro, normalizeWheel, vtkOnceErrorMacro } = macro; @@ -12,14 +12,17 @@ const { vtkWarningMacro, vtkErrorMacro, normalizeWheel, vtkOnceErrorMacro } = // ---------------------------------------------------------------------------- const deviceInputMap = { - 'xr-standard': [ - Input.Trigger, - Input.Grip, - Input.TrackPad, - Input.Thumbstick, - Input.A, - Input.B, - ], + 'xr-standard': { + button: [ + Input.Trigger, + Input.Grip, + Input.TrackPad, + Input.Thumbstick, + Input.A, + Input.B, + ], + axis: [Axis.TouchpadX, Axis.TouchpadY, Axis.ThumbstickX, Axis.ThumbstickY], + }, }; const handledEvents = [ @@ -418,54 +421,103 @@ function vtkRenderWindowInteractor(publicAPI, model) { }; publicAPI.updateXRGamepads = (xrSession, xrFrame, xrRefSpace) => { + // Fire binary events when axis magnitude crosses threshold + const axisThreshold = 0.9; // watch for when buttons change state and fire events xrSession.inputSources.forEach((inputSource) => { - const pose = xrFrame.getPose(inputSource.gripSpace, xrRefSpace); const gp = inputSource.gamepad; + if (gp === null) return; + + const pose = xrFrame.getPose(inputSource.gripSpace, xrRefSpace); const hand = inputSource.handedness; - if (gp) { - if (!(gp.index in model.lastGamepadValues)) { - model.lastGamepadValues[gp.index] = { - left: { buttons: {} }, - right: { buttons: {} }, - }; + + // Init + if (!(gp.index in model.lastGamepadValues)) { + model.lastGamepadValues[gp.index] = { + left: { + buttons: {}, + axes: {}, + }, + right: { + buttons: {}, + axes: {}, + }, + }; + } + + // Query buttons + for (let b = 0; b < gp.buttons.length; ++b) { + // Init + if (!(b in model.lastGamepadValues[gp.index][hand].buttons)) { + model.lastGamepadValues[gp.index][hand].buttons[b] = false; + } + + // State change + if ( + model.lastGamepadValues[gp.index][hand].buttons[b] !== + gp.buttons[b].pressed + ) { + publicAPI.button3DEvent({ + gamepad: gp, + position: pose.transform.position, + orientation: pose.transform.orientation, + pressed: gp.buttons[b].pressed, + device: + hand === 'left' ? Device.LeftController : Device.RightController, + input: + deviceInputMap[gp.mapping] && + deviceInputMap[gp.mapping]['button'][b] + ? deviceInputMap[gp.mapping]['button'][b] + : Input.Trigger, + }); + model.lastGamepadValues[gp.index][hand].buttons[b] = + gp.buttons[b].pressed; + } + + // State + if (gp.buttons[b].pressed) { + publicAPI.move3DEvent({ + gamepad: gp, + position: pose.transform.position, + orientation: pose.transform.orientation, + device: + hand === 'left' ? Device.LeftController : Device.RightController, + input: + deviceInputMap[gp.mapping] && + deviceInputMap[gp.mapping]['button'][b] + ? deviceInputMap[gp.mapping]['button'][b] + : Input.Unknown, + }); + } + } + + for (let a = 0; a < gp.axes.length; ++a) { + // Init + if (!(a in model.lastGamepadValues[gp.index][hand].axes)) { + model.lastGamepadValues[gp.index][hand].axes[a] = 0.0; } - for (let b = 0; b < gp.buttons.length; ++b) { - if (!(b in model.lastGamepadValues[gp.index][hand].buttons)) { - model.lastGamepadValues[gp.index][hand].buttons[b] = false; - } - if ( - model.lastGamepadValues[gp.index][hand].buttons[b] !== - gp.buttons[b].pressed - ) { - publicAPI.button3DEvent({ - gamepad: gp, - position: pose.transform.position, - orientation: pose.transform.orientation, - pressed: gp.buttons[b].pressed, - device: - inputSource.handedness === 'left' - ? Device.LeftController - : Device.RightController, - input: - deviceInputMap[gp.mapping] && deviceInputMap[gp.mapping][b] - ? deviceInputMap[gp.mapping][b] - : Input.Trigger, - }); - model.lastGamepadValues[gp.index][hand].buttons[b] = - gp.buttons[b].pressed; - } - if (model.lastGamepadValues[gp.index][hand].buttons[b]) { - publicAPI.move3DEvent({ - gamepad: gp, - position: pose.transform.position, - orientation: pose.transform.orientation, - device: - inputSource.handedness === 'left' - ? Device.LeftController - : Device.RightController, - }); - } + + // State change + if ( + gp.axes[a] > axisThreshold && + model.lastGamepadValues[gp.index][hand].axes[a] < axisThreshold + ) { + } + + // State + // TODO debounce + if (gp.axes[a] > axisThreshold) { + //model.rotate3DEvent({ + // gamepad: gp, + // position: pose.transform.position, + // orientation: pose.transform.orientation, + // device: + // hand === 'left' ? Device.LeftController : Device.RightController, + // input: deviceInputMap[gp.mapping] && deviceInputMap[gp.mapping]['axis'][a] + // ? deviceInputMap[gp.mapping]['axis'][a] + // : Axis.Unknown, + // value: gp.axes[a], + //}); } } }); diff --git a/Sources/Rendering/OpenGL/RenderWindow/index.js b/Sources/Rendering/OpenGL/RenderWindow/index.js index 36897d8dc2f..cfc8ad92934 100644 --- a/Sources/Rendering/OpenGL/RenderWindow/index.js +++ b/Sources/Rendering/OpenGL/RenderWindow/index.js @@ -388,11 +388,11 @@ function vtkOpenGLRenderWindow(publicAPI, model) { return; } - ren - .getActiveCamera() - .computeViewParametersFromPhysicalMatrix( - view.transform.inverse.matrix - ); + ren.getActiveCamera().computeViewParametersFromViewMatrix( + // FIXME use pose for each eye + //view.transform.inverse.matrix + xrPose.transform.inverse.matrix + ); ren.getActiveCamera().setProjectionMatrix(view.projectionMatrix); publicAPI.traverseAllPasses(); From 5afcbccfe9b34b63c57fdaff700f70242d867cae Mon Sep 17 00:00:00 2001 From: Tom Birdsong Date: Mon, 13 Dec 2021 07:58:54 -0500 Subject: [PATCH 3/3] test(XR): Remove commented snap rotation experiments --- Sources/Rendering/Core/Camera/index.js | 91 ++------------------------ 1 file changed, 6 insertions(+), 85 deletions(-) diff --git a/Sources/Rendering/Core/Camera/index.js b/Sources/Rendering/Core/Camera/index.js index 070058c11d0..d8b763b7b7b 100644 --- a/Sources/Rendering/Core/Camera/index.js +++ b/Sources/Rendering/Core/Camera/index.js @@ -397,18 +397,6 @@ function vtkCamera(publicAPI, model) { mat4.scale(result, result, tmpvec1); mat4.translate(result, result, model.physicalTranslation); - - // let rot = mat4.identity(new Float64Array(16)); - //mat4.fromRotation(rot, model.physicalYawAngle / 180 * 3.14, model.physicalViewUp); - //// mat4.invert(rot, rot); - //mat4.mul(result, rot, result); - - //let tmpRot = mat4.identity(new Float64Array(16)); - //let matInv = mat4.identity(new Float64Array(16)); - //mat4.rotateY(tmpRot, tmpRot, model.physicalYawAngle / 180 * 3.14); - //mat4.transpose(tmpRot, tmpRot); - //mat4.invert(matInv, ) - // mat4.mul(result, tmpRot, result); }; publicAPI.applyPhysicalYaw = (angle) => { @@ -422,48 +410,18 @@ function vtkCamera(publicAPI, model) { publicAPI.computeViewParametersFromViewMatrix = (vmat) => { // invert to get view to world - let worldToViewPos = new Float64Array(4); let viewToWorldPos = new Float64Array(4); let v2wMatrix = new Float64Array(16); - worldToViewPos[0] = vmat[12]; - worldToViewPos[1] = vmat[13]; - worldToViewPos[2] = vmat[14]; - worldToViewPos[3] = 1; mat4.invert(v2wMatrix, vmat); + viewToWorldPos[0] = v2wMatrix[12]; viewToWorldPos[1] = v2wMatrix[13]; viewToWorldPos[2] = v2wMatrix[14]; viewToWorldPos[3] = 1; + mat4.copy(tmpMatrix, v2wMatrix); - //console.log('View -> World'); - //console.log(v2wMatrix); - //mat4.copy(tmpMatrix, vmat); - //v[0] = tmpMatrix[12]; //tmpMatrix[12] = 0; - //tmpMatrix[13] = 0; - //tmpMatrix[14] = 0; - //mat4.invert(tmpMatrix, tmpMatrix); - - //// - //// - //// mat4.invert(tmpMatrix, tmpMatrix); - //// mat4.rotateY(tmpMatrix, tmpMatrix, model.physicalYawAngle / 180 * 3.14); - //// mat4.translate(tmpMatrix, tmpMatrix, [-v[0], -v[1], -v[2]]); - - ////// Correct center of rotation, incorrect view translation - ////mat4.invert(tmpMatrix, tmpMatrix); - ////mat4.rotateY(tmpMatrix, tmpMatrix, model.physicalYawAngle / 180 * 3.14); - - //// Correct view translation, incorrect center of rotation - //// mat4.invert(tmpMatrix, tmpMatrix);); - ////let tmp = mat4.identity(new Float64Array(16)); - ////tmpMatrix[12] = 0; - ////tmpMatrix[14] = 0; - //mat4.invert(tmpMatrix, tmpMatrix); - - let w2vTranslate = mat4.identity(new Float64Array(16)); + let rotate = mat4.identity(new Float64Array(16)); - let rotateRev = mat4.identity(new Float64Array(16)); - let w2vTranslateReverse = mat4.identity(new Float64Array(16)); let v2wTranslate = mat4.identity(new Float64Array(16)); let v2wTranslateReverse = mat4.identity(new Float64Array(16)); @@ -473,48 +431,11 @@ function vtkCamera(publicAPI, model) { -viewToWorldPos[2], ]); mat4.rotateY(rotate, rotate, (model.physicalYawAngle / 180) * 3.14); - mat4.rotateY( - rotateRev, - rotateRev, - ((-1 * model.physicalYawAngle) / 180) * 3.14 - ); mat4.translate(v2wTranslateReverse, v2wTranslateReverse, viewToWorldPos); - mat4.translate(w2vTranslate, w2vTranslate, [ - -worldToViewPos[0], - -worldToViewPos[1], - -worldToViewPos[2], - ]); - mat4.translate(w2vTranslateReverse, w2vTranslateReverse, worldToViewPos); - - //mat4.mul(tmpMatrix, w2vTranslate, vmat); - //mat4.mul(tmpMatrix, rotate, tmpMatrix); - //mat4.mul(tmpMatrix, w2vTranslateReverse, tmpMatrix); - //mat4.invert(tmpMatrix, tmpMatrix); - - // FIXME works post-snap? mat4.mul(v2wTranslateReverse, v2wTranslate, rotate); - // mat4.mul(v2wTranslate, v2wTranslate, rotate); - //mat4.mul(v2wTranslateReverse, v2wTranslateReverse, rotate); - mat4.mul(v2wTranslateReverse, v2wTranslate, rotate); - mat4.mul(tmpMatrix, v2wTranslateReverse, v2wMatrix); - mat4.mul(tmpMatrix, tmpMatrix, rotate); - mat4.mul(tmpMatrix, v2wTranslate, tmpMatrix); - //mat4.rotateY(tmpMatrix, tmpMatrix, -1 * model.physicalYawAngle / 180 * 3.14); - //mat4.translate(tmpMatrix, tmpMatrix, [0, 0, 0.01 * model.physicalYawAngle]); - //mat4.translate(tmpMatrix, tmpMatrix, v); - //mat4.invert(tmpMatrix, tmpMatrix); - //// - //mat4.invert(tmpMatrix, tmpMatrix); - //tmpMatrix[12] = v[0]; - //tmpMatrix[13] = v[1]; - //tmpMatrix[14] = v[2]; - - // FIXME try pushing through the cone position at <0,0,-1> - //v[0] = 0; - //v[1] = 0; - //v[1] = -1; - //vec3.transformMat4(tmpvec1, v, tmpMatrix); - // console.log(v); + mat4.mul(tmpMatrix, v2wTranslate, v2wMatrix); + mat4.mul(tmpMatrix, tmpMatrix, rotate); + mat4.mul(tmpMatrix, v2wTranslateReverse, tmpMatrix); // note with glmatrix operations happen in // the reverse order