improving boundingbox scaling by hiding invisible objects

This commit is contained in:
Leon van Kammen 2023-11-17 09:30:39 +01:00
parent 7e656a02f0
commit 211652fa5e
5 changed files with 37 additions and 54 deletions

Binary file not shown.

View File

@ -12,7 +12,9 @@ xrf.filter.scene = function(opts){
xrf.filter
.sort(frag) // get (sorted) filters from XR Fragments
.process(frag,scene) // show/hide things
scene.visible = true // always enable scene
return scene
}
@ -25,22 +27,27 @@ xrf.filter.sort = function(frag){
}
xrf.filter.process = function(frag,scene,opts){
// include all when query starts with negative objectnames/tags are included
let firstFilter = frag.filters[0].filter.get()
let showAll = firstFilter.show === false
let showers = frag.filters.filter( (v) => v.filter.get().show === true )
if( !showAll ) scene.traverse( (n) => n.visible = false )
const hasName = (m,name,filter) => m.name == name
const hasNameOrTag = (m,name_or_tag,filter) => hasName(m,name_or_tag) || m.userData[filter.key]
const cleanupKey = (k) => k.replace(/[-\*]/g,'')
// reparent if first selector is positive and has no value
if( firstFilter.show === true ){
let obj = scene.getObjectByName( firstFilter.key )
while( scene.children.length > 0 ) scene.children[0].removeFromParent()
if(obj) scene.add(obj)
let firstFilter = frag.filters[0].filter.get()
let showers = frag.filters.filter( (v) => v.filter.get().show === true )
// reparent scene based on object in case it matches a primary (non-negating) selector
if( !firstFilter.value && firstFilter.show === true ){
let obj
scene.traverse( (n) => hasName(n, firstFilter.key,firstFilter) && (obj = n) )
if(obj){
while( scene.children.length > 0 ) scene.children[0].removeFromParent()
scene.add( obj )
}
}
// then show/hide things based on secondary selectors
frag.filters.map( (v) => {
const filter = v.filter.get()
const name_or_tag = v.fragment.replace(/[-\*]/g,'')
const name_or_tag = cleanupKey(v.fragment)
let seen = {}
const setVisibleUnseen = (m,visible) => {
@ -50,7 +57,6 @@ xrf.filter.process = function(frag,scene,opts){
}
scene.traverse( (m) => {
const isMatch = m.name == name_or_tag || m.userData[filter.key]
// filter on value(expression) #foo=>3 e.g.
if( filter.value && m.userData[filter.key] ){
@ -63,12 +69,13 @@ xrf.filter.process = function(frag,scene,opts){
}
// include/exclude object(s) when id/tag matches (#foo or #-foo e.g.)
if( isMatch ){
if( hasNameOrTag(m,name_or_tag,filter) ){
m.visible = filter.show
if( filter.deep ) m.traverse( (n) => n.visible = m.visible )
}
})
})
return xrf.filter
}

View File

@ -28,7 +28,7 @@ xrf.frag.src = function(v, opts){
mesh.add(model.scene)
mesh.traverse( (n) => n.isSRC = n.isXRF = true ) // mark everything SRC
xrf.emit('parseModel', {...opts, scene, model})
if( mesh.material ) mesh.material.visible = false
if( mesh.material ) mesh.material.visible = false // hide placeholder object
}
const enableSourcePortation = (src) => {
@ -93,6 +93,13 @@ xrf.frag.src.eval = function(scene, opts, url){
xrf.frag.src.scale = function(scene, opts, url){
let { mesh, model, camera, renderer, THREE} = opts
// remove invisible objects (hidden by selectors) which might corrupt boundingbox size-detection
let cleanScene = scene.clone()
if( !cleanScene ) debugger
let remove = []
cleanScene.traverse( (n) => !n.visible && n.children.length == 0 && (remove.push(n)) )
remove.map( (n) => n.removeFromParent() )
let restrictTo3DBoundingBox = mesh.geometry
if( restrictTo3DBoundingBox ){
// spec 3 of https://xrfragment.org/#src
@ -100,23 +107,11 @@ xrf.frag.src.scale = function(scene, opts, url){
// normalize instanced objectsize to boundingbox
let sizeFrom = new THREE.Vector3()
let sizeTo = new THREE.Vector3()
let empty = new THREE.Object3D()
// *TODO* exclude invisible objects from boundingbox size-detection
//
// THREE.Box3.prototype.expandByObject = (function(expandByObject){
// return function(object,precise){
// return expandByObject.call(this, object.visible ? object : empty, precise)
// }
// })(THREE.Box3.prototype.expandByObject)
new THREE.Box3().setFromObject(mesh).getSize(sizeTo)
new THREE.Box3().setFromObject(scene).getSize(sizeFrom)
new THREE.Box3().setFromObject(cleanScene).getSize(sizeFrom)
let ratio = sizeFrom.divide(sizeTo)
scene.scale.multiplyScalar( 1.0 / Math.max(ratio.x, ratio.y, ratio.z));
// let factor = getMax(sizeTo) < getMax(sizeFrom) ? getMax(sizeTo) / getMax(sizeFrom) : getMax(sizeFrom) / getMax(sizeTo)
// scene.scale.multiplyScalar( factor )
}else{
// spec 4 of https://xrfragment.org/#src
// spec 2 of https://xrfragment.org/#scaling%20of%20instanced%20objects
@ -131,30 +126,10 @@ xrf.frag.src.filterScene = (scene,opts) => {
xrf.filter.scene({scene,frag})
if( scene.children.length == 1 ) scene.children[0].position.set(0,0,0)
/*
if( !frag.filter ){
src = new THREE.Group()
if( Object.keys(frag).length > 0 ){
for( var i in frag ){
if( scene.getObjectByName(i) ){
src.add( obj = scene.getObjectByName(i).clone(true) )
}
hashbus.pub.fragment(i, Object.assign(opts,{frag, model,scene}))
}
}
if( src.children.length == 1 ) obj.position.set(0,0,0);
}
// filtering of objects using query
if( Object.keys(frag).length > 1 ){
src = scene
xrf.filter.scene(src,frag)
}
src.traverse( (m) => {
scene.traverse( (m) => {
if( m.userData && (m.userData.src || m.userData.href) ) return ; // prevent infinite recursion
hashbus.pub.mesh(m,{scene,recursive:true}) // cool idea: recursion-depth based distance between face & src
})
*/
return scene
}

View File

@ -16,7 +16,7 @@ let loadVideo = (mimetype) => function(url,opts){
mesh.material = mat
// set range
video.addEventListener('timeupdate', function timeupdate() {
if (video.t && video.currentTime < video.t.y || video.currentTime >= video.y.z ) {
if (video.t && video.currentTime < video.t.y || video.currentTime >= video.t.z ) {
vid.currentTime = video.t.y
}
},false)

View File

@ -28,7 +28,7 @@ filterScene = (URI) => {
scene = filterScene("#b")
test = () => !scene.getObjectByName("a") &&
scene.getObjectByName("b").visible &&
!scene.getObjectByName("c")
!scene.getObjectByName("c").visible
console.assert( test(), {scene,reason:`objectname: #b => a = removed b = visible c = removed`})
scene = filterScene("#b*")
@ -68,6 +68,7 @@ test = () => scene.getObjectByName("a").visible &&
console.assert( test(), {scene,reason:`objectname: #-b&b => a = visible b = visible c = invisible`})
scene = filterScene("#score")
console.dir(scene)
test = () => !scene.getObjectByName("a") &&
scene.getObjectByName("b").visible &&
!scene.getObjectByName("c").visible
@ -80,13 +81,13 @@ test = () => !scene.getObjectByName("a") &&
console.assert( test(), {scene,reason:`objectname: #score=>1 => a = removed b = visible c = invisible`})
scene = filterScene("#score=>3")
test = () => !scene.getObjectByName("a").visible &&
test = () => !scene.getObjectByName("a") &&
!scene.getObjectByName("b").visible &&
!scene.getObjectByName("c").visible
console.assert( test(), {scene,reason:`objectname: #score=>3 => a = invisible b = visible c = invisible`})
scene = filterScene("#score*=>1")
test = () => !scene.getObjectByName("a").visible &&
test = () => !scene.getObjectByName("a") &&
scene.getObjectByName("b").visible &&
scene.getObjectByName("c").visible
console.assert( test(), {scene,reason:`objectname: #score*=>1 => a = invisible b = visible c = visible`})