chore/better-handcontrol: work in progress [might break]
This commit is contained in:
parent
8aa59cb9b8
commit
db021d0a33
12 changed files with 85 additions and 103 deletions
|
|
@ -15,17 +15,18 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a-scene xr-mode-ui="XRMode: xr"
|
<a-scene xr-mode-ui="XRMode: xr"
|
||||||
renderer="colorManagement: true; highRefreshRate:true;"
|
renderer="colorManagement: false; antialias:true; highRefreshRate:true; foveationLevel: 0.5; toneMapping: ACESFilmic; exposure: 3.0"
|
||||||
|
obb-collider="showColliders: true"
|
||||||
light="defaultLightsEnabled: false">
|
light="defaultLightsEnabled: false">
|
||||||
<a-entity id="player" movement-controls touch-controls wasd-controls="fly:false" look-controls>
|
<a-entity id="player" movement-controls touch-controls wasd-controls="fly:false" look-controls>
|
||||||
<a-entity camera="fov:90" position="0 1.6 0" id="camera"></a-entity>
|
<a-entity camera="fov:90" position="0 1.6 0" id="camera"></a-entity>
|
||||||
<a-entity id="left-hand" hand-tracking-controls="hand:left;modelColor:#cccccc" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor">
|
<a-entity id="left-hand" hand-tracking-grab-controls="hand:left;modelColor:#cccccc" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor">
|
||||||
<a-entity rotation="-35 0 0" position="0 0.1 0" id="navigator">
|
<a-entity rotation="-35 0 0" position="0 0.1 0" id="navigator">
|
||||||
<a-entity id="back" xrf-button="label: <; width:0.05; action: history.back()" position="-0.025 0 0" class="ray"></a-entity>
|
<a-entity id="back" xrf-button="label: <; width:0.05; action: history.back()" position="-0.025 0 0" class="ray"></a-entity>
|
||||||
<a-entity id="next" xrf-button="label: >; width:0.05; action: history.forward()" position=" 0.025 0 0" class="ray"></a-entity>
|
<a-entity id="next" xrf-button="label: >; width:0.05; action: history.forward()" position=" 0.025 0 0" class="ray"></a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
<a-entity id="right-hand" hand-tracking-controls="hand:right;modelColor:#cccccc" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor" xrf-pinchmove="rig: #player"></a-entity>
|
<a-entity id="right-hand" hand-tracking-grab-controls="hand:right;modelColor:#cccccc" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor" xrf-pinchmove="rig: #player"></a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
|
|
||||||
<a-entity id="home" xrf="index.glb" xrf-menu></a-entity>
|
<a-entity id="home" xrf="index.glb" xrf-menu></a-entity>
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -39,8 +39,6 @@ window.AFRAME.registerComponent('xrf', {
|
||||||
col: THREE.ColladaLoader
|
col: THREE.ColladaLoader
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
aScene.renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
|
||||||
aScene.renderer.toneMappingExposure = 1.25;
|
|
||||||
if( !XRF.camera ) throw 'xrfragment: no camera detected, please declare <a-entity camera..> ABOVE entities with xrf-attributes'
|
if( !XRF.camera ) throw 'xrfragment: no camera detected, please declare <a-entity camera..> ABOVE entities with xrf-attributes'
|
||||||
|
|
||||||
if( AFRAME.utils.device.isMobile() ){
|
if( AFRAME.utils.device.isMobile() ){
|
||||||
|
|
@ -60,18 +58,22 @@ window.AFRAME.registerComponent('xrf', {
|
||||||
// this is just for convenience (not part of spec): enforce AR + hide/show stuff based on VR tags in 3D model
|
// this is just for convenience (not part of spec): enforce AR + hide/show stuff based on VR tags in 3D model
|
||||||
aScene.canvas.addEventListener('mousedown', () => xrf.camera.el.setAttribute("look-controls","") )
|
aScene.canvas.addEventListener('mousedown', () => xrf.camera.el.setAttribute("look-controls","") )
|
||||||
})
|
})
|
||||||
|
|
||||||
XRF.addEventListener('rot',(e) => {
|
XRF.addEventListener('rot',(e) => {
|
||||||
let lookcontrols = document.querySelector('[look-controls]')
|
let lookcontrols = document.querySelector('[look-controls]')
|
||||||
if( lookcontrols ) lookcontrols.removeAttribute("look-controls")
|
if( lookcontrols ) lookcontrols.removeAttribute("look-controls")
|
||||||
})
|
})
|
||||||
|
|
||||||
let repositionUser = (scale) => () => {
|
let repositionUser = (scale) => () => {
|
||||||
// sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why)
|
// sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why)
|
||||||
let pos = xrf.frag.pos.last
|
setTimeout( () => {
|
||||||
if( pos ){ AFRAME.XRF.camera.position.set(pos.x, pos.y*scale, pos.z) }
|
let pos = xrf.frag.pos.lastVector3
|
||||||
|
if( pos ){ xrf.camera.position.set(pos.x, pos.y*scale, pos.z) }
|
||||||
|
},500)
|
||||||
}
|
}
|
||||||
aScene.addEventListener('enter-vr', () => setTimeout( () => repositionUser(1),100 ) )
|
|
||||||
aScene.addEventListener('enter-ar', () => setTimeout( () => repositionUser(2),100 ) )
|
aScene.addEventListener('enter-vr', repositionUser(1) )
|
||||||
|
aScene.addEventListener('enter-ar', repositionUser(2) )
|
||||||
|
|
||||||
xrf.addEventListener('navigateLoaded', (opts) => {
|
xrf.addEventListener('navigateLoaded', (opts) => {
|
||||||
setTimeout( () => AFRAME.fade.out(),500)
|
setTimeout( () => AFRAME.fade.out(),500)
|
||||||
|
|
@ -145,9 +147,11 @@ window.AFRAME.registerComponent('xrf', {
|
||||||
let {mesh,clickHandler} = opts;
|
let {mesh,clickHandler} = opts;
|
||||||
let createEl = function(c){
|
let createEl = function(c){
|
||||||
let el = document.createElement("a-entity")
|
let el = document.createElement("a-entity")
|
||||||
el.setAttribute("xrf-get",c.name ) // turn into AFRAME entity
|
// raycaster
|
||||||
el.setAttribute("pressable", '' ) // detect click via hand-detection
|
el.setAttribute("pressable", '' ) // detect click via hand-detection
|
||||||
|
el.setAttribute("xrf-get",c.name ) // turn into AFRAME entity
|
||||||
el.setAttribute("class","ray") // expose to raycaster
|
el.setAttribute("class","ray") // expose to raycaster
|
||||||
|
|
||||||
// respond to cursor via laser-controls (https://aframe.io/docs/1.4.0/components/laser-controls.html)
|
// respond to cursor via laser-controls (https://aframe.io/docs/1.4.0/components/laser-controls.html)
|
||||||
el.addEventListener("click", clickHandler )
|
el.addEventListener("click", clickHandler )
|
||||||
el.addEventListener("mouseenter", mesh.userData.XRF.href.selected(true) )
|
el.addEventListener("mouseenter", mesh.userData.XRF.href.selected(true) )
|
||||||
|
|
@ -175,6 +179,8 @@ window.AFRAME.registerComponent('xrf', {
|
||||||
// enable gaze-click on Mobile VR
|
// enable gaze-click on Mobile VR
|
||||||
aScene.setAttribute('xrf-gaze','')
|
aScene.setAttribute('xrf-gaze','')
|
||||||
|
|
||||||
|
if( xrf.debug !== undefined && parseInt(xrf.debug) > 1) aScene.setAttribute('stats','')
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,55 @@
|
||||||
// this makes WebXR hand controls able to click things (by touching it)
|
//// this makes WebXR hand controls able to click things (by touching it)
|
||||||
|
|
||||||
AFRAME.registerComponent('pressable', {
|
AFRAME.registerComponent('pressable', {
|
||||||
schema: {
|
|
||||||
pressDistance: {
|
|
||||||
default: 0.01
|
|
||||||
}
|
|
||||||
},
|
|
||||||
init: function() {
|
|
||||||
this.worldPosition = new THREE.Vector3();
|
|
||||||
this.fingerWorldPosition = new THREE.Vector3();
|
|
||||||
this.raycaster = new THREE.Raycaster()
|
|
||||||
this.handEls = document.querySelectorAll('[hand-tracking-controls]');
|
|
||||||
this.pressed = false;
|
|
||||||
this.distance = -1
|
|
||||||
// we throttle by distance, to support scenes with loads of clickable objects (far away)
|
|
||||||
this.tick = this.throttleByDistance( () => this.detectPress() )
|
|
||||||
},
|
|
||||||
throttleByDistance: function(f){
|
|
||||||
return function(){
|
|
||||||
if( this.distance < 0 ) return f() // first call
|
|
||||||
if( !f.tid ){
|
|
||||||
let x = this.distance
|
|
||||||
let y = x*(x*0.05)*1000 // parabolic curve
|
|
||||||
f.tid = setTimeout( function(){
|
|
||||||
f.tid = null
|
|
||||||
f()
|
|
||||||
}, y )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
detectPress: function(){
|
|
||||||
if( !AFRAME.scenes[0].renderer.xr.isPresenting ) return
|
|
||||||
|
|
||||||
var handEls = this.handEls;
|
init: function(){
|
||||||
var handEl;
|
let handEls = [...document.querySelectorAll('[hand-tracking-controls]')]
|
||||||
let minDistance = 5
|
|
||||||
|
|
||||||
// compensate for xrf-get AFRAME component (which references non-reparented buffergeometries from the 3D model)
|
for( let i in handEls ){
|
||||||
let object3D = this.el.object3D.child || this.el.object3D
|
let handEl = handEls[i]
|
||||||
|
handEl.addEventListener('model-loaded', () => {
|
||||||
|
if( handEl.pressable ) return
|
||||||
|
|
||||||
for (var i = 0; i < handEls.length; i++) {
|
// wait for bones get initialized
|
||||||
handEl = handEls[i];
|
setTimeout( () => {
|
||||||
let indexTipPosition = handEl.components['hand-tracking-controls'].indexTipPosition
|
let bones = handEl.components['hand-tracking-controls'].bones
|
||||||
// Apply the relative position to the parent's world position
|
let indexFinger
|
||||||
handEl.object3D.updateMatrixWorld();
|
for( let i = 0; i < bones.length; i++){
|
||||||
handEl.object3D.getWorldPosition( this.fingerWorldPosition )
|
if( bones[i].name == "index-finger-tip" ){
|
||||||
this.fingerWorldPosition.add( indexTipPosition )
|
indexFinger = i
|
||||||
|
break
|
||||||
this.raycaster.far = this.data.pressDistance
|
|
||||||
// Create a direction vector (doesnt matter because it is supershort for 'touch' purposes)
|
|
||||||
const direction = new THREE.Vector3(1.0,0,0);
|
|
||||||
this.raycaster.set(this.fingerWorldPosition, direction)
|
|
||||||
intersects = this.raycaster.intersectObjects([object3D],true)
|
|
||||||
|
|
||||||
object3D.getWorldPosition(this.worldPosition)
|
|
||||||
|
|
||||||
distance = this.fingerWorldPosition.distanceTo(this.worldPosition)
|
|
||||||
minDistance = distance < minDistance ? distance : minDistance
|
|
||||||
|
|
||||||
if (intersects.length ){
|
|
||||||
if( !this.pressed ){
|
|
||||||
this.el.emit('pressedstarted');
|
|
||||||
this.el.emit('click');
|
|
||||||
this.pressed = setTimeout( () => {
|
|
||||||
this.el.emit('pressedended');
|
|
||||||
this.pressed = false
|
|
||||||
},300)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.distance = minDistance
|
// add obb-collider to index finger-tip
|
||||||
|
let aentity = document.createElement('a-entity')
|
||||||
|
trackedObject3DVariable = `parentNode.components.hand-tracking-controls.bones.${indexFinger}`;
|
||||||
|
console.log(trackedObject3DVariable)
|
||||||
|
handEl.appendChild(aentity)
|
||||||
|
aentity.setAttribute('obb-collider', {trackedObject3D: trackedObject3DVariable, size: 0.015});
|
||||||
|
},500)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
events:{
|
||||||
|
obbcollisionstarted: function(e){
|
||||||
|
if( !e.detail.trackedObject3D ) return
|
||||||
|
if( e.currentTarget && e.currentTarget.emit ){
|
||||||
|
//e.currentTarget.emit('click',
|
||||||
|
}
|
||||||
|
console.dir(e)
|
||||||
|
},
|
||||||
|
"xrf-get": function(){
|
||||||
|
//this.el.setAttribute('obb-collider',{trackedObject3D: 'el.object3D.child' }) // set collider on xrf-get object
|
||||||
|
let aentity = document.createElement('a-entity')
|
||||||
|
trackedObject3DVariable = this.el.object3D.child ? `parentNode.object3D.child` : `parentNode.object3D`
|
||||||
|
console.log(trackedObject3DVariable)
|
||||||
|
this.el.appendChild(aentity)
|
||||||
|
aentity.setAttribute('obb-collider', {trackedObject3D: trackedObject3DVariable});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,13 @@ window.AFRAME.registerComponent('xrf-get', {
|
||||||
// as this would break animations
|
// as this would break animations
|
||||||
this.el.object3D.add = (a) => a
|
this.el.object3D.add = (a) => a
|
||||||
}
|
}
|
||||||
|
this.el.object3D.parent = mesh.parent
|
||||||
|
|
||||||
this.el.setObject3D('mesh',mesh) // (doing this.el.object3D = mesh causes AFRAME to crash when resetting scene)
|
this.el.setObject3D('mesh',mesh) // (doing this.el.object3D = mesh causes AFRAME to crash when resetting scene)
|
||||||
this.el.object3D.child = mesh // keep reference (because .children will be empty)
|
this.el.object3D.child = mesh // keep reference (because .children will be empty)
|
||||||
|
|
||||||
if( !this.el.id ) this.el.setAttribute("id",`xrf-${mesh.name}`)
|
if( !this.el.id ) this.el.setAttribute("id",`xrf-${mesh.name}`)
|
||||||
|
this.el.emit('xrf-get',{})
|
||||||
}
|
}
|
||||||
|
|
||||||
}, evt && evt.timeout ? evt.timeout: 500)
|
}, evt && evt.timeout ? evt.timeout: 500)
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,10 @@ xrf.init = function(opts){
|
||||||
opts = opts || {}
|
opts = opts || {}
|
||||||
|
|
||||||
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
|
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
|
||||||
if( xrf.debug === false ){
|
if( document.location.hash.match(/debug=([0-9])/) ){
|
||||||
console.log("add #debug=[0-9] to URL to see XR Fragment debuglog")
|
|
||||||
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
|
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
|
||||||
}else{
|
|
||||||
xrf.stats()
|
|
||||||
}
|
}
|
||||||
|
if( xrf.debug === false ) console.log("add #debug=[0-9] to URL to see XR Fragment debuglog")
|
||||||
|
|
||||||
xrf.Parser.debug = xrf.debug
|
xrf.Parser.debug = xrf.debug
|
||||||
xrf.detectCameraRig(opts)
|
xrf.detectCameraRig(opts)
|
||||||
|
|
@ -40,15 +38,6 @@ xrf.detectCameraRig = function(opts){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xrf.stats = () => {
|
|
||||||
// bookmarklet from https://github.com/zlgenuine/threejs_stats
|
|
||||||
(function(){
|
|
||||||
let i = 0;
|
|
||||||
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
|
|
||||||
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
|
|
||||||
})()
|
|
||||||
}
|
|
||||||
|
|
||||||
xrf.hasTag = (tag,tags) => String(tags).match( new RegExp(`(^| )${tag}( |$)`,`g`) )
|
xrf.hasTag = (tag,tags) => String(tags).match( new RegExp(`(^| )${tag}( |$)`,`g`) )
|
||||||
|
|
||||||
// map library functions to xrf
|
// map library functions to xrf
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,9 @@ window.frontend = (opts) => new Proxy({
|
||||||
|
|
||||||
updateHashPosition(randomize){
|
updateHashPosition(randomize){
|
||||||
const pos = xrf.frag.pos.get()
|
const pos = xrf.frag.pos.get()
|
||||||
|
xrf.navigator.reactifyHash.enabled = false // prevent teleport
|
||||||
xrf.navigator.URI.hash.pos = `${pos.x},${pos.y},${pos.z}`
|
xrf.navigator.URI.hash.pos = `${pos.x},${pos.y},${pos.z}`
|
||||||
|
xrf.navigator.reactifyHash.enabled = true
|
||||||
this.copyToClipboard( window.location.href );
|
this.copyToClipboard( window.location.href );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ xrf.emit = function(eventName, data){
|
||||||
console.groupCollapsed(label)
|
console.groupCollapsed(label)
|
||||||
console.info(data)
|
console.info(data)
|
||||||
console.groupEnd(label)
|
console.groupEnd(label)
|
||||||
if( xrf.debug > 1 ) debugger
|
if( xrf.debug > 2 ) debugger
|
||||||
}
|
}
|
||||||
return xrf.emit.promise(eventName,data)
|
return xrf.emit.promise(eventName,data)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ xrf.mixers = []
|
||||||
xrf.init = ((init) => function(opts){
|
xrf.init = ((init) => function(opts){
|
||||||
// operate in own subscene
|
// operate in own subscene
|
||||||
let scene = new opts.THREE.Group()
|
let scene = new opts.THREE.Group()
|
||||||
|
xrf.clock = new opts.THREE.Clock()
|
||||||
opts.scene.add(scene)
|
opts.scene.add(scene)
|
||||||
opts.sceneRoot = opts.scene
|
opts.sceneRoot = opts.scene
|
||||||
opts.scene = scene
|
opts.scene = scene
|
||||||
|
|
@ -17,8 +18,6 @@ xrf.init = ((init) => function(opts){
|
||||||
// return xrfragment lib as 'xrf' query functor (like jquery)
|
// return xrfragment lib as 'xrf' query functor (like jquery)
|
||||||
for ( let i in xrf ) xrf.query[i] = xrf[i]
|
for ( let i in xrf ) xrf.query[i] = xrf[i]
|
||||||
|
|
||||||
if( xrf.debug ) xrf.stats()
|
|
||||||
|
|
||||||
return xrf.query
|
return xrf.query
|
||||||
})(xrf.init)
|
})(xrf.init)
|
||||||
|
|
||||||
|
|
@ -26,7 +25,6 @@ xrf.patchRenderer = function(opts){
|
||||||
let {renderer,camera} = opts
|
let {renderer,camera} = opts
|
||||||
renderer.xr.addEventListener( 'sessionstart', () => xrf.baseReferenceSpace = renderer.xr.getReferenceSpace() );
|
renderer.xr.addEventListener( 'sessionstart', () => xrf.baseReferenceSpace = renderer.xr.getReferenceSpace() );
|
||||||
renderer.xr.enabled = true;
|
renderer.xr.enabled = true;
|
||||||
xrf.clock = new xrf.THREE.Clock()
|
|
||||||
renderer.render = ((render) => function(scene,camera){
|
renderer.render = ((render) => function(scene,camera){
|
||||||
// update clock
|
// update clock
|
||||||
let time = xrf.clock.delta = xrf.clock.getDelta()
|
let time = xrf.clock.delta = xrf.clock.getDelta()
|
||||||
|
|
@ -65,7 +63,6 @@ xrf.parseModel.metadataInMesh = (mesh,model) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xrf.getLastModel = () => xrf.model.last
|
xrf.getLastModel = () => xrf.model.last
|
||||||
|
|
||||||
xrf.reset = () => {
|
xrf.reset = () => {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
|
||||||
if( !url ) throw 'xrf.navigator.to(..) no url given'
|
if( !url ) throw 'xrf.navigator.to(..) no url given'
|
||||||
|
|
||||||
let URI = xrfragment.URI.toAbsolute( xrf.navigator.URI, url )
|
let URI = xrfragment.URI.toAbsolute( xrf.navigator.URI, url )
|
||||||
URI.hash = xrf.navigator.reactifyHash(URI.hash)
|
URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...)
|
||||||
// decorate with extra state
|
// decorate with extra state
|
||||||
URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file
|
URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file
|
||||||
URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname
|
URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname
|
||||||
|
|
@ -152,7 +152,7 @@ xrf.navigator.setupNavigateFallbacks = () => {
|
||||||
let {fileExt} = xrfragment.URI.parse(url)
|
let {fileExt} = xrfragment.URI.parse(url)
|
||||||
|
|
||||||
// handle http links
|
// handle http links
|
||||||
if( url.match(/^http/) && !xrf.loaders[fileExt] ){
|
if( url.match(/^http/) && url != xrf.navigator.URI.URN && !xrf.loaders[fileExt] ){
|
||||||
let inIframe
|
let inIframe
|
||||||
try { inIframe = window.self !== window.top; } catch (e) { inIframe = true; }
|
try { inIframe = window.self !== window.top; } catch (e) { inIframe = true; }
|
||||||
return inIframe ? window.parent.postMessage({ url }, '*') : window.open( url, '_blank')
|
return inIframe ? window.parent.postMessage({ url }, '*') : window.open( url, '_blank')
|
||||||
|
|
@ -189,7 +189,9 @@ xrf.navigator.reactifyHash = ( obj ) => {
|
||||||
get(me,k) { return me[k] },
|
get(me,k) { return me[k] },
|
||||||
set(me,k,v){
|
set(me,k,v){
|
||||||
me[k] = v
|
me[k] = v
|
||||||
xrf.navigator.to( "#" + this.toString(me) )
|
if( xrf.navigator.reactifyHash.enabled ){
|
||||||
|
xrf.navigator.to( "#" + this.toString(me) )
|
||||||
|
}
|
||||||
},
|
},
|
||||||
toString(me){
|
toString(me){
|
||||||
let parts = []
|
let parts = []
|
||||||
|
|
@ -200,3 +202,4 @@ xrf.navigator.reactifyHash = ( obj ) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
xrf.navigator.reactifyHash.enabled = true
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ xrf.frag.pos = function(v, opts){
|
||||||
if( xrf.debug ) console.log(`#pos.js: setting camera to position ${pos.x},${pos.y},${pos.z}`)
|
if( xrf.debug ) console.log(`#pos.js: setting camera to position ${pos.x},${pos.y},${pos.z}`)
|
||||||
|
|
||||||
xrf.frag.pos.last = v.string // remember
|
xrf.frag.pos.last = v.string // remember
|
||||||
|
xrf.frag.pos.lastVector3 = camera.position.clone()
|
||||||
|
|
||||||
camera.updateMatrixWorld()
|
camera.updateMatrixWorld()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,9 @@ xrf.frag.src.addModel = (model,url,frag,opts) => {
|
||||||
if( mesh.material && mesh.userData.src ) mesh.material.visible = false // hide placeholder object
|
if( mesh.material && mesh.userData.src ) mesh.material.visible = false // hide placeholder object
|
||||||
|
|
||||||
if( opts.isPortal ){
|
if( opts.isPortal ){
|
||||||
// only add remote objects, because
|
|
||||||
// local scene-objects are already added to scene
|
|
||||||
xrf.portalNonEuclidian({...opts,model,scene:model.scene})
|
xrf.portalNonEuclidian({...opts,model,scene:model.scene})
|
||||||
|
// only add external objects, because
|
||||||
|
// local scene-objects are already added to scene
|
||||||
if( !opts.isLocal ) xrf.scene.add(scene)
|
if( !opts.isLocal ) xrf.scene.add(scene)
|
||||||
}else{
|
}else{
|
||||||
xrf.frag.src.scale( scene, opts, url ) // scale scene
|
xrf.frag.src.scale( scene, opts, url ) // scale scene
|
||||||
|
|
@ -45,7 +45,7 @@ xrf.frag.src.addModel = (model,url,frag,opts) => {
|
||||||
xrf.frag.src.enableSourcePortation({scene,mesh,url,model})
|
xrf.frag.src.enableSourcePortation({scene,mesh,url,model})
|
||||||
// flag everything isSRC & isXRF
|
// flag everything isSRC & isXRF
|
||||||
mesh.traverse( (n) => { n.isSRC = n.isXRF = n[ opts.isLocal ? 'isSRCLocal' : 'isSRCExternal' ] = true })
|
mesh.traverse( (n) => { n.isSRC = n.isXRF = n[ opts.isLocal ? 'isSRCLocal' : 'isSRCExternal' ] = true })
|
||||||
|
|
||||||
xrf.emit('parseModel', {...opts, isSRC:true, mesh, model}) // this will execute all embedded metadata/fragments e.g.
|
xrf.emit('parseModel', {...opts, isSRC:true, mesh, model}) // this will execute all embedded metadata/fragments e.g.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ xrf.frag.src.externalSRC = (url,frag,opts) => {
|
||||||
fetch(url, { method: 'HEAD' })
|
fetch(url, { method: 'HEAD' })
|
||||||
.then( (res) => {
|
.then( (res) => {
|
||||||
let mimetype = res.headers.get('Content-type')
|
let mimetype = res.headers.get('Content-type')
|
||||||
if(xrf.debug > 0 ) console.log("HEAD "+url+" => "+mimetype)
|
if(xrf.debug != undefined ) console.log("HEAD "+url+" => "+mimetype)
|
||||||
if( url.replace(/#.*/,'').match(/\.(gltf|glb)$/) ) mimetype = 'gltf'
|
if( url.replace(/#.*/,'').match(/\.(gltf|glb)$/) ) mimetype = 'gltf'
|
||||||
if( url.replace(/#.*/,'').match(/\.(frag|fs|glsl)$/) ) mimetype = 'x-shader/x-fragment'
|
if( url.replace(/#.*/,'').match(/\.(frag|fs|glsl)$/) ) mimetype = 'x-shader/x-fragment'
|
||||||
if( url.replace(/#.*/,'').match(/\.(vert|vs)$/) ) mimetype = 'x-shader/x-fragment'
|
if( url.replace(/#.*/,'').match(/\.(vert|vs)$/) ) mimetype = 'x-shader/x-fragment'
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue