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); } }