fix: fix basic vr support & test dom overlay
sentry-ref: 5517390383, 5517390775
This commit is contained in:
parent
97ad6d9ff8
commit
f8980836dc
5 changed files with 49 additions and 26 deletions
|
|
@ -168,7 +168,8 @@
|
|||
"ignoreDependencies": []
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"minecraft-protocol@1.47.0": "patches/minecraft-protocol@1.47.0.patch"
|
||||
"minecraft-protocol@1.47.0": "patches/minecraft-protocol@1.47.0.patch",
|
||||
"three@0.154.0": "patches/three@0.154.0.patch"
|
||||
}
|
||||
},
|
||||
"packageManager": "pnpm@9.0.4"
|
||||
|
|
|
|||
16
patches/three@0.154.0.patch
Normal file
16
patches/three@0.154.0.patch
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
diff --git a/examples/jsm/webxr/VRButton.js b/examples/jsm/webxr/VRButton.js
|
||||
index 6856a21b17aa45d7922bbf776fd2d7e63c7a9b4e..0925b706f7629bd52f0bb5af469536af8f5fce2c 100644
|
||||
--- a/examples/jsm/webxr/VRButton.js
|
||||
+++ b/examples/jsm/webxr/VRButton.js
|
||||
@@ -62,7 +62,10 @@ class VRButton {
|
||||
// ('local' is always available for immersive sessions and doesn't need to
|
||||
// be requested separately.)
|
||||
|
||||
- const sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor', 'hand-tracking', 'layers' ] };
|
||||
+ const sessionInit = {
|
||||
+ optionalFeatures: ['local-floor', 'bounded-floor', 'layers'],
|
||||
+ domOverlay: { root: document.body },
|
||||
+ };
|
||||
navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted );
|
||||
|
||||
} else {
|
||||
15
pnpm-lock.yaml
generated
15
pnpm-lock.yaml
generated
|
|
@ -20,6 +20,9 @@ patchedDependencies:
|
|||
minecraft-protocol@1.47.0:
|
||||
hash: 2uxevyasyasdavsxuehfavgkjq
|
||||
path: patches/minecraft-protocol@1.47.0.patch
|
||||
three@0.154.0:
|
||||
hash: sj7ocb4p23jym6bkfgueanti2e
|
||||
path: patches/three@0.154.0.patch
|
||||
|
||||
importers:
|
||||
|
||||
|
|
@ -341,7 +344,7 @@ importers:
|
|||
version: 3.0.0
|
||||
three:
|
||||
specifier: 0.154.0
|
||||
version: 0.154.0
|
||||
version: 0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e)
|
||||
timers-browserify:
|
||||
specifier: ^2.0.12
|
||||
version: 2.0.12
|
||||
|
|
@ -410,7 +413,7 @@ importers:
|
|||
version: 4.7.2
|
||||
three-stdlib:
|
||||
specifier: ^2.26.11
|
||||
version: 2.28.5(three@0.154.0)
|
||||
version: 2.28.5(three@0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e))
|
||||
three.meshline:
|
||||
specifier: ^1.3.0
|
||||
version: 1.4.0
|
||||
|
|
@ -17565,7 +17568,7 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/three': 0.156.0
|
||||
skinview-utils: 0.7.1
|
||||
three: 0.154.0
|
||||
three: 0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e)
|
||||
|
||||
slash@3.0.0: {}
|
||||
|
||||
|
|
@ -18018,7 +18021,7 @@ snapshots:
|
|||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
|
||||
three-stdlib@2.28.5(three@0.154.0):
|
||||
three-stdlib@2.28.5(three@0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e)):
|
||||
dependencies:
|
||||
'@types/draco3d': 1.4.7
|
||||
'@types/offscreencanvas': 2019.7.2
|
||||
|
|
@ -18026,11 +18029,11 @@ snapshots:
|
|||
draco3d: 1.5.6
|
||||
fflate: 0.6.10
|
||||
potpack: 1.0.2
|
||||
three: 0.154.0
|
||||
three: 0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e)
|
||||
|
||||
three.meshline@1.4.0: {}
|
||||
|
||||
three@0.154.0: {}
|
||||
three@0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e): {}
|
||||
|
||||
throttle-debounce@3.0.1: {}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,6 +163,9 @@ body {
|
|||
animation-timing-function: ease-in-out;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
#viewer-canvas::xr-overlay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.full-svg svg {
|
||||
width: 100%;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
const { VRButton } = require('three/examples/jsm/webxr/VRButton.js')
|
||||
const { GLTFLoader } = require('three/examples/jsm/loaders/GLTFLoader.js')
|
||||
const { XRControllerModelFactory } = require('three/examples/jsm/webxr/XRControllerModelFactory.js')
|
||||
const { buttonMap: standardButtonsMap } = require('contro-max/build/gamepad')
|
||||
const { activeModalStack, hideModal } = require('./globalState')
|
||||
import { VRButton } from 'three/examples/jsm/webxr/VRButton.js'
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
|
||||
import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js'
|
||||
import { buttonMap as standardButtonsMap } from 'contro-max/build/gamepad'
|
||||
import { activeModalStack, hideModal } from './globalState'
|
||||
|
||||
async function initVR() {
|
||||
export async function initVR () {
|
||||
const { renderer } = viewer
|
||||
if (!('xr' in navigator)) return
|
||||
const isSupported = await navigator.xr.isSessionSupported('immersive-vr') && !!XRSession.prototype.updateRenderState // e.g. android webview doesn't support updateRenderState
|
||||
const isSupported = await navigator.xr?.isSessionSupported('immersive-vr') && !!XRSession.prototype.updateRenderState // e.g. android webview doesn't support updateRenderState
|
||||
if (!isSupported) return
|
||||
|
||||
// VR
|
||||
|
|
@ -25,22 +25,23 @@ async function initVR() {
|
|||
// todo the logic written here can be hard to understand as it was designed to work in gamepad api emulation mode, will be refactored once there is a contro-max rewrite is done
|
||||
const virtualGamepadIndex = 4
|
||||
let connectedVirtualGamepad
|
||||
//@ts-expect-error
|
||||
const manageXrInputSource = ({ gamepad, handedness = defaultHandedness }, defaultHandedness, removeAction = false) => {
|
||||
if (handedness === 'right') {
|
||||
const event = new Event(removeAction ? 'gamepaddisconnected' : 'gamepadconnected') // todo need to expose and use external gamepads api in contro-max instead
|
||||
const event: any = new Event(removeAction ? 'gamepaddisconnected' : 'gamepadconnected') // todo need to expose and use external gamepads api in contro-max instead
|
||||
event.gamepad = removeAction ? connectedVirtualGamepad : { ...gamepad, mapping: 'standard', index: virtualGamepadIndex }
|
||||
connectedVirtualGamepad = event.gamepad
|
||||
window.dispatchEvent(event)
|
||||
}
|
||||
}
|
||||
let hand1 = controllerModelFactory.createControllerModel(controller1)
|
||||
let hand1: any = controllerModelFactory.createControllerModel(controller1)
|
||||
controller1.addEventListener('connected', (event) => {
|
||||
hand1.xrInputSource = event.data
|
||||
manageXrInputSource(event.data, 'left')
|
||||
user.add(controller1)
|
||||
})
|
||||
controller1.add(hand1)
|
||||
let hand2 = controllerModelFactory.createControllerModel(controller2)
|
||||
let hand2: any = controllerModelFactory.createControllerModel(controller2)
|
||||
controller2.addEventListener('connected', (event) => {
|
||||
hand2.xrInputSource = event.data
|
||||
manageXrInputSource(event.data, 'right')
|
||||
|
|
@ -50,15 +51,17 @@ async function initVR() {
|
|||
|
||||
controller1.addEventListener('disconnected', () => {
|
||||
// don't handle removal of gamepads for now as is don't affect contro-max
|
||||
hand1.xrInputSource = undefined
|
||||
manageXrInputSource(hand1.xrInputSource, 'left', true)
|
||||
hand1.xrInputSource = undefined
|
||||
})
|
||||
controller2.addEventListener('disconnected', () => {
|
||||
hand2.xrInputSource = undefined
|
||||
manageXrInputSource(hand1.xrInputSource, 'right', true)
|
||||
hand2.xrInputSource = undefined
|
||||
})
|
||||
|
||||
const originalGetGamepads = navigator.getGamepads.bind(navigator)
|
||||
// is it okay to patch this?
|
||||
//@ts-expect-error
|
||||
navigator.getGamepads = () => {
|
||||
const originalGamepads = originalGetGamepads()
|
||||
if (!hand1.xrInputSource || !hand2.xrInputSource) return originalGamepads
|
||||
|
|
@ -105,15 +108,14 @@ async function initVR() {
|
|||
viewer.setFirstPersonCamera(null, bot.entity.yaw, bot.entity.pitch)
|
||||
|
||||
// todo restore this logic (need to preserve ability to move camera)
|
||||
// const xrCamera = renderer.xr.getCamera(viewer.camera)
|
||||
// const d = xrCamera.getWorldDirection() // todo target
|
||||
// const xrCamera = renderer.xr.getCamera()
|
||||
// const d = xrCamera.getWorldDirection(new THREE.Vector3())
|
||||
// bot.entity.yaw = Math.atan2(-d.x, -d.z)
|
||||
// bot.entity.pitch = Math.asin(d.y)
|
||||
|
||||
// todo ?
|
||||
// bot.physics.stepHeight = 1
|
||||
|
||||
viewer.update()
|
||||
viewer.render()
|
||||
})
|
||||
renderer.xr.addEventListener('sessionstart', () => {
|
||||
|
|
@ -128,8 +130,6 @@ async function initVR() {
|
|||
})
|
||||
}
|
||||
|
||||
module.exports.initVR = initVR
|
||||
|
||||
const xrStandardRightButtonsMap = [
|
||||
[0 /* trigger */, 'Right Trigger'],
|
||||
[1 /* squeeze */, 'Right Bumper'],
|
||||
|
|
@ -146,9 +146,9 @@ const xrStandardLeftButtonsMap = [
|
|||
[4 /* A */, 'X'],
|
||||
[5 /* B */, 'Y'],
|
||||
]
|
||||
const remapButtons = (rightButtons, leftButtons) => {
|
||||
const remapButtons = (rightButtons: any[], leftButtons: any[]) => {
|
||||
// return remapped buttons
|
||||
const remapped = []
|
||||
const remapped = [] as string[]
|
||||
const remapWithMap = (buttons, map) => {
|
||||
for (const [index, standardName] of map) {
|
||||
const standardMappingIndex = standardButtonsMap.findIndex((aliases) => aliases.find(alias => standardName === alias))
|
||||
Loading…
Add table
Add a link
Reference in a new issue