modelviewer wip

This commit is contained in:
Leon van Kammen 2024-07-15 15:15:11 +02:00
parent ca39e2d9aa
commit 15bf278c9f

View file

@ -14,31 +14,19 @@
<model-viewer <model-viewer
src="./../assets/index.glb" src="./../assets/index.glb"
environment-image="https://cdn.glitch.global/8e507517-31ff-4aa5-80c1-10ea6de9483d/white_furnace.hdr" environment-image="https://cdn.glitch.global/8e507517-31ff-4aa5-80c1-10ea6de9483d/white_furnace.hdr"
ar alt="XR Fragments demo scene" touch-action="none" disable-pan disable-zoom ar alt="XR Fragments demo scene"camera-controls touch-action="none" disable-tap
field-of-view="75deg" min-field-of-view="25deg" max-field-of-view="100deg" field-of-view="80deg" min-field-of-view="25deg" max-field-of-view="100deg"
interpolation-decay="200" camera-target="0m 0m 0m" min-camera-orbit="0.1% 0.1% 0.1%"
style="width:80%; height:50vh; border-radius:5px; border:1px solid #CCC" style="width:80%; height:50vh; border-radius:5px; border:1px solid #CCC"
> >
</model-viewer> </model-viewer>
<script type="importmap"> <script src="./../../dist/xrfragment.js"></script>
{ <script>
"imports": {
"three": "https://unpkg.com/three@0.165.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.165.0/examples/jsm/"
}
}
</script>
<script type="module">
import xrf from "./../../../dist/xrfragment.three.module.js";
import * as THREE from 'three'; // *TODO* get three handle from mv
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
import { USDZLoader } from 'three/addons/loaders/USDZLoader.js';
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
const mv = window.mv = document.querySelector("model-viewer"); const mv = window.mv = document.querySelector("model-viewer");
const $url = document.querySelector('#url') const $url = document.querySelector('#url')
const orbitDefault = '50deg 90deg 1.0m' const orbitDefault = '50deg 90deg 1.0m'
const panOffset = 1.6
function getSymbol(name) { function getSymbol(name) {
let obj = mv; let obj = mv;
@ -67,9 +55,6 @@
btn.setAttribute('data-position',`${pos.x}m ${pos.y}m ${pos.z}m`) btn.setAttribute('data-position',`${pos.x}m ${pos.y}m ${pos.z}m`)
btn.setAttribute('data-target',`${pos.x}m ${pos.y}m ${pos.z}m`) btn.setAttribute('data-target',`${pos.x}m ${pos.y}m ${pos.z}m`)
btn.setAttribute('data-orbit', orbitDefault ) btn.setAttribute('data-orbit', orbitDefault )
// btn.style.opacity = 0.01
btn.style.borderRadius = '50%'
btn.style.padding = '30px'
btn.style.cursor = 'pointer' btn.style.cursor = 'pointer'
mv.appendChild(btn) mv.appendChild(btn)
} }
@ -77,7 +62,7 @@
const setupHotspots = (scene) => { const setupHotspots = (scene) => {
scene.traverse( (n) => { scene.traverse( (n) => {
if( n.userData.href ){ if( n.userData.href ){
let pos = new THREE.Vector3() let pos = n.position.clone()
n.getWorldPosition(pos) n.getWorldPosition(pos)
createHotspot(pos, n) createHotspot(pos, n)
} }
@ -95,7 +80,6 @@
mv.fieldOfView = '45deg'; mv.fieldOfView = '45deg';
console.dir(node) console.dir(node)
if( node && node.userData.href ){ if( node && node.userData.href ){
// xrf.navigator.to( node.userData.href )
//node.userData.XRF.href.exec({type:'click'}) //node.userData.XRF.href.exec({type:'click'})
console.log("clicked!") console.log("clicked!")
} }
@ -105,16 +89,19 @@
}); });
} }
const setupDefaultProjection = () => { const setupDefaultProjection = (scene) => {
let frag = xrf.URI.parse( xrf.scene.children[0].userData['#'] ) let defaultStr = scene.userData['#']
if( !defaultStr ) return console.warn('no default # fragment found in 3D model')
console.log("defaultStr "+defaultStr)
let frag = xrf.URI.parse( defaultStr )
if( frag.XRF.pos ){ if( frag.XRF.pos ){
let obj = xrf.scene.getObjectByName( frag.XRF.pos.string ) let obj = scene.getObjectByName( frag.XRF.pos.string )
if( !obj ) return console.error('obj '+frag.XRF.pos.string+" not found") if( !obj ) return console.error('obj '+frag.XRF.pos.string+" not found")
console.log("updating cam") console.log("updating cam")
const pos = new THREE.Vector3() const pos = obj.position.clone()
obj.getWorldPosition(pos) obj.getWorldPosition(pos)
obj.position.y += 1.6 // add person length pos.y += panOffset
mv.cameraTarget = `${pos.x} ${pos.y} ${pos.z}` mv.cameraTarget = `${pos.x}m ${pos.y}m ${pos.z}m`
console.log(`${pos.x} ${pos.y} ${pos.z}`) console.log(`${pos.x} ${pos.y} ${pos.z}`)
mv.cameraOrbit = orbitDefault; mv.cameraOrbit = orbitDefault;
mv.fieldOfView = '45deg'; mv.fieldOfView = '45deg';
@ -122,84 +109,48 @@
} }
const setupCSS = (scene) => { const setupCSS = (scene) => {
//if( document.querySelector('#viewbutton-css') ) return if( document.querySelector('#viewbutton-css') ) return
//let style = document.createElement('style') let style = document.createElement('style')
//style.type = 'text/css' style.type = 'text/css'
//style.innerHTML = ` style.id = 'viewbutton-css'
// .view-button { style.innerHTML = `
// background: #fff; .view-button{
// border-radius: 4px; opacity:0.001;
// border: none; cursor:pointer;
// box-sizing: border-box; }
// box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); .view-button:hover{
// color: rgba(0, 0, 0, 0.8); opacity:1;
// display: block; cursor:pointer;
// font-family: Futura, Helvetica Neue, sans-serif; }
// font-size: 12px; `
// font-weight: 700; document.body.appendChild(style)
// max-width: 128px;
// overflow-wrap: break-word;
// padding: 0.5em 1em;
// position: absolute;
// width: max-content;
// height: max-content;
// transform: translate3d(-50%, -50%, 0);
// }
//`
//document.body.appendChild(style)
} }
const opts = { const onLoad = () => function(){
xrf, const scene = mv[getSymbol('scene')].getObjectByName('Target').children[0]
THREE,
}
const onLoad = (opts) => function(){
const scene = mv[getSymbol('scene')]
const renderer = mv[getSymbol("renderer")].threeRenderer const renderer = mv[getSymbol("renderer")].threeRenderer
const controls = mv[getSymbol("controls")] const controls = mv[getSymbol("controls")]
const camera = mv[getSymbol("scene")].getCamera() const camera = mv[getSymbol("scene")].getCamera()
const url = mv.src const url = mv.src
opts = window.opts = { opts = window.opts = {
...opts,
scene, scene,
renderer, renderer,
camera, camera,
loaders: { gltf: GLTFLoader, glb: GLTFLoader, fbx: FBXLoader, obj: OBJLoader, usdz: USDZLoader },
controls controls
} }
window.opts = opts window.opts = opts
window.xrf = window.xrfragment // shorten
// mark current loaded scene for deletion by xrfragment library (except camera) setupCSS()
//scene.traverse( (o) => o.isXRF = o.id != camera.id ) setupHotspots(scene)
setupDefaultProjection(scene)
// enable XR fragments
if( camera.parent == null ) scene.add(camera) // xr fragments expects in-scene camera
let xrf = opts.xrf.init(opts)
window.xrf = xrf
xrf.sceneRoot.children.map( (c) => (camera.id != c.id) && (c.visible = false) )
xrf.addEventListener('href', (opts) => {
console.dir(opts)
})
xrf.addEventListener('navigateLoaded', function(opts){
console.dir(xrf.scene)
setupCSS()
setupHotspots(scene)
// setupDefaultProjection()
console.log("ready")
})
// now we re-insert the model via the XR Fragments lib (so it will parse the XRF metadata) // now we re-insert the model via the XR Fragments lib (so it will parse the XRF metadata)
xrf.navigator.to(url)
} }
mv.addEventListener("load", onLoad(opts) ) mv.addEventListener("load", onLoad() )
//mv.addEventListener('before-render', function(){ //mv.addEventListener('before-render', function(){
// const scene = mv[getSymbol('scene')] // const scene = mv[getSymbol('scene')]
// scene.visible = false // scene.visible = false