├── .gitmodules
├── ASHIMA.md
├── LICENSE
├── README.md
├── glocd
├── .gitignore
├── Makefile
├── Stone1.jpg
├── abs.glsl
├── blend.glsl
├── demo.html
├── demo.js
├── engine
├── light.glsl
├── nplain.glsl
├── plain.glsl
├── sphere.glsl
├── tex.glsl
└── vert.glsl
└── pano
├── .gitignore
├── README.md
├── apollo
├── .gitignore
├── Makefile
└── manifest.xml
├── atom.xsl
├── fs.xsl
├── gallery.xsl
├── lang
└── en.xml
├── manifest.xml
├── manifest.xsl
├── mars
├── .gitignore
├── Makefile
└── gallery.xml
├── pano.css
├── pano.html
├── pano.js
├── pano_ui.js
├── subpath.xsl
└── xhtml.xsl
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "pano/engine"]
2 | path = pano/engine
3 | url = git://github.com/ashima/webgl-engine.git
4 | [submodule "pano/demo-lib"]
5 | path = pano/demo-lib
6 | url = git://github.com/ashima/demo-lib.git
7 | [submodule "webgl-noise"]
8 | path = webgl-noise
9 | url = git@github.com:ashima/webgl-noise.git
10 |
--------------------------------------------------------------------------------
/ASHIMA.md:
--------------------------------------------------------------------------------
1 | # Ashima webgl-demos
2 |
3 | webgl-demos is a collection of WebGL demonstrations from Ashima
4 | Group. The software is free and open source under the MIT Expat license
5 | which can be found in the LICENSE file.
6 |
7 | ###License
8 | [MIT Expat](http://ashimagroup.net/os/license/mit-expat)
9 |
10 | ###Tags
11 | [WebGL](http://ashimagroup.net/os/tag/webgl)
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2011 Ashima Arts
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ashima webgl-demos
2 |
3 | webgl-demos is a collection of WebGL demonstrations from Ashima
4 | Group. The software is free and open source under the MIT Expat license
5 | which can be found in the LICENSE file.
6 |
7 | ## Usage
8 |
9 | Don't forget to
10 | ```git submodule update --init --recursive```
11 | to clone dependencies!
12 |
13 | ## Demos
14 |
15 | - [Multiple Panorama Viewer](https://github.com/ashima/webgl-demos/tree/master/pano)
16 |
--------------------------------------------------------------------------------
/glocd/.gitignore:
--------------------------------------------------------------------------------
1 | *.glo
2 |
--------------------------------------------------------------------------------
/glocd/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all noise
2 |
3 | GLSL := $(wildcard *.glsl)
4 | GLO := $(GLSL:.glsl=.glo)
5 |
6 | all: ${GLO} noise
7 |
8 | noise:
9 | cd ../webgl-noise/src && make
10 | cp ../webgl-noise/src/noise.glo .
11 |
12 | %.glo: %.glsl
13 | gloc -c --dissolve $*.glsl -o $*.glo
14 |
--------------------------------------------------------------------------------
/glocd/Stone1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ashima/webgl-demos/a63f8a19ea74c89abca2f6eac6b876a35dd01aa7/glocd/Stone1.jpg
--------------------------------------------------------------------------------
/glocd/abs.glsl:
--------------------------------------------------------------------------------
1 | vec4 abs_(vec2 xy) {
2 | return vec4(abs(xy),1.0,1.0);
3 | }
4 |
5 | vec4 abs_noise(vec2 xy) {
6 | float t = time/1000.;
7 | return vec4((0.2+snoise(vec3(xy,t)))/1.2,
8 | (0.2+snoise(vec3(xy.y,t,xy.x)))/1.2,
9 | (0.2+snoise(vec3(t,xy)))/1.2,1.0);
10 | }
11 |
--------------------------------------------------------------------------------
/glocd/blend.glsl:
--------------------------------------------------------------------------------
1 | const float ipi = 1.0 / 3.1415926535897932384626433832795029;
2 | uniform sampler2D tex0;
3 | uniform float time;
4 | uniform float mixf;
5 |
6 | varying vec2 texCoord;
7 | varying vec4 normal;
8 | varying vec4 pointLightingDirection;
9 |
10 | uniform vec4 ambientColor;
11 | uniform vec4 directionalColor;
12 | uniform vec4 lightingDirection;
13 | uniform vec4 pointLightingColor;
14 |
15 | void main(void) {
16 | vec4 lt_att = light(vec4(0.));
17 | gl_FragColor = lt_att * mix(blenda(texCoord),blendb(texCoord),mixf);
18 | }
19 |
--------------------------------------------------------------------------------
/glocd/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebGL glo Demo
4 |
23 |
24 |
25 |
26 | Loading ...
27 |
28 |
29 |
32 |
33 |
34 |
36 |
37 |
38 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/glocd/demo.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 Ashima Arts All rights reserved.
3 | * License: MIT expat <../LICENSE>
4 | * Author: Ian McEwan, Ashima Arts
5 | * Author: David Sheets, Ashima Arts
6 | * Description: A gloc demo module
7 | */
8 |
9 | function ashimaGlocDemo(onprogress, onprogchange) {
10 | var D = this;
11 | var awe = ashimaWebGLEngine0;
12 | var epoch = (new Date()).getTime();
13 |
14 | var vcycle = ["map2Rs","map2Rpp","map2Rnp","map2Rns"];
15 | var fcycle = ["tex_","abs_","abs_noise","tex_noise"];
16 | var vtrans = 7000.;
17 | var ftrans = 3000.;
18 | var currentvi = 0, currentfi = 0;
19 | function ready_for_switch() {
20 | var now = (new Date()).getTime() - epoch;
21 | var vi = Math.floor((now/vtrans) % vcycle.length);
22 | var fi = Math.floor((now/ftrans) % fcycle.length);
23 | var ovi = currentvi, ofi = currentfi;
24 | currentvi=vi; currentfi=fi;
25 | return (ovi != vi) || (ofi != fi);
26 | }
27 | var prog_cache = {};
28 | function make_progs(callback) {
29 | var total = vcycle.length * fcycle.length;
30 | var complete = 0;
31 | for (var vi = 0; vi < vcycle.length; vi++) {
32 | for (var fi = 0; fi < fcycle.length; fi++) {
33 | (function() {
34 | var av, bv, af, bf;
35 | av = vcycle[vi]; bv = vcycle[(vi + 1) % vcycle.length];
36 | af = fcycle[fi]; bf = fcycle[(fi + 1) % fcycle.length];
37 | get_glo(["vert.glo",
38 | make_blend(av,bv),
39 | "sphere.glo",
40 | "plain.glo",
41 | "nplain.glo",
42 | "noise.glo"],
43 | ["blend.glo",
44 | make_blend(af,bf),
45 | make_light(["point_light","ambient_light"]),
46 | "abs.glo",
47 | "tex.glo",
48 | "light.glo",
49 | "noise.glo"],
50 | function (vglom, fglom) {
51 | if (!( av in prog_cache)) prog_cache[av] = {};
52 | prog_cache[av][af] = link_prog(vglom,fglom);
53 | complete++;
54 | onprogress(complete,av,af);
55 | if (total == complete) callback();
56 | });
57 | })();
58 | }
59 | }
60 | }
61 | function get_prog() {
62 | var now = (new Date()).getTime() - epoch;
63 | var vi = Math.floor((now/vtrans) % vcycle.length);
64 | var fi = Math.floor((now/ftrans) % fcycle.length);
65 | onprogchange(vi,fi);
66 | return prog_cache[vcycle[vi]][fcycle[fi]];
67 | }
68 |
69 | //var gl, prog, verts, tris;
70 | var pi = 3.1415926535897932384626433832795029 ;
71 | var elemDemo, elemRoot, elemCanvas;
72 | var curW , curH ;
73 | //var mvMatrix, pMatrix;
74 |
75 | theta = 0.;
76 | phi = 0.;
77 | function makePerspective(fovy, aspect, near, far)
78 | { // swipped from somewhere!
79 | var tp = near * Math.tan(fovy * Math.PI / 360.0);
80 | var bt = -tp;
81 | var lt = bt * aspect;
82 | var rt = tp * aspect;
83 |
84 | var X = 2*near/(rt-lt);
85 | var Y = 2*near/(tp-bt);
86 | var A = (rt+lt)/(rt-lt);
87 | var B = (tp+bt)/(tp-bt);
88 | var C = -(far+near)/(far-near);
89 | var D = -2*far*near/(far-near);
90 |
91 | return [X, 0, 0, 0,
92 | 0, Y, 0, 0,
93 | A, B, C, -1,
94 | 0, 0, D, 0 ] ;
95 | }
96 |
97 | var precdecl = "#ifdef GL_ES\nprecision highp float;\n#endif\n";
98 | var glol = new GLOL();
99 |
100 | function link_prog(vglom,fglom) {
101 | var vs;
102 | try { vs = glol.link(precdecl,[],vglom) }
103 | catch(e) { console.log(e); };
104 | var fs;
105 | try { fs = glol.link(precdecl,[],fglom) }
106 | catch(e) { console.log(e); };
107 |
108 | r = awe.compileAndLink(vs,fs);
109 | return r;
110 | }
111 |
112 | function use_prog() {
113 | prog.aweUse();
114 | demoTex.aweSet(0, prog.aweSym['tex0'] );
115 | verts.aweSetVertexAttPtr(prog.aweSym["position2D"]);
116 | }
117 |
118 | function make_blend(a,b) {
119 | return [a+"2"+b,
120 | {"glo": [1,0,0],
121 | "target": ["webgl",[1,0,0]],
122 | "units":[
123 | {"insym": [a],
124 | "outmac": ["blenda"],
125 | "source":"#define blenda "+a},
126 | {"insym": [b],
127 | "outmac": ["blendb"],
128 | "source":"#define blendb "+b}
129 | ]
130 | }
131 | ];
132 | }
133 | function make_light(a) {
134 | var compose = a.join("(")+"(c"+a.map(function(k){ return ""; }).join(")")+")";
135 | return [a.join("_"),
136 | {"glo": [1,0,0],
137 | "target": ["webgl",[1,0,0]],
138 | "units":[
139 | {"insym": a,
140 | "outmac": ["light"],
141 | "source":"#define light(c) "+compose }
142 | ]
143 | }
144 | ];
145 | }
146 |
147 | var glo_cache = {};
148 |
149 | function get_glo(vpaths,fpaths,callback) {
150 | var complete = vpaths.length+fpaths.length;
151 | var progress = 0;
152 | function error() {
153 | throw ("Error requesting '"+path+"'.");
154 | }
155 | function got_glo(path,set_path) {
156 | progress++;
157 | set_path(path,[path,glo_cache[path]]);
158 | if (progress == complete) { callback(vpaths,fpaths); }
159 | }
160 | function request_path(path,set_path) {
161 | if ( Object.prototype.toString.call(path) === "[object Array]") {
162 | glo_cache[path[0]] = path[1];
163 | got_glo(path[0],set_path);
164 | return;
165 | }
166 | if (path in glo_cache) { got_glo(path,set_path); return; }
167 | var req = new XMLHttpRequest();
168 |
169 | req.onerror = req.onabort = error;
170 |
171 | req.onreadystatechange = function() {
172 | if (req.readyState == 4) {
173 | if (req.responseText == null) error();
174 | else {
175 | glo_cache[path] = JSON.parse(req.responseText);
176 | got_glo(path,set_path);
177 | }
178 | }
179 | };
180 | req.open("GET",path);
181 |
182 | try { req.send(); }
183 | catch (x) {
184 | throw ("File exception caught requesting "+s+" :\n'"+x.toString()+"'");
185 | return true;
186 | }
187 | }
188 |
189 | vpaths.forEach(function (path) {
190 | request_path(path,
191 | function(p,v) {
192 | vpaths[vpaths.indexOf(p)] = v;
193 | });
194 | });
195 | fpaths.forEach(function (path) {
196 | request_path(path,
197 | function(p,v) {
198 | fpaths[fpaths.indexOf(p)] = v;
199 | });
200 | });
201 | }
202 |
203 | function glinit() {
204 | gl = awe.getGlContext(elemCanvas,{"warningsAsErrors":true});
205 |
206 | if (!gl) throw "No webgl here";
207 |
208 | var num = 20;
209 | var step = 2 / (num-1);
210 | jverts = new Array;
211 | for (var j = 0; j < num; j++ )
212 | for (var i = 0; i < num; i++ )
213 | {
214 | jverts[(j*num+i)*2+0] = i * step - 1.0;
215 | jverts[(j*num+i)*2+1] = j * step - 1.0;
216 | }
217 | jtris = new Array;
218 | for (var j = 0; j < num-1 ; j++ )
219 | for (var i = 0; i < num-1 ; i++ )
220 | {
221 | jtris[ (j*(num-1)+i)*6 +0] = (j+0)*num+(i+0) ;
222 | jtris[ (j*(num-1)+i)*6 +1] = (j+0)*num+(i+1) ;
223 | jtris[ (j*(num-1)+i)*6 +2] = (j+1)*num+(i+0) ;
224 |
225 | jtris[ (j*(num-1)+i)*6 +3] = (j+0)*num+(i+1) ;
226 | jtris[ (j*(num-1)+i)*6 +4] = (j+1)*num+(i+1) ;
227 | jtris[ (j*(num-1)+i)*6 +5] = (j+1)*num+(i+0) ;
228 | }
229 | verts = awe.makeBuffer(gl.ARRAY_BUFFER,gl.FLOAT,2,gl.STATIC_DRAW,jverts );
230 | tris = awe.makeBuffer(gl.ELEMENT_ARRAY_BUFFER,gl.UNSIGNED_SHORT,3,gl.STATIC_DRAW,jtris );
231 |
232 | pMatrix = new Float32Array(makePerspective( 120, 1, 0.1, 10. ));
233 | mvMatrix = new Float32Array([0.5,0.5,0,0, -0.5,0.5,0,0, 0,0,1,0, 0,0,0,1]);
234 | }
235 |
236 | var demoTex, demoImg;
237 | function renderinit()
238 | {
239 | demoTex = awe.textureCreate();
240 | demoImg = new Image ;
241 | demoImg.onload = function() {
242 | demoTex.aweFromElem(demoImg);
243 | demoTex.aweParams( gl.LINEAR, gl.LINEAR,
244 | gl.REPEAT, gl.REPEAT, false);
245 | }
246 | demoImg.onerror = function(e) { console.log(e); };
247 | demoImg.src = "Stone1.jpg";
248 | }
249 |
250 | function updateCanvasSize() {
251 | curW = elemRoot.clientWidth;
252 | curH = elemRoot.clientHeight;
253 | pMatrix = new Float32Array(makePerspective(45, curW/curH, 2, 10.));
254 | gl.viewport(0, 0,
255 | gl.viewportWidth = elemCanvas.width = curW,
256 | gl.viewportHeight = elemCanvas.height = curH );
257 | }
258 |
259 | function resizeNow()
260 | {
261 | updateCanvasSize();
262 | D.animator.play();
263 | }
264 |
265 | function clearFrame()
266 | {
267 | gl.clearColor(0.0,0.0,0.0,1.0);
268 | gl.clearDepth(100.0);
269 | gl.enable(gl.DEPTH_TEST);
270 | gl.disable(gl.BLEND);
271 | gl.enable(gl.CULL_FACE);
272 | gl.depthFunc(gl.LEQUAL);
273 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
274 | }
275 |
276 | function render() {
277 | var w = elemRoot.clientWidth;
278 | var h = elemRoot.clientHeight;
279 | var now = (new Date()).getTime()-epoch;
280 |
281 | phi += pi / 240;
282 | if (w != curW || h != curH) {
283 | D.animator.pause();
284 | setTimeout(resizeNow,200);
285 | }
286 | else {
287 | ct = Math.cos(theta); st = Math.sin(theta);
288 | cp = Math.cos(phi); sp = Math.sin(phi);
289 |
290 | mvMatrix = new Float32Array([ cp, -sp, 0, 0,
291 | ct*sp, ct*cp, -st, 0,
292 | st*sp, st*cp, ct, 0,
293 | 0, 0, 0, 1.0]);
294 |
295 | if (ready_for_switch())
296 | prog = get_prog();
297 |
298 | use_prog();
299 | clearFrame();
300 | gl.uniformMatrix4fv(prog.aweSym["pMatrix"], false, pMatrix);
301 | gl.uniformMatrix4fv(prog.aweSym["mvMatrix"], false, mvMatrix);
302 | gl.uniform1f(prog.aweSym["time"], now);
303 | var sv = (now % vtrans) / vtrans;
304 | var sf = (now % ftrans) / ftrans;
305 | gl.uniform1f(prog.aweSym["mixv"], 3*Math.pow(sv,2) - 2*Math.pow(sv,3));
306 | gl.uniform1f(prog.aweSym["mixf"], 3*Math.pow(sf,2) - 2*Math.pow(sf,3));
307 |
308 | gl.uniform4fv(prog.aweSym["ambientColor"], [0.1,0.1,0.1,1.0]);
309 | gl.uniform4fv(prog.aweSym["directionalColor"], [0.9,0.9,0.9,1.0]);
310 | gl.uniform4fv(prog.aweSym["lightingDirection"],
311 | [sp*cp+cp*sp,1.0,cp*cp-sp*sp,1.0]);
312 | gl.uniform4fv(prog.aweSym["pointLightingColor"], [0.9,0.9,0.9,1.]);
313 | gl.uniform4fv(prog.aweSym["pointLightingLocation"], [10.0,10.0,10.0,1.0]);
314 |
315 | tris.drawElements(gl.TRIANGLES);
316 | }
317 | }
318 | D.updateCanvasSize = updateCanvasSize;
319 | //D.updateElems = updateElems;
320 |
321 | D.init = function(p, callback) {
322 | elemRoot = p;
323 |
324 | elemCanvas = document.createElement("canvas");
325 | elemCanvas.style.zIndex = -1;
326 | elemCanvas.style.position = "absolute";
327 | elemDemo = document.createElement("div");
328 | elemDemo.style.zIndex = 1;
329 | elemDemo.appendChild(elemCanvas);
330 | elemRoot.appendChild(elemDemo);
331 |
332 | glinit();
333 | renderinit();
334 | make_progs(function() { prog = get_prog(); callback(); } );
335 | D.animator = awe.animationStart(render,gl.canvas,1000/60,true);
336 | theta = -1.0;
337 | phi = 0;
338 | }
339 | };
340 |
341 |
342 |
--------------------------------------------------------------------------------
/glocd/engine:
--------------------------------------------------------------------------------
1 | ../pano/engine/
--------------------------------------------------------------------------------
/glocd/light.glsl:
--------------------------------------------------------------------------------
1 | vec4 ambient_light(vec4 c) {
2 | return c + ambientColor;
3 | }
4 |
5 | vec4 diffuse_light(vec4 c) {
6 | return c + directionalColor * max(dot(normal, lightingDirection),0.);
7 | }
8 |
9 | vec4 point_light(vec4 c) {
10 | return c + pointLightingColor * max(dot(normal, pointLightingDirection),0.);
11 | }
12 |
13 | vec4 null_light(vec4 c) {
14 | return vec4(1.0);
15 | }
16 |
--------------------------------------------------------------------------------
/glocd/nplain.glsl:
--------------------------------------------------------------------------------
1 | void map2Rnp(out vec4 P, out vec4 N, vec2 v) { /* plain */
2 | P = vec4(v.x,v.y,-1.0-snoise(vec3(v,time/1000.))/10.,1.);
3 | N = vec4(0.,0.,1.,1.);
4 | }
5 |
--------------------------------------------------------------------------------
/glocd/plain.glsl:
--------------------------------------------------------------------------------
1 | void map2Rpp(out vec4 P, out vec4 N, vec2 v) { /* plain */
2 | P = vec4(v.x,v.y,0.,1.);
3 | N = vec4(0.,0.,1.,1.);
4 | }
5 |
--------------------------------------------------------------------------------
/glocd/sphere.glsl:
--------------------------------------------------------------------------------
1 | void map2Rs(out vec4 P, out vec4 N, vec2 v) { /* sphere */
2 | v *= pi;
3 | P = vec4(cos(v.x)*sin(v.y),sin(v.x)*sin(v.y), cos(v.y),1.0);
4 | N = normalize(P);
5 | }
6 |
7 | void map2Rns(out vec4 P, out vec4 N, vec2 v) {
8 | v *= pi;
9 | float t = time/1000.;
10 | vec3 s = vec3(cos(v.x)*sin(v.y),sin(v.x)*sin(v.y),cos(v.y));
11 | P = vec4((2.+snoise(vec3(v,t)))*s/2.5,1.0);
12 | N = normalize(P);
13 | }
14 |
--------------------------------------------------------------------------------
/glocd/tex.glsl:
--------------------------------------------------------------------------------
1 | vec4 tex_(vec2 xy) {
2 | return texture2D(tex0, xy);
3 | }
4 |
5 | vec4 tex_noise(vec2 xy) {
6 | float t = time/1000.;
7 | vec4 tf = texture2D(tex0, xy);
8 | return vec4(tf.r*(0.2+snoise(vec3(xy,t)))/1.2,
9 | tf.g*(0.2+snoise(vec3(xy.y,t,xy.x)))/1.2,
10 | tf.b*(0.2+snoise(vec3(t,xy)))/1.2, 1.0);
11 | }
12 |
--------------------------------------------------------------------------------
/glocd/vert.glsl:
--------------------------------------------------------------------------------
1 | const float pi = 3.1415926535897932384626433832795029;
2 |
3 | attribute vec2 Rxy;
4 | attribute vec2 position2D;
5 | vec4 P,N;
6 |
7 | uniform mat4 pMatrix;
8 | uniform mat4 mvMatrix;
9 | uniform vec4 pointLightingLocation;
10 |
11 | uniform float time;
12 | uniform float mixv;
13 |
14 | varying vec4 normal;
15 | varying vec2 texCoord;
16 | varying vec4 pointLightingDirection;
17 |
18 | void main(void) {
19 | vec4 position4;
20 | vec4 Pa, Na, Pb, Nb;
21 | blenda(Pa, Na, position2D);
22 | blendb(Pb, Nb, position2D);
23 | P = mix(Pa,Pb,mixv);
24 | N = mix(Na,Nb,mixv);
25 |
26 | texCoord = position2D;
27 | normal = N*mvMatrix;
28 |
29 | position4 = P*mvMatrix - vec4(0.,0.,4.,0.);
30 | position4 /= position4.w;
31 | pointLightingDirection = vec4(
32 | normalize( pointLightingLocation.xyz - position4.xyz ), 0. );
33 | gl_Position = pMatrix * position4;
34 | }
35 |
--------------------------------------------------------------------------------
/pano/.gitignore:
--------------------------------------------------------------------------------
1 | img/
2 | panos/
3 | mars/index.html
4 | mars/static-manifest.xml
5 | mars/panos/
6 |
--------------------------------------------------------------------------------
/pano/README.md:
--------------------------------------------------------------------------------
1 | # Ashima webgl-demos
2 | ## Multiple Panorama Viewer
3 | ### Requirements
4 |
5 | To automatically fetch assets or wrap the demo in
6 | [webgl-diagnostic](https://github.com/ashima/webgl-diagnostic), you will
7 | need **make**, **xsltproc**, and **wget**.
8 |
9 | ### Assets
10 |
11 | To automatically fetch the large, binary panorama images, run *make*
12 | *static* in this directory.
13 |
14 | ### Demo Wrapping
15 |
16 | To wrap the Mars demo in
17 | [webgl-diagnostic](https://github.com/ashima/webgl-diagnostic) and
18 | prepare for publication, run *make* in *mars/*.
19 |
20 |
--------------------------------------------------------------------------------
/pano/apollo/.gitignore:
--------------------------------------------------------------------------------
1 | index.html
2 | static-manifest.xml
3 |
--------------------------------------------------------------------------------
/pano/apollo/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all static clean
2 |
3 | all: index.html static
4 |
5 | static-manifest.xml: manifest.xml
6 | xsltproc ../demo-lib/static-manifest.xsl manifest.xml > static-manifest.xml
7 |
8 | index.html: static-manifest.xml
9 | xsltproc ../gallery.xsl static-manifest.xml > index.html
10 |
11 | static: static-manifest.xml
12 | xsltproc ../demo-lib/local-assets.xsl static-manifest.xml | uniq | sh
13 |
14 | clean:
15 | rm static-manifest.xml index.html
--------------------------------------------------------------------------------
/pano/apollo/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/pano/atom.xsl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/pano/fs.xsl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | #!/bin/sh
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | mkdir -p
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | ln -fs
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | xsltproc --stringparam host
51 |
52 | --param subfeed
53 |
54 | ../atom.xsl gallery.xml >
55 |
56 | /index.atom
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | rm -rfv
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/pano/gallery.xsl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/pano/lang/en.xml:
--------------------------------------------------------------------------------
1 |
2 | View Gallery
3 | Try Viewing Gallery Anyway
4 |
5 | An Ashima WebGL Demonstration
6 |
7 | Downloading
8 | Download Error
9 |
10 |
--------------------------------------------------------------------------------
/pano/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/pano/manifest.xsl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
45 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/pano/mars/.gitignore:
--------------------------------------------------------------------------------
1 | css/
2 | engine/
3 | gallery.xhtml
4 | index.atom
5 | js/
6 | manifest.xml
7 | mer/
8 | mpf/
9 | msl/
10 | pano.css
11 | pano.js
12 | pano_ui.js
13 | phx/
14 | webgl-diagnostic/
15 |
--------------------------------------------------------------------------------
/pano/mars/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all dev static fs clean
2 |
3 | OBJS := manifest.xml static-manifest.xml gallery.xhtml index.html index.atom
4 |
5 | all: dev
6 |
7 | manifest.xml: gallery.xml ../manifest.xsl
8 | xsltproc ../manifest.xsl gallery.xml > manifest.xml
9 |
10 | static-manifest.xml: manifest.xml
11 | xsltproc --param rooted true\(\) \
12 | ../demo-lib/static-manifest.xsl manifest.xml > static-manifest.xml
13 |
14 | gallery.xhtml: gallery.xml ../xhtml.xsl
15 | xsltproc ../xhtml.xsl gallery.xml > gallery.xhtml
16 |
17 | index.html: static-manifest.xml gallery.xhtml ../gallery.xsl
18 | xsltproc ../gallery.xsl static-manifest.xml > index.html
19 |
20 | index.atom: gallery.xml ../atom.xsl
21 | xsltproc ../atom.xsl gallery.xml > index.atom
22 |
23 | fs: gallery.xml ../fs.xsl
24 | xsltproc ../fs.xsl gallery.xml | sh
25 |
26 | dev: fs static-manifest.xml index.html index.atom
27 | xsltproc --stringparam profile dev \
28 | ../demo-lib/local-assets.xsl static-manifest.xml | uniq | sh
29 |
30 | static: fs static-manifest.xml index.html index.atom
31 | xsltproc --stringparam profile static \
32 | ../demo-lib/local-assets.xsl static-manifest.xml | uniq | sh
33 |
34 | clean: static-manifest.xml
35 | xsltproc --stringparam action delete \
36 | ../demo-lib/local-assets.xsl static-manifest.xml | uniq | sh
37 | xsltproc --stringparam action delete \
38 | ../fs.xsl gallery.xml | sh
39 | rm -f ${OBJS}
40 |
41 |
--------------------------------------------------------------------------------
/pano/mars/gallery.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | Mars Panorama Archive
6 |
7 | This is the Ashima Group Mars Panorama Archive. These panoramic
8 | images were captured by NASA/JPL robots on the surface of Mars.
9 |
10 |
11 |
12 | Mars Science Laboratory
13 | The Mars
15 | Science Laboratory is a currently ongoing (as of Aug. 28,
16 | 2012) NASA mission which landed a rover, Curiosity,
17 | in Gale
18 | Crater on Aug. 6, 2012.
19 |
20 |
21 | Curiosity NavCam Full 2012
22 | 2012-09-03T14:06:41-07:00
23 | Captured: 2012
24 |
25 |
26 | Curiosity First Color Pan 2012
27 | 2012-09-03T14:08:41-07:00
28 | Captured: 2012
29 |
30 |
31 | First Curiosity Pan 2012
32 | 2012-09-03T14:10:41-07:00
33 | Captured: 2012
34 |
35 |
36 |
37 |
38 | Phoenix Lander
39 | The Phoenix
41 | Lander descended to the surface of Mars on May 25, 2008.
42 |
43 |
44 | PHX 2008
45 | 2012-08-01T12:00:01-07:00
46 | Captured: 2008
47 |
48 |
49 |
50 |
51 | Mars Exploration Rover
52 |
56 | MER-B 2012
57 | 2012-08-27T13:00:00-07:00
58 | Captured: 2012
59 |
60 |
61 | The Mars
63 | Exploration Rover mission involved two rovers,
64 | Spirit and Opportunity. The rovers
65 | were launched in June and July 2003 and landed successfully in
66 | January 2004.
67 |
68 |
69 | MER-B 2004
70 | 2012-08-01T13:00:00-07:00
71 | Captured: 2004
72 |
73 |
74 | MER-A 2004
75 | 2012-08-01T13:00:01-07:00
76 | Captured: 2004
77 |
78 |
79 | MER-A 2009
80 | 2012-08-01T13:00:02-07:00
81 | Captured: 2009
82 |
83 |
84 | MER-B 2008
85 | 2012-08-01T13:00:03-07:00
86 | Captured: 2008
87 |
88 |
89 | MER-B 2006
90 | 2012-08-01T13:00:04-07:00
91 | Captured: 2006
92 |
93 |
94 |
95 |
96 | Mars Pathfinder
97 | The Mars
99 | Pathfinder mission landed a stationary base station,
100 | Carl Sagan Memorial Station, and a 10.6 kg rover,
101 | Sojourner.
102 |
103 | MPF 1997
104 | 2012-08-01T12:00:00-07:00
105 | Captured: 1997
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/pano/pano.css:
--------------------------------------------------------------------------------
1 | /*
2 | *************************************
3 | WebGL Panorama
4 | Created: 26 sep 2011
5 | Updated: 11 oct 2011
6 | *************************************
7 | */
8 |
9 |
10 | body {
11 | font:12px/18px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", helvetica, arial, verdana, sans-serif;
12 | color:#000;
13 | margin:0;
14 | padding:0;
15 | }
16 |
17 | article h1 { font-size: 2em; font-weight: bold; margin: 0.5em 0em; }
18 | article ul { padding-left: 2em; }
19 | nav h1 { font-size: 1.1em; margin: 0; }
20 |
21 | #pano-container {
22 | height:100%;
23 | width:100%;
24 | margin:auto;
25 | display: -moz-box;
26 | display: -webkit-box;
27 | display: box;
28 | }
29 |
30 | nav.gallery-nav {
31 | background-color:#fff;
32 | background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#FFFFFF), to(#bbb));
33 | background:-moz-linear-gradient(0% 0% 270deg,#FFFFFF, #bbb);
34 | background: -webkit-linear-gradient(#fff, #bbb);
35 | width:172px;
36 | height:100%;
37 | border-left:1px solid #aaa;
38 | overflow-y: auto;
39 | }
40 |
41 | ul {
42 | list-style:none;
43 | }
44 |
45 | .index ul {
46 | list-style:circle;
47 | }
48 |
49 | .isResizable {
50 | display:block;
51 | -moz-box-flex: 1;
52 | -webkit-box-flex: 1;
53 | box-flex: 1;
54 | clear:both;
55 | background: rgba(0, 0, 0, 0.0);
56 | overflow: scroll;
57 | resize: both;
58 | padding:0;
59 | margin:0;
60 | height:100%;
61 | width:100%;
62 | }
63 |
64 | #zoom {
65 | width:93px;
66 | height:34px;
67 | padding-top:15px;
68 | padding-left:34px;
69 | }
70 |
71 | .zoomin, .zoomout {
72 | width:39px;
73 | height:34px;
74 | float:left;
75 | position:block;
76 | cursor:pointer;
77 | }
78 |
79 | .zoomin {
80 | background:url("img/zoom_more.png") no-repeat scroll top right transparent;
81 | margin-right:15px;
82 | }
83 |
84 | .zoomout {
85 | background:url("img/zoom_less.png") no-repeat scroll top right transparent;
86 | }
87 |
88 | .rss {
89 | width: 34px; height: 34px;
90 | background:url("img/rss.png") no-repeat scroll top right transparent;
91 | }
92 |
93 | .rss:hover {
94 | width: 34px; height:34px;
95 | background:url("img/rss_orange.png") no-repeat scroll top right transparent;
96 | }
97 |
98 | div#navcat {
99 | margin:0 auto;
100 | padding-top:15px;
101 | width:82px;
102 | }
103 |
104 | .status {
105 | display:none;
106 | }
107 |
108 | .pano {
109 | color: #000;
110 | border:1px solid #999;
111 | text-align:center;
112 | margin-bottom:10px;
113 | }
114 |
115 | .pano img {
116 | min-width: 80;
117 | min-height: 40;
118 | max-width: 80;
119 | max-height: 40;
120 | width: 80;
121 | height: 40;
122 | margin-bottom:2px;
123 | cursor:pointer;
124 | }
125 |
126 | .panoInAct {
127 | opacity:0.7;
128 | }
129 |
130 | .panoAct, .pano:hover {
131 | opacity:1.0;
132 | }
133 |
134 | .index { display: none; }
135 | .infoOverlay {
136 | display: block;
137 | position: absolute;
138 | opacity: 0.8; background-color: #bbb; padding: 1em; padding-top: 0;
139 | top: 30px; left: 30px; width: 30%;
140 | }
141 |
142 | .infoOverlay.status {
143 | display: block;
144 | position: absolute;
145 | top: 45%; opacity: 1.0;
146 | left: 30%; right: 40%;
147 | background-color: #bbb; padding: 0.5em;
148 | font-size: 1.5em;
149 | overflow: hidden;
150 | }
151 |
152 | #caption {
153 | position: absolute;
154 | bottom: 2em; left: 1em;
155 | color: white;
156 | opacity: 0.8;
157 | font-size: 2em;
158 | }
159 |
--------------------------------------------------------------------------------
/pano/pano.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Multiple Panorama Viewer
4 |
6 |
7 |
9 |
10 |
12 |
13 |
15 |
16 |
18 |
19 |
21 |
22 |
24 |
25 |
29 |
30 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/pano/pano.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Description : Simple Panorama Viewing module.
3 | * Author : Ian McEwan, Ashima Arts.
4 | * License : Copyright (C) 2011 Ashima Arts. All rights reserved.
5 | * Distributed under the MIT License. See LICENSE file.
6 | */
7 |
8 | function ashimaPanoViewer() {
9 | var P = this;
10 | var awe = ashimaWebGLEngine0;
11 |
12 | var gl, prog, verts, panoTex, panoStopTimer;
13 | var pi = 3.1415926535897932384626433832795029 ;
14 | var elemPan, elemRoot, elemCanvas;
15 | var zoom = 1.0;
16 | var saspect = 8 /2;
17 | var panoStopDelay = 500;
18 |
19 | function glinit() {
20 | gl = awe.getGlContext(elemCanvas,{});
21 |
22 | if (!gl)
23 | throw "No webgl here";
24 |
25 | var vs = "\
26 | attribute vec2 p; \
27 | uniform vec3 z; \
28 | varying vec3 fpos; \
29 | void main(void) { \
30 | fpos = vec3(p*z.z, z.x); \
31 | fpos.y *= z.y; \
32 | gl_Position = vec4(p.x,p.y,z.x,1.0); \
33 | }";
34 |
35 | var fs = "#ifdef GL_ES\nprecision highp float;\n#endif\n\
36 | const float ipi = 1.0 / 3.1415926535897932384626433832795029 ; \
37 | uniform sampler2D pan; \
38 | uniform mat3 trans; \
39 | uniform vec2 sas; \
40 | varying vec3 fpos; \
41 | void main(void) { \
42 | vec3 q = normalize(fpos) * trans ; \
43 | vec2 l = vec2( atan(q.z,q.x) * 0.5, sas.y-asin(q.y)*sas.x) * ipi ; \
44 | l.y += 0.5; \
45 | gl_FragColor = texture2D(pan, l.xy ); \
46 | }";
47 |
48 |
49 | prog = awe.compileAndLink(vs, fs);
50 |
51 | verts = awe.makeBuffer(gl.ARRAY_BUFFER,gl.FLOAT,2,gl.STATIC_DRAW,
52 | [ -1.,-1., 1.,-1., -1.,1., 1.,1. ] );
53 |
54 | }
55 |
56 | function renderinit()
57 | {
58 | panoTex = awe.textureCreate();
59 | panoTex.aweParams( gl.LINEAR, gl.LINEAR, gl.REPEAT, gl.CLAMP_TO_EDGE, false);
60 | gl.disable(gl.DEPTH_TEST);
61 | gl.disable(gl.BLEND);
62 |
63 | prog.aweUse();
64 | panoTex.aweSet(0, prog.aweSym['pan'] );
65 | verts.aweSetVertexAttPtr(prog.aweSym["p"]);
66 | }
67 |
68 | var el = 0;
69 | var az = 0;
70 | var prev_el = null;
71 | var prev_az = null;
72 | curW = 0;
73 | curH = 0;
74 | wrap = 4;
75 | function updateElems() {
76 | curW = elemRoot.clientWidth;
77 | curH = elemRoot.clientHeight;
78 |
79 | elemPan.style.width = curW * 2/ zoom + wrap ;
80 | elemPan.style.height = curH * 2/(zoom *saspect);
81 | elemRoot.scrollLeft = az * (elemPan.offsetWidth - curW-wrap) / (2*pi)+wrap/2;
82 | elemRoot.scrollTop = (-el*saspect / pi + 0.5) * (elemPan.offsetHeight - curH) ;
83 | }
84 |
85 | function updateCanvasSize() {
86 | gl.viewport(0, 0,
87 | gl.viewportWidth = elemCanvas.width = curW,
88 | gl.viewportHeight = elemCanvas.height = curH );
89 | }
90 |
91 | function resizeNow()
92 | {
93 | updateElems();
94 | updateCanvasSize();
95 | P.animator.play();
96 | }
97 |
98 | function render() {
99 | var w = elemRoot.clientWidth;
100 | var h = elemRoot.clientHeight;
101 |
102 | az = 2* pi * ( elemRoot.scrollLeft-wrap/2)/(elemPan.offsetWidth - w - wrap);
103 | el = (1/saspect)* -pi * (elemRoot.scrollTop/(elemPan.offsetHeight - h)-0.5);
104 | if (az > 2*pi) {
105 | az -= 2*pi;
106 | updateElems();
107 | }
108 |
109 | if (az < 0) {
110 | az += 2*pi;
111 | updateElems();
112 | }
113 | if (w != curW || h != curH) {
114 | P.animator.pause();
115 | setTimeout(resizeNow,200);
116 | }
117 | else if (el != prev_el || az != prev_az)
118 | {
119 | var ce = Math.cos(el), se = Math.sin(el);
120 | var ca = Math.cos(az), sa = Math.sin(az);
121 |
122 | var trans = [ ca, -sa*se, sa*ce, 0, ce, se, sa, se*ca, -ca*ce ];
123 |
124 | var z_dist = 1.0;
125 |
126 | gl.uniform3f(prog.aweSym["z"], z_dist, h/w, zoom);
127 | gl.uniform2f(prog.aweSym["sas"], saspect, 0);
128 | gl.uniformMatrix3fv(prog.aweSym["trans"], false,trans);
129 | gl.drawArrays(gl.TRIANGLE_STRIP,0,verts.aweNumItems);
130 |
131 | prev_el = el; prev_az = az;
132 | clearTimeout(panoStopTimer);
133 | panoStopTimer = setTimeout(P.onPanoStop,panoStopDelay,az,el,zoom);
134 | }
135 | }
136 |
137 | P.updateCanvasSize = updateCanvasSize;
138 | P.updateElems = updateElems;
139 |
140 | P.init = function(p) {
141 | elemRoot = p;
142 |
143 | elemCanvas = document.createElement("canvas");
144 | elemCanvas.style.zIndex = -1;
145 | elemCanvas.style.position = "absolute";
146 | elemPan = document.createElement("div");
147 | elemPan.style.zIndex = 1;
148 | elemPan.appendChild(elemCanvas);
149 | elemRoot.appendChild(elemPan);
150 |
151 | glinit();
152 | renderinit();
153 | updateElems();
154 | updateCanvasSize();
155 | P.animator = awe.animationStart(render,gl.canvas,1000/30,true);
156 | };
157 |
158 | P.setImage = function(i) {
159 | var iw = i.naturalWidth,
160 | ih = i.naturalHeight;
161 | saspect = (iw / ih) *0.5 ;
162 | panoTex.aweFromElem(i);
163 | zoom = 1 / saspect;
164 | prev_el = prev_az = null;
165 | resizeNow();
166 | };
167 | P.setZoom = function(_z) {
168 | zoom = _z;
169 | updateElems();
170 | };
171 | P.setView = function(az_,el_) {
172 | el = el_;
173 | az = az_;
174 | };
175 | P.onPanoStop = function(az,el,z) { }
176 | };
177 |
--------------------------------------------------------------------------------
/pano/pano_ui.js:
--------------------------------------------------------------------------------
1 | var run_main = false;
2 | var main_pause = function() { // namespace
3 |
4 | var path_prefix = document.querySelector('nav').attributes['data-base-uri'].value;
5 |
6 | var gif1x1 = "data:image/gif;base64,R0lGODlhAQABAJEAAP/Mmf/Mmf4BAgAAACH5BAQUAP8ALAAAAAABAAEAAAICRAEAOw==";
7 |
8 | var zoomDelta = (1-1/16);
9 | var zoom = 1.0;
10 |
11 | var apv = new ashimaPanoViewer();
12 |
13 | var addEvent = (document.addEventListener)
14 | ? function (e, v, f, c) { e.addEventListener(v,f,c); }
15 | : function (e, v, f) { e.attachEvent("on"+v,f); }
16 |
17 | var panos = document.querySelectorAll('.pano');
18 | var subpath_els = document.querySelectorAll('*[data-uri]');
19 |
20 | function showInfoOverlay(el) {
21 | var div = document.getElementById("panodiv");
22 | var info = el.cloneNode(true);
23 | info.className += " infoOverlay";
24 | var internal_links = info.querySelectorAll("a.internal");
25 | for (var i = 0; i < internal_links.length; i++) {
26 | addEvent(internal_links[i],"click",function(e) {
27 | e.preventDefault();
28 | pushPath(subpath_of_path(this.pathname+this.hash))();
29 | },false);
30 | }
31 | div.appendChild(info);
32 |
33 | return info;
34 | }
35 |
36 | function hideInfoOverlay() {
37 | var div = document.getElementById("panodiv");
38 | var infos = div.querySelectorAll(".infoOverlay");
39 | if (infos) for (var i = 0; i < infos.length; i++) {
40 | div.removeChild(infos[i]);
41 | }
42 | }
43 |
44 | function showErrorStatus() {
45 | showInfoOverlay(document.getElementById("errormsg"));
46 | }
47 |
48 | function showLoadStatus() {
49 | var loader = showInfoOverlay(document.getElementById("loadmsg"));
50 | var timer = setInterval(function() {
51 | loader.innerText += ".";
52 | }, 200); // TODO: test spinner
53 | return {finish:function() {
54 | clearInterval(timer);
55 | loader.parentNode.removeChild(loader);
56 | }};
57 | }
58 |
59 | apv.onPanoStop = function(az, el, z) {
60 | var zs = "";
61 | if (z!=1) zs = "&z="+z;
62 | if (az!=0 || el!=0)
63 | history.replaceState({webgl:1},"","#?az="+az+"&el="+el+zs);
64 | }
65 |
66 | function normHash(h) {
67 | var hfqp = {az: 0, el: 0, z: 1};
68 | var q = h.substr(2);
69 | var kvp = q.split("&");
70 | if ("#?" == h.substr(0,2)) {
71 | for (var i = 0; i < kvp.length; i++) {
72 | kvp[i] = kvp[i].split("=");
73 | hfqp[kvp[i][0]] = parseFloat(kvp[i][1]);
74 | }
75 |
76 | apv.onPanoStop(hfqp.az,hfqp.el,hfqp.z);
77 | }
78 | return hfqp;
79 | }
80 |
81 | function showPano(i,subpath) {
82 | var caption = document.getElementById("caption");
83 | var link = document.getElementById(subpath);
84 | var href = link.attributes['href'].value;
85 | var img = new Image;
86 | var error = false;
87 | img.src = gif1x1;
88 | return function() {
89 | for (var j = 0; j < panos.length; j++) {
90 | panos[j].className = "pano panoInAct";
91 | }
92 | subpath_els[i].className = "pano panoAct";
93 |
94 | var spinner = showLoadStatus();
95 | img.onload = function(e) {
96 | var panoCoord = normHash(window.location.hash);
97 | spinner.finish();
98 |
99 | apv.setView(panoCoord.az,panoCoord.el);
100 | zoom = 1.0;
101 | apv.setImage(img);
102 | zoom = tryZoom(panoCoord.z);
103 |
104 | caption.innerText = subpath_els[i].querySelector(".thumb").attributes['title'].value;
105 |
106 | // preload the next pano
107 | setTimeout(function () {
108 | var link;
109 | if (subpath_els[i+1].className.indexOf("pano") != -1) {
110 | link = document.getElementById(constructPath(subpath_els[i+1],""));
111 | (new Image).src = link.attributes['href'].value;
112 | }
113 | },0);
114 | };
115 | img.onerror = function() {
116 | spinner.finish();
117 | showErrorStatus();
118 | error = true;
119 | };
120 | var a_uri = document.createElement("a");
121 | a_uri.href = img.src;
122 | if (a_uri.pathname==href && !error) img.onload();
123 | else if (error) img.onerror();
124 | else img.src = href;
125 | };
126 | }
127 |
128 | function showSection(i,subpath) {
129 | return function() { // TODO: check
130 | loadPath(constructPath(subpath_els[i].querySelector(".pano"),""));
131 | showInfoOverlay(subpath_els[i].querySelector(".index"));
132 | };
133 | }
134 |
135 | function showIndex() {
136 | return function() {
137 | loadPath(constructPath(document.querySelector(".pano"),""));
138 | showInfoOverlay(document.querySelector(".index"));
139 | };
140 | }
141 |
142 | function constructPath(el, path_suffix) {
143 | var attr = el.attributes['data-uri'];
144 | if (attr) {
145 | return constructPath(el.parentNode,attr.value+"/"+path_suffix);
146 | } else {
147 | return path_suffix;
148 | }
149 | }
150 |
151 | var subpaths = {};
152 | var subpath;
153 | for (var i = 0; i < subpath_els.length; i++) {
154 | subpath = constructPath(subpath_els[i],"");
155 | subpaths[subpath] = {
156 | "section": function() { return showSection(i,subpath); },
157 | "pano": function() { return showPano(i,subpath); }
158 | }[subpath_els[i].className]();
159 | }
160 |
161 | function loadPath(subpath) {
162 | hideInfoOverlay();
163 |
164 | if (subpath === "") showIndex()();
165 | else if (!(subpath in subpaths)) window.location = path_prefix;
166 | else subpaths[subpath]();
167 | }
168 |
169 | function pushPath(subpath) {
170 | return function() {
171 | loadPath(subpath);
172 | history.pushState({webgl:1},"",path_prefix+subpath);
173 | };
174 | }
175 |
176 | function subpath_of_path(path) {
177 | var subpath_requested = "";
178 | for (var i = 0; i < path.length; i++) {
179 | if (i >= path_prefix.length || path[i] !== path_prefix[i])
180 | subpath_requested += path[i];
181 | }
182 | return subpath_requested;
183 | }
184 |
185 | function tryZoom(z) {
186 | if (z < 1.9) { apv.setZoom(z); return z; }
187 | else return zoom;
188 | }
189 | function zoomIn() { zoom = tryZoom( zoom * zoomDelta) }
190 | function zoomOut() { zoom = tryZoom( zoom / zoomDelta) }
191 |
192 | return [function() { // main
193 | if (!run_main) {
194 | var label,f,img;
195 | apv.init( document.getElementById("panodiv") );
196 |
197 | for (var i = 0; i < panos.length; i++) {
198 | var pano_path = constructPath(panos[i],"");
199 | addEvent(panos[i], "click", pushPath(pano_path), false);
200 |
201 | label = document.createTextNode(panos[i].querySelector('img').attributes['title'].value);
202 | panos[i].appendChild(label);
203 | }
204 |
205 | function zoomButton(e,f,dt) {
206 | var t = 0;
207 | function clear() {
208 | if (t) {
209 | clearTimeout(t); t = 0;
210 | }
211 | }
212 | addEvent( e, "mousedown", function() { t = setInterval(f,dt); f(); }, false);
213 | addEvent( e, "mouseup", clear, false);
214 | addEvent( e, "mouseout", clear, false);
215 | addEvent( e, "mouseleave", clear, false);
216 | addEvent( e, "blur", clear, false);
217 | }
218 |
219 | zoomButton( document.getElementById("bZoomIn"), zoomIn, 33 ) ;
220 | zoomButton( document.getElementById("bZoomOut"), zoomOut, 33 ) ;
221 |
222 | loadPath(subpath_of_path(window.location.pathname));
223 | history.replaceState({webgl:1},"");
224 |
225 | run_main = true;
226 | } else {
227 | loadPath(subpath_of_path(window.location.pathname));
228 | apv.updateElems();
229 | apv.animator.play();
230 | }
231 | },
232 | function() { // pause
233 | apv.animator.pause();
234 | }];
235 | }();
236 |
237 | main = main_pause[0];
238 | pause = main_pause[1];
239 |
--------------------------------------------------------------------------------
/pano/subpath.xsl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | \'\'
36 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/pano/xhtml.xsl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
25 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------