corrade-http-templates – Blame information for rev 13

Subversion Repositories:
Rev:
Rev Author Line No. Line
2 eva 1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <title>Wizardry and Steamworks - Real Time Avatar Tracking using Corrade in SecondLife.</title>
5 <meta charset="utf-8">
6 <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
7 <link rel="stylesheet" href="css/style.css?v=1.0">
8 </head>
9  
10 <body>
11 <div id="container"></div>
12 <div id="info">
13 Wizardry and Steamworks - Real Time Avatar Tracking using Corrade in SecondLife.<br/>
14 All the graphical elements and data are generated dynamically!<br/>
15 MOVE mouse &amp; press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan<br/>
16 <a href="#" target="_blank">Click to Open in new Window</a><br/>
17 </div>
18  
19 <!-- Terrain Vertex and Fragment Shaders -->
20 <!-- Vertex Shader -->
21 <script id="terrainVertex" type="x-shader/x-vertex">
22 uniform sampler2D bumpTexture;
23 uniform float bumpScale;
24  
25 varying vec2 vUV;
26  
27 void main() {
28 vUV = uv;
29 vec4 bumpData = texture2D(bumpTexture, uv);
30  
31 // move the position along the normal
32 vec3 newPosition =
33 position +
34 normal *
35 bumpScale *
36 bumpData.r; // use red channel (all equal in greyscale)
37  
38 gl_Position =
39 projectionMatrix *
40 modelViewMatrix *
41 vec4(newPosition, 1.0);
42 }
43 </script>
44 <!-- Fragment Shader / Pixel Shader -->
45 <script id="terrainFragment" type="x-shader/x-vertex">
46 uniform sampler2D mapTexture;
47 varying vec2 vUV;
48  
49 void main() {
50 vec4 map = texture2D(mapTexture, vUV);
51 gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) + map; //, 1.0);
52 }
53 </script>
54 <!-- -->
55  
56 <script src="js/jquery.min.js"></script>
57 <script src="js/three.min.js"></script>
58 <script src="js/OrbitControls.min.js"></script>
59 <script src="js/CMUTypewriter_Regular.min.js"></script>
60  
61 <script>
62  
63 /* The bounds of the plot. */
64 var plotBounds = {
65 'maxx' : 256,
66 'minx' : -256,
67 'maxy' : 256,
68 'miny' : -256,
69 'maxz' : 256,
70 'minz' : -256
71 };
72  
73 /* This represents the bounds of the data to plot.
74 * These values will be linearly mapped onto the
75 * bounds for the plot.
76 */
77 var dataBounds = {
78 'maxx' : 256,
79 'minx' : 0,
80 'maxy' : 256,
81 'miny' : 0,
82 'maxz' : 256, // Second Life maximum rez altitude
83 'minz' : 0
84 }
85  
86 /* Structure to be filled by the backend scripts. */
87 var csv =
88 {
89 'header' : [ "x", "y", "z" ],
90 'positions' : [],
91 'names' : [],
92 'colors' : []
93 };
94  
95 /* The size of the cursor for each avatar. */
96 var dotSize = 8;
97 /* The interval in milliseconds for updating the terrain. */
98 var mapFetchInterval = 60000;
99 /* The interval in milliseconds for avatar position updates. */
100 var avatarsFetchInterval = 1000;
101  
102 var container;
103 var camera, controls, scene, renderer;
104 var scatterPlot;
105 var points;
106 var avatarLabels = [];
107 var avatarProjections = [];
108 var mapImageData = null;
109 var mapBumpData = null;
110 var mapHeight;
111 var mapMesh;
112  
113 init();
114 animate();
115  
116 function init() {
117 /* Create the camera. */
118 camera = new THREE.PerspectiveCamera(
119 60,
120 window.innerWidth / window.innerHeight,
121 2,
122 10000
123 );
124 camera.position.z = plotBounds.maxz * 2;
125 camera.position.x = 0;
126 camera.position.y = plotBounds.maxy * 1.25;
127 controls = new THREE.OrbitControls(camera);
128 controls.damping = 0.2;
129 controls.addEventListener('change', render);
130  
131 /* Create the scene. */
132 scene = new THREE.Scene();
133  
134 /* Add the scatterplot to it. */
135 scatterPlot = new THREE.Object3D();
136 scene.add(scatterPlot);
137  
138 /* Draw axes. */
139 var xAxisGeo = new THREE.Geometry();
140 var yAxisGeo = new THREE.Geometry();
141 var zAxisGeo = new THREE.Geometry();
142  
143 xAxisGeo.vertices.push(
144 new THREE.Vector3(
145 plotBounds.minx/2,
146 plotBounds.miny/2,
147 plotBounds.minz/2
148 ),
149 new THREE.Vector3(
150 plotBounds.maxx/2,
151 plotBounds.miny/2,
152 plotBounds.minz/2
153 )
154 );
155 yAxisGeo.vertices.push(
156 new THREE.Vector3(
157 plotBounds.minx/2,
158 plotBounds.miny/2,
159 plotBounds.minz/2
160 ),
161 new THREE.Vector3(
162 plotBounds.minx/2,
163 plotBounds.maxy/2,
164 plotBounds.minz/2
165 )
166 );
167 zAxisGeo.vertices.push(
168 new THREE.Vector3(
169 plotBounds.minx/2,
170 plotBounds.miny/2,
171 plotBounds.minz/2
172 ),
173 new THREE.Vector3(
174 plotBounds.minx/2,
175 plotBounds.miny/2,
176 plotBounds.maxz/2
177 )
178 );
179  
180 var xAxisMat = new THREE.LineBasicMaterial(
181 {
182 color: 0xa60000,
183 lineWidth: 1
184 }
185 );
186 var xAxis = new THREE.Line(xAxisGeo, xAxisMat);
187 xAxis.type = THREE.Lines;
188 scatterPlot.add(xAxis);
189  
190 var yAxisMat = new THREE.LineBasicMaterial(
191 {
192 color: 0x0000a6,
193 lineWidth: 1
194 }
195 );
196 var yAxis = new THREE.Line(yAxisGeo, yAxisMat);
197 yAxis.type = THREE.Lines;
198 scatterPlot.add(yAxis);
199  
200 var zAxisMat = new THREE.LineBasicMaterial(
201 {
202 color: 0x00a600,
203 lineWidth: 1
204 }
205 );
206 var zAxis = new THREE.Line(zAxisGeo, zAxisMat);
207 zAxis.type = THREE.Lines;
208 scatterPlot.add(zAxis);
209  
210 /* Add axes text. */
211 var text3d = new THREE.TextGeometry("O", {
212 size: 8,
213 height: 2,
214 curveSegments: 2,
215 font: "cmutypewriter_regular"
216  
217 });
218 text3d.computeBoundingBox();
219 var centerOffset = -0.5 * (
220 text3d.boundingBox.max.x -
221 text3d.boundingBox.min.x
222 );
223 var textMaterial = new THREE.MeshBasicMaterial(
224 {
225 color: 0xa6a6a6,
226 overdraw: 0.5
227 }
228 );
229 text = new THREE.Mesh(text3d, textMaterial);
230 text.position.x = plotBounds.minx/2 + 2 * centerOffset;
231 text.position.y = plotBounds.minx/2 + 2 * centerOffset;
232 text.position.z = plotBounds.minx/2;
233 scatterPlot.add(text);
234  
235 text3d = new THREE.TextGeometry(
236 csv.header[0] +
237 " " +
238 "(" +
239 dataBounds.maxx +
240 "m)",
241 {
242 size: 8,
243 height: 2,
244 curveSegments: 2,
245 font: "cmutypewriter_regular"
246 }
247 );
248 text3d.computeBoundingBox();
249 centerOffset = -0.5 * (
250 text3d.boundingBox.max.x -
251 text3d.boundingBox.min.x
252 );
253 textMaterial = new THREE.MeshBasicMaterial(
254 {
255 color: 0xa60000,
256 overdraw: 0.5
257 }
258 );
259 text = new THREE.Mesh(text3d, textMaterial);
260 text.position.x = plotBounds.maxx/2 - centerOffset / 4;
261 text.position.y = plotBounds.miny/2 + centerOffset / 8;
262 text.position.z = plotBounds.minz/2;
263 scatterPlot.add(text);
264  
265 text3d = new THREE.TextGeometry(
266 csv.header[2] +
267 " " +
268 "(" +
269 dataBounds.maxz +
270 "m)",
271 {
272 size: 8,
273 height: 2,
274 curveSegments: 2,
275 font: "cmutypewriter_regular"
276 }
277 );
278 text3d.computeBoundingBox();
279 centerOffset = -0.5 * (
280 text3d.boundingBox.max.x -
281 text3d.boundingBox.min.x
282 );
283 textMaterial = new THREE.MeshBasicMaterial(
284 {
285 color: 0x0000a6,
286 overdraw: 0.5
287 }
288 );
289 text = new THREE.Mesh( text3d, textMaterial );
290 text.position.x = plotBounds.minx/2 + centerOffset;
291 text.position.y = plotBounds.maxy/2 - centerOffset / 4;
292 text.position.z = plotBounds.minz/2;
293 scatterPlot.add(text);
294  
295 text3d = new THREE.TextGeometry(
296 csv.header[1] +
297 " " +
298 "(" +
299 dataBounds.maxy +
300 "m)",
301 {
302 size: 8,
303 height: 2,
304 curveSegments: 2,
305 font: "cmutypewriter_regular"
306 }
307 );
308 text3d.computeBoundingBox();
309 centerOffset = -0.5 * (
310 text3d.boundingBox.max.x -
311 text3d.boundingBox.min.x
312 );
313 textMaterial = new THREE.MeshBasicMaterial(
314 {
315 color: 0x00a600,
316 overdraw: 0.5
317 }
318 );
319 text = new THREE.Mesh(text3d, textMaterial);
320 text.position.x = plotBounds.minx/2 + centerOffset;
321 text.position.y = plotBounds.miny/2;
322 text.position.z = plotBounds.maxz/2 - centerOffset / 4;
323 scatterPlot.add(text);
324  
325 /* Add enclosing case. */
326 var enclosingCubeGeometry = enclosingCase(plotBounds.maxx);
327 enclosingCubeGeometry.computeLineDistances();
328 var enclosingCube =
329 new THREE.Line(
330 enclosingCubeGeometry,
331 new THREE.LineDashedMaterial(
332 {
333 color: 0xa6a6a6,
334 dashSize: 3,
335 gapSize: 1,
336 linewidth: 2
337 }
338 ),
339 THREE.LinePieces
340 );
341 scene.add(enclosingCube);
342  
343 // renderer
344 renderer = new THREE.WebGLRenderer(
345 {
346 antialias: true
347 }
348 );
349 renderer.setClearColor(0x1d475f, 1.0);
350 renderer.setPixelRatio(window.devicePixelRatio);
351 renderer.setSize(window.innerWidth, window.innerHeight);
352  
353 container = document.getElementById( 'container' );
354 container.appendChild( renderer.domElement );
355  
356 window.addEventListener('resize', onWindowResize, false );
357  
358 render();
359  
360 getAvatars();
361 getMapTexture();
362 getMapHeight();
363 getMapTerrain();
364 }
365  
366 function onWindowResize() {
367  
368 camera.aspect = window.innerWidth / window.innerHeight;
369 camera.updateProjectionMatrix();
370 renderer.setSize( window.innerWidth, window.innerHeight );
371 //controls.handleResize();
372 render();
373 }
374  
375 function animate() {
376 requestAnimationFrame(animate);
377 controls.update();
378 }
379  
380 function render() {
381 renderer.render(scene,camera);
382 }
383  
384 function enclosingCase(size) {
385 var h = size * 0.5;
386 var geometry = new THREE.Geometry();
387 geometry.vertices.push(
388 // Oz
389 //new THREE.Vector3( -h, -h, -h ),
390 //new THREE.Vector3( -h, h, -h ),
391  
392 new THREE.Vector3( -h, h, -h ),
393 new THREE.Vector3( h, h, -h ),
394  
395 new THREE.Vector3( h, h, -h ),
396 new THREE.Vector3( h, -h, -h ),
397  
398 // Ox
399 //new THREE.Vector3( h, -h, -h ),
400 //new THREE.Vector3( -h, -h, -h ),
401  
402 new THREE.Vector3( -h, -h, h ),
403 new THREE.Vector3( -h, h, h ),
404  
405 new THREE.Vector3( -h, h, h ),
406 new THREE.Vector3( h, h, h ),
407  
408 new THREE.Vector3( h, h, h ),
409 new THREE.Vector3( h, -h, h ),
410  
411 new THREE.Vector3( h, -h, h ),
412 new THREE.Vector3( -h, -h, h ),
413  
414 // Oy
415 //new THREE.Vector3( -h, -h, -h ),
416 //new THREE.Vector3( -h, -h, h ),
417  
418 new THREE.Vector3( -h, h, -h ),
419 new THREE.Vector3( -h, h, h ),
420  
421 new THREE.Vector3( h, h, -h ),
422 new THREE.Vector3( h, h, h ),
423  
424 new THREE.Vector3( h, -h, -h ),
425 new THREE.Vector3( h, -h, h )
426 );
427 return geometry;
428 }
429  
430 function makeTextSprite(message, parameters) {
431 if ( parameters === undefined ) parameters = {};
432  
433 var fontface = parameters.hasOwnProperty("fontface") ?
434 parameters["fontface"] :
435 "Computer Modern Typewriter";
436  
437 var fontsize = parameters.hasOwnProperty("fontsize") ?
438 parameters["fontsize"] :
439 18;
440  
441 var borderThickness =
442 parameters.hasOwnProperty("borderThickness") ?
443 parameters["borderThickness"] :
444 4;
445  
446 var borderColor =
447 parameters.hasOwnProperty("borderColor") ?
448 parameters["borderColor"] :
449 { r:0, g:0, b:0, a:1.0 };
450  
451 var backgroundColor =
452 parameters.hasOwnProperty("backgroundColor") ?
453 parameters["backgroundColor"] :
454 { r:255, g:255, b:255, a:1.0 };
455  
456 var canvas = document.createElement('canvas');
457 canvas.width = 162;
458 canvas.height = 64;
459 var context = canvas.getContext('2d');
460 context.font = "Bold " + fontsize + "px " + fontface;
461 context.imageSmoothingEnabled = true;
462  
463 // determine the longest line
464 var textLines = message.split("\n");
465 var longestLine = textLines[0].length;
466 var longestIndex = 0;
467 for(var i = 1; i <textLines.length; ++i) {
468 if(textLines[i].length > longestLine) {
469 longestLine = textLines[i].length;
470 longestIndex = i;
471 }
472 }
473  
474 // get size data (height depends only on font size)
475 var metrics = context.measureText(textLines[longestIndex]);
476 var textWidth = metrics.width;
477  
478 // background color
479 context.fillStyle =
480 "rgba(" +
481 backgroundColor.r +
482 "," +
483 backgroundColor.g +
484 "," +
485 backgroundColor.b +
486 "," +
487 backgroundColor.a +
488 ")";
489 // border color
490 context.strokeStyle =
491 "rgba(" +
492 borderColor.r +
493 "," +
494 borderColor.g +
495 "," +
496 borderColor.b +
497 "," +
498 borderColor.a +
499 ")";
500  
501 context.lineWidth = borderThickness;
502 roundRect(
503 context,
504 borderThickness/2,
505 borderThickness/2,
506 textWidth + borderThickness,
507 // 1.2 is extra height factor for text below baseline
508 textLines.length * fontsize * 1.2 + borderThickness,
509 6
510 );
511  
512 // add the text color
513 context.fillStyle =
514 "rgba(" +
515 borderColor.r +
516 "," +
517 borderColor.g +
518 "," +
519 borderColor.b +
520 "," +
521 borderColor.a +
522 ")";
523  
524 // add all the requested lines whist increasing lines
525 for(var i = 0; i< textLines.length; ++ i) {
526 context.fillText(
527 textLines[i],
528 borderThickness,
529 fontsize
530 );
531 fontsize += fontsize;
532 }
533  
534 // canvas contents will be used for a texture
535 var spriteTexture = new THREE.Texture(canvas,
536 THREE.UVMapping, // mapping
537 THREE.ClampToEdgeWrapping, // wrapS
538 THREE.ClampToEdgeWrapping, // wrapT
539 THREE.NearestFilter, // magfilter
540 THREE.NearestFilter, //minfilter,
541 THREE.RGBAFormat, // format
542 THREE.UnsignedByteType // type
543 )
544 spriteTexture.anisotropy = renderer.getMaxAnisotropy();
545 spriteTexture.needsUpdate = true;
546 var spriteMaterial = new THREE.SpriteMaterial(
547 {
548 map: spriteTexture,
549 useScreenCoordinates: false,
550 overdraw: false,
551 side:THREE.DoubleSide
552 }
553 );
554 var sprite = new THREE.Sprite(spriteMaterial);
555 sprite.scale.set(64,32, 1.0);
556 return sprite;
557 }
558  
559 // function for drawing rounded rectangles
560 function roundRect(ctx, x, y, w, h, r)
561 {
562 ctx.beginPath();
563 ctx.moveTo(x+r, y);
564 ctx.lineTo(x+w-r, y);
565 ctx.quadraticCurveTo(x+w, y, x+w, y+r);
566 ctx.lineTo(x+w, y+h-r);
567 ctx.quadraticCurveTo(x+w, y+h, x+w-r, y+h);
568 ctx.lineTo(x+r, y+h);
569 ctx.quadraticCurveTo(x, y+h, x, y+h-r);
570 ctx.lineTo(x, y+r);
571 ctx.quadraticCurveTo(x, y, x+r, y);
572 ctx.closePath();
573 ctx.fill();
574 ctx.stroke();
575 }
13 eva 576  
2 eva 577 /*************************************************************************/
578 /* Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 */
579 /*************************************************************************/
580 function wasMapValueToRange(value, xMin, xMax, yMin, yMax) {
581 return yMin + (
582 ( yMax - yMin ) * ( value - xMin ) / ( xMax - xMin )
583 );
584 }
585  
586 function updatePoints() {
587 /* Remove points. */
588 scatterPlot.remove(points);
589 /* Remove labels. */
590 for(i=0; i
591
592
593 * Remove projections. */
594 for(i=0; i
595
596
597  
598
599
600
601  
602
603
604
605
606 * For SecondLife the z and y axes must be swapped
607 in order to attain
608 for threejs.
609 /
610 var x = wasMapValueToRange(
611 csv.positions[i][1],
612 dataBounds.minx,
613 dataBounds.maxx,
614 plotBounds.minx/2,
615 /2
616 );
617 var y = wasMapValueToRange(
618 csv.positions[i][j],
619 dataBounds.minz,
620 dataBounds.maxz,
621 plotBounds.minz/2,
622 /2
623 );
624 var z = wasMapValueToRange(
625 csv.positions[i][0],
626 dataBounds.miny,
627 dataBounds.maxy,
628 plotBounds.miny/2,
629 /2
630 );
631  
632 // Add the points
633 pointGeo.vertices.push(
634 new THREE.Vector3(
635 x,
636 y + dotSize/4,
637
638
639
640  
641 // Add the color for the point.
642 var pointColor = new THREE.Color().setRGB(
643
644
645
646
647
648  
649 // Add the projection in plane xOy
650 var lineMaterial = new THREE.LineDashedMaterial(
651
652
653
654
655
656
657 var lineGeometry = new THREE.Geometry();
658
659 new THREE.Vector3(
660
661
662
663
664
665
666 new THREE.Vector3(
667
668 /2,
669 z
670 )
671 );
672 lineGeometry.computeLineDistances();
673 var xOyProjection = new THREE.Line(
674 lineGeometry,
675 lineMaterial,
676 THREE.LineStrip
677 );
678 avatarProjections.push(xOyProjection)
679 scatterPlot.add(xOyProjection);
680  
681 // Generate the label.
682 var sprite = makeTextSprite(
683 " " +
684 csv.names[i] +
685 " " +
686 "\n" +
687 " " +
688 "@" +
689 "<" +
690 <" + csv.positions[i][0] +
691 <" + "," +
692 <" + csv.positions[i][1] +
693 <" + "," +
694 <" + csv.positions[i][j] +
695 <" + ">" +
696 <" + " ",
697 <" + {
698 <" + "fontsize": 9,
699 <" + "backgroundColor":
700 <" + {r:255, g:255, b:255, a:1},
701 <" + "borderColor":
702 <" + {
703 <" + r:Math.round(wasMapValueToRange(
704 <" + csv.colors[i][0],
705 <" + 0,
706 <" + 1,
707 <" + 0,
708 <" + 255
709 <" + )),
710 <" + g:Math.round(wasMapValueToRange(
711 <" + csv.colors[i][1],
712 <" + 0,
713 <" + 1,
714 <" + 0,
715 <" + 255
716 <" + )),
717 <" + b:Math.round(wasMapValueToRange(
718 <" + csv.colors[i][2],
719 <" + 0,
720 <" + 1,
721 <" + 0,
722 <" + 255
723 <" + )),
724 <" + a:1
725 <" + },
726 <" + "borderThickness": 1
727 <" + }
728 <" + );
729  
730 <" + sprite.position.x = pointGeo.vertices[i].x;
731 <" + sprite.position.y = pointGeo.vertices[i].y;
732 <" + sprite.position.z = pointGeo.vertices[i].z;
733  
734 <" + avatarLabels.push(sprite);
735 <" + scatterPlot.add(sprite);
736  
737 <" + }
738 <" + }
739 <" + var pointCloudTexture = THREE.ImageUtils.loadTexture(
740 <" + "images/triangle.gif"
741 );
742 pointCloudTexture.anisotropy = renderer.getMaxAnisotropy();
743 var pointCloudMaterial = new THREE.PointCloudMaterial(
744 {
745 size: dotSize,
746 map: pointCloudTexture,
747 blending: THREE.NormalBlending, // required
748 depthTest: true, // required
749 transparent: true,
750 opacity: 1,
751 vertexColors: true // optional
752 });
753 //pointCloudTexture.needsUpdate = true;
754 points = new THREE.PointCloud(
755 pointGeo,
756 pointCloudMaterial
757 );
758 scatterPlot.add(points);
759 scatterPlot.needsUpdate = true;
760 }
761  
762 function updateMap() {
763 if(mapBumpData == null || mapImageData == null) return;
764  
765 scatterPlot.remove(mapMesh);
766 // texture used to generate "bumpiness"
767 var bumpTexture = new THREE.ImageUtils.loadTexture(
768 'data:image/png;base64,' + mapBumpData
769 );
770 bumpTexture.wrapS =
771 bumpTexture.wrapT =
772 THREE.RepeatWrapping;
773 bumpTexture.anisotropy = renderer.getMaxAnisotropy();
774 // magnitude of normal displacement
775 var bumpScale = mapHeight;
776  
777 var mapTexture = new THREE.ImageUtils.loadTexture(
778 'data:image/png;base64,' + mapImageData
779 );
780 mapTexture.anisotropy = renderer.getMaxAnisotropy();
781 mapTexture.wrapS = mapTexture.wrapT;
782  
783 // Create the uniforms.
784 this.customUniforms = {
785 bumpTexture: {
786 type: "t",
787 value: bumpTexture
788 },
789 bumpScale: {
790 type: "f",
791 value: bumpScale
792 },
793 mapTexture: {
794 type: "t",
795 value: mapTexture
796 },
797 };
798  
799 // create custom material from the shader code above
800 // that is within specially labelled script tags
801 var customMaterial =
802 new THREE.ShaderMaterial(
803 {
804 uniforms: customUniforms,
805 vertexShader: document.getElementById(
806 'terrainVertex'
807 ).textContent,
808 fragmentShader: document.getElementById(
809 'terrainFragment'
810 ).textContent,
811 side: THREE.DoubleSide
812 }
813 );
814  
815 var planeGeo = new THREE.PlaneBufferGeometry(
816 plotBounds.maxx,
817 plotBounds.maxy,
818 100,
819 100
820 );
821  
822 mapMesh = new THREE.Mesh(
823 planeGeo,
824 customMaterial
825 );
826 mapMesh.rotation.x = - Math.PI / 2;
827 mapMesh.rotation.z = - Math.PI / 2;
828 mapMesh.position.y = -plotBounds.maxy/2;
829 scatterPlot.add(mapMesh);
830 scatterPlot.needsUpdate = true;
831 }
832  
833 function getAvatars() {
834 $.ajax({
835 type: 'POST',
836 url: "getAvatars.php",
837 cache: false,
838 timeout: 60000
839 }).done(function(data) {
840 switch(data != null && data != "") {
841 case false:
842 setTimeout(getAvatars, 1000);
843 return;
844 }
845 var json = jQuery.parseJSON(data);
846 switch(JSON.stringify(json) != JSON.stringify(csv)) {
847 case true:
848 csv = json;
849 updatePoints();
850 render();
851 break;
852 }
853 setTimeout(getAvatars, avatarsFetchInterval);
854 }).error(function() {
855 setTimeout(getAvatars, 1000);
856 });
857 }
858  
859 function getMapTerrain() {
860 $.ajax({
861 type: 'POST',
862 url: "generateTerrainHeightMap.php",
863 cache: false,
864 timeout: 60000
865 }).done(function(data) {
866 // Only update if the data changed.
867 switch(data != null && data != '') {
868 case false:
869 setTimeout(getMapTerrain, 1000);
870 return;
871 }
872 switch(data != mapHeight) {
873 case true:
874 mapBumpData = data;
875 updateMap();
876 render();
877 break;
878 }
879 setTimeout(getMapTerrain, mapFetchInterval);
880 }).error(function() {
881 setTimeout(getMapTerrain, 1000);
882 });
883 }
884  
885 function getMapTexture() {
886 $.ajax({
887 type: 'POST',
888 url: "getMapTexture.php",
889 cache: false,
890 timeout: 60000
891 }).done(function(data) {
892 // Only update if the data changed.
893 switch(data != null && data != '') {
894 case false:
895 setTimeout(getMapTexture, 1000);
896 return;
897 }
898 switch(data != mapHeight) {
899 case true:
900 mapImageData = data;
901 updateMap();
902 render();
903 break;
904 }
905 setTimeout(getMapTexture, mapFetchInterval);
906 }).error(function() {
907 setTimeout(getMapTexture, 1000);
908 });
909 }
910  
911 function getMapHeight() {
912 $.ajax({
913 type: 'POST',
914 url: "getMapHeight.php",
915 cache: false,
916 timeout: 60000
917 }).done(function(data) {
918 // Only update if the data changed.
919 switch(data != null && data != '') {
920 case false:
921 setTimeout(getMapHeight, 1000);
922 return;
923 }
924 switch(data != mapHeight) {
925 case true:
926 mapHeight = data;
927 updateMap();
928 render();
929 break;
930 }
931 setTimeout(getMapHeight, mapFetchInterval);
932 }).error(function() {
933 setTimeout(getMapHeight, 1000);
934 });
935 }
936  
937 </script>
938  
939 </body>
940 </html>