Skip to content

Commit 04efb31

Browse files
committed
docs: pitfalls, faw, anchors tutorial, dom overlay tutorial, hit test tutorial, store tutorial
1 parent e796aa3 commit 04efb31

File tree

12 files changed

+398
-23
lines changed

12 files changed

+398
-23
lines changed

README.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
<h3 align="center">Turn any R3F app into an interactive immersive experience.</h3>
77
<br/>
88

9-
109
<p align="center">
1110
<a href="https://npmjs.com/package/@react-three/xr" target="_blank">
1211
<img src="https://img.shields.io/npm/v/@react-three/xr?style=flat&colorA=000000&colorB=000000" alt="NPM" />
@@ -29,7 +28,7 @@ npm install three @react-three/fiber @react-three/xr@latest
2928
## What does it look like?
3029

3130
| A simple scene with a mesh that toggles its material color between `"red"` and `"blue"` when clicked through touching or pointing. | ![recording of interacting with the code below](./docs/getting-started/basic-example.gif) |
32-
|-|-|
31+
| ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
3332

3433
```tsx
3534
import { Canvas } from '@react-three/fiber'
@@ -40,17 +39,19 @@ const store = createXRStore()
4039

4140
export function App() {
4241
const [red, setRed] = useState(false)
43-
return <>
44-
<button onClick={() => store.enterAR()}>Enter AR</button>
45-
<Canvas>
46-
<XR store={store}>
47-
<mesh pointerEventsType={{ deny: 'grab' }} onClick={() => setRed(!red)} position={[0, 1, -1]}>
48-
<boxGeometry />
49-
<meshBasicMaterial color={red ? 'red' : 'blue'} />
50-
</mesh>
51-
</XR>
52-
</Canvas>
53-
</>
42+
return (
43+
<>
44+
<button onClick={() => store.enterAR()}>Enter AR</button>
45+
<Canvas>
46+
<XR store={store}>
47+
<mesh pointerEventsType={{ deny: 'grab' }} onClick={() => setRed(!red)} position={[0, 1, -1]}>
48+
<boxGeometry />
49+
<meshBasicMaterial color={red ? 'red' : 'blue'} />
50+
</mesh>
51+
</XR>
52+
</Canvas>
53+
</>
54+
)
5455
}
5556
```
5657

@@ -64,24 +65,25 @@ export function App() {
6465

6566
## Tutorials
6667

68+
- 💾 [Store](https://docs.pmnd.rs/xr/tutorials/store)
6769
- 👌 [Interactions](https://docs.pmnd.rs/xr/tutorials/interactions)
6870
- 🔧 [Options](https://docs.pmnd.rs/xr/tutorials/options)
6971
- 🧊 [Object Detection](https://docs.pmnd.rs/xr/tutorials/object-detection)
7072
-[Origin](https://docs.pmnd.rs/xr/tutorials/origin)
7173
- 🪄 [Teleport](https://docs.pmnd.rs/xr/tutorials/teleport)
7274
- 🕹️ [Gamepad](https://docs.pmnd.rs/xr/tutorials/gamepad)
7375
- 🎮 [Custom Controller/Hands/...](https://docs.pmnd.rs/xr/tutorials/custom-inputs)
76+
- ⚓️ [Anchors](https://docs.pmnd.rs/xr/tutorials/anchors)
77+
- 📱 [Dom Overlays](https://docs.pmnd.rs/xr/tutorials/dom-overlay)
78+
- 🎯 [Hit Test](https://docs.pmnd.rs/xr/tutorials/hit-test)
7479
-[Guards](https://docs.pmnd.rs/xr/tutorials/guards)
7580

7681
## Roadmap
7782

7883
- 🤳 XR Gestures
7984
- ➕ Multimodal
80-
- ⚓️ Anchors
8185
- 📺 Layers
82-
- 📱 Dom Overlays
8386
- 🕺 Tracked Body
84-
- 🎯 Hit Test
8587
- ↕ react-three/controls
8688

8789
## Migration guides

docs/advanced/pitfalls.md

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,34 @@ In contrast to non-immersive 3D applications, the camera transformation in MR/VR
1010

1111
## Reading the camera position in XR
1212

13-
When using @react-three/xr, the useThree hook will return the XR camera when in XR. Therefore, the returned camera and the `getWorldPosition` function can be used to get the world position of the xr camera, as well as the normal camera, when not in XR.
13+
When using @react-three/xr, the useThree hook will return the XR camera when in XR. Therefore, the returned camera and the `getWorldPosition` function can be used to get the world position of the xr camera, as well as the normal camera, when not in XR.
1414

1515
```tsx
16-
const camera = useThree(state => state.camera)
16+
const camera = useThree((state) => state.camera)
1717
useFrame(() => camera.getWorldPosition(target))
18-
```
18+
```
19+
20+
## Missing Https
21+
22+
If you are trying to enter the AR or VR modus and nothing is happening, make sure that you are accessing the website using `https://`.
23+
In case you are using vite, we recommend using the `@vitejs/plugin-basic-ssl` to try out your vite application on your device while developing.
24+
25+
## Missing XR component
26+
27+
If you made sure that the website is accessed using `https://` and still nothing happens when executing `enterAR` or `enterVR`, it is likely that the `<XR>` component is missing. Be sure to add the `<XR>` component directly into the `<Canvas>` and make sure both the `<Canvas>` and the `<XR>` component are present when the button is pressed.
28+
29+
## Entering while loading content
30+
31+
If you cannot enter the VR or AR experience while the assets in your scene are loading, make sure to place a suspense boundary around your scene. With this setup, the `<XR>` component stays mounted while your scene loads.
32+
33+
```tsx
34+
<Canvas>
35+
<XR>
36+
<Suspense>... your scene</Suspense>
37+
</XR>
38+
</Canvas>
39+
```
40+
41+
## XRSpace
42+
43+
If you are placing `<XRSpace>` components outside of the `<XROrigin>` while changing the transformation of the `<XROrigin>` (e.g. by setting `<XROrigin position={[0,1,0]} />`), the elements rendered inside of the `<XRSpace>` will not be transformed with the origin. If the transformations of the origin should be applied to the `<XRSpace>`, make sure to place those components inside the `<XROrigin>`. Not placing `<XRSpace>` components into the `<XROrigin>` can be useful in scenarios where you want to move the `<XROrigin>` independently from the `<XRSpace>`. For instance, building a virtual elevator where your actual room is duplicated into the x-axis so that you can use the elevator to travel between multiple instances of your room.

docs/getting-started/all-components.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ Component that positions its children in the provided space.
6060

6161
Component that allows to declare its children as teleport targets.
6262

63+
### `XRHitTest`
64+
65+
Component that allows to emit hit tests from its position in the scene graph.
66+
6367
## Pointer
6468

6569
The core interaction concept is based on (touch/grab/ray) pointers.

docs/getting-started/all-hooks.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@ Hook for checking if a session mode is supported.
2626

2727
Hook for getting the session visibility state.
2828

29+
### `useXRHitTestSource`
30+
31+
Hook for creating a hit test source originating from the provided object or xr space.
32+
33+
### `useXRHitTest`
34+
35+
Hook that allows to set up a continous hit test originating from the provided object or xr space.
36+
37+
### `useXRRequestHitTest`
38+
39+
Hook that returns a function to request a single hit test.
40+
41+
42+
### `useRequestXRAnchor`
43+
44+
Hook that returns a function that allows to request a xr anchor.
45+
46+
### `useXRAnchor`
47+
48+
Hook for requesting and storing a single xr anchor.
49+
2950
## Space
3051

3152
@react-three/xr provides several hooks to synchronize the space provided by WebXR with the scene.
@@ -59,10 +80,14 @@ Hook for creating a grab pointer.
5980

6081
Hook for creating a ray pointer.
6182

62-
### `usePointerXRSessionEvent`
83+
### `usePointerXRInputSourceEvents`
6384

6485
Hook for binding the XR session events such as `selectstart` to the provided pointer down/up events.
6586

87+
### `useXRInputSourceEvent`
88+
89+
Hook for listening to xr input source events.
90+
6691
## Inputs
6792

6893
Building custom inputs requires access and bindings to the events. The following hook allow to access the inputs state and bind function to events.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Development Setup
3+
description: Setup your development environment for building XR experiences.
4+
nav: 2
5+
---
6+
7+
Building WebXR experiences has all the advantages of building for the web, with a lot of tool chains, debugging tools, and resources available.
8+
Because there are so many tools available, it is often hard to choose a development setup. Therefore, we would like to recommend you a development setup for developing with `react-three/xr`.
9+
10+
## 1. Build tool: [vite](https://vitejs.dev/)
11+
12+
Vite is easy to set up and has all the features we need. We recommend using the packages `@vitejs/plugin-react` to enable hot module reloading and `@vitejs/plugin-basic-ssl` to enable `https`, which is required for any WebXR experience.
13+
14+
A basic `vite.config.ts` would look like this:
15+
16+
```ts
17+
import { defineConfig } from 'vite'
18+
import react from '@vitejs/plugin-react'
19+
import basicSsl from '@vitejs/plugin-basic-ssl'
20+
21+
export default defineConfig({
22+
plugins: [react(), basicSsl()],
23+
})
24+
```
25+
26+
## 2. emulator: [iwer/devui](https://github.com/meta-quest/immersive-web-emulation-runtime/tree/main/devui)
27+
28+
Developing WebXR experiences often requires testing WebXR-specific features, which either require an actual device or an emulator. An emulator allows testing without a specific device and without continuously switching a headset on and off.
29+
30+
`react-three/xr` includes the [iwer/devui](https://github.com/meta-quest/immersive-web-emulation-runtime/tree/main/devui) emulator out of the box. The emulator builds on [IWER by meta](https://github.com/meta-quest/immersive-web-emulation-runtime/) and adds a easy to use overlay on top of your application. The emulator is activated if no WebXR support is detected on `localhost` or by pressing `Window/Command + Alt/Option + E`.
31+
32+
![iwer/devui](./emulator.gif)
33+
34+
The existing [Immersive Web Emulator](https://chromewebstore.google.com/detail/immersive-web-emulator/cgffilbpcibhmcfbgggfhfolhkfbhmik) and the previous [WebXR API Emulator](https://chromewebstore.google.com/detail/webxr-api-emulator/mjddjgeghkdijejnciaefnkjmkafnnje?hl=de) are not supported because they do not comply to the WebXR spec. If you have one of those installed and active, please turn them off, as they will prevent activiting the built-in emulator.
35+
36+
Another supported alternative is the Apple Vision Pro Simulator.
37+
38+
### 3. ADB
39+
40+
Sometimes, a WebXR experience works floorless in the emulator but fails on the actual device. In this case we recommend using Android Device Bridge (ADB) to debug your experience from another device. For example, to remotely debug a WebXR experience on a Meta Quest 3, the Meta Quest 3 must be in developer mode, and remote debugging must be enabled. Then, the Meta Quest 3 must be connected to a PC via a USB cable with ADB installed. With this setup, the Chrome browser can now be used to access `chrome://inspect` to inspect specific tabs on the device remotely.
41+
42+
If you are using the Apple Vision Pro, there are similar features to remotely debug a WebXR experience on the Apple Vision Pro from a Safari browser on another device.

docs/getting-started/emulator.gif

1020 KB
Loading

docs/getting-started/faq.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: FAQ
3+
description: Frequently asked questions about react-three/xr.
4+
nav: 5
5+
---
6+
7+
## How can I exit an XR session?
8+
9+
```ts
10+
store.getState().session?.end()
11+
```
12+
13+
## WebGPU
14+
15+
WebGPU is finding its way to more and more devices. However, AR and VR devices do not yet implement WebGPU for WebXR, which requires the [WebXR-WebGPU-Binding](https://github.com/immersive-web/WebXR-WebGPU-Binding/blob/main/explainer.md). Therefore, WebGPU is not yet usable for WebXR in general.
16+
17+
## How can I put HTML in my XR scene?
18+
19+
If you are targeting only handheld AR experiences (e.g., for smartphones), you can use dom overlay. Here's a [tutorial for using XRDomOverlays](../tutorials/dom-overlay.md) in your `react-three/xr` experience.
20+
21+
For non-handheld VR and AR experiences, you can use [react-three/uikit](https://github.com/pmndrs/uikit), which renders user interfaces directly inside the 3D scene and is aligned with HTML and CSS concepts.
22+
23+
## Does it work on iOS?
24+
25+
WebXR for VR experiences is supported on Safari for Apple Vision Pro.
26+
WebXR is not supported on iOS Safari yet. The alternative is to use products such as [Variant Launch](https://launch.variant3d.com/), which allow to build WebXR experiences for iOS.

docs/getting-started/introduction.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,25 @@ export function App() {
4646

4747
## Tutorials
4848

49+
- 💾 [Store](../tutorials/store.md)
4950
- 👌 [Interactions](../tutorials/interactions.md)
5051
- 🔧 [Options](../tutorials/options.md)
5152
- 🧊 [Object Detection](../tutorials/object-detection.md)
5253
-[Origin](../tutorials/origin.md)
5354
- 🪄 [Teleport](../tutorials/teleport.md)
5455
- 🕹️ [Gamepad](../tutorials/gamepad.md)
5556
- 🎮 [Custom Controller/Hands/...](../tutorials/custom-inputs.md)
57+
- ⚓️ [Anchors](../tutorials/anchors.md)
58+
- 📱 [Dom Overlay](../tutorials/dom-overlay.md)
59+
- 🎯 [Hit Test](../tutorials/hit-test.md)
5660
-[Guards](../tutorials/guards.md)
5761

5862
## Roadmap
5963

6064
- 🤳 XR Gestures
6165
- ➕ Multimodal
62-
- ⚓️ Anchors
6366
- 📺 Layers
64-
- 📱 Dom Overlays
6567
- 🕺 Tracked Body
66-
- 🎯 Hit Test
6768
- ↕ react-three/controls
6869

6970
## Migration guides

docs/tutorials/anchors.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
title: Anchors
3+
description: How to create and manage anchors in your AR experience?
4+
nav: 12
5+
---
6+
7+
Anchors allow to anchor virtual objects into the physical world in AR experiences. `react-three/xr` offers a multitude of ways to create and manage anchors. A simple solution is `useXRAnchor`, which works similarly to `useState` as it returns the current anchor and a function to request a new anchor as a tuple.
8+
9+
```tsx
10+
const [anchor, requestAnchor] = useXRAnchor()
11+
```
12+
13+
With the `requestAnchor` function, we can request an anchor relative to the `"world"`, a `"space"`, or a `"hitTestResult"`
14+
15+
```tsx
16+
requestAnchor({ relativeTo: "space", space: ... })
17+
```
18+
19+
Once the anchor is created, the `useXRAnchor` hook exposes it as `anchor`. We can now use this `anchor` to put content into it using the `<XRSpace>` component.
20+
21+
```tsx
22+
<XRSpace space={anchor.anchorSpace}>
23+
...your content
24+
</XRSpace>
25+
```
26+
27+
The following example shows a `Anchor` component that uses the `useXRAnchor` hook and the `XRSpace` component to anchor a Box to the position of the right hand or controller when the respective hand or controller is selected (pinch/trigger).
28+
29+
```tsx
30+
export function Anchor() {
31+
const [anchor, requestAnchor] = useXRAnchor()
32+
const controllerState = useXRControllerState('right')
33+
const handState = useXRHandState('right')
34+
const inputSource = controllerState?.inputSource ?? handState?.inputSource
35+
useXRInputSourceEvent(
36+
inputSource,
37+
'select',
38+
async () => {
39+
if (inputSource == null) {
40+
return
41+
}
42+
requestAnchor({ relativeTo: 'space', space: inputSource.targetRaySpace })
43+
},
44+
[requestAnchor, inputSource],
45+
)
46+
if (anchor == null) {
47+
return null
48+
}
49+
return (
50+
<XRSpace space={anchor.anchorSpace}>
51+
<mesh scale={0.1}>
52+
<boxGeometry />
53+
</mesh>
54+
</XRSpace>
55+
)
56+
}
57+
```

docs/tutorials/dom-overlay.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: Dom Overlay
3+
description: How to add HTML elements for hand-held AR experiences with Dom overlay?
4+
nav: 13
5+
---
6+
7+
For hand-held AR experiences, such as those using a Smartphone, WebXR offers the dom overlay capability, allowing developers to use HTML code overlayed over the experience. In case scene 3D overlays or overlays in non-handheld AR/VR experiences are needed, check out [pmndrs/uikit](https://github.com/pmndrs/uikit).
8+
9+
We can add dom overlay content to an experience using the `XRDomOverlay` component, which allows to write html code inside it. This HTML code will be overlayed over the hand-held AR experience.
10+
11+
```tsx
12+
<XRDomOverlay
13+
style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
14+
>
15+
<div style={{ backgroundColor: 'red', padding: '1rem 2rem' }}>Hello World</div>
16+
</XRDomOverlay>
17+
```
18+
19+
The following shows the complete code for a simple AR experience with a `Hello World` button that can toggle its color when clicked on.
20+
21+
```tsx
22+
const store = createXRStore()
23+
24+
export function App() {
25+
const [bool, setBool] = useState(false)
26+
return (
27+
<>
28+
<button onClick={() => store.enterAR()}>Enter AR</button>
29+
<Canvas>
30+
<XR store={store}>
31+
<ambientLight />
32+
<XRDomOverlay
33+
style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
34+
>
35+
<div
36+
style={{ backgroundColor: bool ? 'red' : 'green', padding: '1rem 2rem' }}
37+
onClick={() => setBool((b) => !b)}
38+
>
39+
Hello World
40+
</div>
41+
</XRDomOverlay>
42+
</XR>
43+
</Canvas>
44+
</>
45+
)
46+
}
47+
```

0 commit comments

Comments
 (0)