-/* Copyright 2018 Paul Hänsch
+/* Copyright 2018, 2023 Paul Hänsch
This file is part of Serve0
along with Serve0 If not, see <http://www.gnu.org/licenses/>.
*/
-var render, video, controlTimeout = 0;
-var pitch = 0, roll = 0, yaw = 0;
-var w, h, hdeg, vdeg, scale, fov = 90, dist=0;
+var contLeft = document.createElement("div");
+var contRight = document.createElement("div");
var lv = document.createElement("canvas");
var rv = document.createElement("canvas");
var debug = document.createElement("p");
-var gp;
-
-function draw() {
- sw = fov * hdeg |0;
- sh = h / 2 |0;
- dh = h / 2 * scale |0;
-
- if ( layout == "180" ) {
- sx = (w / 2 - fov * hdeg) / 2 + yaw * hdeg |0;
- sy = ( h - fov * vdeg) / 2 + pitch * vdeg |0;
- if (sx + sw > w / 2) { sx = w / 2 - sw; } else if (sx < 0) { sx = 0; }
- lc.drawImage(video, sx + dist, sy, sw, sh, 0, 0, lv.width, dh);
- rc.drawImage(video, w / 2 + sx - dist, sy, sw, sh, 0, 0, rv.width, dh);
- } else {
- sx = (w - fov * hdeg) / 2 + yaw * hdeg |0;
- sy = (h - fov * vdeg) / 4 + pitch * vdeg |0;
- lc.drawImage(video, sx + dist, sy, sw, sh, 0, 0, lv.width, dh);
- rc.drawImage(video, sx - dist, h/2 + sy, sw, sh, 0, 0, rv.width, dh);
- if (sx + dist < 0) { lc.drawImage(video, sx + w + dist, sy, sw, sh, 0, 0, lv.width, dh); }
- if (sx - dist < 0) { rc.drawImage(video, sx + w - dist, h/2 + sy, sw, sh, 0, 0, rv.width, dh); }
- if (sx + dist + fov * hdeg > w) { lc.drawImage(video, sx - w + dist, sy, sw, sh, 0, 0, lv.width, dh); }
- if (sx - dist + fov * hdeg > w) { rc.drawImage(video, sx - w - dist, h/2 + sy, sw, sh, 0, 0, rv.width, dh); }
- }
- lv.style.transform = "rotate(" + roll + "deg)";
- rv.style.transform = "rotate(" + roll + "deg)";
-
- requestAnimationFrame(draw);
-
- gp = navigator.getGamepads()[0];
- if ( gp && Date.now() > controlTimeout ) {
- if ( gp.axes[0] > .3) { video.currentTime += 10; controlTimeout = Date.now() + 500; }
- if ( gp.axes[0] < -.3) { video.currentTime -= 10; controlTimeout = Date.now() + 500; }
- if ( gp.axes[1] < -.3) { video.currentTime += 60; controlTimeout = Date.now() + 500; }
- if ( gp.axes[1] > .3) { video.currentTime -= 60; controlTimeout = Date.now() + 500; }
- if ( gp.buttons[0].pressed ) { video.currentTime += 1/30; video.pause(); }
- if ( gp.buttons[1].pressed ) { video.play(); }
- if ( gp.buttons[2].pressed ) { fov -= 10; controlTimeout = Date.now() + 500; }
- if ( gp.buttons[3].pressed ) { fov += 10; controlTimeout = Date.now() + 500; }
- if ( gp.axes[2] < -.3) { dist -= 1; controlTimeout = Date.now() + 500; }
- if ( gp.axes[2] > .3) { dist += 1; controlTimeout = Date.now() + 500; }
-
- date = new Date();
- date.setTime(date.getTime() + 3 * 365 * 86400 * 1000)
- document.cookie = "StereoDist=" + dist + "; expires=" + date.toUTCString() + "; path=/";
- document.cookie = "StereoFOV=" + fov + "; expires=" + date.toUTCString() + "; path=/";
- }
+ contLeft.setAttribute("style", "position: fixed; top: 0; left: 0; width: 50%; height: 100%; overflow: hidden; z-index: 100; background-color: #000;");
+contRight.setAttribute("style", "position: fixed; top: 0; right: 0; width: 50%; height: 100%; overflow: hidden; z-index: 100; background-color: #000;");
+ lv.setAttribute("style", "position: absolute; top: 50%; left: calc(100% - 32mm); max-width: unset; max-height: unset;");
+ rv.setAttribute("style", "position: absolute; top: 50%; left: 32mm; max-width: unset; max-height: unset;");
+ debug.setAttribute("style", "display: none; position: fixed; top: 0; left: 0; z-index: 101; background: #000;");
- // debug.textContent = "" + video.currentTime + " " + controlTimeout + " " + tx + " " + ty + " " + tz;
- // debug.textContent = "Pitch: " + pitch + " | Yaw: " + yaw + " | Roll: " + roll;
-};
function stereoview(layout, video) {
this.layout = layout; this.video = video;
- document.body.appendChild( lv );
- document.body.appendChild( rv );
+
+ let w = video.videoWidth; h = video.videoHeight;
+ let render, controlTimeout = 0;
+ let pitch = 0, roll = 0, yaw = 0;
+ let scale, fov = 90, dist = 32;
+
+ document.body.appendChild(contLeft ).appendChild( lv );
+ document.body.appendChild(contRight).appendChild( rv );
document.body.appendChild( debug );
+
+ if ( layout == "180") {
+ lv.width = rv.width = w / 2; lv.height = rv.height = h;
+ } else {
+ lv.width = rv.width = w; lv.height = rv.height = h / 2;
+ }
+
+ lc = lv.getContext("2d"); rc = rv.getContext("2d");
+
+ function draw() {
+ if ( layout == "180" ) {
+ scale = contLeft.offsetHeight / h * 2 * fov / 90;
+ lc.drawImage(video, 0, 0);
+ rc.drawImage(video, -w / 2, 0);
+ lv.style.transform = rv.style.transform =
+ "translate(" + (yaw / 180 * -w / 4 * scale - w / 4) + "px, " +
+ (pitch / 90 * -h / 2 * scale - h / 2) + "px)" +
+ "rotate(" + roll + "deg) " + "scale(" + (scale / 2) + ", " + scale + ")";
+ } else {
+ scale = contLeft.offsetHeight / h * 4 * fov / 90;
+ lc.drawImage(video, yaw / 180 * -w / 2, 0);
+ lc.drawImage(video, yaw / 180 * -w / 2 + ((yaw>0) ? w : -w), 0);
+ rc.drawImage(video, yaw / 180 * -w / 2, -h/2);
+ rc.drawImage(video, yaw / 180 * -w / 2 + ((yaw>0) ? w : -w), -h/2);
+ lv.style.transform = rv.style.transform =
+ "translate(" + (- w / 2) + "px, " + (pitch / 90 * -h / 2 * (scale / 2) - h / 4) + "px) " +
+ "rotate(" + roll + "deg) " + "scale(" + (scale / 2) + ", " + scale + ")";
+ }
+
+ // debug.textContent = "" + video.currentTime + " " + controlTimeout + " " + tx + " " + ty + " " + tz;
+ debug.textContent = "Pitch: " + pitch.toFixed(2) + " | Yaw: " + yaw.toFixed(2) + " | Roll: " + roll.toFixed(2) +
+ " | FOV: " + fov + " | Eye Distance: " + (2 * dist) + "mm";
- lv.setAttribute( "style", "position: fixed; top: 0; left: 0 ; width: 50%; height: 100%; z-index: 100;");
- rv.setAttribute( "style", "position: fixed; top: 0; left: 50%; width: 50%; height: 100%; z-index: 100;");
- debug.setAttribute( "style", "position: fixed; top: 0; left: 0; z-index: 101; background: #000;");
-
- lv.setAttribute( "width", "" + lv.offsetWidth);
- rv.setAttribute( "width", "" + rv.offsetWidth);
- lv.setAttribute("height", "" + lv.offsetHeight);
- rv.setAttribute("height", "" + rv.offsetHeight);
-
- lc = lv.getContext("2d");
- rc = rv.getContext("2d");
+ requestAnimationFrame(draw);
+
+ gpinput();
+ };
+
+ function gpinput() {
+ let gp = navigator.getGamepads()[0];
+ let date = new Date();
+
+ debug.innerHTML += "<br/><br/>GamePad: " + gp.axes[0].toFixed(3) + " | " + gp.axes[1].toFixed(3)
+ for (cnt = 0; cnt < 16; cnt++) {
+ gp.buttons[cnt].pressed ? debug.textContent += " | B" + cnt + " 1" : debug.textContent += " | B" + cnt + " 0";
+ }
+
+ if ( gp && Date.now() < controlTimeout ) {
+ true;
+ } else if (gp.buttons[0].pressed && gp.buttons[5].pressed) {
+ this.layout = layout = "180";
+ document.body.appendChild(contLeft ).appendChild( lv );
+ document.body.appendChild(contRight).appendChild( rv );
+ lv.width = rv.width = w / 2; lv.height = rv.height = h;
+ video.play();
+ controlTimeout = Date.now() + 600;
+ } else if (gp.buttons[0].pressed && gp.buttons[4].pressed) {
+ this.layout = layout = "360";
+ document.body.appendChild(contLeft ).appendChild( lv );
+ document.body.appendChild(contRight).appendChild( rv );
+ lv.width = rv.width = w; lv.height = rv.height = h / 2;
+ video.play();
+ controlTimeout = Date.now() + 600;
+ } else if (gp.buttons[0].pressed) {
+ ( contLeft.parentElement)? contLeft.parentElement.removeChild(contLeft ):{};
+ (contRight.parentElement)?contRight.parentElement.removeChild(contRight):{};
+ video.pause();
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[1].pressed) {
+ (debug.style.display == "block") ? debug.style.display = "none" : debug.style.display = "block";
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[5].pressed) {
+ video.paused ? video.play() : video.pause();
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[4].pressed) {
+ video.currentTime += 1 / 30;
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[3].pressed && gp.axes[0] < -.3) {
+ dist -= .5;
+ lv.style.left = "calc(100% - " + dist + "mm)";
+ rv.style.left = "" + dist + "mm";
+ date.setTime(date.getTime() + 3 * 365 * 86400 * 1000)
+ document.cookie = "StereoDist=" + dist + "; expires=" + date.toUTCString() + "; path=/";
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[3].pressed && gp.axes[0] > .3) {
+ dist += .5;
+ lv.style.left = "calc(100% - " + dist + "mm)";
+ rv.style.left = "" + dist + "mm";
+ date.setTime(date.getTime() + 3 * 365 * 86400 * 1000)
+ document.cookie = "StereoDist=" + dist + "; expires=" + date.toUTCString() + "; path=/";
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[3].pressed && gp.axes[1] < -.3) {
+ fov -= 10;
+ date.setTime(date.getTime() + 3 * 365 * 86400 * 1000)
+ document.cookie = "StereoFOV=" + fov + "; expires=" + date.toUTCString() + "; path=/";
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[3].pressed && gp.axes[1] > .3) {
+ fov += 10;
+ date.setTime(date.getTime() + 3 * 365 * 86400 * 1000)
+ document.cookie = "StereoFOV=" + fov + "; expires=" + date.toUTCString() + "; path=/";
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[2].pressed && gp.axes[0] < -.3) {
+ yaw -= pitch ? ( Math.cos(pitch * Math.PI / 180) % 360 ) : 1;
+ if ( yaw > 180) yaw -= 360;
+ if ( yaw < -180) yaw += 360;
+ controlTimeout = Date.now() + 30;
+ } else if (gp.buttons[2].pressed && gp.axes[0] > .3) {
+ yaw += pitch ? ( Math.cos(pitch * Math.PI / 180) % 360 ) : 1;
+ if ( yaw > 180) yaw -= 360;
+ if ( yaw < -180) yaw += 360;
+ controlTimeout = Date.now() + 30;
+ } else if (gp.buttons[2].pressed && gp.axes[1] < -.3) {
+ video.volume += .05;
+ controlTimeout = Date.now() + 300;
+ } else if (gp.buttons[2].pressed && gp.axes[1] > .3) {
+ video.volume -= .05;
+ controlTimeout = Date.now() + 300;
+ } else if ( gp.axes[0] > .3) {
+ video.currentTime += 10;
+ controlTimeout = Date.now() + 200;
+ } else if ( gp.axes[0] < -.3) {
+ video.currentTime -= 10;
+ controlTimeout = Date.now() + 200;
+ } else if ( gp.axes[1] > .3) {
+ video.currentTime -= 60;
+ controlTimeout = Date.now() + 300;
+ } else if ( gp.axes[1] < -.3) {
+ video.currentTime += 60;
+ controlTimeout = Date.now() + 300;
+ }
+ }
// mpuevent = new EventSource("http://localhost:314");
// var x = [], y = [], z = [], cnt = -1, inertia = 6;
// }, false );
window.addEventListener("devicemotion", (function() {
- var x = [], y = [], z = [], cnt = -1, inertia = 6;
- return function(event) {
+ let x = [], y = [], z = [], cnt = -1, inertia = 6;
+ return event => {
cnt = (cnt + 1) % inertia;
x[cnt] = event.accelerationIncludingGravity.x;
- event.rotationRate.alpha / 1000 * event.interval * Math.cos(pitch * Math.PI / 180)
- event.rotationRate.gamma / 1000 * event.interval * Math.sin(pitch * Math.PI / 180)
) % 360 : yaw;
+ if ( yaw > 180) yaw -= 360;
+ if ( yaw < -180) yaw += 360;
// pitch = (pitch + event.rotationRate.beta / 1000 * event.interval) % 360;
// roll = (roll + event.rotationRate.gamma / 1000 * event.interval) % 360;
})());
window.addEventListener("click", function(event) {
- (lv.parentElement)?lv.parentElement.removeChild(lv):{};
- (rv.parentElement)?rv.parentElement.removeChild(rv):{};
- video.style.display = "block";
+ ( contLeft.parentElement)? contLeft.parentElement.removeChild(contLeft ):{};
+ (contRight.parentElement)?contRight.parentElement.removeChild(contRight):{};
+ // video.style.display = "block";
video.pause();
}, true);
- w = video.videoWidth; h = video.videoHeight;
- hdeg = w / 360; vdeg = h / 180;
- scale = lv.width / (fov * hdeg |0);
+ dist = dist ? dist : parseInt(document.getElementById("StereoDist").getAttribute("value"));
+ fov = fov ? fov : parseInt(document.getElementById("StereoFOV" ).getAttribute("value"));
- dist = parseInt(document.getElementById("StereoDist").getAttribute("value"));
- fov = parseInt(document.getElementById("StereoFOV").getAttribute("value"));
- // scale = lv.width / (w / 4);
video.play();
- video.style.display = "none";
+ // video.style.display = "none";
draw();
};