]> git.plutz.net Git - serve0/commitdiff
rewrite of stereo renderer and input
authorPaul Hänsch <paul@plutz.net>
Sun, 31 Dec 2023 00:07:44 +0000 (01:07 +0100)
committerPaul Hänsch <paul@plutz.net>
Sun, 31 Dec 2023 00:07:44 +0000 (01:07 +0100)
stereoview.js
view.sh

index d2c4ec54cfb2d093acdd876ef6ab70af28026ef7..aadb68b2f7bd14752b0ee838ee4b35bde70f8231 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, 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;
@@ -117,8 +197,8 @@ function stereoview(layout, video) {
   // }, 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;
@@ -135,6 +215,8 @@ function stereoview(layout, video) {
               - 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;
@@ -143,20 +225,16 @@ function stereoview(layout, video) {
   })());
 
   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();
 };
diff --git a/view.sh b/view.sh
index 0bc524ad2710491122af4ae564696f3695f85168..5263e2c59d84a10dc27949262739d52d5513b3e0 100755 (executable)
--- a/view.sh
+++ b/view.sh
@@ -27,7 +27,7 @@ printf 'Content-Type: text/html;charset=utf-8\r\n\r\n'
   w_prefs
   cat <<-EOF
          [input type=hidden id=StereoFOV  name=StereoFOV  value="$(COOKIE StereoFOV  |grep -xE '[0-9]+' || printf 90)"]
-         [input type=hidden id=StereoDist name=StereoDist value="$(COOKIE StereoDist |grep -xE '[0-9]+' || printf  0)"]
+         [input type=hidden id=StereoDist name=StereoDist value="$(COOKIE StereoDist |grep -xE '[0-9]+' || printf 32)"]
          [video #mainvideo controls="controls" preload="auto" [source src="?a=download" type="video/mp4"]]
          [a "?a=download" Download]
          [a "javascript:stereoview(180, document.getElementById(&#34;mainvideo&#34;));" View 180° Stereoscopic]