From 62b6717d1b1e02c34d8ad87dabcd5f57aa8a0656 Mon Sep 17 00:00:00 2001 From: Ruben van de Ven Date: Thu, 18 Jun 2020 09:58:04 +0200 Subject: [PATCH] First WIP of parade --- index.html | 74 ++++++++++++++++++ parade.js | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 index.html create mode 100644 parade.js diff --git a/index.html b/index.html new file mode 100644 index 0000000..e13d0a9 --- /dev/null +++ b/index.html @@ -0,0 +1,74 @@ + + + + + Parade + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+ + + + + + + + + diff --git a/parade.js b/parade.js new file mode 100644 index 0000000..c3f4090 --- /dev/null +++ b/parade.js @@ -0,0 +1,220 @@ +var parade; +var interview_sorter; + +// polyfill +window.performance = window.performance || {}; +performance.now = (function() { + return performance.now || + performance.mozNow || + performance.msNow || + performance.oNow || + performance.webkitNow || + Date.now /*none found - fallback to browser default */ +})(); + + +const request = new Request('dataset/images_prop.json'); +fetch(request) +.then(response => { + if (response.status === 200) { + return response.json(); + } else { + throw new Error('Something went wrong on api server!'); + } +}) +.then(data => { + console.debug(data); + // loaded data from json, initialise interface + const canvas = document.getElementById("renderCanvas"); + parade = new Parade(canvas, data['image']); + parade.createScene(); + // parade.scene.debugLayer.show(); +}).catch(error => { + console.error(error); +}); + + +class Parade { + constructor(canvasEl, images) { + this.speedFactor = -.05; + this.distanceFactor = 20; + this.startOffset = 800; + this.maxStepSize = 1; + + this.prevRenderTime = null; + this.canvasEl = canvasEl; + this.engine = new BABYLON.Engine(canvasEl, true); + + this.audioEl = document.getElementById('interview'); // audio player + this.subtitleEl = document.getElementById('subtitles'); // the subtitle div + this.trackEl = this.audioEl.querySelector('track'); // the subtitle track + + + // set up subtitles: + this.trackEl.addEventListener("cuechange", (event) => { + console.log(event); + let cues = event.target.track.activeCues; + let content = ""; + for(let cue of cues) { + content += "

"+cue.text+"

"; + } + this.subtitleEl.innerHTML = content; + }); + + + // initialise image objects: + this.images = []; + for(let i in images) { + this.images.push(new ParadeImage(images[i], i)); + // for testing: + // if(this.images.length > 5) + // break; + } + + // Watch for browser/canvas resize events + window.addEventListener("resize", function () { + this.engine.resize(); + }.bind(this)); + + //Register a render loop to repeatedly render the scene + this.engine.runRenderLoop(this.renderLoop.bind(this)); + } + + renderLoop() { + // limit camera movement: + // let camera = this.scene.cameras[0]; + // if(camera.rotation['x'] < 0.1) { + // camera.rotation['x'] = 0.1 + // } + // if(camera.rotation['x'] > .3) { + // camera.rotation['x'] = .3 + // } + this.animate(); + this.scene.render(); + } + + animate() { + let t = window.performance.now() - this.startTime; + // let maxStepSize = Math.inf; + + // if (this.prevRenderTime === null) { + + // } else { + // let tdiff = t - this.prevRenderTime; + // if(tdiff < 1) { + // // sometimes multiple render calls within very short moment?? + // // skip some work. + // return; + // } + + // maxStepSize = Math.abs(this.maxStepSize * tdiff * this.speedFactor); + // } + + + // this.prevRenderTime = t; + // console.log(tdiff); + t -= 800/this.speedFactor; // start offset ( milliseconds) + // console.log(maxStepSize); + for(let i of this.images){ + i.updateMeshPosition(t*this.speedFactor/1000); + t-= this.distanceFactor/this.speedFactor; + } + } + + createScene() { + // This creates a basic Babylon Scene object (non-mesh) + this.scene = new BABYLON.Scene(this.engine); + // return this.scene; + // this.scene.clearColor = new BABYLON.Color3(0.6, 0.6, 0.); // color RGB + // this.scene.clearColor = new BABYLON.Color4(0.6, 0.6, 0.,0); // transparent - RGBA + this.scene.fogMode = BABYLON.Scene.FOGMODE_EXP; + this.scene.fogColor = this.scene.clearColor; + this.scene.fogDensity = 0.002; + + // let camera = new BABYLON.UniversalCamera("camera1", new BABYLON.Vector3( 0.0, 0.0, 120.86337575312979), this.scene); + // camera.rotation = new BABYLON.Vector3(0, Math.PI, 0); + // camera.fov = 1.1; // default: 0.8 + let camera = new BABYLON.UniversalCamera("camera2", new BABYLON.Vector3( -14.40894348196419, 0.9954991699417852, 17.582966906902247), this.scene); + camera.rotation = new BABYLON.Vector3(0.023121520223909536, 2.5494248799675163, 0); + camera.fov = 1.5; + // camera.rotation = new BABYLON.Vector3(0.1, 0,0); + // camera.lowerRadiusLimit = 6; + // camera.upperRadiusLimit = 20; + // This attaches the camera to the canvas + camera.attachControl(this.canvasEl, true); + + let radius = 60; + for(let i in this.images) { + // console.log(i, this.images, this); + this.images[i].makeMesh(this.scene); + } + + + this.startTime = window.performance.now(); + // this.scene.registerBeforeRender(this.animate.bind(this)); + return this.scene; + } +} + +class ParadeImage { + constructor(info, position) { + this.info = info; + this.weight = info['weight']; + this.position = position; // index in list + } + + makeMesh(scene) { + // let videoSrc = this.images[i]['image']; + // random fluctuation in radius + let i = 1; + let radius = 60 + let localRadius = (Math.random() * .2 + 1) * radius; + let x = Math.sin(2*Math.PI * i / 1) * localRadius; + let y = Math.cos(2*Math.PI * i / 1) * localRadius; + var planeOpts = { + height: 5.4762, + width: 7.3967, + sideOrientation: BABYLON.Mesh.DOUBLESIDE + }; + this.mesh = BABYLON.MeshBuilder.CreatePlane("plane", planeOpts, scene); + + var ANote0VideoMat = new BABYLON.StandardMaterial("m", scene); + + let imgUrl = 'dataset/small/'+ this.info['image']; + // console.log(imgUrl); + ANote0VideoMat.diffuseTexture = new BABYLON.Texture(imgUrl, scene); + ANote0VideoMat.roughness = 1; + ANote0VideoMat.emissiveColor = new BABYLON.Color3.White(); + this.mesh.material = ANote0VideoMat; + + // this.updateMeshPosition(1, Math.inf); //TODO: remove when animating + } + + updateMeshPosition(t){ + // factors determine scale of animation + let target_x = Math.sin(2*t)*100; + let target_z = Math.sin(t)*1300; + + // let diff_x = target_x - this.mesh.position.x; + // let diff_z = target_z - this.mesh.position.z; + + // let stepSize = Math.sqrt( Math.pow(diff_x, 2) + Math.pow(diff_z, 2) ); + + // if(stepSize > maxStepSize) { + // // console.log('throttle', maxStepSize, stepSize); + // // throttle the step, so switching items looks like movement + // diff_x *= maxStepSize/stepSize; + // diff_z *= maxStepSize/stepSize; + // } + + // // console.log(diff_x, diff_z, stepSize); + // this.mesh.position.x += diff_x; + // this.mesh.position.z += diff_z; + this.mesh.position.x = target_x; + this.mesh.position.z = target_z; + + // this.mesh.position = new BABYLON.Vector3(x,0,y); + } + + +}