corrade-http-templates – Blame information for rev 2

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