2024-02-08 19:40:43 +01:00
|
|
|
xrf.frag = {dynamic:{}}
|
2023-05-17 21:31:28 +02:00
|
|
|
xrf.model = {}
|
2023-10-30 16:15:08 +01:00
|
|
|
xrf.mixers = []
|
2023-05-04 16:24:54 +02:00
|
|
|
|
2023-06-07 17:42:21 +02:00
|
|
|
xrf.init = ((init) => function(opts){
|
2023-09-21 13:05:30 +02:00
|
|
|
let scene = new opts.THREE.Group()
|
|
|
|
|
opts.scene.add(scene)
|
|
|
|
|
opts.scene = scene
|
2023-06-07 17:42:21 +02:00
|
|
|
init(opts)
|
2024-02-13 17:10:24 +00:00
|
|
|
//if( opts.loaders ) Object.values(opts.loaders).map( xrf.patchLoader )
|
2023-05-17 21:31:28 +02:00
|
|
|
|
2023-10-30 16:15:08 +01:00
|
|
|
xrf.patchRenderer(opts)
|
2023-05-18 12:32:57 +02:00
|
|
|
xrf.navigator.init()
|
2023-06-07 17:42:21 +02:00
|
|
|
// return xrfragment lib as 'xrf' query functor (like jquery)
|
|
|
|
|
for ( let i in xrf ) xrf.query[i] = xrf[i]
|
2023-12-19 20:40:40 +01:00
|
|
|
|
2024-02-17 12:02:07 +00:00
|
|
|
if( xrf.debug ) xrf.stats()
|
|
|
|
|
|
2023-06-07 17:42:21 +02:00
|
|
|
return xrf.query
|
|
|
|
|
})(xrf.init)
|
2023-05-04 16:24:54 +02:00
|
|
|
|
2023-10-30 16:15:08 +01:00
|
|
|
xrf.patchRenderer = function(opts){
|
|
|
|
|
let {renderer,camera} = opts
|
2023-05-12 22:06:21 +02:00
|
|
|
renderer.xr.addEventListener( 'sessionstart', () => xrf.baseReferenceSpace = renderer.xr.getReferenceSpace() );
|
|
|
|
|
renderer.xr.enabled = true;
|
2023-10-30 16:15:08 +01:00
|
|
|
xrf.clock = new xrf.THREE.Clock()
|
2023-05-10 19:12:15 +02:00
|
|
|
renderer.render = ((render) => function(scene,camera){
|
2023-10-26 18:45:13 +02:00
|
|
|
// update clock
|
2024-02-08 19:40:43 +01:00
|
|
|
let time = xrf.clock.delta = xrf.clock.getDelta()
|
2023-11-08 18:28:18 +01:00
|
|
|
xrf.emit('render',{scene,camera,time,render}) // allow fragments to do something at renderframe
|
2023-05-10 19:12:15 +02:00
|
|
|
render(scene,camera)
|
2023-11-14 18:08:19 +01:00
|
|
|
xrf.emit('renderPost',{scene,camera,time,render,renderer}) // allow fragments to do something after renderframe
|
2023-05-10 19:12:15 +02:00
|
|
|
})(renderer.render.bind(renderer))
|
2023-10-30 16:15:08 +01:00
|
|
|
|
2023-05-10 19:12:15 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-12 22:06:21 +02:00
|
|
|
xrf.getFile = (url) => url.split("/").pop().replace(/#.*/,'')
|
2023-05-05 18:53:42 +02:00
|
|
|
|
2024-01-30 09:58:00 +00:00
|
|
|
// parseModel event is essential for src.js to hook into embedded loaded models
|
2023-05-12 22:06:21 +02:00
|
|
|
xrf.parseModel = function(model,url){
|
|
|
|
|
let file = xrf.getFile(url)
|
2023-05-05 18:53:42 +02:00
|
|
|
model.file = file
|
2024-01-30 09:58:00 +00:00
|
|
|
model.isXRF = true
|
|
|
|
|
model.scene.traverse( (n) => n.isXRF = true ) // mark for deletion during reset()
|
2024-02-29 09:57:20 +00:00
|
|
|
|
2023-10-24 18:18:29 +02:00
|
|
|
xrf.emit('parseModel',{model,url,file})
|
2023-05-12 22:06:21 +02:00
|
|
|
}
|
|
|
|
|
|
2024-02-29 09:57:20 +00:00
|
|
|
xrf.parseModel.metadataInMesh = (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: model.scene, renderer: xrf.renderer, THREE: xrf.THREE, hashbus: xrf.hashbus }
|
|
|
|
|
mesh.userData.XRF = frag // allow fragment impl to access XRF obj already
|
|
|
|
|
xrf.emit('frag2mesh',opts)
|
|
|
|
|
.then( () => {
|
|
|
|
|
xrf.hashbus.pub.fragment(k, {...opts, skipXRWG:true})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-09-15 19:42:37 +02:00
|
|
|
xrf.getLastModel = () => xrf.model.last
|
2023-05-12 22:06:21 +02:00
|
|
|
|
|
|
|
|
xrf.reset = () => {
|
2024-02-01 09:04:01 +00:00
|
|
|
|
|
|
|
|
// allow others to reset certain events
|
|
|
|
|
xrf.emit('reset',{})
|
2024-01-31 18:47:02 +00:00
|
|
|
|
2023-05-17 21:31:28 +02:00
|
|
|
const disposeObject = (obj) => {
|
|
|
|
|
if (obj.children.length > 0) obj.children.forEach((child) => disposeObject(child));
|
|
|
|
|
if (obj.geometry) obj.geometry.dispose();
|
|
|
|
|
if (obj.material) {
|
|
|
|
|
if (obj.material.map) obj.material.map.dispose();
|
|
|
|
|
obj.material.dispose();
|
2023-05-12 22:06:21 +02:00
|
|
|
}
|
2023-05-22 15:03:23 +02:00
|
|
|
obj.clear()
|
|
|
|
|
obj.removeFromParent()
|
2023-05-17 21:31:28 +02:00
|
|
|
return true
|
|
|
|
|
};
|
2023-05-22 15:03:23 +02:00
|
|
|
let nodes = []
|
2023-11-09 18:20:47 +01:00
|
|
|
xrf.scene.traverse( (child) => child.isXRF && (nodes.push(child)) )
|
2023-05-22 15:03:23 +02:00
|
|
|
nodes.map( disposeObject ) // leave non-XRF objects intact
|
2023-11-09 18:20:47 +01:00
|
|
|
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
|
2023-09-21 13:05:30 +02:00
|
|
|
xrf.add( xrf.interactive )
|
|
|
|
|
xrf.layers = 0
|
2023-05-12 22:06:21 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-18 12:32:57 +02:00
|
|
|
xrf.add = (object) => {
|
|
|
|
|
object.isXRF = true // mark for easy deletion when replacing scene
|
|
|
|
|
xrf.scene.add(object)
|
|
|
|
|
}
|
2023-11-24 17:32:53 +01:00
|
|
|
|
|
|
|
|
xrf.hasNoMaterial = (mesh) => {
|
|
|
|
|
const hasTexture = mesh.material && mesh.material.map
|
|
|
|
|
const hasMaterialName = mesh.material && mesh.material.name.length > 0
|
|
|
|
|
return mesh.geometry && !hasMaterialName && !hasTexture
|
|
|
|
|
}
|