]> git.plutz.net Git - serve0/blob - stereoview.js
adjustable eye distance in stereoview + use of gyroscopes
[serve0] / stereoview.js
1 /*  Copyright 2018 Paul Hänsch
2    
3     This file is part of Serve0
4     
5     Serve0 is free software: you can redistribute it and/or modify
6     it under the terms of the GNU Affero General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9     
10     Serve0 is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU Affero General Public License for more details.
14     
15     You should have received a copy of the GNU Affero General Public License
16     along with Serve0  If not, see <http://www.gnu.org/licenses/>. 
17 */
18
19 var render, video, controlTimeout = 0;
20 var pitch = 0, roll = 0, yaw = 0;
21 var w, h, hdeg, vdeg, scale, fov = 90, dist=0;
22 var lv = document.createElement("canvas");
23 var rv = document.createElement("canvas");
24 var debug = document.createElement("p");
25 var gp;
26
27 function draw() {
28   sw = fov * hdeg |0;
29   sh = h / 2 |0;
30   dh = h / 2 * scale |0;
31
32   if ( layout == "180" ) {
33     sx = (w / 2 - fov * hdeg) / 2 +   yaw * hdeg |0;
34     sy = (    h - fov * vdeg) / 2 + pitch * vdeg |0;
35     if   (sx + sw > w / 2) { sx = w / 2 - sw; } else if (sx < 0) { sx = 0; }
36     lc.drawImage(video,         sx + dist, sy, sw, sh, 0, 0, lv.width, dh);
37     rc.drawImage(video, w / 2 + sx - dist, sy, sw, sh, 0, 0, rv.width, dh);
38   } else {
39     sx = (w - fov * hdeg) / 2 + yaw   * hdeg |0;
40     sy = (h - fov * vdeg) / 4 + pitch * vdeg |0;
41     lc.drawImage(video, sx + dist,       sy, sw, sh, 0, 0, lv.width, dh);
42     rc.drawImage(video, sx - dist, h/2 + sy, sw, sh, 0, 0, rv.width, dh);
43     if (sx + dist < 0) { lc.drawImage(video, sx + w + dist,       sy, sw, sh, 0, 0, lv.width, dh); }
44     if (sx - dist < 0) { rc.drawImage(video, sx + w - dist, h/2 + sy, sw, sh, 0, 0, rv.width, dh); }
45     if (sx + dist + fov * hdeg > w) { lc.drawImage(video, sx - w + dist,       sy, sw, sh, 0, 0, lv.width, dh); }
46     if (sx - dist + fov * hdeg > w) { rc.drawImage(video, sx - w - dist, h/2 + sy, sw, sh, 0, 0, rv.width, dh); }
47   }
48
49   lv.style.transform = "rotate(" + roll + "deg)";
50   rv.style.transform = "rotate(" + roll + "deg)";
51
52   requestAnimationFrame(draw);
53
54   gp = navigator.getGamepads()[0];
55   if ( gp && Date.now() > controlTimeout ) {
56     if ( gp.axes[0] >  .3) { video.currentTime += 10; controlTimeout = Date.now() + 500; }
57     if ( gp.axes[0] < -.3) { video.currentTime -= 10; controlTimeout = Date.now() + 500; }
58     if ( gp.axes[1] < -.3) { video.currentTime += 60; controlTimeout = Date.now() + 500; }
59     if ( gp.axes[1] >  .3) { video.currentTime -= 60; controlTimeout = Date.now() + 500; }
60     if ( gp.buttons[0].pressed ) { video.currentTime += 1/30; video.pause(); }
61     if ( gp.buttons[1].pressed ) { video.play(); }
62     if ( gp.buttons[2].pressed ) { fov -= 10; controlTimeout = Date.now() + 500; }
63     if ( gp.buttons[3].pressed ) { fov += 10; controlTimeout = Date.now() + 500; }
64     if ( gp.axes[2] < -.3) { dist -= 1; controlTimeout = Date.now() + 500; }
65     if ( gp.axes[2] >  .3) { dist += 1; controlTimeout = Date.now() + 500; }
66
67     date = new Date();
68     date.setTime(date.getTime() + 3 * 365 * 86400 * 1000)
69     document.cookie = "StereoDist=" + dist + "; expires=" + date.toUTCString() + "; path=/";
70     document.cookie = "StereoFOV=" + fov + "; expires=" + date.toUTCString() + "; path=/";
71   }
72
73   // debug.textContent = "" + video.currentTime + " " + controlTimeout + " " + tx + " " + ty + " " + tz;
74   // debug.textContent = "Pitch: " + pitch + " | Yaw: " + yaw + " | Roll: " + roll;
75 };
76
77 function stereoview(layout, video) {
78   this.layout = layout; this.video = video;
79   document.body.appendChild( lv );
80   document.body.appendChild( rv );
81   document.body.appendChild( debug );
82   
83   lv.setAttribute( "style", "position: fixed; top: 0; left:  0 ; width: 50%; height: 100%; z-index: 100;");
84   rv.setAttribute( "style", "position: fixed; top: 0; left: 50%; width: 50%; height: 100%; z-index: 100;");
85   debug.setAttribute( "style", "position: fixed; top: 0; left: 0; z-index: 101; background: #000;");
86
87   lv.setAttribute( "width", "" + lv.offsetWidth);
88   rv.setAttribute( "width", "" + rv.offsetWidth);
89   lv.setAttribute("height", "" + lv.offsetHeight);
90   rv.setAttribute("height", "" + rv.offsetHeight);
91   
92   lc = lv.getContext("2d");
93   rc = rv.getContext("2d");
94   
95   // mpuevent = new EventSource("http://localhost:314");
96   // var x = [], y = [], z = [], cnt = -1, inertia = 6;
97
98   // mpuevent.addEventListener("bearing", function(e) {
99   //   bearing = e.data.split(" ");
100   //   yaw = -parseFloat(bearing[0]);
101   // }, false);
102   // mpuevent.addEventListener("motion", function(e) {
103   //   motion = e.data.split(" ");
104
105   //   cnt = (cnt + 1) % inertia;
106   //   x[cnt] = parseFloat(motion[0]);
107   //   y[cnt] = parseFloat(motion[1]);
108   //   z[cnt] = parseFloat(motion[2]);
109
110   //   // tx = 0; x.forEach( function(n, i){ tx += n; } ); tx /= inertia;
111   //   ty = 0; y.forEach( function(n, i){ ty += n; } ); ty /= inertia;
112   //   tz = 0; z.forEach( function(n, i){ tz += n; } ); tz /= inertia;
113
114   //   pitch =   Math.asin((tz / 9.81 > 1)?1:(tz/9.81)) / Math.PI * 180 + 22.5;
115   //   roll  = - Math.asin((ty / 9.81 > 1)?1:(ty/9.81)) / Math.PI * 180;
116   //   // yaw   = (yaw + ty) % 360;
117   // }, false );
118
119   window.addEventListener("devicemotion", (function() {
120     var x = [], y = [], z = [], cnt = -1, inertia = 6;
121     return function(event) {
122       cnt = (cnt + 1) % inertia;
123
124       x[cnt] = event.accelerationIncludingGravity.x;
125       y[cnt] = event.accelerationIncludingGravity.y;
126       z[cnt] = event.accelerationIncludingGravity.z;
127
128       tx = 0; x.forEach( function(n, i){ tx += n; } ); tx /= inertia;
129       ty = 0; y.forEach( function(n, i){ ty += n; } ); ty /= inertia;
130       tz = 0; z.forEach( function(n, i){ tz += n; } ); tz /= inertia;
131
132       pitch =   Math.asin((tz / 9.81 > 1)?1:(tz/9.81)) / Math.PI * 180;
133       roll  = - Math.asin((ty / 9.81 > 1)?1:(ty/9.81)) / Math.PI * 180;
134       // pitch = (pitch + event.rotationRate.beta  / 1000 * event.interval) % 360;
135       // roll  = (roll  + event.rotationRate.gamma / 1000 * event.interval) % 360;
136       yaw   = (yaw   - event.rotationRate.alpha / 1000 * event.interval) % 360;
137       // yaw   = (yaw + ty) % 360;
138     };
139   })());
140
141   window.addEventListener("click", function(event) {
142     (lv.parentElement)?lv.parentElement.removeChild(lv):{};
143     (rv.parentElement)?rv.parentElement.removeChild(rv):{};
144     video.style.display = "block";
145     video.pause();
146   }, true);
147
148   w = video.videoWidth; h = video.videoHeight;
149   hdeg = w / 360; vdeg = h / 180;
150   scale = lv.width / (fov * hdeg |0);
151
152   dist = parseInt(document.getElementById("StereoDist").getAttribute("value"));
153   fov  = parseInt(document.getElementById("StereoFOV").getAttribute("value"));
154   // scale = lv.width / (w / 4);
155   video.play();
156   video.style.display = "none";
157   draw();
158 };