Try the coordinates without the XRCoordinates.

This commit is contained in:
Trevor F. Smith 2017-10-30 19:34:03 -07:00
Родитель 523ee0916b
Коммит 72ce0e7e9a
12 изменённых файлов: 94 добавлений и 157 удалений

Просмотреть файл

@ -84,20 +84,10 @@
// Called once per frame
updateScene(frame){
const headCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.HEAD_MODEL)
const trackerCoordinateSystem = frame.getCoordinateSystem(XRCoordinateSystem.TRACKER)
// Create anchors and start tracking them
for(let anchorToAdd of this.anchorsToAdd){
// Create an anchor that we'd like to add, relative to the current head position
const anchorCoordinates = new XRCoordinates(
this.session.display,
headCoordinateSystem,
[anchorToAdd.x, anchorToAdd.y, anchorToAdd.z]
)
const anchor = new XRAnchor(anchorCoordinates)
// Create the anchor and tell the base class to update the node with its position
const anchorUID = frame.addAnchor(anchor)
const anchorUID = frame.addAnchor(headCoordinateSystem, [anchorToAdd.x, anchorToAdd.y, anchorToAdd.z])
this.addAnchoredNode(new XRAnchorOffset(anchorUID), anchorToAdd.node)
}
this.anchorsToAdd = []

Просмотреть файл

@ -241,16 +241,8 @@ class XRExampleBase {
throttledConsoleLog('Unknown anchor uid', anchorOffset.anchorUID)
return
}
node.matrixAutoUpdate = false
const offsetCoordinates = anchorOffset.getTransformedCoordinates(anchor)
if(offsetCoordinates.coordinateSystem.type === XRCoordinateSystem.TRACKER){
node.matrix.fromArray(offsetCoordinates.poseMatrix)
} else {
node.matrix.fromArray(
offsetCoordinates.getTransformedCoordinates(frame.getCoordinateSystem(XRCoordinateSystem.TRACKER)).poseMatrix
)
}
node.matrix.fromArray(anchorOffset.getOffsetTransform(anchor.coordinateSystem))
node.updateMatrixWorld(true)
}
}

Просмотреть файл

@ -67,13 +67,12 @@ export default class Reality extends EventHandlerBase {
_findFloorAnchor(display, uid=null){
// Copy the head model matrix for the current pose so we have it in the promise below
const headModelMatrix = new Float32Array(display._headPose.poseModelMatrix)
return new Promise((resolve, reject) => {
// For now, just create an anchor at origin level. Maybe in the future search for a surface?
const coordinates = new XRCoordinates(display, display._trackerCoordinateSystem)
headModelMatrix[13] = 0 // Set height to 0
coordinates.poseMatrix = headModelMatrix
const anchor = new XRAnchor(coordinates, uid)
const coordinateSystem = new XRCoordinateSystem(display, XRCoordinateSystem.TRACKER)
coordinateSystem._relativeMatrix = headModelMatrix
const anchor = new XRAnchor(coordinateSystem, uid)
this._addAnchor(anchor, display)
resolve(new XRAnchorOffset(anchor.uid))
})

Просмотреть файл

@ -1,19 +1,17 @@
/*
XRAnchors provide per-frame coordinates which the Reality attempts to pin "in place".
In a virtual Reality these coordinates do not change.
In a Reality based on environment mapping sensors, the anchors may change coordinates on a per-frame bases as the system refines its map.
In a Reality based on environment mapping sensors, the anchors may change pose on a per-frame bases as the system refines its map.
*/
export default class XRAnchor {
constructor(xrCoordinates, uid=null){
this._uid = uid == null ? XRAnchor._generateUID() : uid
this._coordinates = xrCoordinates
constructor(xrCoordinateSystem){
this._uid = XRAnchor._generateUID()
this._coordinateSystem = xrCoordinateSystem
}
get uid(){ return this._uid }
get coordinates(){ return this._coordinates }
set coordinates(value) { this._coordinates = value }
get coordinateSystem(){ return this._coordinateSystem }
static _generateUID(){
return 'anchor-' + new Date().getTime() + '-' + Math.floor((Math.random() * Number.MAX_SAFE_INTEGER))

Просмотреть файл

@ -2,7 +2,6 @@ import MatrixMath from './fill/MatrixMath.js'
import Quaternion from './fill/Quaternion.js'
import XRAnchor from './XRAnchor.js'
import XRCoordinates from './XRCoordinates.js'
/*
XRAnchorOffset represents a pose in relation to an XRAnchor
@ -43,11 +42,9 @@ export default class XRAnchorOffset {
}
/*
Return an XRCoordinates in the same coordinate system as `anchor` that is offset by this XRAnchorOffset.poseMatrix
Return a transform matrix that is offset by this XRAnchorOffset.poseMatrix relative to coordinateSystem
*/
getTransformedCoordinates(anchor){
const coordinates = new XRCoordinates(anchor.coordinates._display, anchor.coordinates.coordinateSystem)
MatrixMath.mat4_multiply(coordinates.poseMatrix, this._poseMatrix, anchor.coordinates.poseMatrix)
return coordinates
getOffsetTransform(coordinateSystem){
return MatrixMath.mat4_multiply(new Float32Array(16), this._poseMatrix, coordinateSystem._poseModelMatrix)
}
}

Просмотреть файл

@ -1,5 +1,4 @@
import MatrixMath from './fill/MatrixMath.js'
import XRCoordinates from './XRCoordinates.js'
/*
XRCoordinateSystem represents the origin of a 3D coordinate system positioned at a known frame of reference.
@ -16,12 +15,34 @@ export default class XRCoordinateSystem {
this._display = display
this._type = type
this._cartographicCoordinates = cartographicCoordinates
this.__relativeMatrix = MatrixMath.mat4_generateIdentity()
this._workingMatrix = MatrixMath.mat4_generateIdentity()
}
get cartographicCoordinates(){ return this._cartographicCoordinates }
get type(){ return this._type }
getTransformTo(otherCoordinateSystem){
// apply inverse of the poseModelMatrix to the identity matrix
let inverse = MatrixMath.mat4_invert(new Float32Array(16), otherCoordinateSystem._poseModelMatrix)
let out = MatrixMath.mat4_generateIdentity()
MatrixMath.mat4_multiply(out, inverse, out)
// apply the other system's poseModelMatrix
MatrixMath.mat4_multiply(out, this._poseModelMatrix, out)
return out
}
get _relativeMatrix(){ return this.__relativeMatrix }
set _relativeMatrix(value){
for(let i=0; i < 16; i++){
this.__relativeMatrix[i] = value[i]
}
}
get _poseModelMatrix(){
switch(this._type){
case XRCoordinateSystem.HEAD_MODEL:
@ -29,35 +50,15 @@ export default class XRCoordinateSystem {
case XRCoordinateSystem.EYE_LEVEL:
return this._display._eyeLevelPose.poseModelMatrix
case XRCoordinateSystem.TRACKER:
return this._display._trackerPoseModelMatrix
MatrixMath.mat4_multiply(this._workingMatrix, this.__relativeMatrix, this._display._trackerPoseModelMatrix)
return this._workingMatrix
case XRCoordinateSystem.GEOSPATIAL:
throw 'This polyfill does not yet handle geospatial coordinate systems'
throw new Error('This polyfill does not yet handle geospatial coordinate systems')
default:
throw 'Unknown coordinate system type: ' + this._type
throw new Error('Unknown coordinate system type: ' + this._type)
}
}
getCoordinates(position=[0,0,0], orientation=[0,0,0,1]){
return new XRCoordinates(this._display, this, position, orientation)
}
getTransformTo(otherCoordinateSystem){
let out = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
])
// apply inverse of other system's poseModelMatrix to the identity matrix
let inverse = new Float32Array(16)
MatrixMath.mat4_invert(inverse, otherCoordinateSystem._poseModelMatrix)
MatrixMath.mat4_multiply(out, inverse, out)
// apply this system's poseModelMatrix
MatrixMath.mat4_multiply(out, this._poseModelMatrix, out)
return out
}
}
XRCoordinateSystem.HEAD_MODEL = 'headModel'

Просмотреть файл

@ -1,56 +0,0 @@
import MatrixMath from './fill/MatrixMath.js'
import Quaternion from './fill/Quaternion.js'
import XRCoordinateSystem from './XRCoordinateSystem.js'
/*
XRCoordinates represent a pose (position and orientation) in relation to a XRCoordinateSystem.
*/
export default class XRCoordinates {
constructor(display, coordinateSystem, position=[0, 0, 0], orientation=[0, 0, 0, 1]){
this._display = display
this._coordinateSystem = coordinateSystem
this._poseMatrix = new Float32Array(16)
MatrixMath.mat4_fromRotationTranslation(this._poseMatrix, orientation, position)
}
get coordinateSystem(){ return this._coordinateSystem }
get poseMatrix(){ return this._poseMatrix }
set poseMatrix(array16){
for(let i=0; i < 16; i++){
this._poseMatrix[i] = array16[i]
}
}
get position(){
return new Float32Array([this._poseMatrix[12], this._poseMatrix[13], this._poseMatrix[14]])
}
get orientation(){
let quat = new Quaternion()
quat.setFromRotationMatrix(this._poseMatrix)
return quat.toArray()
}
/*
Returns a new XRCoordinates that represents this XRCoordinates's pose in the otherCoordinateSystem
May return null if there is no transform between this.coordinateSystem and otherCoordinateSystem
*/
getTransformedCoordinates(otherCoordinateSystem){
// XRCoordinates? getTransformedCoordinates(XRCoordinateSystem otherCoordinateSystem)
if(this._coordinateSystem.type === XRCoordinateSystem.GEOSPATIAL || otherCoordinateSystem.type === XRCoordinateSystem.GEOSPATIAL){
console.error('This polyfill does not yet support geospatial coordinate systems')
return null
}
const transform = this._coordinateSystem.getTransformTo(otherCoordinateSystem)
if(transform === null){
console.error('Could not get a transform between', this._coordinateSystem, otherCoordinateSystem)
return null
}
const out = new XRCoordinates(this._display, otherCoordinateSystem)
MatrixMath.mat4_multiply(out._poseMatrix, transform, this._poseMatrix)
return out
}
}

Просмотреть файл

@ -1,8 +1,11 @@
import MatrixMath from './fill/MatrixMath.js'
import EventHandlerBase from './fill/EventHandlerBase.js'
import XRFieldOfView from './XRFieldOfView.js'
import VirtualReality from './reality/VirtualReality.js'
import XRFieldOfView from './XRFieldOfView.js'
/*
Each XRDisplay represents a method of using a specific type of hardware to render AR or VR realities and layers.
@ -22,12 +25,7 @@ export default class XRDisplay extends EventHandlerBase {
this._headPose = new XRViewPose([0, XRViewPose.SITTING_EYE_HEIGHT, 0])
this._eyeLevelPose = new XRViewPose([0, XRViewPose.SITTING_EYE_HEIGHT, 0])
this._trackerPoseModelMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
])
this._trackerPoseModelMatrix = MatrixMath.mat4_generateIdentity()
var fov = 50/2;
this._fov = new XRFieldOfView(fov, fov, fov, fov)

Просмотреть файл

@ -14,7 +14,6 @@ import XRView from './XRView.js'
import XRViewport from './XRViewport.js'
import XRCartographicCoordinates from './XRCartographicCoordinates.js'
import XRCoordinateSystem from './XRCoordinateSystem.js'
import XRCoordinates from './XRCoordinates.js'
import XRViewPose from './XRViewPose.js'
import XRLayer from './XRLayer.js'
import XRWebGLLayer from './XRWebGLLayer.js'
@ -50,7 +49,6 @@ class XRPolyfill extends EventHandlerBase {
window.XRViewport = XRViewport
window.XRCartographicCoordinates = XRCartographicCoordinates
window.XRCoordinateSystem = XRCoordinateSystem
window.XRCoordinates = XRCoordinates
window.XRViewPose = XRViewPose
window.XRLayer = XRLayer
window.XRWebGLLayer = XRWebGLLayer

Просмотреть файл

@ -1,4 +1,5 @@
import XRAnchor from './XRAnchor.js'
import MatrixMath from './fill/MatrixMath.js'
/*
XRPresentationFrame provides all of the values needed to render a single frame of an XR scene to the XRDisplay.
@ -50,9 +51,13 @@ export default class XRPresentationFrame {
/*
Create an anchor at a specific position defined by XRAnchor.coordinates
*/
addAnchor(anchor){
//DOMString? addAnchor(XRAnchor anchor);
return this._session.reality._addAnchor(anchor, this._session.display)
addAnchor(coordinateSystem, position=[0,0,0], orientation=[0,0,0,1]){
//DOMString? addAnchor(XRCoordinateSystem, position, orientation);
let poseMatrix = MatrixMath.mat4_fromRotationTranslation(new Float32Array(16), orientation, position)
MatrixMath.mat4_multiply(poseMatrix, coordinateSystem.getTransformTo(this._session._display._trackerCoordinateSystem), poseMatrix)
let anchorCoordinateSystem = new XRCoordinateSystem(this._session._display, XRCoordinateSystem.TRACKER)
anchorCoordinateSystem._relativeMatrix = poseMatrix
return this._session.reality._addAnchor(new XRAnchor(anchorCoordinateSystem), this._session.display)
}
// normalized screen x and y are in range 0..1, with 0,0 at top left and 1,1 at bottom right

Просмотреть файл

@ -1,7 +1,7 @@
import Reality from '../Reality.js'
import XRAnchor from '../XRAnchor.js'
import XRViewPose from '../XRViewPose.js'
import XRCoordinates from '../XRCoordinates.js'
import XRAnchorOffset from '../XRAnchorOffset.js'
import MatrixMath from '../fill/MatrixMath.js'
@ -151,14 +151,13 @@ export default class CameraReality extends Reality {
return
}
// This assumes that the anchor's coordinates are in the tracker coordinate system
anchor.coordinates.poseMatrix = anchorInfo.transform
anchor.coordinateSystem._relativeMatrix = anchorInfo.transform
}
_addAnchor(anchor, display){
// Convert coordinates to the tracker coordinate system so that updating from ARKit transforms is simple
anchor.coordinates = anchor.coordinates.getTransformedCoordinates(display._trackerCoordinateSystem)
if(this._arKitWrapper !== null){
this._arKitWrapper.addAnchor(anchor.uid, anchor.coordinates.poseMatrix).then(
this._arKitWrapper.addAnchor(anchor.uid, anchor.coordinateSystem._poseModelMatrix).then(
detail => this._handleARKitAddObject(detail)
)
}
@ -192,9 +191,9 @@ export default class CameraReality extends Reality {
let anchor = this._getAnchor(hit.uuid)
if(anchor === null){
let anchorCoordinates = new XRCoordinates(display, display._trackerCoordinateSystem)
anchorCoordinates.poseMatrix = hit.anchor_transform
anchor = new XRAnchor(anchorCoordinates, hit.uuid)
let coordinateSystem = new XRCoordinateSystem(display, XRCoordinateSystem.TRACKER)
coordinateSystem._relativeMatrix = hit.anchor_transform
anchor = new XRAnchor(coordinateSystem, hit.uuid)
this._anchors.set(anchor.uid, anchor)
}
@ -220,10 +219,10 @@ export default class CameraReality extends Reality {
hits.sort((a, b) => a.distance - b.distance)
let anchor = this._getAnchor(hits[0].uuid)
if(anchor === null){
let coordinates = new XRCoordinates(display, display._trackerCoordinateSystem)
coordinates.poseMatrix = hits[0].modelMatrix
coordinates._poseMatrix[13] += XRViewPose.SITTING_EYE_HEIGHT
anchor = new XRAnchor(coordinates)
let coordinateSystem = new XRCoordinateSystem(display, XRCoordinateSystem.TRACKER)
coordinateSystem._relativeMatrix = hits[0].modelMatrix
coordinateSystem._relativeMatrix[13] += XRViewPose.SITTING_EYE_HEIGHT
anchor = new XRAnchor(coordinateSystem)
this._anchors.set(anchor.uid, anchor)
}
resolve(new XRAnchorOffset(anchor.uid))

Просмотреть файл

@ -1,7 +1,7 @@
import Test from './Test.js'
import MatrixMath from '../polyfill/fill/MatrixMath.js'
import XRDisplay from '../polyfill/XRDisplay.js'
import XRCoordinates from '../polyfill/XRCoordinates.js'
import XRCoordinateSystem from '../polyfill/XRCoordinateSystem.js'
import Quaternion from '../polyfill/fill/Quaternion.js'
@ -9,29 +9,45 @@ import Quaternion from '../polyfill/fill/Quaternion.js'
export default class CoordinatesTest extends Test {
testTransform(){
let display1 = new MockXRDisplay()
let trackerCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.TRACKER)
let headCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.HEAD_MODEL)
let eyeLevelCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.EYE_LEVEL)
let headCoordinates = new XRCoordinates(display1, headCoordinateSystem, [0, 0, -0.5])
let trackerCoordinates = headCoordinates.getTransformedCoordinates(trackerCoordinateSystem)
// Test that relative coordinate systems correctly provide transforms
let relativeCoordinateSystem = new XRCoordinateSystem(display1, XRCoordinateSystem.TRACKER)
let pose = MatrixMath.mat4_generateIdentity()
pose[12] = 1
pose[13] = 2
pose[14] = 3
relativeCoordinateSystem._relativeMatrix = pose
let r2hTransform = relativeCoordinateSystem.getTransformTo(display1._headModelCoordinateSystem)
this.assertFloatArraysEqual(
trackerCoordinates.position,
[headCoordinates.position[0], XRViewPose.SITTING_EYE_HEIGHT + headCoordinates.position[1], headCoordinates.position[2]]
[1, 2 - XRViewPose.SITTING_EYE_HEIGHT, 3],
[r2hTransform[12], r2hTransform[13], r2hTransform[14]]
)
// Test the transform is where we expect it
let h2tTransform = display1._headModelCoordinateSystem.getTransformTo(display1._trackerCoordinateSystem)
this.assertFloatArraysEqual(
[0, XRViewPose.SITTING_EYE_HEIGHT, 0],
[h2tTransform[12], h2tTransform[13], h2tTransform[14]]
)
// Offset the head and test the transform
display1._headPose._position = [0, XRViewPose.SITTING_EYE_HEIGHT, 0.5]
h2tTransform = display1._headModelCoordinateSystem.getTransformTo(display1._trackerCoordinateSystem)
this.assertFloatArraysEqual(
[0, XRViewPose.SITTING_EYE_HEIGHT, display1._headPose._position[2]],
[h2tTransform[12], h2tTransform[13], h2tTransform[14]]
)
this.assertFloatArraysEqual(trackerCoordinates.orientation, headCoordinates.orientation)
// Rotate the head and test the transform
let quat1 = new Quaternion()
quat1.setFromEuler(0, -Math.PI, 0)
display1._headPose._orientation = quat1.toArray()
trackerCoordinates = headCoordinates.getTransformedCoordinates(trackerCoordinateSystem)
this.assertFloatArraysEqual(
trackerCoordinates.position,
[headCoordinates.position[0], XRViewPose.SITTING_EYE_HEIGHT + headCoordinates.position[1], -1 * headCoordinates.position[2]]
)
h2tTransform = display1._headModelCoordinateSystem.getTransformTo(display1._trackerCoordinateSystem)
let trackerPosition = MatrixMath.mat4_get_position(new Float32Array(3), h2tTransform)
this.assertEqual(trackerPosition[2], display1._headPose._position[2])
quat1.inverse()
this.assertFloatArraysEqual(quat1.toArray(), trackerCoordinates.orientation)
let trackerOrientation = MatrixMath.mat4_get_rotation(new Float32Array(4), h2tTransform)
this.assertFloatArraysEqual(quat1.toArray(), trackerOrientation)
}
}