First WIP of parade

This commit is contained in:
Ruben van de Ven 2020-06-18 09:58:04 +02:00
commit 62b6717d1b
2 changed files with 294 additions and 0 deletions

74
index.html Normal file
View file

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Parade</title>
<style media="screen">
html,body{
margin: 0;
overflow: hidden;
width: 100%;
height: 100%;
font-family: sans-serif;
}
canvas{
margin:0;
width:100vw;
height:100vh;
}
/* audio{
position: absolute;
top:0;
} */
#subtitles{
position:fixed;
bottom:0;
width:100%;
color:white;
text-shadow: black 0 0 10px;;
text-align: center;
font-size: 20px;
}
</style>
<!-- Will automatically be injected if needed: <script src=https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js></script> -->
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas> <!--touch-action="none" for best results from PEP-->
<div id='annotation'>
<template id="annotationContent">
<img id='img'>
<input type='number' id='weight'>
</template>
</div>
<audio id='interview'
src="/interview/interview-with-ellen.mp3">
<track default kind="captions"
srclang="en"
src="/interview/interview-with-ellen_v3.mp3.vtt"/>
</audio>
<div id='subtitles'>
</div>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>
<script src="parade.js"></script>
</body>
</html>

220
parade.js Normal file
View file

@ -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 += "<p>"+cue.text+"</p>";
}
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);
}
}