Use a tracker coordinate system instead of stage. Update examples so they function but next they need to use the (not yet implemented) floor anchors.
This commit is contained in:
Родитель
a86bafcab0
Коммит
34e88a32ef
11
CODING.md
11
CODING.md
|
@ -57,9 +57,8 @@ The scene, camera, and renderer objects below are representative APIs that have
|
||||||
// Set up for the next frame
|
// Set up for the next frame
|
||||||
session.requestFrame(frame => { handleFrame(frame) })
|
session.requestFrame(frame => { handleFrame(frame) })
|
||||||
|
|
||||||
// Get the pose for the world coordinate system
|
// Get the pose for the HMD or handset tracker coordinate system
|
||||||
let stageCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.STAGE)
|
let trackerCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.TRACKER)
|
||||||
let stagePose = frame.getViewPose(stageCoordinateSystem)
|
|
||||||
|
|
||||||
// Get the pose for the head
|
// Get the pose for the head
|
||||||
let headCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.HEAD_MODEL)
|
let headCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.HEAD_MODEL)
|
||||||
|
@ -126,11 +125,11 @@ You now have a couple of anchored nodes save in `anchoredNodes`, so during each
|
||||||
const anchor = frame.getAnchor(anchoredNode.anchorOffset.anchorUID)
|
const anchor = frame.getAnchor(anchoredNode.anchorOffset.anchorUID)
|
||||||
// Get the offset coordinates relative to the anchor
|
// Get the offset coordinates relative to the anchor
|
||||||
let offsetCoordinates = anchoredNode.anchorOffset.getTransformedCoordinates(anchor)
|
let offsetCoordinates = anchoredNode.anchorOffset.getTransformedCoordinates(anchor)
|
||||||
// Now use the offset coordinates, possibly by converting to the stage coordinate system.
|
// Now use the offset coordinates, possibly by converting to the tracker coordinate system.
|
||||||
if(offsetCoordinates.coordinateSystem.type === XRCoordinateSystem.STAGE){
|
if(offsetCoordinates.coordinateSystem.type === XRCoordinateSystem.TRACKER){
|
||||||
anchoredNode.node.matrix = offsetCoordinates.poseMatrix
|
anchoredNode.node.matrix = offsetCoordinates.poseMatrix
|
||||||
} else {
|
} else {
|
||||||
anchoredNode.node.matrix = offsetCoordinates.getTransformedCoordinates(stageCoordinateSystem).poseMatrix
|
anchoredNode.node.matrix = offsetCoordinates.getTransformedCoordinates(trackerCoordinateSystem).poseMatrix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,11 +58,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called during construction
|
// Called during construction
|
||||||
initializeStageGroup(){
|
initializeScene(){
|
||||||
this.stageGroup.add(new THREE.AmbientLight('#FFF', 0.2))
|
this.scene.add(new THREE.AmbientLight('#FFF', 0.2))
|
||||||
let directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
|
let directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
|
||||||
directionalLight.position.set(0, 10, 0)
|
directionalLight.position.set(0, 10, 0)
|
||||||
this.stageGroup.add(directionalLight)
|
this.scene.add(directionalLight)
|
||||||
}
|
}
|
||||||
|
|
||||||
createSceneGraphNode(){
|
createSceneGraphNode(){
|
||||||
|
@ -83,8 +83,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called once per frame
|
// Called once per frame
|
||||||
updateStageGroup(frame, stageCoordinateSystem, stagePose){
|
updateScene(frame){
|
||||||
let headCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.HEAD_MODEL)
|
const headCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.HEAD_MODEL)
|
||||||
|
const trackerCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.TRACKER)
|
||||||
|
|
||||||
// Create anchors for newly anchored nodes
|
// Create anchors for newly anchored nodes
|
||||||
for(let anchorToAdd of this.anchorsToAdd){
|
for(let anchorToAdd of this.anchorsToAdd){
|
||||||
|
@ -102,7 +103,7 @@
|
||||||
anchorUID: anchorUID,
|
anchorUID: anchorUID,
|
||||||
node: anchorToAdd.node
|
node: anchorToAdd.node
|
||||||
})
|
})
|
||||||
this.stageGroup.add(anchorToAdd.node)
|
this.scene.add(anchorToAdd.node)
|
||||||
}
|
}
|
||||||
this.anchorsToAdd = []
|
this.anchorsToAdd = []
|
||||||
|
|
||||||
|
@ -113,7 +114,7 @@
|
||||||
console.error('Unknown anchor ID', anchoredNode.anchorId)
|
console.error('Unknown anchor ID', anchoredNode.anchorId)
|
||||||
} else {
|
} else {
|
||||||
anchoredNode.node.matrixAutoUpdate = false
|
anchoredNode.node.matrixAutoUpdate = false
|
||||||
anchoredNode.node.matrix.fromArray(anchor.coordinates.getTransformedCoordinates(stageCoordinateSystem).poseMatrix)
|
anchoredNode.node.matrix.fromArray(anchor.coordinates.getTransformedCoordinates(trackerCoordinateSystem).poseMatrix)
|
||||||
anchoredNode.node.updateMatrixWorld(true)
|
anchoredNode.node.updateMatrixWorld(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,45 +36,45 @@
|
||||||
<div id="target" />
|
<div id="target" />
|
||||||
<script>
|
<script>
|
||||||
/*
|
/*
|
||||||
ARSimplestExample shows how to populate the stage group that is rendered on the stage
|
ARSimplestExample shows how to populate the content scene
|
||||||
*/
|
*/
|
||||||
class ARSimplestExample extends XRExampleBase {
|
class ARSimplestExample extends XRExampleBase {
|
||||||
constructor(domElement){
|
constructor(domElement){
|
||||||
super(domElement, false)
|
super(domElement, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called during construction to allow the app to populate this.stageGroup (a THREE.Group)
|
// Called during construction to allow the app to populate the THREE.Scene
|
||||||
initializeStageGroup(){
|
initializeScene(){
|
||||||
// Add a teapot at about eye level
|
// Add a teapot at about eye level
|
||||||
var geometry = new THREE.TeapotBufferGeometry(0.1)
|
const geometry = new THREE.TeapotBufferGeometry(0.1)
|
||||||
let materialColor = new THREE.Color()
|
const materialColor = new THREE.Color()
|
||||||
materialColor.setRGB(1.0, 1.0, 1.0)
|
materialColor.setRGB(1.0, 1.0, 1.0)
|
||||||
let material = new THREE.MeshLambertMaterial({
|
const material = new THREE.MeshLambertMaterial({
|
||||||
color: materialColor,
|
color: materialColor,
|
||||||
side: THREE.DoubleSide
|
side: THREE.DoubleSide
|
||||||
})
|
})
|
||||||
let mesh = new THREE.Mesh(geometry, material)
|
const mesh = new THREE.Mesh(geometry, material)
|
||||||
mesh.position.set(0, 1.4, -1)
|
mesh.position.set(0, 1.4, -1)
|
||||||
this.stageGroup.add(mesh)
|
this.scene.add(mesh)
|
||||||
|
|
||||||
// Add a box at the stage origin
|
// Add a box at the scene origin
|
||||||
let box = new THREE.Mesh(
|
const box = new THREE.Mesh(
|
||||||
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
|
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
|
||||||
new THREE.MeshPhongMaterial({ color: '#DDFFDD' })
|
new THREE.MeshPhongMaterial({ color: '#DDFFDD' })
|
||||||
)
|
)
|
||||||
box.position.set(0, 0, 0)
|
box.position.set(0, 0, 0)
|
||||||
this.stageGroup.add(box)
|
this.scene.add(box)
|
||||||
|
|
||||||
this.stageGroup.add(new THREE.AmbientLight('#FFF', 0.2))
|
this.scene.add(new THREE.AmbientLight('#FFF', 0.2))
|
||||||
let directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
|
const directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
|
||||||
directionalLight.position.set(0, 10, 0)
|
directionalLight.position.set(0, 10, 0)
|
||||||
this.stageGroup.add(directionalLight)
|
this.scene.add(directionalLight)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called once per frame, before render to give the app a chance to update this.stageGroup (a THREE.Group)
|
// Called once per frame, before render to give the app a chance to update the this.scene
|
||||||
updateStageGroup(frame, stageCoordinateSystem, stagePose){
|
updateScene(frame){
|
||||||
// Uncomment the next line to spin the teapot
|
// Uncomment the next line to spin the teapot
|
||||||
//this.stageGroup.children[0].rotation.y += 0.01
|
//this.scene.children[0].rotation.y += 0.01
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,12 @@ class XRExampleBase {
|
||||||
|
|
||||||
// Create a simple THREE test scene for the layer
|
// Create a simple THREE test scene for the layer
|
||||||
this.scene = new THREE.Scene() // The scene will be rotated and oriented around the camera using the head pose
|
this.scene = new THREE.Scene() // The scene will be rotated and oriented around the camera using the head pose
|
||||||
this.stageGroup = new THREE.Group() // The group that stays on the "stage", which is at foot level relative to the head
|
|
||||||
this.scene.add(this.stageGroup)
|
|
||||||
|
|
||||||
this.camera = new THREE.PerspectiveCamera(70, 1024, 1024, 0.1, 1000) // These values will be overwritten by the projection matrix from ARKit or ARCore
|
this.camera = new THREE.PerspectiveCamera(70, 1024, 1024, 0.1, 1000) // These values will be overwritten by the projection matrix from ARKit or ARCore
|
||||||
this.renderer = null // Set in this.handleNewSession
|
this.renderer = null // Set in this.handleNewSession
|
||||||
|
|
||||||
// Give extending classes the opportunity to initially populate the stage group
|
// Give extending classes the opportunity to initially populate the scene
|
||||||
this.initializeStageGroup(this.stageGroup)
|
this.initializeScene()
|
||||||
|
|
||||||
if(typeof navigator.XR === 'undefined'){
|
if(typeof navigator.XR === 'undefined'){
|
||||||
this.showMessage('No WebXR API found, usually because the WebXR polyfill has not loaded')
|
this.showMessage('No WebXR API found, usually because the WebXR polyfill has not loaded')
|
||||||
|
@ -154,46 +152,27 @@ class XRExampleBase {
|
||||||
handleLayerBlur(ev){}
|
handleLayerBlur(ev){}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Extending classes should override this to set up the stageGroup during class construction
|
Extending classes should override this to set up the scene during class construction
|
||||||
*/
|
*/
|
||||||
initializeStageGroup(){}
|
initializeScene(){}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Extending classes that need to update the layer during each frame should override this method
|
Extending classes that need to update the layer during each frame should override this method
|
||||||
*/
|
*/
|
||||||
updateStageGroup(frame, stageCoordinateSystem, stagePose){}
|
updateScene(frame){}
|
||||||
|
|
||||||
handleFrame(frame){
|
handleFrame(frame){
|
||||||
const nextFrameRequest = this.session.requestFrame(frame => { this.handleFrame(frame) })
|
const nextFrameRequest = this.session.requestFrame(frame => { this.handleFrame(frame) })
|
||||||
let stageCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.STAGE)
|
|
||||||
if(stageCoordinateSystem === null){
|
|
||||||
this.showMessage('Could not get a usable stage coordinate system')
|
|
||||||
this.session.cancelFrame(nextFrameRequest)
|
|
||||||
this.session.endSession()
|
|
||||||
// Production apps could render a 'waiting' message and keep checking for an acceptable coordinate system
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the two poses we care about: the foot level stage and head pose which is updated by ARKit, ARCore, or orientation events
|
|
||||||
let stagePose = frame.getViewPose(stageCoordinateSystem)
|
|
||||||
let headPose = frame.getViewPose(frame.getCoordinateSystem(XRCoordinateSystem.HEAD_MODEL))
|
let headPose = frame.getViewPose(frame.getCoordinateSystem(XRCoordinateSystem.HEAD_MODEL))
|
||||||
|
|
||||||
// Let the extending class update the stageGroup before each render
|
// Let the extending class update the scene before each render
|
||||||
this.updateStageGroup(frame, stageCoordinateSystem, stagePose)
|
this.updateScene(frame)
|
||||||
|
|
||||||
// Update the stage group relative to the current head pose
|
|
||||||
this.stageGroup.matrixAutoUpdate = false
|
|
||||||
this.stageGroup.matrix.fromArray(stagePose.poseModelMatrix)
|
|
||||||
this.stageGroup.updateMatrixWorld(true)
|
|
||||||
|
|
||||||
// Prep THREE.js for the render of each XRView
|
// Prep THREE.js for the render of each XRView
|
||||||
//this.renderer.resetGLState()
|
|
||||||
this.scene.matrixAutoUpdate = false
|
|
||||||
this.renderer.autoClear = false
|
this.renderer.autoClear = false
|
||||||
this.renderer.setSize(this.session.baseLayer.framebufferWidth, this.session.baseLayer.framebufferHeight, false)
|
this.renderer.setSize(this.session.baseLayer.framebufferWidth, this.session.baseLayer.framebufferHeight, false)
|
||||||
this.renderer.clear()
|
this.renderer.clear()
|
||||||
|
this.scene.matrixAutoUpdate = false
|
||||||
//this.session.baseLayer.context.bindFramebuffer(this.session.baseLayer.context.FRAMEBUFFER, this.session.baseLayer.framebuffer)
|
|
||||||
|
|
||||||
// Render each view into this.session.baseLayer.context
|
// Render each view into this.session.baseLayer.context
|
||||||
for(const view of frame.views){
|
for(const view of frame.views){
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
class HitTestExample extends XRExampleBase {
|
class HitTestExample extends XRExampleBase {
|
||||||
constructor(domElement){
|
constructor(domElement){
|
||||||
super(domElement, false)
|
super(domElement, false)
|
||||||
this._tapEventData = null // Will be filled in on touch start and used in updateStageGroup
|
this._tapEventData = null // Will be filled in on touch start and used in updateScene
|
||||||
|
|
||||||
this.anchoredNodes = [] // { XRAnchorOffset, Three.js Object3D }
|
this.anchoredNodes = [] // { XRAnchorOffset, Three.js Object3D }
|
||||||
|
|
||||||
|
@ -63,33 +63,33 @@
|
||||||
this.el.addEventListener('touchstart', this._onTouchStart.bind(this), false)
|
this.el.addEventListener('touchstart', this._onTouchStart.bind(this), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called during construction to allow the app to populate this.stageGroup (a THREE.Group)
|
// Called during construction to allow the app to populate this.scene
|
||||||
initializeStageGroup(){
|
initializeScene(){
|
||||||
// Add a box at the stage origin to show where the stage group is located
|
// Add a box at the scene origin
|
||||||
let box = new THREE.Mesh(
|
let box = new THREE.Mesh(
|
||||||
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
|
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
|
||||||
new THREE.MeshPhongMaterial({ color: '#DDFFDD' })
|
new THREE.MeshPhongMaterial({ color: '#DDFFDD' })
|
||||||
)
|
)
|
||||||
box.position.set(0, 0, 0)
|
box.position.set(0, 0, 0)
|
||||||
this.stageGroup.add(box)
|
this.scene.add(box)
|
||||||
|
|
||||||
// Add a box one meter in front of stage origin to show the direction of the Z axis
|
// Add a box one meter in front of scene origin to show the direction of the Z axis
|
||||||
box = new THREE.Mesh(
|
box = new THREE.Mesh(
|
||||||
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
|
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
|
||||||
new THREE.MeshPhongMaterial({ color: '#FF0000' })
|
new THREE.MeshPhongMaterial({ color: '#FF0000' })
|
||||||
)
|
)
|
||||||
box.position.set(0, 0, -1)
|
box.position.set(0, 0, -1)
|
||||||
this.stageGroup.add(box)
|
this.scene.add(box)
|
||||||
|
|
||||||
// Add a few lights
|
// Add a few lights
|
||||||
this.stageGroup.add(new THREE.AmbientLight('#FFF', 0.2))
|
this.scene.add(new THREE.AmbientLight('#FFF', 0.2))
|
||||||
let directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
|
let directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
|
||||||
directionalLight.position.set(0, 10, 0)
|
directionalLight.position.set(0, 10, 0)
|
||||||
this.stageGroup.add(directionalLight)
|
this.scene.add(directionalLight)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called once per frame, before render, to give the app a chance to update this.stageGroup (a THREE.Group)
|
// Called once per frame, before render, to give the app a chance to update this.scene
|
||||||
updateStageGroup(frame, stageCoordinateSystem, stagePose){
|
updateScene(frame){
|
||||||
// If we have tap data, attempt a hit test for a surface
|
// If we have tap data, attempt a hit test for a surface
|
||||||
if(this._tapEventData !== null){
|
if(this._tapEventData !== null){
|
||||||
const x = this._tapEventData[0]
|
const x = this._tapEventData[0]
|
||||||
|
@ -116,13 +116,14 @@
|
||||||
|
|
||||||
// Add a block to the scene to indicate the position of the XRAnchorOffset
|
// Add a block to the scene to indicate the position of the XRAnchorOffset
|
||||||
// Its position will be updated below along with the other anchored nodes
|
// Its position will be updated below along with the other anchored nodes
|
||||||
this.stageGroup.add(anchorInfo.node)
|
this.scene.add(anchorInfo.node)
|
||||||
}
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('Error in hit test', err)
|
console.error('Error in hit test', err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const trackerCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.TRACKER)
|
||||||
// Update anchored node positions in the scene graph using updated anchor positions
|
// Update anchored node positions in the scene graph using updated anchor positions
|
||||||
for(let anchoredNode of this.anchoredNodes){
|
for(let anchoredNode of this.anchoredNodes){
|
||||||
const anchor = frame.getAnchor(anchoredNode.anchorOffset.anchorUID)
|
const anchor = frame.getAnchor(anchoredNode.anchorOffset.anchorUID)
|
||||||
|
@ -131,17 +132,17 @@
|
||||||
} else {
|
} else {
|
||||||
anchoredNode.node.matrixAutoUpdate = false
|
anchoredNode.node.matrixAutoUpdate = false
|
||||||
let offsetCoordinates = anchoredNode.anchorOffset.getTransformedCoordinates(anchor)
|
let offsetCoordinates = anchoredNode.anchorOffset.getTransformedCoordinates(anchor)
|
||||||
if(offsetCoordinates.coordinateSystem.type === XRCoordinateSystem.STAGE){
|
if(offsetCoordinates.coordinateSystem.type === XRCoordinateSystem.TRACKER){
|
||||||
anchoredNode.node.matrix.fromArray(offsetCoordinates.poseMatrix)
|
anchoredNode.node.matrix.fromArray(offsetCoordinates.poseMatrix)
|
||||||
} else {
|
} else {
|
||||||
anchoredNode.node.matrix.fromArray(offsetCoordinates.getTransformedCoordinates(stageCoordinateSystem).poseMatrix)
|
anchoredNode.node.matrix.fromArray(offsetCoordinates.getTransformedCoordinates(trackerCoordinateSystem).poseMatrix)
|
||||||
}
|
}
|
||||||
anchoredNode.node.updateMatrixWorld(true)
|
anchoredNode.node.updateMatrixWorld(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save screen taps as normalized coordinates for use in this.updateStageGroup
|
// Save screen taps as normalized coordinates for use in this.updateScene
|
||||||
_onTouchStart(ev){
|
_onTouchStart(ev){
|
||||||
if (!ev.touches || ev.touches.length === 0) {
|
if (!ev.touches || ev.touches.length === 0) {
|
||||||
console.error('No touches on touch event', ev)
|
console.error('No touches on touch event', ev)
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called during construction
|
// Called during construction
|
||||||
initializeStageGroup(){
|
initializeScene(){
|
||||||
// Add a teapot at about eye level
|
// Add a teapot at about eye level
|
||||||
var geometry = new THREE.TeapotBufferGeometry(0.1)
|
var geometry = new THREE.TeapotBufferGeometry(0.1)
|
||||||
let materialColor = new THREE.Color()
|
let materialColor = new THREE.Color()
|
||||||
|
@ -61,26 +61,26 @@
|
||||||
})
|
})
|
||||||
let mesh = new THREE.Mesh(geometry, material)
|
let mesh = new THREE.Mesh(geometry, material)
|
||||||
mesh.position.set(0, 1.6, -1)
|
mesh.position.set(0, 1.6, -1)
|
||||||
this.stageGroup.add(mesh)
|
this.scene.add(mesh)
|
||||||
|
|
||||||
// Add a box at the stage origin
|
// Add a box at the scene origin
|
||||||
let box = new THREE.Mesh(
|
let box = new THREE.Mesh(
|
||||||
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
|
new THREE.BoxBufferGeometry(0.1, 0.1, 0.1),
|
||||||
new THREE.MeshPhongMaterial({ color: '#DDFFDD' })
|
new THREE.MeshPhongMaterial({ color: '#DDFFDD' })
|
||||||
)
|
)
|
||||||
box.position.set(0, 0, 0)
|
box.position.set(0, 0, 0)
|
||||||
this.stageGroup.add(box)
|
this.scene.add(box)
|
||||||
|
|
||||||
this.stageGroup.add(new THREE.AmbientLight('#FFF', 0.2))
|
this.scene.add(new THREE.AmbientLight('#FFF', 0.2))
|
||||||
let directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
|
let directionalLight = new THREE.DirectionalLight('#FFF', 0.6)
|
||||||
directionalLight.position.set(0, 10, 0)
|
directionalLight.position.set(0, 10, 0)
|
||||||
this.stageGroup.add(directionalLight)
|
this.scene.add(directionalLight)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called once per frame
|
// Called once per frame
|
||||||
updateStageGroup(frame, stageCoordinateSystem, stagePose){
|
updateScene(frame){
|
||||||
// Uncomment the next line to spin the box
|
// Uncomment the next line to spin the box
|
||||||
// this.stageGroup.children[0].rotation.y += 0.01
|
// this.scene.children[0].rotation.y += 0.01
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ The XRCoordinateSystem is a string from XRCoordinateSystem.TYPES:
|
||||||
|
|
||||||
- XRCoordinateSystem.HEAD_MODEL: origin is aligned with the pose of the head, as sensed by HMD or handset trackers
|
- XRCoordinateSystem.HEAD_MODEL: origin is aligned with the pose of the head, as sensed by HMD or handset trackers
|
||||||
- XRCoordinateSystem.EYE_LEVEL: origin is at a fixed distance above the ground
|
- XRCoordinateSystem.EYE_LEVEL: origin is at a fixed distance above the ground
|
||||||
- XRCoordinateSystem.STAGE: origin is at ground level
|
- XRCoordinateSystem.TRACKER: The origin of this coordinate system is at floor level at or below the origin of the HMD or handset provided tracking system
|
||||||
- XRCoordinateSystem.GEOSPATIAL: origin is at the East, Up, South plane tangent to the planet at the latitude, longitude, and altitude represented by the `XRCoordinateSystem.cartographicCoordinates`.
|
- XRCoordinateSystem.GEOSPATIAL: origin is at the East, Up, South plane tangent to the planet at the latitude, longitude, and altitude represented by the `XRCoordinateSystem.cartographicCoordinates`.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -28,8 +28,8 @@ export default class XRCoordinateSystem {
|
||||||
return this._display._headPose.poseModelMatrix
|
return this._display._headPose.poseModelMatrix
|
||||||
case XRCoordinateSystem.EYE_LEVEL:
|
case XRCoordinateSystem.EYE_LEVEL:
|
||||||
return this._display._eyeLevelPose.poseModelMatrix
|
return this._display._eyeLevelPose.poseModelMatrix
|
||||||
case XRCoordinateSystem.STAGE:
|
case XRCoordinateSystem.TRACKER:
|
||||||
return this._display._stagePose.poseModelMatrix
|
return this._display._trackerPoseModelMatrix
|
||||||
case XRCoordinateSystem.GEOSPATIAL:
|
case XRCoordinateSystem.GEOSPATIAL:
|
||||||
throw 'This polyfill does not yet handle geospatial coordinate systems'
|
throw 'This polyfill does not yet handle geospatial coordinate systems'
|
||||||
default:
|
default:
|
||||||
|
@ -60,14 +60,14 @@ export default class XRCoordinateSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XRCoordinateSystem.HEAD_MODEL = "headModel"
|
XRCoordinateSystem.HEAD_MODEL = 'headModel'
|
||||||
XRCoordinateSystem.EYE_LEVEL = "eyeLevel"
|
XRCoordinateSystem.EYE_LEVEL = 'eyeLevel'
|
||||||
XRCoordinateSystem.STAGE = "stage"
|
XRCoordinateSystem.TRACKER = 'tracker'
|
||||||
XRCoordinateSystem.GEOSPATIAL = "geospatial"
|
XRCoordinateSystem.GEOSPATIAL = 'geospatial'
|
||||||
|
|
||||||
XRCoordinateSystem.TYPES = [
|
XRCoordinateSystem.TYPES = [
|
||||||
XRCoordinateSystem.HEAD_MODEL,
|
XRCoordinateSystem.HEAD_MODEL,
|
||||||
XRCoordinateSystem.EYE_LEVEL,
|
XRCoordinateSystem.EYE_LEVEL,
|
||||||
XRCoordinateSystem.STAGE,
|
XRCoordinateSystem.TRACKER,
|
||||||
XRCoordinateSystem.GEOSPATIAL
|
XRCoordinateSystem.GEOSPATIAL
|
||||||
]
|
]
|
|
@ -18,11 +18,16 @@ export default class XRDisplay extends EventHandlerBase {
|
||||||
|
|
||||||
this._headModelCoordinateSystem = new XRCoordinateSystem(this, XRCoordinateSystem.HEAD_MODEL)
|
this._headModelCoordinateSystem = new XRCoordinateSystem(this, XRCoordinateSystem.HEAD_MODEL)
|
||||||
this._eyeLevelCoordinateSystem = new XRCoordinateSystem(this, XRCoordinateSystem.EYE_LEVEL)
|
this._eyeLevelCoordinateSystem = new XRCoordinateSystem(this, XRCoordinateSystem.EYE_LEVEL)
|
||||||
this._stageCoordinateSystem = new XRCoordinateSystem(this, XRCoordinateSystem.STAGE)
|
this._trackerCoordinateSystem = new XRCoordinateSystem(this, XRCoordinateSystem.TRACKER)
|
||||||
|
|
||||||
this._headPose = new XRViewPose([0, XRViewPose.SITTING_EYE_HEIGHT, 0])
|
this._headPose = new XRViewPose([0, XRViewPose.SITTING_EYE_HEIGHT, 0])
|
||||||
this._eyeLevelPose = new XRViewPose([0, XRViewPose.SITTING_EYE_HEIGHT, 0])
|
this._eyeLevelPose = new XRViewPose([0, XRViewPose.SITTING_EYE_HEIGHT, 0])
|
||||||
this._stagePose = new XRViewPose([0, 0, 0])
|
this._trackerPoseModelMatrix = new Float32Array([
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
])
|
||||||
|
|
||||||
var fov = 50/2;
|
var fov = 50/2;
|
||||||
this._fov = new XRFieldOfView(fov, fov, fov, fov)
|
this._fov = new XRFieldOfView(fov, fov, fov, fov)
|
||||||
|
|
|
@ -86,8 +86,6 @@ export default class XRPresentationFrame {
|
||||||
return this._session._display._headPose
|
return this._session._display._headPose
|
||||||
case XRCoordinateSystem.EYE_LEVEL:
|
case XRCoordinateSystem.EYE_LEVEL:
|
||||||
return this._session._display._eyeLevelPose
|
return this._session._display._eyeLevelPose
|
||||||
case XRCoordinateSystem.STAGE:
|
|
||||||
return this._session._display._stagePose
|
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,8 +75,8 @@ export default class XRSession extends EventHandlerBase {
|
||||||
return this._display._headModelCoordinateSystem
|
return this._display._headModelCoordinateSystem
|
||||||
case XRCoordinateSystem.EYE_LEVEL:
|
case XRCoordinateSystem.EYE_LEVEL:
|
||||||
return this._display._eyeLevelCoordinateSystem
|
return this._display._eyeLevelCoordinateSystem
|
||||||
case XRCoordinateSystem.STAGE:
|
case XRCoordinateSystem.TRACKER:
|
||||||
return this._display._stageCoordinateSystem
|
return this._display._trackerCoordinateSystem
|
||||||
case XRCoordinateSystem.GEOSPATIAL:
|
case XRCoordinateSystem.GEOSPATIAL:
|
||||||
// Not supported yet
|
// Not supported yet
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -6,11 +6,11 @@ Other XR platforms sometimes refer to this concept as "room scale" or "standing
|
||||||
export default class XRStageBounds {
|
export default class XRStageBounds {
|
||||||
get center(){
|
get center(){
|
||||||
//readonly attribute XRCoordinates center;
|
//readonly attribute XRCoordinates center;
|
||||||
throw 'Not implemented'
|
throw new Error('Not implemented')
|
||||||
}
|
}
|
||||||
|
|
||||||
get geometry(){
|
get geometry(){
|
||||||
//readonly attribute FrozenArray<XRStageBoundsPoint>? geometry;
|
//readonly attribute FrozenArray<XRStageBoundsPoint>? geometry;
|
||||||
throw 'Not implemented'
|
throw new Error('Not implemented')
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,11 +4,11 @@ XRStageBoundPoints represent the offset in meters from the stage origin along th
|
||||||
export default class XRStageBoundsPoint {
|
export default class XRStageBoundsPoint {
|
||||||
get x(){
|
get x(){
|
||||||
//readonly attribute double x;
|
//readonly attribute double x;
|
||||||
throw 'Not implemented'
|
throw new Error('Not implemented')
|
||||||
}
|
}
|
||||||
|
|
||||||
get y(){
|
get y(){
|
||||||
//readonly attribute double z;
|
//readonly attribute double z;
|
||||||
throw 'Not implemented'
|
throw new Error('Not implemented')
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -109,7 +109,6 @@ export default class FlatDisplay extends XRDisplay {
|
||||||
MatrixMath.mat4_fromRotationTranslation(this._deviceWorldMatrix, this._deviceOrientation.toArray(), this._devicePosition.toArray())
|
MatrixMath.mat4_fromRotationTranslation(this._deviceWorldMatrix, this._deviceOrientation.toArray(), this._devicePosition.toArray())
|
||||||
this._headPose._setPoseModelMatrix(this._deviceWorldMatrix)
|
this._headPose._setPoseModelMatrix(this._deviceWorldMatrix)
|
||||||
this._eyeLevelPose._position = this._devicePosition.toArray()
|
this._eyeLevelPose._position = this._devicePosition.toArray()
|
||||||
this._stagePose._position = [0, 0, 0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateFromDeviceOrientationTracker(){
|
_updateFromDeviceOrientationTracker(){
|
||||||
|
@ -120,7 +119,6 @@ export default class FlatDisplay extends XRDisplay {
|
||||||
MatrixMath.mat4_fromRotationTranslation(this._deviceWorldMatrix, this._deviceOrientation.toArray(), this._devicePosition.toArray())
|
MatrixMath.mat4_fromRotationTranslation(this._deviceWorldMatrix, this._deviceOrientation.toArray(), this._devicePosition.toArray())
|
||||||
this._headPose._setPoseModelMatrix(this._deviceWorldMatrix)
|
this._headPose._setPoseModelMatrix(this._deviceWorldMatrix)
|
||||||
this._eyeLevelPose._position = this._devicePosition.toArray()
|
this._eyeLevelPose._position = this._devicePosition.toArray()
|
||||||
this._stagePose._position = [0, 0, 0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleARKitUpdate(...params){
|
_handleARKitUpdate(...params){
|
||||||
|
@ -129,7 +127,6 @@ export default class FlatDisplay extends XRDisplay {
|
||||||
this._headPose._setPoseModelMatrix(cameraTransformMatrix)
|
this._headPose._setPoseModelMatrix(cameraTransformMatrix)
|
||||||
this._headPose._poseModelMatrix[13] += XRViewPose.SITTING_EYE_HEIGHT
|
this._headPose._poseModelMatrix[13] += XRViewPose.SITTING_EYE_HEIGHT
|
||||||
this._eyeLevelPose._position = this._headPose._position
|
this._eyeLevelPose._position = this._headPose._position
|
||||||
this._stagePose._position = [0, 0, 0]
|
|
||||||
} else {
|
} else {
|
||||||
console.log('no camera transform', this._arKitWrapper.rawARData)
|
console.log('no camera transform', this._arKitWrapper.rawARData)
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,6 @@ export default class HeadMountedDisplay extends XRDisplay {
|
||||||
}
|
}
|
||||||
this._headPose._setPoseModelMatrix(this._deviceWorldMatrix)
|
this._headPose._setPoseModelMatrix(this._deviceWorldMatrix)
|
||||||
this._eyeLevelPose.position = this._devicePosition.toArray()
|
this._eyeLevelPose.position = this._devicePosition.toArray()
|
||||||
this._stagePose._position = [0, 0, 0]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -150,13 +150,13 @@ export default class CameraReality extends Reality {
|
||||||
console.log('unknown anchor', anchor)
|
console.log('unknown anchor', anchor)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// This assumes that the anchor's coordinates are in the stage coordinate system
|
// This assumes that the anchor's coordinates are in the tracker coordinate system
|
||||||
anchor.coordinates.poseMatrix = anchorInfo.transform
|
anchor.coordinates.poseMatrix = anchorInfo.transform
|
||||||
}
|
}
|
||||||
|
|
||||||
_addAnchor(anchor, display){
|
_addAnchor(anchor, display){
|
||||||
// Convert coordinates to the stage coordinate system so that updating from ARKit transforms is simple
|
// Convert coordinates to the tracker coordinate system so that updating from ARKit transforms is simple
|
||||||
anchor.coordinates = anchor.coordinates.getTransformedCoordinates(display._stageCoordinateSystem)
|
anchor.coordinates = anchor.coordinates.getTransformedCoordinates(display._trackerCoordinateSystem)
|
||||||
if(this._arKitWrapper !== null){
|
if(this._arKitWrapper !== null){
|
||||||
this._arKitWrapper.addAnchor(anchor.uid, anchor.coordinates.poseMatrix).then(
|
this._arKitWrapper.addAnchor(anchor.uid, anchor.coordinates.poseMatrix).then(
|
||||||
detail => this._handleARKitAddObject(detail)
|
detail => this._handleARKitAddObject(detail)
|
||||||
|
@ -192,7 +192,7 @@ export default class CameraReality extends Reality {
|
||||||
|
|
||||||
let anchor = this._getAnchor(hit.uuid)
|
let anchor = this._getAnchor(hit.uuid)
|
||||||
if(anchor === null){
|
if(anchor === null){
|
||||||
let anchorCoordinates = new XRCoordinates(display, display._stageCoordinateSystem)
|
let anchorCoordinates = new XRCoordinates(display, display._trackerCoordinateSystem)
|
||||||
anchorCoordinates.poseMatrix = hit.anchor_transform
|
anchorCoordinates.poseMatrix = hit.anchor_transform
|
||||||
anchor = new XRAnchor(anchorCoordinates, hit.uuid)
|
anchor = new XRAnchor(anchorCoordinates, hit.uuid)
|
||||||
this._anchors.set(anchor.uid, anchor)
|
this._anchors.set(anchor.uid, anchor)
|
||||||
|
@ -220,7 +220,7 @@ export default class CameraReality extends Reality {
|
||||||
hits.sort((a, b) => a.distance - b.distance)
|
hits.sort((a, b) => a.distance - b.distance)
|
||||||
let anchor = this._getAnchor(hits[0].uuid)
|
let anchor = this._getAnchor(hits[0].uuid)
|
||||||
if(anchor === null){
|
if(anchor === null){
|
||||||
let coordinates = new XRCoordinates(display, display._stageCoordinateSystem)
|
let coordinates = new XRCoordinates(display, display._trackerCoordinateSystem)
|
||||||
coordinates.poseMatrix = hits[0].modelMatrix
|
coordinates.poseMatrix = hits[0].modelMatrix
|
||||||
coordinates._poseMatrix[13] += XRViewPose.SITTING_EYE_HEIGHT
|
coordinates._poseMatrix[13] += XRViewPose.SITTING_EYE_HEIGHT
|
||||||
anchor = new XRAnchor(coordinates)
|
anchor = new XRAnchor(coordinates)
|
||||||
|
|
|
@ -9,29 +9,29 @@ import Quaternion from '../polyfill/fill/Quaternion.js'
|
||||||
export default class CoordinatesTest extends Test {
|
export default class CoordinatesTest extends Test {
|
||||||
testTransform(){
|
testTransform(){
|
||||||
let display1 = new MockXRDisplay()
|
let display1 = new MockXRDisplay()
|
||||||
let stageCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.STAGE)
|
let trackerCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.TRACKER)
|
||||||
let headCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.HEAD_MODEL)
|
let headCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.HEAD_MODEL)
|
||||||
let eyeLevelCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.EYE_LEVEL)
|
let eyeLevelCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.EYE_LEVEL)
|
||||||
|
|
||||||
let headCoordinates = new XRCoordinates(display1, headCoordinateSystem, [0, 0, -0.5])
|
let headCoordinates = new XRCoordinates(display1, headCoordinateSystem, [0, 0, -0.5])
|
||||||
let stageCoordinates = headCoordinates.getTransformedCoordinates(stageCoordinateSystem)
|
let trackerCoordinates = headCoordinates.getTransformedCoordinates(trackerCoordinateSystem)
|
||||||
this.assertFloatArraysEqual(
|
this.assertFloatArraysEqual(
|
||||||
stageCoordinates.position,
|
trackerCoordinates.position,
|
||||||
[headCoordinates.position[0], XRViewPose.SITTING_EYE_HEIGHT + headCoordinates.position[1], headCoordinates.position[2]]
|
[headCoordinates.position[0], XRViewPose.SITTING_EYE_HEIGHT + headCoordinates.position[1], headCoordinates.position[2]]
|
||||||
)
|
)
|
||||||
this.assertFloatArraysEqual(stageCoordinates.orientation, headCoordinates.orientation)
|
this.assertFloatArraysEqual(trackerCoordinates.orientation, headCoordinates.orientation)
|
||||||
|
|
||||||
// Rotate the head and test the transform
|
// Rotate the head and test the transform
|
||||||
let quat1 = new Quaternion()
|
let quat1 = new Quaternion()
|
||||||
quat1.setFromEuler(0, -Math.PI, 0)
|
quat1.setFromEuler(0, -Math.PI, 0)
|
||||||
display1._headPose._orientation = quat1.toArray()
|
display1._headPose._orientation = quat1.toArray()
|
||||||
stageCoordinates = headCoordinates.getTransformedCoordinates(stageCoordinateSystem)
|
trackerCoordinates = headCoordinates.getTransformedCoordinates(trackerCoordinateSystem)
|
||||||
this.assertFloatArraysEqual(
|
this.assertFloatArraysEqual(
|
||||||
stageCoordinates.position,
|
trackerCoordinates.position,
|
||||||
[headCoordinates.position[0], XRViewPose.SITTING_EYE_HEIGHT + headCoordinates.position[1], -1 * headCoordinates.position[2]]
|
[headCoordinates.position[0], XRViewPose.SITTING_EYE_HEIGHT + headCoordinates.position[1], -1 * headCoordinates.position[2]]
|
||||||
)
|
)
|
||||||
quat1.inverse()
|
quat1.inverse()
|
||||||
this.assertFloatArraysEqual(quat1.toArray(), stageCoordinates.orientation)
|
this.assertFloatArraysEqual(quat1.toArray(), trackerCoordinates.orientation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче