Skip to content

Commit 82c1b03

Browse files
authored
Merge pull request #439 from acrilique/main
XRLayer: depth sorting prototype
2 parents bcef5d5 + ae67c5b commit 82c1b03

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed

packages/react/xr/src/layer.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,11 @@ export const XRLayerImplementation = forwardRef<
239239
if (layer == null) {
240240
return
241241
}
242-
const layerEntry = (layerEntryRef.current = { layer, renderOrder: renderOrderRef.current })
242+
const layerEntry = (layerEntryRef.current = {
243+
layer,
244+
renderOrder: renderOrderRef.current,
245+
object3D: internalRef.current!,
246+
})
243247
store.addLayerEntry(layerEntry)
244248
if (resolvedSrc instanceof HTMLVideoElement || resolvedSrc instanceof WebGLRenderTarget) {
245249
return () => {

packages/xr/src/layer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ import { getSpaceFromAncestors } from './space.js'
2020
import { XRState, XRStore } from './store.js'
2121
import { toDOMPointInit } from './utils.js'
2222

23-
export type XRLayerEntry = { renderOrder: number; readonly layer: XRCylinderLayer | XRQuadLayer | XREquirectLayer }
23+
export type XRLayerEntry = {
24+
renderOrder: number
25+
readonly layer: XRCylinderLayer | XRQuadLayer | XREquirectLayer
26+
readonly object3D: Object3D
27+
}
2428

2529
export type XRLayerOptions = Pick<
2630
Partial<XRCylinderLayerInit & XRQuadLayerInit & XREquirectLayerInit>,

packages/xr/src/store.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { XRDevice } from 'iwer'
2-
import { Camera, Object3D, WebXRManager } from 'three'
2+
import { Camera, Object3D, WebXRManager, Vector3 } from 'three'
33
import { StoreApi, createStore } from 'zustand/vanilla'
44
import { XRControllerLayoutLoaderOptions, updateXRControllerState } from './controller/index.js'
55
import { XRHandLoaderOptions } from './hand/index.js'
@@ -427,6 +427,10 @@ declare global {
427427
}
428428
}
429429

430+
//helpers for layer sorting
431+
const cameraWorldPosition = new Vector3()
432+
const tempLayerWorldPosition = new Vector3()
433+
430434
export function createXRStore<T extends XRElementImplementations>(options?: XRStoreOptions<T>): XRStore<T> {
431435
//dom overlay root element creation
432436
const domOverlayRoot =
@@ -678,8 +682,25 @@ export function createXRStore<T extends XRElementImplementations>(options?: XRSt
678682
if (currentLayers == null) {
679683
return
680684
}
681-
//TODO: sort by distance to camera
682-
;(layerEntries as Array<(typeof layerEntries)[number]>).sort((l1, l2) => l1.renderOrder - l2.renderOrder)
685+
//layer sorting
686+
const xrCamera = xrManager.getCamera()
687+
xrCamera.getWorldPosition(cameraWorldPosition)
688+
;(layerEntries as Array<XRLayerEntry>).sort((entryA, entryB) => {
689+
const renderOrderDifference = entryA.renderOrder - entryB.renderOrder
690+
691+
//if renderOrder is the same, sort by distance to camera
692+
if (renderOrderDifference !== 0) {
693+
return renderOrderDifference
694+
}
695+
696+
entryA.object3D.getWorldPosition(tempLayerWorldPosition)
697+
const distA_sq = tempLayerWorldPosition.distanceToSquared(cameraWorldPosition)
698+
699+
entryB.object3D.getWorldPosition(tempLayerWorldPosition)
700+
const distB_sq = tempLayerWorldPosition.distanceToSquared(cameraWorldPosition)
701+
702+
return distB_sq - distA_sq
703+
})
683704
let changed = false
684705
const layers = layerEntries.map<XRLayer>(({ layer }, i) => {
685706
if (layer != currentLayers[i]) {

packages/xr/src/vanilla/layer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export class XRLayer extends Mesh<BufferGeometry, MeshBasicMaterial> {
6969
this.cleanup = () => {}
7070
return
7171
}
72-
const layerEntry = (this.layerEntry = { layer, renderOrder: this.layerRenderOrder })
72+
const layerEntry = (this.layerEntry = { layer, renderOrder: this.layerRenderOrder, object3D: this })
7373
store.addLayerEntry(this.layerEntry)
7474
if (options.src instanceof HTMLVideoElement || options.src instanceof WebGLRenderTarget) {
7575
this.cleanup = () => this.store.removeLayerEntry(layerEntry)

0 commit comments

Comments
 (0)