audio first attempt
This commit is contained in:
parent
4c92ead37f
commit
5c2602d40b
|
@ -891,6 +891,8 @@ xrf.reset = () => {
|
|||
xrf.scene.traverse( (child) => child.isXRF ? nodes.push(child) : false )
|
||||
nodes.map( disposeObject ) // leave non-XRF objects intact
|
||||
xrf.interactive = xrf.InteractiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
|
||||
if( xrf.audio ) xrf.audio.map( (a) => a.remove() )
|
||||
xrf.audio = []
|
||||
xrf.add( xrf.interactive )
|
||||
xrf.layers = 0
|
||||
}
|
||||
|
@ -908,7 +910,6 @@ xrf.add = (object) => {
|
|||
object.isXRF = true // mark for easy deletion when replacing scene
|
||||
xrf.scene.add(object)
|
||||
}
|
||||
|
||||
// wrapper to survive in/outside modules
|
||||
|
||||
xrf.InteractiveGroup = function(THREE,renderer,camera){
|
||||
|
@ -1820,9 +1821,100 @@ xrf.frag.src.type = {}
|
|||
|
||||
xrf.frag.src.type['unknown'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
reject(`${url} mimetype not supported (yet)`)
|
||||
reject(`${url} mimetype not found or supported (yet)`)
|
||||
})
|
||||
}
|
||||
xrf.frag.t = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(` └ setting animation loop to ${v.x} ${v.y} ${v.z}` )
|
||||
if( !model.animations || model.animations[0] == undefined ) return console.warn('no animation in scene')
|
||||
|
||||
model.mixer.t = v
|
||||
let duration = model.animations[0].duration
|
||||
let frames = model.animations[0].tracks[0].times.length
|
||||
let mixer = model.mixer
|
||||
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
||||
let fps = frames / duration
|
||||
|
||||
mixer.loop.speed = v.x
|
||||
mixer.loop.speedAbs = Math.abs(v.x)
|
||||
mixer.loop.frameStart = v.y || mixer.loop.frameStart
|
||||
mixer.loop.frameStop = v.z || mixer.loop.frameStop
|
||||
// always recalculate time using frameStart/Stop
|
||||
mixer.loop.timeStart = mixer.loop.frameStart / (fps * mixer.loop.speedAbs)
|
||||
mixer.loop.timeStop = mixer.loop.frameStop / (fps * mixer.loop.speedAbs)
|
||||
|
||||
// update speed
|
||||
mixer.timeScale = mixer.loop.speed
|
||||
|
||||
let updateTime = (time) => {
|
||||
mixer.setTime(time)
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||
// (re)trigger audio
|
||||
xrf.audio.map( (a) => {
|
||||
a.play()
|
||||
a.currentTime = time
|
||||
})
|
||||
}
|
||||
|
||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||
|
||||
// update loop when needed
|
||||
if( !mixer.update.patched ){
|
||||
let update = mixer.update
|
||||
mixer.update = function(time){
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
if( time == 0 ) return update.call(mixer,time)
|
||||
|
||||
if( mixer.loop.speed > 0.0 && mixer.time > mixer.loop.timeStop * mixer.loop.speedAbs ){
|
||||
setTimeout( (time) => updateTime(time),0,mixer.loop.timeStart) // prevent recursion
|
||||
}
|
||||
return update.call( mixer, time )
|
||||
}
|
||||
mixer.update.patched = true
|
||||
}
|
||||
}
|
||||
/*
|
||||
* mimetype: audio/aac
|
||||
* mimetype: audio/mpeg
|
||||
* mimetype: audio/ogg
|
||||
* mimetype: audio/weba
|
||||
* mimetype: audio/wav
|
||||
*/
|
||||
|
||||
let loadAudio = (mimetype) => function(url,opts){
|
||||
let {mesh} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
|
||||
// global audio
|
||||
if( mesh.position.x == 0 && mesh.position.y == 0 && mesh.position.z == 0 ){
|
||||
let audio = window.document.createElement('audio')
|
||||
// init fallback formats
|
||||
let fallback = ['mp3','ogg','wav','weba','aac']
|
||||
let addSource = (ext) => {
|
||||
const src = window.document.createElement('source')
|
||||
src.setAttribute("src", url)
|
||||
src.setAttribute("type",mimetype)
|
||||
audio.appendChild(src)
|
||||
}
|
||||
fallback
|
||||
.filter( (e) => e != ext )
|
||||
.map( addSource )
|
||||
document.body.appendChild(audio)
|
||||
xrf.audio.push(audio)
|
||||
}
|
||||
}
|
||||
|
||||
let audioMimeTypes = [
|
||||
'audio/wav',
|
||||
'audio/mpeg',
|
||||
'audio/weba',
|
||||
'audio/aac',
|
||||
'audio/ogg',
|
||||
'application/ogg'
|
||||
]
|
||||
audioMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadAudio(mimetype) )
|
||||
|
||||
/*
|
||||
* mimetype: model/gltf+json
|
||||
|
@ -1889,52 +1981,6 @@ xrf.frag.src.type['image/png'] = function(url,opts){
|
|||
xrf.frag.src.type['image/gif'] = xrf.frag.src.type['image/png']
|
||||
xrf.frag.src.type['image/jpg'] = xrf.frag.src.type['image/png']
|
||||
|
||||
xrf.frag.t = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(` └ setting animation loop to ${v.x} ${v.y} ${v.z}` )
|
||||
if( !model.animations || model.animations[0] == undefined ) return console.warn('no animation in scene')
|
||||
|
||||
model.mixer.t = v
|
||||
let duration = model.animations[0].duration
|
||||
let frames = model.animations[0].tracks[0].times.length
|
||||
let mixer = model.mixer
|
||||
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
||||
let fps = frames / duration
|
||||
|
||||
mixer.loop.speed = v.x
|
||||
mixer.loop.speedAbs = Math.abs(v.x)
|
||||
mixer.loop.frameStart = v.y || mixer.loop.frameStart
|
||||
mixer.loop.frameStop = v.z || mixer.loop.frameStop
|
||||
// always recalculate time using frameStart/Stop
|
||||
mixer.loop.timeStart = mixer.loop.frameStart / (fps * mixer.loop.speedAbs)
|
||||
mixer.loop.timeStop = mixer.loop.frameStop / (fps * mixer.loop.speedAbs)
|
||||
|
||||
// update speed
|
||||
mixer.timeScale = mixer.loop.speed
|
||||
|
||||
let updateTime = (time) => {
|
||||
mixer.setTime(time)
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||
}
|
||||
|
||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||
|
||||
// update loop when needed
|
||||
if( !mixer.update.patched ){
|
||||
let update = mixer.update
|
||||
mixer.update = function(time){
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
if( time == 0 ) return update.call(mixer,time)
|
||||
|
||||
if( mixer.loop.speed > 0.0 && mixer.time > mixer.loop.timeStop * mixer.loop.speedAbs ){
|
||||
setTimeout( (time) => updateTime(time),0,mixer.loop.timeStart) // prevent recursion
|
||||
}
|
||||
return update.call( mixer, time )
|
||||
}
|
||||
mixer.update.patched = true
|
||||
}
|
||||
}
|
||||
window.AFRAME.registerComponent('xrf', {
|
||||
schema: {
|
||||
},
|
||||
|
|
|
@ -891,6 +891,8 @@ xrf.reset = () => {
|
|||
xrf.scene.traverse( (child) => child.isXRF ? nodes.push(child) : false )
|
||||
nodes.map( disposeObject ) // leave non-XRF objects intact
|
||||
xrf.interactive = xrf.InteractiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
|
||||
if( xrf.audio ) xrf.audio.map( (a) => a.remove() )
|
||||
xrf.audio = []
|
||||
xrf.add( xrf.interactive )
|
||||
xrf.layers = 0
|
||||
}
|
||||
|
@ -908,7 +910,6 @@ xrf.add = (object) => {
|
|||
object.isXRF = true // mark for easy deletion when replacing scene
|
||||
xrf.scene.add(object)
|
||||
}
|
||||
|
||||
// wrapper to survive in/outside modules
|
||||
|
||||
xrf.InteractiveGroup = function(THREE,renderer,camera){
|
||||
|
@ -1820,9 +1821,100 @@ xrf.frag.src.type = {}
|
|||
|
||||
xrf.frag.src.type['unknown'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
reject(`${url} mimetype not supported (yet)`)
|
||||
reject(`${url} mimetype not found or supported (yet)`)
|
||||
})
|
||||
}
|
||||
xrf.frag.t = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(` └ setting animation loop to ${v.x} ${v.y} ${v.z}` )
|
||||
if( !model.animations || model.animations[0] == undefined ) return console.warn('no animation in scene')
|
||||
|
||||
model.mixer.t = v
|
||||
let duration = model.animations[0].duration
|
||||
let frames = model.animations[0].tracks[0].times.length
|
||||
let mixer = model.mixer
|
||||
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
||||
let fps = frames / duration
|
||||
|
||||
mixer.loop.speed = v.x
|
||||
mixer.loop.speedAbs = Math.abs(v.x)
|
||||
mixer.loop.frameStart = v.y || mixer.loop.frameStart
|
||||
mixer.loop.frameStop = v.z || mixer.loop.frameStop
|
||||
// always recalculate time using frameStart/Stop
|
||||
mixer.loop.timeStart = mixer.loop.frameStart / (fps * mixer.loop.speedAbs)
|
||||
mixer.loop.timeStop = mixer.loop.frameStop / (fps * mixer.loop.speedAbs)
|
||||
|
||||
// update speed
|
||||
mixer.timeScale = mixer.loop.speed
|
||||
|
||||
let updateTime = (time) => {
|
||||
mixer.setTime(time)
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||
// (re)trigger audio
|
||||
xrf.audio.map( (a) => {
|
||||
a.play()
|
||||
a.currentTime = time
|
||||
})
|
||||
}
|
||||
|
||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||
|
||||
// update loop when needed
|
||||
if( !mixer.update.patched ){
|
||||
let update = mixer.update
|
||||
mixer.update = function(time){
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
if( time == 0 ) return update.call(mixer,time)
|
||||
|
||||
if( mixer.loop.speed > 0.0 && mixer.time > mixer.loop.timeStop * mixer.loop.speedAbs ){
|
||||
setTimeout( (time) => updateTime(time),0,mixer.loop.timeStart) // prevent recursion
|
||||
}
|
||||
return update.call( mixer, time )
|
||||
}
|
||||
mixer.update.patched = true
|
||||
}
|
||||
}
|
||||
/*
|
||||
* mimetype: audio/aac
|
||||
* mimetype: audio/mpeg
|
||||
* mimetype: audio/ogg
|
||||
* mimetype: audio/weba
|
||||
* mimetype: audio/wav
|
||||
*/
|
||||
|
||||
let loadAudio = (mimetype) => function(url,opts){
|
||||
let {mesh} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
|
||||
// global audio
|
||||
if( mesh.position.x == 0 && mesh.position.y == 0 && mesh.position.z == 0 ){
|
||||
let audio = window.document.createElement('audio')
|
||||
// init fallback formats
|
||||
let fallback = ['mp3','ogg','wav','weba','aac']
|
||||
let addSource = (ext) => {
|
||||
const src = window.document.createElement('source')
|
||||
src.setAttribute("src", url)
|
||||
src.setAttribute("type",mimetype)
|
||||
audio.appendChild(src)
|
||||
}
|
||||
fallback
|
||||
.filter( (e) => e != ext )
|
||||
.map( addSource )
|
||||
document.body.appendChild(audio)
|
||||
xrf.audio.push(audio)
|
||||
}
|
||||
}
|
||||
|
||||
let audioMimeTypes = [
|
||||
'audio/wav',
|
||||
'audio/mpeg',
|
||||
'audio/weba',
|
||||
'audio/aac',
|
||||
'audio/ogg',
|
||||
'application/ogg'
|
||||
]
|
||||
audioMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadAudio(mimetype) )
|
||||
|
||||
/*
|
||||
* mimetype: model/gltf+json
|
||||
|
@ -1889,49 +1981,3 @@ xrf.frag.src.type['image/png'] = function(url,opts){
|
|||
xrf.frag.src.type['image/gif'] = xrf.frag.src.type['image/png']
|
||||
xrf.frag.src.type['image/jpg'] = xrf.frag.src.type['image/png']
|
||||
|
||||
xrf.frag.t = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(` └ setting animation loop to ${v.x} ${v.y} ${v.z}` )
|
||||
if( !model.animations || model.animations[0] == undefined ) return console.warn('no animation in scene')
|
||||
|
||||
model.mixer.t = v
|
||||
let duration = model.animations[0].duration
|
||||
let frames = model.animations[0].tracks[0].times.length
|
||||
let mixer = model.mixer
|
||||
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
||||
let fps = frames / duration
|
||||
|
||||
mixer.loop.speed = v.x
|
||||
mixer.loop.speedAbs = Math.abs(v.x)
|
||||
mixer.loop.frameStart = v.y || mixer.loop.frameStart
|
||||
mixer.loop.frameStop = v.z || mixer.loop.frameStop
|
||||
// always recalculate time using frameStart/Stop
|
||||
mixer.loop.timeStart = mixer.loop.frameStart / (fps * mixer.loop.speedAbs)
|
||||
mixer.loop.timeStop = mixer.loop.frameStop / (fps * mixer.loop.speedAbs)
|
||||
|
||||
// update speed
|
||||
mixer.timeScale = mixer.loop.speed
|
||||
|
||||
let updateTime = (time) => {
|
||||
mixer.setTime(time)
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||
}
|
||||
|
||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||
|
||||
// update loop when needed
|
||||
if( !mixer.update.patched ){
|
||||
let update = mixer.update
|
||||
mixer.update = function(time){
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
if( time == 0 ) return update.call(mixer,time)
|
||||
|
||||
if( mixer.loop.speed > 0.0 && mixer.time > mixer.loop.timeStop * mixer.loop.speedAbs ){
|
||||
setTimeout( (time) => updateTime(time),0,mixer.loop.timeStart) // prevent recursion
|
||||
}
|
||||
return update.call( mixer, time )
|
||||
}
|
||||
mixer.update.patched = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -891,6 +891,8 @@ xrf.reset = () => {
|
|||
xrf.scene.traverse( (child) => child.isXRF ? nodes.push(child) : false )
|
||||
nodes.map( disposeObject ) // leave non-XRF objects intact
|
||||
xrf.interactive = xrf.InteractiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
|
||||
if( xrf.audio ) xrf.audio.map( (a) => a.remove() )
|
||||
xrf.audio = []
|
||||
xrf.add( xrf.interactive )
|
||||
xrf.layers = 0
|
||||
}
|
||||
|
@ -908,7 +910,6 @@ xrf.add = (object) => {
|
|||
object.isXRF = true // mark for easy deletion when replacing scene
|
||||
xrf.scene.add(object)
|
||||
}
|
||||
|
||||
// wrapper to survive in/outside modules
|
||||
|
||||
xrf.InteractiveGroup = function(THREE,renderer,camera){
|
||||
|
@ -1820,9 +1821,100 @@ xrf.frag.src.type = {}
|
|||
|
||||
xrf.frag.src.type['unknown'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
reject(`${url} mimetype not supported (yet)`)
|
||||
reject(`${url} mimetype not found or supported (yet)`)
|
||||
})
|
||||
}
|
||||
xrf.frag.t = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(` └ setting animation loop to ${v.x} ${v.y} ${v.z}` )
|
||||
if( !model.animations || model.animations[0] == undefined ) return console.warn('no animation in scene')
|
||||
|
||||
model.mixer.t = v
|
||||
let duration = model.animations[0].duration
|
||||
let frames = model.animations[0].tracks[0].times.length
|
||||
let mixer = model.mixer
|
||||
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
||||
let fps = frames / duration
|
||||
|
||||
mixer.loop.speed = v.x
|
||||
mixer.loop.speedAbs = Math.abs(v.x)
|
||||
mixer.loop.frameStart = v.y || mixer.loop.frameStart
|
||||
mixer.loop.frameStop = v.z || mixer.loop.frameStop
|
||||
// always recalculate time using frameStart/Stop
|
||||
mixer.loop.timeStart = mixer.loop.frameStart / (fps * mixer.loop.speedAbs)
|
||||
mixer.loop.timeStop = mixer.loop.frameStop / (fps * mixer.loop.speedAbs)
|
||||
|
||||
// update speed
|
||||
mixer.timeScale = mixer.loop.speed
|
||||
|
||||
let updateTime = (time) => {
|
||||
mixer.setTime(time)
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||
// (re)trigger audio
|
||||
xrf.audio.map( (a) => {
|
||||
a.play()
|
||||
a.currentTime = time
|
||||
})
|
||||
}
|
||||
|
||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||
|
||||
// update loop when needed
|
||||
if( !mixer.update.patched ){
|
||||
let update = mixer.update
|
||||
mixer.update = function(time){
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
if( time == 0 ) return update.call(mixer,time)
|
||||
|
||||
if( mixer.loop.speed > 0.0 && mixer.time > mixer.loop.timeStop * mixer.loop.speedAbs ){
|
||||
setTimeout( (time) => updateTime(time),0,mixer.loop.timeStart) // prevent recursion
|
||||
}
|
||||
return update.call( mixer, time )
|
||||
}
|
||||
mixer.update.patched = true
|
||||
}
|
||||
}
|
||||
/*
|
||||
* mimetype: audio/aac
|
||||
* mimetype: audio/mpeg
|
||||
* mimetype: audio/ogg
|
||||
* mimetype: audio/weba
|
||||
* mimetype: audio/wav
|
||||
*/
|
||||
|
||||
let loadAudio = (mimetype) => function(url,opts){
|
||||
let {mesh} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
|
||||
// global audio
|
||||
if( mesh.position.x == 0 && mesh.position.y == 0 && mesh.position.z == 0 ){
|
||||
let audio = window.document.createElement('audio')
|
||||
// init fallback formats
|
||||
let fallback = ['mp3','ogg','wav','weba','aac']
|
||||
let addSource = (ext) => {
|
||||
const src = window.document.createElement('source')
|
||||
src.setAttribute("src", url)
|
||||
src.setAttribute("type",mimetype)
|
||||
audio.appendChild(src)
|
||||
}
|
||||
fallback
|
||||
.filter( (e) => e != ext )
|
||||
.map( addSource )
|
||||
document.body.appendChild(audio)
|
||||
xrf.audio.push(audio)
|
||||
}
|
||||
}
|
||||
|
||||
let audioMimeTypes = [
|
||||
'audio/wav',
|
||||
'audio/mpeg',
|
||||
'audio/weba',
|
||||
'audio/aac',
|
||||
'audio/ogg',
|
||||
'application/ogg'
|
||||
]
|
||||
audioMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadAudio(mimetype) )
|
||||
|
||||
/*
|
||||
* mimetype: model/gltf+json
|
||||
|
@ -1889,50 +1981,4 @@ xrf.frag.src.type['image/png'] = function(url,opts){
|
|||
xrf.frag.src.type['image/gif'] = xrf.frag.src.type['image/png']
|
||||
xrf.frag.src.type['image/jpg'] = xrf.frag.src.type['image/png']
|
||||
|
||||
xrf.frag.t = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(` └ setting animation loop to ${v.x} ${v.y} ${v.z}` )
|
||||
if( !model.animations || model.animations[0] == undefined ) return console.warn('no animation in scene')
|
||||
|
||||
model.mixer.t = v
|
||||
let duration = model.animations[0].duration
|
||||
let frames = model.animations[0].tracks[0].times.length
|
||||
let mixer = model.mixer
|
||||
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
||||
let fps = frames / duration
|
||||
|
||||
mixer.loop.speed = v.x
|
||||
mixer.loop.speedAbs = Math.abs(v.x)
|
||||
mixer.loop.frameStart = v.y || mixer.loop.frameStart
|
||||
mixer.loop.frameStop = v.z || mixer.loop.frameStop
|
||||
// always recalculate time using frameStart/Stop
|
||||
mixer.loop.timeStart = mixer.loop.frameStart / (fps * mixer.loop.speedAbs)
|
||||
mixer.loop.timeStop = mixer.loop.frameStop / (fps * mixer.loop.speedAbs)
|
||||
|
||||
// update speed
|
||||
mixer.timeScale = mixer.loop.speed
|
||||
|
||||
let updateTime = (time) => {
|
||||
mixer.setTime(time)
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||
}
|
||||
|
||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||
|
||||
// update loop when needed
|
||||
if( !mixer.update.patched ){
|
||||
let update = mixer.update
|
||||
mixer.update = function(time){
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
if( time == 0 ) return update.call(mixer,time)
|
||||
|
||||
if( mixer.loop.speed > 0.0 && mixer.time > mixer.loop.timeStop * mixer.loop.speedAbs ){
|
||||
setTimeout( (time) => updateTime(time),0,mixer.loop.timeStart) // prevent recursion
|
||||
}
|
||||
return update.call( mixer, time )
|
||||
}
|
||||
mixer.update.patched = true
|
||||
}
|
||||
}
|
||||
export default xrf;
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
3
make
3
make
|
@ -70,7 +70,8 @@ build_js(){
|
|||
src/3rd/js/*.js \
|
||||
src/3rd/js/three/*.js \
|
||||
src/3rd/js/three/xrmacro/*.js \
|
||||
src/3rd/js/three/xrf/*.js > dist/xrfragment.three.js
|
||||
src/3rd/js/three/xrf/*.js \
|
||||
src/3rd/js/three/xrf/src/*.js > dist/xrfragment.three.js
|
||||
# add THREE module
|
||||
cat dist/xrfragment.three.js > dist/xrfragment.three.module.js
|
||||
echo "export default xrf;" >> dist/xrfragment.three.module.js
|
||||
|
|
|
@ -90,6 +90,8 @@ xrf.reset = () => {
|
|||
xrf.scene.traverse( (child) => child.isXRF ? nodes.push(child) : false )
|
||||
nodes.map( disposeObject ) // leave non-XRF objects intact
|
||||
xrf.interactive = xrf.InteractiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
|
||||
if( xrf.audio ) xrf.audio.map( (a) => a.remove() )
|
||||
xrf.audio = []
|
||||
xrf.add( xrf.interactive )
|
||||
xrf.layers = 0
|
||||
}
|
||||
|
@ -107,4 +109,3 @@ xrf.add = (object) => {
|
|||
object.isXRF = true // mark for easy deletion when replacing scene
|
||||
xrf.scene.add(object)
|
||||
}
|
||||
|
||||
|
|
|
@ -153,72 +153,6 @@ xrf.frag.src.type = {}
|
|||
|
||||
xrf.frag.src.type['unknown'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
reject(`${url} mimetype not supported (yet)`)
|
||||
reject(`${url} mimetype not found or supported (yet)`)
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* mimetype: model/gltf+json
|
||||
*/
|
||||
|
||||
xrf.frag.src.type['gltf'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
let {mesh,src} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
let loader
|
||||
|
||||
const Loader = xrf.loaders[ext]
|
||||
if( !Loader ) throw 'xrfragment: no loader passed to xrfragment for extension .'+ext
|
||||
if( !dir.match("://") ){ // force relative path
|
||||
dir = dir[0] == './' ? dir : `./${dir}`
|
||||
loader = new Loader().setPath( dir )
|
||||
}else loader = new Loader()
|
||||
|
||||
loader.load(url, (model) => {
|
||||
resolve(model)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* mimetype: image/png
|
||||
* mimetype: image/jpg
|
||||
* mimetype: image/gif
|
||||
*/
|
||||
|
||||
xrf.frag.src.type['image/png'] = function(url,opts){
|
||||
let {mesh} = opts
|
||||
let restrictTo3DBoundingBox = mesh.geometry
|
||||
const texture = new THREE.TextureLoader().load( url );
|
||||
texture.colorSpace = THREE.SRGBColorSpace;
|
||||
|
||||
//const geometry = new THREE.BoxGeometry();
|
||||
const material = new THREE.MeshBasicMaterial({
|
||||
map: texture,
|
||||
transparent: url.match(/(png|gif)/) ? true : false,
|
||||
side: THREE.DoubleSide,
|
||||
color: 0xFFFFFF,
|
||||
opacity:1
|
||||
});
|
||||
|
||||
// stretch image by pinning uv-coordinates to corners
|
||||
if( mesh.geometry ){
|
||||
if( mesh.geometry.attributes.uv ){ // buffergeometries
|
||||
let uv = mesh.geometry.attributes.uv;
|
||||
// i u v
|
||||
uv.setXY(0, 0, 0 )
|
||||
uv.setXY(1, 1, 0 )
|
||||
uv.setXY(2, 0, 1 )
|
||||
uv.setXY(3, 1, 1 )
|
||||
}else {
|
||||
console.warn("xrfragment: uv's of ${url} might be off for non-buffer-geometries *TODO*")
|
||||
//if( geometry.faceVertexUvs ){
|
||||
// *TODO* force uv's of dynamically created geometries (in threejs)
|
||||
//}
|
||||
}
|
||||
}
|
||||
mesh.material = material
|
||||
}
|
||||
xrf.frag.src.type['image/gif'] = xrf.frag.src.type['image/png']
|
||||
xrf.frag.src.type['image/jpg'] = xrf.frag.src.type['image/png']
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* mimetype: audio/aac
|
||||
* mimetype: audio/mpeg
|
||||
* mimetype: audio/ogg
|
||||
* mimetype: audio/weba
|
||||
* mimetype: audio/wav
|
||||
*/
|
||||
|
||||
let loadAudio = (mimetype) => function(url,opts){
|
||||
let {mesh} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
|
||||
// global audio
|
||||
if( mesh.position.x == 0 && mesh.position.y == 0 && mesh.position.z == 0 ){
|
||||
let audio = window.document.createElement('audio')
|
||||
// init fallback formats
|
||||
let fallback = ['mp3','ogg','wav','weba','aac']
|
||||
let addSource = (ext) => {
|
||||
const src = window.document.createElement('source')
|
||||
src.setAttribute("src", url)
|
||||
src.setAttribute("type",mimetype)
|
||||
audio.appendChild(src)
|
||||
}
|
||||
fallback
|
||||
.filter( (e) => e != ext )
|
||||
.map( addSource )
|
||||
document.body.appendChild(audio)
|
||||
xrf.audio.push(audio)
|
||||
}
|
||||
}
|
||||
|
||||
let audioMimeTypes = [
|
||||
'audio/wav',
|
||||
'audio/mpeg',
|
||||
'audio/weba',
|
||||
'audio/aac',
|
||||
'audio/ogg',
|
||||
'application/ogg'
|
||||
]
|
||||
audioMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadAudio(mimetype) )
|
||||
|
||||
// *TODO* https://www.svgrepo.com/svg/20195/play-button should trigger play?
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* mimetype: model/gltf+json
|
||||
*/
|
||||
|
||||
xrf.frag.src.type['gltf'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
let {mesh,src} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
let loader
|
||||
|
||||
const Loader = xrf.loaders[ext]
|
||||
if( !Loader ) throw 'xrfragment: no loader passed to xrfragment for extension .'+ext
|
||||
if( !dir.match("://") ){ // force relative path
|
||||
dir = dir[0] == './' ? dir : `./${dir}`
|
||||
loader = new Loader().setPath( dir )
|
||||
}else loader = new Loader()
|
||||
|
||||
loader.load(url, (model) => {
|
||||
resolve(model)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* mimetype: image/png
|
||||
* mimetype: image/jpg
|
||||
* mimetype: image/gif
|
||||
*/
|
||||
|
||||
xrf.frag.src.type['image/png'] = function(url,opts){
|
||||
let {mesh} = opts
|
||||
let restrictTo3DBoundingBox = mesh.geometry
|
||||
const texture = new THREE.TextureLoader().load( url );
|
||||
texture.colorSpace = THREE.SRGBColorSpace;
|
||||
|
||||
//const geometry = new THREE.BoxGeometry();
|
||||
const material = new THREE.MeshBasicMaterial({
|
||||
map: texture,
|
||||
transparent: url.match(/(png|gif)/) ? true : false,
|
||||
side: THREE.DoubleSide,
|
||||
color: 0xFFFFFF,
|
||||
opacity:1
|
||||
});
|
||||
|
||||
// stretch image by pinning uv-coordinates to corners
|
||||
if( mesh.geometry ){
|
||||
if( mesh.geometry.attributes.uv ){ // buffergeometries
|
||||
let uv = mesh.geometry.attributes.uv;
|
||||
// i u v
|
||||
uv.setXY(0, 0, 0 )
|
||||
uv.setXY(1, 1, 0 )
|
||||
uv.setXY(2, 0, 1 )
|
||||
uv.setXY(3, 1, 1 )
|
||||
}else {
|
||||
console.warn("xrfragment: uv's of ${url} might be off for non-buffer-geometries *TODO*")
|
||||
//if( geometry.faceVertexUvs ){
|
||||
// *TODO* force uv's of dynamically created geometries (in threejs)
|
||||
//}
|
||||
}
|
||||
}
|
||||
mesh.material = material
|
||||
}
|
||||
xrf.frag.src.type['image/gif'] = xrf.frag.src.type['image/png']
|
||||
xrf.frag.src.type['image/jpg'] = xrf.frag.src.type['image/png']
|
||||
|
|
@ -25,6 +25,11 @@ xrf.frag.t = function(v, opts){
|
|||
mixer.setTime(time)
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||
// (re)trigger audio
|
||||
xrf.audio.map( (a) => {
|
||||
a.play()
|
||||
a.currentTime = time
|
||||
})
|
||||
}
|
||||
|
||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||
|
|
Loading…
Reference in New Issue