84 lines
2.8 KiB
JavaScript
84 lines
2.8 KiB
JavaScript
/* 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')
|
|
|
|
function initVR (bot, renderer, viewer) {
|
|
if (!('xr' in navigator)) return
|
|
if (!navigator.userAgent.includes('OculusBrowser')) return
|
|
|
|
// VR
|
|
document.body.appendChild(VRButton.createButton(renderer))
|
|
renderer.xr.enabled = true
|
|
|
|
// hack for vr camera
|
|
const user = new THREE.Group()
|
|
user.add(viewer.camera)
|
|
viewer.scene.add(user)
|
|
const controllerModelFactory = new XRControllerModelFactory(new GLTFLoader())
|
|
const controller1 = renderer.xr.getControllerGrip(0)
|
|
const controller2 = renderer.xr.getControllerGrip(1)
|
|
let hand1 = controllerModelFactory.createControllerModel(controller1)
|
|
controller1.addEventListener('connected', (event) => {
|
|
hand1.xrInputSource = event.data
|
|
user.add(controller1)
|
|
})
|
|
controller1.add(hand1)
|
|
let hand2 = controllerModelFactory.createControllerModel(controller2)
|
|
controller2.addEventListener('connected', (event) => {
|
|
hand2.xrInputSource = event.data
|
|
user.add(controller2)
|
|
})
|
|
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 (hand1.xrInputSource && hand2.xrInputSource) {
|
|
hand1.xAxis = hand1.xrInputSource.gamepad.axes[2]
|
|
hand1.yAxis = hand1.xrInputSource.gamepad.axes[3]
|
|
hand2.xAxis = hand2.xrInputSource.gamepad.axes[2]
|
|
hand2.yAxis = hand2.xrInputSource.gamepad.axes[3]
|
|
if (hand1.xrInputSource.handedness === 'right') {
|
|
const tmp = hand2
|
|
hand2 = hand1
|
|
hand1 = tmp
|
|
}
|
|
}
|
|
|
|
if (rotSnapReset) {
|
|
if (Math.abs(hand1.xAxis) > 0.8) {
|
|
yawOffset -= Math.PI / 4 * Math.sign(hand1.xAxis)
|
|
rotSnapReset = false
|
|
}
|
|
} else if (Math.abs(hand1.xAxis) < 0.1) {
|
|
rotSnapReset = true
|
|
}
|
|
|
|
viewer.setFirstPersonCamera(null, yawOffset, 0)
|
|
|
|
const xrCamera = renderer.xr.getCamera(viewer.camera)
|
|
const d = xrCamera.getWorldDirection()
|
|
bot.entity.yaw = Math.atan2(-d.x, -d.z)
|
|
bot.entity.pitch = Math.asin(d.y)
|
|
|
|
bot.physics.stepHeight = 1
|
|
bot.setControlState('forward', hand2.yAxis < -0.5)
|
|
bot.setControlState('back', hand2.yAxis > 0.5)
|
|
bot.setControlState('right', hand2.xAxis < -0.5)
|
|
bot.setControlState('left', hand2.xAxis > 0.5)
|
|
|
|
TWEEN.update()
|
|
viewer.update()
|
|
renderer.render(viewer.scene, viewer.camera)
|
|
})
|
|
}
|
|
|
|
module.exports = { initVR }
|