fix: normal mode was unplayable when webxr was available

fix: in vr mode performance was degraded since every frame was rendered twice
fix: enter vr is now displayed propertly on mobile devices
This commit is contained in:
Vitaly 2023-11-10 12:25:39 +03:00
commit 2bd3307199
4 changed files with 23 additions and 16 deletions

View file

@ -20,6 +20,7 @@ export class Viewer {
playerHeight: number
isSneaking: boolean
version: string
cameraObjectOverride?: THREE.Object3D // for xr
constructor (public renderer: THREE.WebGLRenderer, numWorkers?: number) {
this.scene = new THREE.Scene()
@ -81,12 +82,13 @@ export class Viewer {
}
setFirstPersonCamera (pos: Vec3 | null, yaw: number, pitch: number, roll = 0) {
const cam = this.cameraObjectOverride || this.camera
if (pos) {
let y = pos.y + this.playerHeight
if (this.isSneaking) y -= 0.3
new tweenJs.Tween(this.camera.position).to({ x: pos.x, y, z: pos.z }, 50).start()
new tweenJs.Tween(cam.position).to({ x: pos.x, y, z: pos.z }, 50).start()
}
this.camera.rotation.set(pitch, yaw, roll, 'ZYX')
cam.rotation.set(pitch, yaw, roll, 'ZYX')
}
// todo type

View file

@ -129,7 +129,7 @@ let previousWindowHeight = window.innerHeight
const renderFrame = (time: DOMHighResTimeStamp) => {
if (window.stopLoop) return
window.requestAnimationFrame(renderFrame)
if (window.stopRender) return
if (window.stopRender || renderer.xr.isPresenting) return
if (renderInterval) {
delta += time - lastTime
lastTime = time
@ -540,7 +540,7 @@ async function connect (connectOptions: {
window.debugMenu = debugMenu
void initVR(bot, renderer, viewer)
void initVR()
postRenderFrameFn = () => {
viewer.setFirstPersonCamera(null, bot.entity.yaw, bot.entity.pitch)

View file

@ -64,6 +64,12 @@ body {
text-shadow: 1px 1px #222;
}
#VRButton {
background: rgba(0, 0, 0, 0.3) !important;
opacity: 0.7 !important;
position: fixed !important;
}
.dirt-bg {
position: absolute;
top: 0;

View file

@ -1,13 +1,11 @@
/* global THREE */
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 TWEEN = require('@tweenjs/tween.js')
async function initVR (bot, renderer, viewer) {
async function initVR () {
const { renderer } = viewer
if (!('xr' in navigator)) return
const isSupported = await navigator.xr.isSessionSupported('immersive-vr')
const isSupported = await navigator.xr.isSessionSupported('immersive-vr') && !!XRSession.prototype.updateRenderState // e.g. android webview doesn't support updateRenderState
if (!isSupported) return
// VR
@ -34,14 +32,10 @@ async function initVR (bot, renderer, viewer) {
})
controller2.add(hand2)
viewer.setFirstPersonCamera = function (pos, yaw, pitch) {
if (pos) new TWEEN.Tween(user.position).to({ x: pos.x, y: pos.y, z: pos.z }, 50).start()
user.rotation.set(pitch, yaw, 0, 'ZYX')
}
let rotSnapReset = true
let yawOffset = 0
renderer.setAnimationLoop(() => {
if (!renderer.xr.isPresenting) return
if (hand1.xrInputSource && hand2.xrInputSource) {
hand1.xAxis = hand1.xrInputSource.gamepad.axes[2]
hand1.yAxis = hand1.xrInputSource.gamepad.axes[3]
@ -76,9 +70,14 @@ async function initVR (bot, renderer, viewer) {
bot.setControlState('right', hand2.xAxis < -0.5)
bot.setControlState('left', hand2.xAxis > 0.5)
TWEEN.update()
viewer.update()
renderer.render(viewer.scene, viewer.camera)
viewer.render()
})
renderer.xr.addEventListener('sessionstart', () => {
viewer.cameraObjectOverride = user
})
renderer.xr.addEventListener('sessionend', () => {
viewer.cameraObjectOverride = undefined
})
}