xrfragment-haxe/src/3rd/three/index.js

142 lines
4.5 KiB
JavaScript
Raw Normal View History

let xrf = xrfragment
xrf.frag = {}
xrf.model = {}
xrf.init = function(opts){
opts = opts || {}
let XRF = function(){
alert("queries are not implemented (yet)")
}
for ( let i in opts ) xrf[i] = opts[i]
for ( let i in xrf.XRF ) xrf.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
xrf.Parser.debug = xrf.debug
if( opts.loaders ) Object.values(opts.loaders).map( xrf.patchLoader )
xrf.patchRenderer(opts.renderer)
xrf.navigate.init()
return xrf
}
xrf.patchRenderer = function(renderer){
renderer.xr.addEventListener( 'sessionstart', () => xrf.baseReferenceSpace = renderer.xr.getReferenceSpace() );
renderer.xr.enabled = true;
2023-05-10 19:12:15 +02:00
renderer.render = ((render) => function(scene,camera){
if( xrf.model && xrf.model.render )
xrf.model.render(scene,camera)
2023-05-10 19:12:15 +02:00
render(scene,camera)
})(renderer.render.bind(renderer))
}
xrf.patchLoader = function(loader){
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
load.call( this,
url,
(model) => { onLoad(model); xrf.parseModel(model,url) },
onProgress,
onError)
})(loader.prototype.load)
}
xrf.getFile = (url) => url.split("/").pop().replace(/#.*/,'')
2023-05-05 18:53:42 +02:00
xrf.parseModel = function(model,url){
let file = xrf.getFile(url)
2023-05-05 18:53:42 +02:00
model.file = file
model.render = function(){}
model.interactive = xrf.InteractiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
model.scene.add(model.interactive)
console.log("scanning "+file)
2023-05-05 18:53:42 +02:00
model.scene.traverse( (mesh) => {
console.log("◎ "+ (mesh.name||`THREE.${mesh.constructor.name}`))
xrf.eval.mesh(mesh,model)
})
}
2023-05-09 17:42:29 +02:00
xrf.getLastModel = () => xrf.model.last
xrf.eval = function( url, model ){
let notice = false
model = model || xrf.model
let { THREE, camera } = xrf
let frag = xrf.URI.parse( url, xrf.XRF.NAVIGATOR )
2023-05-09 17:42:29 +02:00
let meshes = frag.q ? [] : [camera]
2023-05-09 17:42:29 +02:00
for ( let i in meshes ) {
for ( let k in frag ){
let mesh = meshes[i]
if( !String(k).match(/(pos|rot)/) ) notice = true
let opts = {frag, mesh, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE }
xrf.eval.fragment(k,opts)
}
}
if( notice ) alert("only 'pos' and 'rot' XRF.NAVIGATOR-flagged XR fragments are supported (for now)")
}
xrf.eval.mesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
for( let k in mesh.userData ) xrf.Parser.parse( k, mesh.userData[k], frag )
for( let k in frag ){
let opts = {frag, mesh, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE }
xrf.eval.fragment(k,opts)
}
}
}
xrf.eval.fragment = (k, opts ) => {
// call native function (xrf/env.js e.g.), or pass it to user decorator
let func = xrf.frag[k] || function(){}
if( xrf[k] ) xrf[k]( func, opts.frag[k], opts)
else func( opts.frag[k], opts)
}
xrf.reset = () => {
if( !xrf.model.scene ) return
xrf.scene.remove( xrf.model.scene )
xrf.model.scene.traverse( function(node){
if( node instanceof THREE.Mesh ){
node.geometry.dispose()
node.material.dispose()
}
})
}
xrf.navigate = {}
xrf.navigate.to = (url) => {
return new Promise( (resolve,reject) => {
console.log("xrfragment: navigating to "+url)
if( xrf.model && xrf.model.scene ) xrf.model.scene.visible = false
const urlObj = new URL( url.match(/:\/\//) ? url : String(`https://fake.com/${url}`).replace(/\/\//,'/') )
let dir = url.substring(0, url.lastIndexOf('/') + 1)
const file = urlObj.pathname.substring(urlObj.pathname.lastIndexOf('/') + 1);
const ext = file.split('.').pop()
const Loader = xrf.loaders[ext]
if( !Loader ) throw 'xrfragment: no loader passed to xrfragment for extension .'+ext
// force relative path
if( dir ) dir = dir[0] == '.' ? dir : `.${dir}`
const loader = new Loader().setPath( dir )
loader.load( file, function(model){
xrf.scene.add( model.scene )
xrf.reset()
xrf.model = model
xrf.navigate.commit( file )
resolve(model)
})
})
}
xrf.navigate.init = () => {
if( xrf.navigate.init.inited ) return
window.addEventListener('popstate', function (event){
console.dir(event)
xrf.navigate.to( document.location.search.substr(1) + document.location.hash )
})
xrf.navigate.init.inited = true
}
xrf.navigate.commit = (file) => {
window.history.pushState({},null, document.location.pathname + `?${file}${document.location.hash}` )
}