Skip to content
forked from pmndrs/xr

🤳 VR/AR with react-three-fiber

Notifications You must be signed in to change notification settings

mwmwmw/react-xr

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

react-xr

npm version npm

WebXR + react-three-fiber

React components and hooks for creating VR/AR/XR applications with react-three-fiber

Note: Extremely early in development. Contributors welcome!

These demos are real, you can click them! They contain the full code, too.

Installation

npm install react-xr

Getting started

Add XRCanvas component (or replace your existing react-three-fiber Canvas component)

import { XRCanvas } from 'react-xr'

function App() {
  return <XRCanvas>{/* All the stuff goes here */}</XRCanvas>
}

Adding controllers to the scene

To get started with default controller models add DefaultXRControllers component. It will fetch appropriate input profile models. You can learn more here.

import { XRCanvas, DefaultXRControllers } from 'react-xr'

function App() {
  return (
    <XRCanvas>
      <DefaultXRControllers />
    </XRCanvas>
  )
}

You can access controllers' state (position, orientation, etc.) by using useXR() hook

const { controllers } = useXR()

API

XRCanvas

Extended react-three-fiber Canvas that includes:

  • Button to start VR session
  • Color management
  • VR Mode
  • react-xr context
import { XRCanvas } from 'react-xr'

function App() {
  return <XRCanvas>{/* All the stuff goes here */}</XRCanvas>
}

useXR

Hook that can only beused by components insde component.

const { controllers } = useXR()

Controllers is an array of XRController objects

interface XRController {
  grip: Group
  controller: Group
  inputSource?: XRInputSource
  // ...
  // more in XRController.ts
}

grip and controller are ThreeJS groups that have the position and orientation of xr controllers. grip has an orientation that should be used to render virtual objects such that they appear to be held in the user’s hand and controller has an orientation of the preferred pointing ray.

inputSource is the WebXR input source (MDN). Note that it will not be available before controller is connected.

useXREvent

Every controller emits following events: select, selectstart, selectend, squeeze, squeezestart, squeezeend.

To listen to those events use useXREvent hook:

const onSqueeze = useCallback(() => console.log('Squeezed'), [])

useXREvent('squeeze', onSqueeze)

it supports optional third parameter with options

const onSqueeze = useCallback(() => console.log('Left controller squeeze'), [])

useXREvent('squeeze', onSqueeze, { handedness: 'left' })

Interactions

react-xr comes with built-in high level interaction components.

<Hover>

Hover component will allow you for detecting when ray shot from the controllers is pointing at the given mesh.

<Hover onChange={(value) => console.log(value ? 'hovered' : 'blurred')}>{/* your mesh here */}</Hover>

<Select>

Select can be used when you need to select some mesh. Component will trigger onSelect function when controller is pointing at the given mesh and select event was fired.

<Select onSelect={() => console.log('selected')}>{/* your mesh here */}</Select>

Getting the VR Camera (HMD) Location

To get the position of the VR camera, use three's WebXRManager instance.

useFrame(({gl, camera})=>{
const cam = gl.xr.isPresenting ? gl.xr.getCamera(camera) : camera;
myObj.lookAt(cam.position) 
});

Parent VR HMD and Controllers to another object

If you want to attach the user to an object so it can be moved around, just parent the VR camera and controllers to an object3D.

  const mesh = useRef()
  const { gl, camera } = useThree()
  
  useEffect(() => {
    const cam = gl.xr.isPresenting ? gl.xr.getCamera(camera) : camera
    mesh.current.add(cam)
  }, [gl.xr.isPresenting, gl.xr, camera, mesh])
  
  const { controllers } = useXR()
 // bundle add the controllers to the same object as the camera so it all stays together.
  useEffect(() => {
    if (controllers.length > 0) {
      controllers.forEach(c => mesh.current.add(c.grip))
    }
  }, [controllers, mesh])

About

🤳 VR/AR with react-three-fiber

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 87.9%
  • JavaScript 12.1%