]> git.plutz.net Git - serve0/blobdiff - stereoview.js
Merge commit 'b931bbd0c30907b9cc956d3707b26b449bf41f76'
[serve0] / stereoview.js
index 50863d5533f5219f0db0aff3362d36e2b8a4ffc6..0d46a668cde72876cb24e2fb4e559c7b6296325a 100644 (file)
@@ -1,4 +1,4 @@
-/*  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;
+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, sy, sw, sh, 0, 0, lv.width, dh);
-    rc.drawImage(video, w / 2 + sx, 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,       sy, sw, sh, 0, 0, lv.width, dh);
-    rc.drawImage(video, sx, h/2 + sy, sw, sh, 0, 0, rv.width, dh);
-    if (sx < 0) {
-      lc.drawImage(video, sx + w,       sy, sw, sh, 0, 0, lv.width, dh);
-      rc.drawImage(video, sx + w, h/2 + sy, sw, sh, 0, 0, rv.width, dh);
-    } else if ( sx + fov * hdeg > w) {
-      lc.drawImage(video, sx - w,       sy, sw, sh, 0, 0, lv.width, dh);
-      rc.drawImage(video, sx - w, 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; }
-  }
+ 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;
-};
 
 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, vsf = 1, 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;
+    scale = contLeft.offsetHeight / h * 2 * fov / 90;
+  } else {
+    lv.width = rv.width = w; lv.height = rv.height = h / 2;
+    scale = contLeft.offsetHeight / h * 4 * fov / 90;
+  }
+
+  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 / 2 - w / 4) + "px, " +
+                       (pitch / 90 * -h / 2 * scale - h / 2) + "px)" +
+        "rotate(" + roll + "deg) " + "scale(" + (scale / vsf) + ", " + 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 / vsf) + ", " + 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;
+      scale = contLeft.offsetHeight / h * 2 * fov / 90;
+      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;
+      scale = contLeft.offsetHeight / h * 4 * fov / 90;
+      video.play();
+      controlTimeout = Date.now() + 600;
+    } else if (gp.buttons[3].pressed && gp.buttons[4].pressed) {
+      vsf = (vsf == 1) ? 2 : 1;
+      controlTimeout = Date.now() + 300;
+    } 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;
+
+  // mpuevent.addEventListener("bearing", function(e) {
+  //   bearing = e.data.split(" ");
+  //   yaw = -parseFloat(bearing[0]);
+  // }, false);
+  // mpuevent.addEventListener("motion", function(e) {
+  //   motion = e.data.split(" ");
+
+  //   cnt = (cnt + 1) % inertia;
+  //   x[cnt] = parseFloat(motion[0]);
+  //   y[cnt] = parseFloat(motion[1]);
+  //   z[cnt] = parseFloat(motion[2]);
+
+  //   // tx = 0; x.forEach( function(n, i){ tx += n; } ); tx /= inertia;
+  //   ty = 0; y.forEach( function(n, i){ ty += n; } ); ty /= inertia;
+  //   tz = 0; z.forEach( function(n, i){ tz += n; } ); tz /= inertia;
+
+  //   pitch =   Math.asin((tz / 9.81 > 1)?1:(tz/9.81)) / Math.PI * 180 + 22.5;
+  //   roll  = - Math.asin((ty / 9.81 > 1)?1:(ty/9.81)) / Math.PI * 180;
+  //   // yaw   = (yaw + ty) % 360;
+  // }, 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;
@@ -100,24 +216,32 @@ function stereoview(layout, video) {
       ty = 0; y.forEach( function(n, i){ ty += n; } ); ty /= inertia;
       tz = 0; z.forEach( function(n, i){ tz += n; } ); tz /= inertia;
 
-      pitch =   Math.asin((tz / 9.81 > 1)?1:(tz/9.81)) / Math.PI * 180 + 22.5;
+      pitch =   Math.asin((tz / 9.81 > 1)?1:(tz/9.81)) / Math.PI * 180;
       roll  = - Math.asin((ty / 9.81 > 1)?1:(ty/9.81)) / Math.PI * 180;
-      yaw   = (yaw + ty) % 360;
+      yaw   = pitch ? ( yaw
+              - 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;
+      // yaw   = (yaw + ty) % 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);
-  // scale = lv.width / (w / 4);
+  dist = dist ? dist : parseInt(document.getElementById("StereoDist").getAttribute("value"));
+  fov  =  fov ?  fov : parseInt(document.getElementById("StereoFOV" ).getAttribute("value"));
+
   video.play();
-  video.style.display = "none";
+  // video.style.display = "none";
   draw();
 };