XR/desktop href-navigation works!
This commit is contained in:
parent
cdadc0f9f1
commit
154350897f
9 changed files with 191 additions and 36 deletions
69
dist/xrfragment.aframe.js
vendored
69
dist/xrfragment.aframe.js
vendored
|
|
@ -614,6 +614,10 @@ xrfragment.InteractiveGroup = function(THREE,renderer,camera){
|
|||
super();
|
||||
|
||||
if( !renderer || !camera ) return
|
||||
|
||||
// extract camera when camera-rig is passed
|
||||
camera.traverse( (n) => String(n.type).match(/Camera/) ? camera = n : null )
|
||||
|
||||
const scope = this;
|
||||
|
||||
const raycaster = new Raycaster();
|
||||
|
|
@ -877,7 +881,7 @@ xrf.navigator.to = (url,event) => {
|
|||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
console.log("xrfragment: navigating to "+url)
|
||||
|
||||
if( !file || xrf.model.file == file ){ // we're already loaded
|
||||
if( !file || xrf.model.file == file ){ // we're already loaded
|
||||
document.location.hash = `#${hash}` // just update the hash
|
||||
xrf.eval( url, xrf.model ) // and eval URI XR fragments
|
||||
return resolve(xrf.model)
|
||||
|
|
@ -968,8 +972,6 @@ xrf.frag.env = function(v, opts){
|
|||
xrf.frag.href = function(v, opts){
|
||||
let { mesh, model, camera, scene, renderer, THREE} = opts
|
||||
|
||||
console.log("INIT HREF "+mesh.name)
|
||||
|
||||
const world = {
|
||||
pos: new THREE.Vector3(),
|
||||
scale: new THREE.Vector3(),
|
||||
|
|
@ -1088,9 +1090,48 @@ xrf.frag.pos = function(v, opts){
|
|||
//if( renderer.xr.isPresenting ) return // too far away
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(" └ setting camera position to "+v.string)
|
||||
camera.position.x = v.x
|
||||
camera.position.y = v.y
|
||||
camera.position.z = v.z
|
||||
|
||||
if( !frag.q ){
|
||||
|
||||
if( true ){//!renderer.xr.isPresenting ){
|
||||
console.dir(camera)
|
||||
camera.position.x = v.x
|
||||
camera.position.y = v.y
|
||||
camera.position.z = v.z
|
||||
}
|
||||
/*
|
||||
else{ // XR
|
||||
let cameraWorldPosition = new THREE.Vector3()
|
||||
camera.object3D.getWorldPosition(this.cameraWorldPosition)
|
||||
let newRigWorldPosition = new THREE.Vector3(v.x,v.y,x.z)
|
||||
|
||||
// Finally update the cameras position
|
||||
let newRigLocalPosition.copy(this.newRigWorldPosition)
|
||||
if (camera.object3D.parent) {
|
||||
camera.object3D.parent.worldToLocal(newRigLocalPosition)
|
||||
}
|
||||
camera.setAttribute('position', newRigLocalPosition)
|
||||
|
||||
// Also take the headset/camera rotation itself into account
|
||||
if (this.data.rotateOnTeleport) {
|
||||
this.teleportOcamerainQuaternion
|
||||
.setFromEuler(new THREE.Euler(0, this.teleportOcamerain.object3D.rotation.y, 0))
|
||||
this.teleportOcamerainQuaternion.invert()
|
||||
this.teleportOcamerainQuaternion.multiply(this.hitEntityQuaternion)
|
||||
// Rotate the camera based on calculated teleport ocamerain rotation
|
||||
this.cameraRig.object3D.setRotationFromQuaternion(this.teleportOcamerainQuaternion)
|
||||
}
|
||||
|
||||
console.log("XR")
|
||||
const offsetPosition = { x: - v.x, y: - v.y, z: - v.z, w: 1 };
|
||||
const offsetRotation = new THREE.Quaternion();
|
||||
const transform = new XRRigidTransform( offsetPosition, offsetRotation );
|
||||
const teleportSpaceOffset = xrf.baseReferenceSpace.getOffsetReferenceSpace( transform );
|
||||
renderer.xr.setReferenceSpace( teleportSpaceOffset );
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
xrf.frag.q = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
|
|
@ -1187,6 +1228,7 @@ window.AFRAME.registerComponent('xrf', {
|
|||
// override the camera-related XR Fragments so the camera-rig is affected
|
||||
let camOverride = (xrf,v,opts) => {
|
||||
opts.camera = $('[camera]').object3D.parent
|
||||
console.dir(opts.camera)
|
||||
xrf(v,opts)
|
||||
}
|
||||
|
||||
|
|
@ -1210,7 +1252,20 @@ window.AFRAME.registerComponent('xrf', {
|
|||
let els = [...document.querySelectorAll('[xrf-get]')]
|
||||
els.map( (el) => document.querySelector('a-scene').removeChild(el) )
|
||||
})(XRF.reset)
|
||||
|
||||
|
||||
// disable cam-controls (which will block updating camerarig position)
|
||||
let coms = ['look-controls','wasd-controls']
|
||||
const setComponents = (com,state) => () => {
|
||||
coms.forEach( (com) => {
|
||||
let el = document.querySelector('['+com+']')
|
||||
if(!el) return
|
||||
el.components[com].enabled = state
|
||||
})
|
||||
}
|
||||
aScene.addEventListener('enter-vr', setComponents(coms,false) )
|
||||
aScene.addEventListener('enter-ar', setComponents(coms,false) )
|
||||
aScene.addEventListener('exit-vr', setComponents(coms,true) )
|
||||
aScene.addEventListener('exit-ar', setComponents(coms,true) )
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
|||
53
dist/xrfragment.three.js
vendored
53
dist/xrfragment.three.js
vendored
|
|
@ -614,6 +614,10 @@ xrfragment.InteractiveGroup = function(THREE,renderer,camera){
|
|||
super();
|
||||
|
||||
if( !renderer || !camera ) return
|
||||
|
||||
// extract camera when camera-rig is passed
|
||||
camera.traverse( (n) => String(n.type).match(/Camera/) ? camera = n : null )
|
||||
|
||||
const scope = this;
|
||||
|
||||
const raycaster = new Raycaster();
|
||||
|
|
@ -877,7 +881,7 @@ xrf.navigator.to = (url,event) => {
|
|||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
console.log("xrfragment: navigating to "+url)
|
||||
|
||||
if( !file || xrf.model.file == file ){ // we're already loaded
|
||||
if( !file || xrf.model.file == file ){ // we're already loaded
|
||||
document.location.hash = `#${hash}` // just update the hash
|
||||
xrf.eval( url, xrf.model ) // and eval URI XR fragments
|
||||
return resolve(xrf.model)
|
||||
|
|
@ -968,8 +972,6 @@ xrf.frag.env = function(v, opts){
|
|||
xrf.frag.href = function(v, opts){
|
||||
let { mesh, model, camera, scene, renderer, THREE} = opts
|
||||
|
||||
console.log("INIT HREF "+mesh.name)
|
||||
|
||||
const world = {
|
||||
pos: new THREE.Vector3(),
|
||||
scale: new THREE.Vector3(),
|
||||
|
|
@ -1088,9 +1090,48 @@ xrf.frag.pos = function(v, opts){
|
|||
//if( renderer.xr.isPresenting ) return // too far away
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(" └ setting camera position to "+v.string)
|
||||
camera.position.x = v.x
|
||||
camera.position.y = v.y
|
||||
camera.position.z = v.z
|
||||
|
||||
if( !frag.q ){
|
||||
|
||||
if( true ){//!renderer.xr.isPresenting ){
|
||||
console.dir(camera)
|
||||
camera.position.x = v.x
|
||||
camera.position.y = v.y
|
||||
camera.position.z = v.z
|
||||
}
|
||||
/*
|
||||
else{ // XR
|
||||
let cameraWorldPosition = new THREE.Vector3()
|
||||
camera.object3D.getWorldPosition(this.cameraWorldPosition)
|
||||
let newRigWorldPosition = new THREE.Vector3(v.x,v.y,x.z)
|
||||
|
||||
// Finally update the cameras position
|
||||
let newRigLocalPosition.copy(this.newRigWorldPosition)
|
||||
if (camera.object3D.parent) {
|
||||
camera.object3D.parent.worldToLocal(newRigLocalPosition)
|
||||
}
|
||||
camera.setAttribute('position', newRigLocalPosition)
|
||||
|
||||
// Also take the headset/camera rotation itself into account
|
||||
if (this.data.rotateOnTeleport) {
|
||||
this.teleportOcamerainQuaternion
|
||||
.setFromEuler(new THREE.Euler(0, this.teleportOcamerain.object3D.rotation.y, 0))
|
||||
this.teleportOcamerainQuaternion.invert()
|
||||
this.teleportOcamerainQuaternion.multiply(this.hitEntityQuaternion)
|
||||
// Rotate the camera based on calculated teleport ocamerain rotation
|
||||
this.cameraRig.object3D.setRotationFromQuaternion(this.teleportOcamerainQuaternion)
|
||||
}
|
||||
|
||||
console.log("XR")
|
||||
const offsetPosition = { x: - v.x, y: - v.y, z: - v.z, w: 1 };
|
||||
const offsetRotation = new THREE.Quaternion();
|
||||
const transform = new XRRigidTransform( offsetPosition, offsetRotation );
|
||||
const teleportSpaceOffset = xrf.baseReferenceSpace.getOffsetReferenceSpace( transform );
|
||||
renderer.xr.setReferenceSpace( teleportSpaceOffset );
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
xrf.frag.q = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
<a class="btn-foot" id="model" target="_blank" href="">⬇️ model</a>
|
||||
<textarea style="display:none"></textarea>
|
||||
<a-scene light="defaultLightsEnabled: false">
|
||||
<a-entity id="player" >
|
||||
<a-entity camera="fov:90" position="0 1.6 0" wasd-controls id="camera"></a-entity>
|
||||
<a-entity id="player" wasd-controls>
|
||||
<a-entity camera="fov:90" position="0 1.6 0" id="camera"></a-entity>
|
||||
<a-entity id="left-hand" laser-controls="hand: left" raycaster="objects:.collidable;far:5500" oculus-touch-controls="hand: left" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"></a-entity>
|
||||
<a-entity id="right-hand" laser-controls="hand: right" raycaster="objects:.collidable;far:5500" oculus-touch-controls="hand: right" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"></a-entity>
|
||||
</a-entity>
|
||||
|
|
@ -46,8 +46,6 @@
|
|||
setupConsole( $('textarea') )
|
||||
setupUrlBar( $('input#uri') )
|
||||
|
||||
// add look-controls at last (otherwise it'll be buggy after scene-updates)
|
||||
$('[camera]').setAttribute("look-controls","")
|
||||
// add screenshot component with camera to capture proper equirects
|
||||
$('a-scene').setAttribute("screenshot",{camera: "[camera]",width: 4096*2, height:2048*2})
|
||||
|
||||
|
|
|
|||
|
|
@ -83,10 +83,16 @@
|
|||
|
||||
window.addEventListener( 'resize', onWindowResize );
|
||||
|
||||
let cameraRig = new THREE.Group()
|
||||
cameraRig.position.set( 0, 0, 0 );
|
||||
cameraRig.add(camera)
|
||||
scene.add(cameraRig)
|
||||
|
||||
|
||||
// enable XR fragments
|
||||
let XRF = xrfragment.init({
|
||||
THREE,
|
||||
camera,
|
||||
camera:cameraRig,
|
||||
scene,
|
||||
renderer,
|
||||
debug: true,
|
||||
|
|
@ -116,7 +122,7 @@
|
|||
|
||||
window.XRF = XRF // expose to form
|
||||
|
||||
let file = document.location.search.length > 2 ? document.location.search.substr(1) + document.location.hash : './../../assets/example3.gltf#pos=0,1,15'
|
||||
let file = document.location.search.length > 2 ? document.location.search.substr(1) + document.location.hash : './../../assets/example3.gltf#pos=1,0,4&rot=0,-30,0'
|
||||
$('#model').setAttribute("href","./../../asset/"+file)
|
||||
XRF.navigator.to( file )
|
||||
|
||||
|
|
@ -134,12 +140,6 @@
|
|||
//controls.maxPolarAngle = Math.PI / 2;
|
||||
//controls.target = new THREE.Vector3(0,1.6,0)
|
||||
|
||||
//let cameraRig = new THREE.Group()
|
||||
//cameraRig.position.set( 0, 1.6, 15 );
|
||||
camera.position.set( 0, 1.6, 15 );
|
||||
//cameraRig.add(camera)
|
||||
//cameraRig.position.set( 0, 4, 15 );
|
||||
|
||||
//controls.update()
|
||||
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
|
|
@ -147,22 +147,22 @@
|
|||
|
||||
const controller1 = renderer.xr.getController( 0 );
|
||||
controller1.add( new THREE.Line( geometry ) );
|
||||
scene.add( controller1 );
|
||||
cameraRig.add( controller1 );
|
||||
|
||||
const controller2 = renderer.xr.getController( 1 );
|
||||
controller2.add( new THREE.Line( geometry ) );
|
||||
scene.add( controller2 );
|
||||
cameraRig.add( controller2 );
|
||||
|
||||
|
||||
const controllerModelFactory = new XRControllerModelFactory();
|
||||
|
||||
const controllerGrip1 = renderer.xr.getControllerGrip( 0 );
|
||||
controllerGrip1.add( controllerModelFactory.createControllerModel( controllerGrip1 ) );
|
||||
scene.add( controllerGrip1 );
|
||||
cameraRig.add( controllerGrip1 );
|
||||
|
||||
const controllerGrip2 = renderer.xr.getControllerGrip( 1 );
|
||||
controllerGrip2.add( controllerModelFactory.createControllerModel( controllerGrip2 ) );
|
||||
scene.add( controllerGrip2 );
|
||||
cameraRig.add( controllerGrip2 );
|
||||
|
||||
|
||||
setupConsole()
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ window.AFRAME.registerComponent('xrf', {
|
|||
// override the camera-related XR Fragments so the camera-rig is affected
|
||||
let camOverride = (xrf,v,opts) => {
|
||||
opts.camera = $('[camera]').object3D.parent
|
||||
console.dir(opts.camera)
|
||||
xrf(v,opts)
|
||||
}
|
||||
|
||||
|
|
@ -50,11 +51,25 @@ window.AFRAME.registerComponent('xrf', {
|
|||
|
||||
// cleanup xrf-get objects when resetting scene
|
||||
XRF.reset = ((reset) => () => {
|
||||
reset()
|
||||
console.log("aframe reset")
|
||||
let els = [...document.querySelectorAll('[xrf-get]')]
|
||||
els.map( (el) => document.querySelector('a-scene').removeChild(el) )
|
||||
reset()
|
||||
})(XRF.reset)
|
||||
|
||||
// disable cam-controls (which block updating camerarig position)
|
||||
let coms = ['look-controls','wasd-controls']
|
||||
const setComponents = (com,state) => () => {
|
||||
coms.forEach( (com) => {
|
||||
let el = document.querySelector('['+com+']')
|
||||
if(!el) return
|
||||
el.components[com].enabled = state
|
||||
})
|
||||
}
|
||||
aScene.addEventListener('enter-vr', setComponents(coms,false) )
|
||||
aScene.addEventListener('enter-ar', setComponents(coms,false) )
|
||||
aScene.addEventListener('exit-vr', setComponents(coms,true) )
|
||||
aScene.addEventListener('exit-ar', setComponents(coms,true) )
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ xrfragment.InteractiveGroup = function(THREE,renderer,camera){
|
|||
super();
|
||||
|
||||
if( !renderer || !camera ) return
|
||||
|
||||
// extract camera when camera-rig is passed
|
||||
camera.traverse( (n) => String(n.type).match(/Camera/) ? camera = n : null )
|
||||
|
||||
const scope = this;
|
||||
|
||||
const raycaster = new Raycaster();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ xrf.navigator.to = (url,event) => {
|
|||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
console.log("xrfragment: navigating to "+url)
|
||||
|
||||
if( !file || xrf.model.file == file ){ // we're already loaded
|
||||
if( !file || xrf.model.file == file ){ // we're already loaded
|
||||
document.location.hash = `#${hash}` // just update the hash
|
||||
xrf.eval( url, xrf.model ) // and eval URI XR fragments
|
||||
return resolve(xrf.model)
|
||||
|
|
|
|||
|
|
@ -81,10 +81,10 @@ xrf.frag.href = function(v, opts){
|
|||
}
|
||||
|
||||
let teleport = mesh.userData.XRF.href.exec = (e) => {
|
||||
let portalArea = 1 // 2 meter
|
||||
const meshWorldPosition = new THREE.Vector3();
|
||||
meshWorldPosition.setFromMatrixPosition(mesh.matrixWorld);
|
||||
|
||||
let portalArea = 1 // 2 meter
|
||||
const cameraDirection = new THREE.Vector3();
|
||||
camera.getWorldPosition(cameraDirection);
|
||||
cameraDirection.sub(meshWorldPosition);
|
||||
|
|
@ -93,9 +93,11 @@ xrf.frag.href = function(v, opts){
|
|||
const newPos = meshWorldPosition.clone().add(cameraDirection);
|
||||
|
||||
const distance = camera.position.distanceTo(newPos);
|
||||
if( renderer.xr.isPresenting && distance > portalArea ) return // too far away
|
||||
//if( distance > portalArea ){
|
||||
if( !renderer.xr.isPresenting && !confirm("teleport to "+v.string+" ?") ) return
|
||||
|
||||
xrf.navigator.to(v.string) // ok let's surf to HREF!
|
||||
console.log("teleport!")
|
||||
|
||||
xrf.emit('href',{click:true,mesh,xrf:v})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,47 @@
|
|||
xrf.frag.pos = function(v, opts){
|
||||
//if( renderer.xr.isPresenting ) return // too far away
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(" └ setting camera position to "+v.string)
|
||||
camera.position.x = v.x
|
||||
camera.position.y = v.y
|
||||
camera.position.z = v.z
|
||||
|
||||
if( !frag.q ){
|
||||
|
||||
if( true ){//!renderer.xr.isPresenting ){
|
||||
console.dir(camera)
|
||||
camera.position.x = v.x
|
||||
camera.position.y = v.y
|
||||
camera.position.z = v.z
|
||||
}
|
||||
/*
|
||||
else{ // XR
|
||||
let cameraWorldPosition = new THREE.Vector3()
|
||||
camera.object3D.getWorldPosition(this.cameraWorldPosition)
|
||||
let newRigWorldPosition = new THREE.Vector3(v.x,v.y,x.z)
|
||||
|
||||
// Finally update the cameras position
|
||||
let newRigLocalPosition.copy(this.newRigWorldPosition)
|
||||
if (camera.object3D.parent) {
|
||||
camera.object3D.parent.worldToLocal(newRigLocalPosition)
|
||||
}
|
||||
camera.setAttribute('position', newRigLocalPosition)
|
||||
|
||||
// Also take the headset/camera rotation itself into account
|
||||
if (this.data.rotateOnTeleport) {
|
||||
this.teleportOcamerainQuaternion
|
||||
.setFromEuler(new THREE.Euler(0, this.teleportOcamerain.object3D.rotation.y, 0))
|
||||
this.teleportOcamerainQuaternion.invert()
|
||||
this.teleportOcamerainQuaternion.multiply(this.hitEntityQuaternion)
|
||||
// Rotate the camera based on calculated teleport ocamerain rotation
|
||||
this.cameraRig.object3D.setRotationFromQuaternion(this.teleportOcamerainQuaternion)
|
||||
}
|
||||
|
||||
console.log("XR")
|
||||
const offsetPosition = { x: - v.x, y: - v.y, z: - v.z, w: 1 };
|
||||
const offsetRotation = new THREE.Quaternion();
|
||||
const transform = new XRRigidTransform( offsetPosition, offsetRotation );
|
||||
const teleportSpaceOffset = xrf.baseReferenceSpace.getOffsetReferenceSpace( transform );
|
||||
renderer.xr.setReferenceSpace( teleportSpaceOffset );
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue