-
Notifications
You must be signed in to change notification settings - Fork 1
/
x3dom.js
2864 lines (2864 loc) · 549 KB
/
x3dom.js
1
2
3
4
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
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/** X3DOM Runtime, http://www.x3dom.org */
if(!Array.forEach){Array.forEach=function(array,fun,thisp){var len=array.length;for(var i=0;i<len;i++){if(i in array){fun.call(thisp,array[i],i,array);}}};}
if(!Array.map){Array.map=function(array,fun,thisp){var len=array.length;var res=[];for(var i=0;i<len;i++){if(i in array){res[i]=fun.call(thisp,array[i],i,array);}}
return res;};}
if(!Array.filter){Array.filter=function(array,fun,thisp){var len=array.length;var res=[];for(var i=0;i<len;i++){if(i in array){var val=array[i];if(fun.call(thisp,val,i,array)){res.push(val);}}}
return res;};}
var x3dom={canvases:[]};x3dom.x3dNS='http://www.web3d.org/specifications/x3d-namespace';x3dom.x3dextNS='http://philip.html5.org/x3d/ext';x3dom.xsltNS='http://www.w3.org/1999/XSL/x3dom.Transform';x3dom.xhtmlNS='http://www.w3.org/1999/xhtml';x3dom.nodeTypes={};x3dom.nodeTypesLC={};x3dom.components={};x3dom.geoCache=[];x3dom.caps={PLATFORM:navigator.platform,AGENT:navigator.userAgent};x3dom.registerNodeType=function(nodeTypeName,componentName,nodeDef){x3dom.debug.logInfo("Registering nodetype ["+nodeTypeName+"] in component ["+componentName+"]");if(x3dom.components[componentName]===undefined){x3dom.debug.logInfo("Adding new component ["+componentName+"]");x3dom.components[componentName]={};}
else{x3dom.debug.logInfo("Using component ["+componentName+"]");}
nodeDef._typeName=nodeTypeName;nodeDef._compName=componentName;x3dom.components[componentName][nodeTypeName]=nodeDef;x3dom.nodeTypes[nodeTypeName]=nodeDef;x3dom.nodeTypesLC[nodeTypeName.toLowerCase()]=nodeDef;};x3dom.isX3DElement=function(node){return(node.nodeType===Node.ELEMENT_NODE&&node.localName&&(x3dom.nodeTypes[node.localName]||x3dom.nodeTypesLC[node.localName.toLowerCase()]||node.localName.toLowerCase()==="x3d"||node.localName.toLowerCase()==="websg"||node.localName.toLowerCase()==="scene"||node.localName.toLowerCase()==="route"));};x3dom.extend=function(f){function g(){}
g.prototype=f.prototype||f;return new g();};x3dom.getStyle=function(oElm,strCssRule){var strValue;if(window&&window.getComputedStyle&&window.getComputedStyle(oElm,"")){strValue=window.getComputedStyle(oElm,"")[strCssRule];}
else if(oElm.currentStyle){strCssRule=strCssRule.replace(/\-(\w)/g,function(strMatch,p1){return p1.toUpperCase();});strValue=oElm.currentStyle[strCssRule];}
return strValue;};function defineClass(parent,ctor,methods){function inheritance(){}
if(parent){inheritance.prototype=parent.prototype;ctor.prototype=new inheritance();ctor.prototype.constructor=ctor;ctor.superClass=parent;}
if(methods){for(var m in methods){ctor.prototype[m]=methods[m];}}
return ctor;}
x3dom.isa=function(object,clazz){if(!object){return false;}
if(object.constructor===clazz){return true;}
if(object.constructor.superClass===undefined){return false;}
function f(c){if(c===clazz){return true;}
if(c.prototype&&c.prototype.constructor&&c.prototype.constructor.superClass){return f(c.prototype.constructor.superClass);}
return false;}
return f(object.constructor.superClass);};x3dom.getGlobal=function(){return(function(){return this;}).call(null);};x3dom.isNumber=function(n){return!isNaN(parseFloat(n))&&isFinite(n);};x3dom.loadJS=function(src,path_prefix,blocking){var blocking=(blocking===false)?blocking:true;if(blocking){var req;var url=(path_prefix)?path_prefix.trim()+src:src;if(window.XMLHttpRequest){req=new XMLHttpRequest();}else{req=new ActiveXObject("Microsoft.XMLHTTP");}
if(req){req.open("GET",url,false);req.send(null);eval(req.responseText);}}else{var head=document.getElementsByTagName('HEAD').item(0);var script=document.createElement("script");var loadpath=(path_prefix)?path_prefix.trim()+src:src;if(head){x3dom.debug.logError("Trying to load external JS file: "+loadpath);script.type="text/javascript";script.src=loadpath;head.appendChild(script,head.firstChild);}else{alert("No document object found. Can't load components");}}};function array_to_object(a){var o={};for(var i=0;i<a.length;i++){o[a[i]]='';}
return o;}
window.requestAnimFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(callback,element){window.setTimeout(callback,1000/60);};})();x3dom.debug={INFO:"INFO",WARNING:"WARNING",ERROR:"ERROR",EXCEPTION:"EXCEPTION",isActive:false,isFirebugAvailable:false,isSetup:false,isAppend:false,numLinesLogged:0,maxLinesToLog:100000,logContainer:null,setup:function(){if(x3dom.debug.isSetup){return;}
try{if(window.console.firebug!==undefined){x3dom.debug.isFirebugAvailable=true;}}
catch(err){x3dom.debug.isFirebugAvailable=false;}
x3dom.debug.setupLogContainer();x3dom.debug.isSetup=true;},activate:function(visible){x3dom.debug.isActive=true;x3dom.debug.logContainer.style.display=(visible)?"block":"none";if(!x3dom.debug.isAppend){if(navigator.appName=="Microsoft Internet Explorer"){x3dom.debug.logContainer.style.marginLeft="8px";document.documentElement.appendChild(x3dom.debug.logContainer);}else{document.body.appendChild(x3dom.debug.logContainer);}
x3dom.debug.isAppend=true;}},setupLogContainer:function(){x3dom.debug.logContainer=document.createElement("div");x3dom.debug.logContainer.id="x3dom_logdiv";x3dom.debug.logContainer.style.border="2px solid olivedrab";x3dom.debug.logContainer.style.height="200px";x3dom.debug.logContainer.style.padding="4px";x3dom.debug.logContainer.style.overflow="auto";x3dom.debug.logContainer.style.whiteSpace="pre-wrap";x3dom.debug.logContainer.style.fontFamily="sans-serif";x3dom.debug.logContainer.style.fontSize="x-small";x3dom.debug.logContainer.style.color="#00ff00";x3dom.debug.logContainer.style.backgroundColor="black";x3dom.debug.logContainer.style.clear="both";x3dom.debug.logContainer.style.marginRight="10px";},doLog:function(msg,logType){if(!x3dom.debug.isActive){return;}
if(x3dom.debug.numLinesLogged===x3dom.debug.maxLinesToLog){msg="Maximum number of log lines (="+x3dom.debug.maxLinesToLog+") reached. Deactivating logging...";}
if(x3dom.debug.numLinesLogged>x3dom.debug.maxLinesToLog){return;}
var node=document.createElement("p");node.style.margin=0;switch(logType){case x3dom.debug.INFO:node.style.color="#00ff00";break;case x3dom.debug.WARNING:node.style.color="#cd853f";break;case x3dom.debug.ERROR:node.style.color="#ff4500";break;case x3dom.debug.EXCEPTION:node.style.color="#ffff00";break;default:node.style.color="#00ff00";break;}
try{node.innerHTML=logType+": "+msg;x3dom.debug.logContainer.insertBefore(node,x3dom.debug.logContainer.firstChild);}catch(err){if(window.console.firebug!==undefined){window.console.warn(msg);}}
if(x3dom.debug.isFirebugAvailable){switch(logType){case x3dom.debug.INFO:window.console.info(msg);break;case x3dom.debug.WARNING:window.console.warn(msg);break;case x3dom.debug.ERROR:window.console.error(msg);break;case x3dom.debug.EXCEPTION:window.console.debug(msg);break;default:break;}}
x3dom.debug.numLinesLogged++;},logInfo:function(msg){x3dom.debug.doLog(msg,x3dom.debug.INFO);},logWarning:function(msg){x3dom.debug.doLog(msg,x3dom.debug.WARNING);},logError:function(msg){x3dom.debug.doLog(msg,x3dom.debug.ERROR);},logException:function(msg){x3dom.debug.doLog(msg,x3dom.debug.EXCEPTION);},assert:function(c,msg){if(!c){x3dom.debug.doLog("Assertion failed in "+
x3dom.debug.assert.caller.name+': '+
msg,x3dom.debug.ERROR);}},typeOf:function(obj){var type=typeof obj;return type==="object"&&!obj?"null":type;},exists:function(obj,name,type){type=type||"function";return(obj?this.typeOf(obj[name]):"null")===type;},dumpFields:function(node){var str="";for(var fName in node){str+=(fName+", ");}
str+='\n';x3dom.debug.logInfo(str);return str;}};x3dom.debug.setup();x3dom.ImageLoadManager={heap:[],complete:false,activeDownloads:0,push:function(tex){if(x3dom.caps.BACKEND=='webgl'){if(tex._vf.url[0]!=undefined){x3dom.debug.logInfo("[ImageLoadManager] Push image to queue: URL = "+tex._vf.url[0]+" | Priority = "+tex._vf.priority);x3dom.ImageLoadManager.heapUp(x3dom.ImageLoadManager.heap.push({priority:tex._vf.priority,image:tex._image,url:tex._vf.url[0]})-1);if(x3dom.ImageLoadManager.complete){x3dom.ImageLoadManager.complete=false;x3dom.ImageLoadManager.load();}}}},pop:function(){if(x3dom.ImageLoadManager.isEmpty()){}else{var result=x3dom.ImageLoadManager.heap[0];var tmp=x3dom.ImageLoadManager.heap.pop();if(x3dom.ImageLoadManager.heap.length>0){x3dom.ImageLoadManager.heap[0]=tmp;x3dom.ImageLoadManager.heapDown(0);}
return result;}},load:function(){if(x3dom.caps.BACKEND=='webgl'){x3dom.debug.logInfo("[ImageLoadManager] Start loading...");while(!x3dom.ImageLoadManager.isEmpty()){var item=x3dom.ImageLoadManager.pop();item.image.crossOrigin='';item.image.src=item.url;item.image.onload=x3dom.ImageLoadManager.onLoadFnc;x3dom.ImageLoadManager.activeDownloads++;}
x3dom.ImageLoadManager.complete=true;}},onLoadFnc:function(evt){var event=document.createEvent("HTMLEvents");event.initEvent('ImageLoadManager_Load',true,true);this.dispatchEvent(event);},getLeftChildIndex:function(nodeIndex){return parseInt(2*nodeIndex+1);},getRightChildIndex:function(nodeIndex){return parseInt(2*nodeIndex+2);},getParentIndex:function(nodeIndex){return parseInt((nodeIndex-1)/2);},heapUp:function(nodeIndex){var parentIndex,tmp;if(nodeIndex!=0){parentIndex=x3dom.ImageLoadManager.getParentIndex(nodeIndex);if(x3dom.ImageLoadManager.heap[parentIndex].priority>x3dom.ImageLoadManager.heap[nodeIndex].priority){tmp=x3dom.ImageLoadManager.heap[parentIndex];x3dom.ImageLoadManager.heap[parentIndex]=x3dom.ImageLoadManager.heap[nodeIndex];x3dom.ImageLoadManager.heap[nodeIndex]=tmp;x3dom.ImageLoadManager.heapUp(parentIndex);}}},heapDown:function(nodeIndex){var leftChildIndex,rightChildIndex,minIndex,tmp;leftChildIndex=x3dom.ImageLoadManager.getLeftChildIndex(nodeIndex);rightChildIndex=x3dom.ImageLoadManager.getRightChildIndex(nodeIndex);if(rightChildIndex>=x3dom.ImageLoadManager.heap.length){if(leftChildIndex>=x3dom.ImageLoadManager.heap.length)
return;else
minIndex=leftChildIndex;}else{if(x3dom.ImageLoadManager.heap[leftChildIndex].priority<=x3dom.ImageLoadManager.heap[rightChildIndex].priority)
minIndex=leftChildIndex;else
minIndex=rightChildIndex;}
if(x3dom.ImageLoadManager.heap[nodeIndex].priority>x3dom.ImageLoadManager.heap[minIndex].priority){tmp=x3dom.ImageLoadManager.heap[minIndex];x3dom.ImageLoadManager.heap[minIndex]=x3dom.ImageLoadManager.heap[nodeIndex];x3dom.ImageLoadManager.heap[nodeIndex]=tmp;x3dom.ImageLoadManager.heapDown(minIndex);}},isEmpty:function(){return(x3dom.ImageLoadManager.heap.length==0);},toString:function(){var string="ImageLoadManager("+x3dom.ImageLoadManager.heap.length+") [";for(var i=0;i<x3dom.ImageLoadManager.heap.length;i++){if(i!=0)string+=", ";string+=x3dom.ImageLoadManager.heap[i].priority+" - "+x3dom.ImageLoadManager.heap[i].url;}
string+="]";return string;},length:function(){return x3dom.ImageLoadManager.heap.length;}};var Request=function(url,onloadCallback,priority){this.url=url;this.priority=priority;this.xhr=new XMLHttpRequest();this.onloadCallbacks=[onloadCallback];var self=this;this.xhr.onload=function(){if(x3dom.DownloadManager.debugOutput){x3dom.debug.logInfo('Download manager received data for URL \''+self.url+'\'.');}
--x3dom.DownloadManager.activeDownloads;if((x3dom.DownloadManager.stallToKeepOrder===false)||(x3dom.DownloadManager.resultGetsStalled(self.priority)===false)){var i;for(i=0;i<self.onloadCallbacks.length;++i){self.onloadCallbacks[i](self.xhr.response);}
x3dom.DownloadManager.removeDownload(self);x3dom.DownloadManager.updateStalledResults();}
else if(x3dom.DownloadManager.debugOutput){x3dom.debug.logInfo('Download manager stalled downloaded result for URL \''+self.url+'\'.');}
x3dom.DownloadManager.tryNextDownload();};};Request.prototype.send=function(){this.xhr.open('GET',encodeURI(this.url),true);this.xhr.responseType='arraybuffer';this.xhr.send(null);if(x3dom.DownloadManager.debugOutput){x3dom.debug.logInfo('Download manager posted XHR for URL \''+this.url+'\'.');}};x3dom.DownloadManager={requests:[],maxDownloads:6,activeDownloads:0,debugOutput:false,stallToKeepOrder:false,toggleDebugOutput:function(flag){this.debugOutput=flag;},toggleStrictReturnOrder:function(flag){this.stallToKeepOrder=flag;},removeDownload:function(req){var i,j;var done=false;for(i=0;i<this.requests.length&&!done;++i){if(this.requests[i]){for(j=0;j<this.requests[i].length;++j){if(this.requests[i][j]===req){this.requests[i].splice(j,1);done=true;break;}}}}},tryNextDownload:function(){var firstRequest;var i,j;if(this.activeDownloads<this.maxDownloads){for(i=0;i<this.requests.length&&!firstRequest;++i){if(this.requests[i]){for(j=0;j<this.requests[i].length;++j){if(this.requests[i][j].xhr.readyState===XMLHttpRequest.UNSENT){firstRequest=this.requests[i][j];break;}}}}
if(firstRequest){firstRequest.send();++this.activeDownloads;}}},resultGetsStalled:function(priority){var i;for(i=0;i<priority;++i){if(this.requests[i]&&this.requests[i].length){return true;}}
return false;},updateStalledResults:function(){if(x3dom.DownloadManager.stallToKeepOrder){var i,j,k;var req,pendingRequestFound=false;for(i=0;i<this.requests.length&&!pendingRequestFound;++i){if(this.requests[i]){for(j=0;j<this.requests[i].length;++j){req=this.requests[i][j];if(req.xhr.readyState===XMLHttpRequest.DONE){if(x3dom.DownloadManager.debugOutput){x3dom.debug.logInfo('Download manager releases stalled result for URL \''+req.url+'\'.');}
for(k=0;k<req.onloadCallbacks.length;++k){req.onloadCallbacks[k](req.xhr.response);}
this.requests[i].splice(j,1);}
else{pendingRequestFound=true;}}}}}},get:function(urls,onloadCallbacks,priorities){var i,j,k;var found=false;var url,onloadCallback,priority;if(urls.length!==onloadCallbacks.length||urls.length!==priorities.length)
{x3dom.debug.logError('DownloadManager: The number of given urls, onload callbacks and priorities is not equal. Ignoring requests.');return;}
for(k=0;k<urls.length;++k){if(!onloadCallbacks[k]===undefined||!priorities[k]===undefined){x3dom.debug.logError('DownloadManager: No onload callback and / or priority specified. Ignoring request for \"'+url+'\"');continue;}
else{url=urls[k];onloadCallback=onloadCallbacks[k];priority=priorities[k];for(i=0;i<this.requests.length&&!found;++i){if(this.requests[i]){for(j=0;j<this.requests[i].length;++j){if(this.requests[i][j].url===url){this.requests[i][j].onloadCallbacks.push(onloadCallback);if(x3dom.DownloadManager.debugOutput){x3dom.debug.logInfo('Download manager appended onload callback for URL \''+url+'\' to a running request using the same URL.');}
found=true;break;}}}}
if(!found){var r=new Request(url,onloadCallback,priority);if(this.requests[priority]){this.requests[priority].push(r);}
else{this.requests[priority]=[r];}}}}
while(this.activeDownloads<this.maxDownloads){this.tryNextDownload();}}};x3dom.BitLODComposer=function(){var self=this;if(typeof Worker!=='undefined'){this.worker=new Worker(new x3dom.BitLODWorker().toBlob());this.worker.postMessage=this.worker.webkitPostMessage||this.worker.postMessage;this.worker.addEventListener('message',function(event){return self.messageFromWorker(event);},false);}
else if(!x3dom.BitLODComposer.suppressOnWorkersNotSupported){x3dom.BitLODComposer.suppressOnWorkersNotSupported();x3dom.BitLODComposer.suppressOnWorkersNotSupported=true;}
this.refinementCallback={};this.useDebugOutput=false;};x3dom.BitLODComposer.suppressOnTransferablesNotSupported=false;x3dom.BitLODComposer.suppressOnWorkersNotSupported=false;x3dom.BitLODComposer.onTransferablesNotSupported=function(){alert('Your browser does not support transferables.\n'+'This application might run slower than expected due to data cloning operations.');};x3dom.BitLODComposer.suppressOnWorkersNotSupported=function(){alert('WebWorkers are not supported by your browser. Unable to run BitLODComposer.');};x3dom.BitLODComposer.prototype.toggleDebugOutput=function(flag){this.useDebugOutput=flag;};x3dom.BitLODComposer.prototype.messageFromWorker=function(event){if(event.data.msg){if(event.data.msg=='log'){x3dom.debug.logInfo('Message from WebWorker context: '+event.data.text);}
else if(event.data.msg=='workerSetUp'){var timerDisplay=document.getElementById('workerTimerElement');if(timerDisplay&&(typeof loadingTimer!=='undefined')){timerDisplay.textContent='Worker set up after '+(event.data.timestamp-loadingTimer)+' ms';}}
else if(event.data.msg=='decodeTime'){x3dom.debug.logInfo('Worker needed '+event.data.time+' ms to do the job.');if(typeof UpdateDecode!=='undefined'){UpdateDecode(event.data.time);}}}
else{this.refinementCallback(event.data);}}
x3dom.BitLODComposer.prototype.run=function(numAttributeComponents,numAttributeBitsPerComponent,numAttributeBitsPerLevel,refinementDataURLs,refinementCallback,attributeWriteOffset,strideWriting){var attributeReadOffset=[];var i,off;var refinementBuffers;var self=this;var downloadCallbacks,downloadPriorities;if(numAttributeBitsPerComponent.length>0&&numAttributeBitsPerComponent.length===numAttributeComponents.length&&numAttributeBitsPerComponent.length===numAttributeBitsPerLevel.length){this.refinementCallback=refinementCallback;off=0;for(i=0;i<numAttributeBitsPerComponent.length;++i){attributeReadOffset[i]=off;off+=numAttributeBitsPerLevel[i];}
var testChunk=new ArrayBuffer(1);this.worker.postMessage({cmd:'setAttributes',numAttributeComponents:numAttributeComponents,numAttributeBitsPerComponent:numAttributeBitsPerComponent,numAttributeBitsPerLevel:numAttributeBitsPerLevel,attributeReadOffset:attributeReadOffset,attributeWriteOffset:attributeWriteOffset,strideWriting:strideWriting,testChunk:testChunk},[testChunk]);if(testChunk.byteLength>0&&!x3dom.BitLODComposer.suppressOnTransferablesNotSupported){x3dom.BitLODComposer.onTransferablesNotSupported();x3dom.BitLODComposer.suppressOnTransferablesNotSupported=true;}
downloadCallbacks=[];downloadPriorities=[];for(i=0;i<refinementDataURLs.length;++i){downloadPriorities[i]=i;(function(idx){downloadCallbacks[i]=function(arrayBuffer){self.refinementDataLoaded(arrayBuffer,idx);};})(i);}
x3dom.DownloadManager.toggleStrictReturnOrder(true);x3dom.DownloadManager.get(refinementDataURLs,downloadCallbacks,downloadPriorities);}else{x3dom.debug.logError('Unable to initialize bit composer: the given attribute parameter arrays are not of the same length.');}
this.refine(new ArrayBuffer(0));};x3dom.BitLODComposer.prototype.refine=function(attributeArrayBuffer){this.worker.postMessage(attributeArrayBuffer,[attributeArrayBuffer]);};x3dom.BitLODComposer.prototype.refinementDataLoaded=function(arrayBuffer,l){this.worker.postMessage({buffer:arrayBuffer,level:l},[arrayBuffer]);}
URL=(typeof URL!=='undefined')?URL:(typeof webkitURL!=='undefined')?webkitURL:undefined;x3dom.BitLODWorker=function()
{this.attribArrays=[];this.refinementBufferViews=[];this.strideReading=0;this.globalStrideWriting=0;this.refinementDataURLs=0;this.availableRefinementLevels=[];this.refinementsDone=0;this.requestedRefinements=0;};x3dom.BitLODWorker.prototype.refineAttributeData=function(level)
{var start=Date.now();var refinementBufferView=refinementBufferViews[level];var i,c,nc,attrib,attributeLeftShift;var dataChunk;var m=attribArrays.length;for(i=0;i<m;++i){attrib=attribArrays[i];nc=attrib.numComponents;attributeLeftShift=(strideReading*8)-attrib.readOffset-attrib.numBitsPerComponentPerLevel*nc;attrib.precisionOffset=attrib.numBitsPerComponent-attrib.numBitsPerComponentPerLevel-
(level*attrib.numBitsPerComponentPerLevel);for(c=0;c<nc;++c){attrib.componentLeftShift[c]=attributeLeftShift+(nc-c-1)*attrib.numBitsPerComponentPerLevel;attrib.componentMask[c]=0|(Math.pow(2,attrib.numBitsPerComponentPerLevel)-1);attrib.componentMask[c]<<=attrib.componentLeftShift[c];}}
var n=refinementBufferView.length;var writeTarget,baseIdx,idx;var component;attrib=attribArrays[0];nc=attrib.numComponents;writeTarget=attrib.bufferView;baseIdx=0;for(i=0;i<n;++i){dataChunk=refinementBufferView[i];for(c=0;c<nc;++c){component=dataChunk&attrib.componentMask[c];component>>>=attrib.componentLeftShift[c];component<<=attrib.precisionOffset;idx=baseIdx+c;writeTarget[idx]|=component;}
baseIdx+=attrib.strideWriting;}
attrib=attribArrays[1];nc=attrib.numComponents;writeTarget=attrib.bufferView;baseIdx=0;for(i=0;i<n;++i){dataChunk=refinementBufferView[i];for(c=0;c<nc;++c){component=dataChunk&attrib.componentMask[c];component>>>=attrib.componentLeftShift[c];component<<=attrib.precisionOffset;idx=baseIdx+c;writeTarget[idx]|=component;}
baseIdx+=attrib.strideWriting;}
postMessage({msg:'decodeTime',time:(Date.now()-start)});postMessage(attribArrays[0].bufferView.buffer,[attribArrays[0].bufferView.buffer]);++refinementsDone;};x3dom.BitLODWorker.prototype.onmessage=function(event){var i,j;var numBitsPerElement;if(event.data.cmd!==undefined){if(event.data.cmd==='setAttributes'){if(!refinementsDone){postMessage({msg:'workerSetUp',timestamp:Date.now()});}
for(i=0;i<event.data.numAttributeComponents.length;++i){attribArrays[i]=new AttributeArray(event.data.numAttributeComponents[i],event.data.numAttributeBitsPerComponent[i],event.data.numAttributeBitsPerLevel[i]/event.data.numAttributeComponents[i],event.data.attributeReadOffset[i]);strideReading+=event.data.numAttributeBitsPerLevel[i];if(event.data.attributeWriteOffset&&event.data.strideWriting){attribArrays[i].writeOffset=event.data.attributeWriteOffset[i];attribArrays[i].strideWriting=(event.data.strideWriting/attribArrays[i].numBitsPerComponent);}}
globalStrideWriting=event.data.strideWriting;strideReading=Math.ceil(strideReading/8);}}
else{if(event.data.level!==undefined){refinementDataLoaded(event.data.buffer,event.data.level);}
else{++requestedRefinements;if(refinementsDone){for(i=0;i<attribArrays.length;++i){var ArrayType;switch(attribArrays[i].numBitsPerComponent){case 32:ArrayType=Uint32Array;break;case 16:ArrayType=Uint16Array;break;case 8:ArrayType=Uint8Array;break;default:postMessage({msg:'log',text:'Unable to start refinement: no valid value ('+attribArrays[i].numBitsPerComponent+' instead of 1, 2 or 4) set for bytesPerComponent of attribute array '+i+'.'});}
attribArrays[i].bufferView=new ArrayType(event.data,(attribArrays[i].writeOffset/8));}}
tryNextRefinement();}}};x3dom.BitLODWorker.prototype.refinementDataLoaded=function(buffer,l){var i;switch(strideReading){case 4:refinementBufferViews[l]=new Uint32Array(buffer);break;case 2:refinementBufferViews[l]=new Uint16Array(buffer);break;case 1:refinementBufferViews[l]=new Uint8Array(buffer);break;default:postMessage({msg:'log',text:'Unable to start refinement: no valid value ('+attribArrays[i].numBitsPerComponent+' instead of 1, 2 or 4) set for bytesPerComponent of attribute array '+i+'.'});}
availableRefinementLevels.push(l);availableRefinementLevels.sort(function(a,b){return a-b;});if(!refinementsDone){for(i=0;i<attribArrays.length;++i){if(i===0){attributeArrayBuffer=new ArrayBuffer((globalStrideWriting/8)*refinementBufferViews[l].length);}
else{attributeArrayBuffer=attribArrays[0].bufferView.buffer;}
var ArrayType;switch(attribArrays[i].numBitsPerComponent){case 32:ArrayType=Uint32Array;break;case 16:ArrayType=Uint16Array;break;case 8:ArrayType=Uint8Array;break;default:postMessage({msg:'log',text:'Unable to start refinement: no valid value ('+attribArrays[i].numBitsPerComponent+' instead of 1, 2 or 4) set for bytesPerComponent of attribute array '+i+'.'});}
attribArrays[i].bufferView=new ArrayType(attributeArrayBuffer,(attribArrays[i].writeOffset/8));}}
tryNextRefinement();};x3dom.BitLODWorker.prototype.tryNextRefinement=function(){var nextLevel;if(requestedRefinements&&availableRefinementLevels.length){nextLevel=availableRefinementLevels.shift();--requestedRefinements;refineAttributeData(nextLevel);}};x3dom.BitLODWorker.prototype.AttributeArray=function(numComponents,numBitsPerComponent,numBitsPerComponentPerLevel,readOffset){this.numComponents=numComponents;this.numBitsPerComponent=numBitsPerComponent;this.strideWriting=numComponents;this.numBitsPerComponentPerLevel=numBitsPerComponentPerLevel;this.readOffset=readOffset;this.componentMask=[];this.componentLeftShift=[];this.precisionOffset=0;this.bufferView={};};x3dom.BitLODWorker.prototype.toBlob=function()
{var str='';str+='postMessage = (typeof webkitPostMessage !== "undefined") ? webkitPostMessage : postMessage;\n';for(var p in this)
{if(this[p]!=x3dom.BitLODWorker.prototype.toBlob)
{str+=p+' = ';if(this[p]instanceof String)
{str+='"'+this[p]+'"';}
else if(this[p]instanceof Array)
{str+="[];\n";}
else
{str+=this[p]+';\n';}}}
var blob=new Blob([str]);return URL.createObjectURL(blob);};x3dom.Properties=function(){this.properties={};};x3dom.Properties.prototype.setProperty=function(name,value){x3dom.debug.logInfo("Properties: Setting property '"+name+"' to value '"+value+"'");this.properties[name]=value;};x3dom.Properties.prototype.getProperty=function(name,def){if(this.properties[name]){return this.properties[name]}else{return def;}};x3dom.Properties.prototype.merge=function(other){for(var attrname in other.properties){this.properties[attrname]=other.properties[attrname];}};x3dom.Properties.prototype.toString=function(){var str="";for(var name in this.properties){str+="Name: "+name+" Value: "+this.properties[name]+"\n";}
return str;};x3dom.DoublyLinkedList=function(){this.length=0;this.first=null;this.last=null;};x3dom.DoublyLinkedList.ListNode=function(point,point_index,normals,colors,texCoords){this.point=point;this.point_index=point_index;this.normals=normals;this.colors=colors;this.texCoords=texCoords;this.next=null;this.prev=null;};x3dom.DoublyLinkedList.prototype.appendNode=function(node){if(this.first===null){node.prev=node;node.next=node;this.first=node;this.last=node;}else{node.prev=this.last;node.next=this.first;this.first.prev=node;this.last.next=node;this.last=node;}
this.length++;};x3dom.DoublyLinkedList.prototype.insertAfterNode=function(node,newNode){newNode.prev=node;newNode.next=node.next;node.next.prev=newNode;node.next=newNode;if(newNode.prev==this.last){this.last=newNode;}
this.length++;};x3dom.DoublyLinkedList.prototype.deleteNode=function(node){if(this.length>1){node.prev.next=node.next;node.next.prev=node.prev;if(node==this.first){this.first=node.next;}
if(node==this.last){this.last=node.prev;}}else{this.first=null;this.last=null;}
node.prev=null;node.next=null;this.length--;};x3dom.DoublyLinkedList.prototype.getNode=function(index){var node=null;if(index>this.length){return node;}
for(var i=0;i<this.length;i++){if(i==0){node=this.first;}else{node=node.next;}
if(i==index){return node;}}};x3dom.DoublyLinkedList.prototype.invert=function(){var node=null;var tmp=null;node=this.first;for(var i=0;i<this.length;i++){tmp=node.prev;node.prev=node.next;node.next=tmp;node=node.prev;}
tmp=this.first;this.first=this.last;this.last=tmp;};x3dom.EarClipping={reversePointDirection:function(linklist,plane){var l,k;var count=0;var z;var nodei,nodel,nodek;if(linklist.length<3){return false;}
for(var i=0;i<linklist.length;i++){l=(i+1)%linklist.length;k=(i+2)%linklist.length;nodei=linklist.getNode(i);nodel=linklist.getNode(l);nodek=linklist.getNode(k);if(plane=='YZ'){z=(nodel.point.y-nodei.point.y)*(nodek.point.z-nodel.point.z);z-=(nodel.point.z-nodei.point.z)*(nodek.point.y-nodel.point.y);}else if(plane=='XZ'){z=(nodel.point.z-nodei.point.z)*(nodek.point.x-nodel.point.x);z-=(nodel.point.x-nodei.point.x)*(nodek.point.z-nodel.point.z);}else{z=(nodel.point.x-nodei.point.x)*(nodek.point.y-nodel.point.y);z-=(nodel.point.y-nodei.point.y)*(nodek.point.x-nodel.point.x);}
if(z<0){count--;}else if(z>0){count++;}}
if(count<0){linklist.invert();return true;}
return false;},getIndexes:function(linklist){var node=linklist.first.next;var plane=this.identifyPlane(node.prev.point,node.point,node.next.point);var invers=this.reversePointDirection(linklist,plane);var indexes=[];node=linklist.first.next;var next=null;var count=0;var isEar=true;while(linklist.length>=3&&count<15){next=node.next;for(var i=0;i<linklist.length;i++){if(this.isNotEar(linklist.getNode(i).point,node.prev.point,node.point,node.next.point,plane)){isEar=false;}}
if(isEar){if(this.isKonvex(node.prev.point,node.point,node.next.point,plane)){indexes.push(node.prev.point_index,node.point_index,node.next.point_index);linklist.deleteNode(node);}else{count++;}}
node=next;isEar=true;}
if(invers){return indexes.reverse();}else{return indexes;}},getMultiIndexes:function(linklist){var node=linklist.first.next;var plane=this.identifyPlane(node.prev.point,node.point,node.next.point);var invers=this.reversePointDirection(linklist,plane);var data=new Object();data.indices=[];data.point=[];data.normals=[];data.colors=[];data.texCoords=[];node=linklist.first.next;var next=null;var count=0;var isEar=true;while(linklist.length>=3&&count<15){next=node.next;for(var i=0;i<linklist.length;i++){if(this.isNotEar(linklist.getNode(i).point,node.prev.point,node.point,node.next.point,plane)){isEar=false;}}
if(isEar){if(this.isKonvex(node.prev.point,node.point,node.next.point,plane)){data.indices.push(node.prev.point_index,node.point_index,node.next.point_index);data.point.push(node.prev.point,node.point,node.next.point);if(node.normals){data.normals.push(node.prev.normals,node.normals,node.next.normals);}
if(node.colors){data.colors.push(node.prev.colors,node.colors,node.next.colors);}
if(node.texCoords){data.texCoords.push(node.prev.texCoords,node.texCoords,node.next.texCoords);}
linklist.deleteNode(node);}else{count++;}}
node=next;isEar=true;}
if(invers){data.indices=data.indices.reverse();data.point=data.point.reverse();data.normals=data.normals.reverse();data.colors=data.colors.reverse();data.texCoords=data.texCoords.reverse();return data;}else{return data;}},isNotEar:function(ap1,tp1,tp2,tp3,plane){var b0,b1,b2,b3;var ap1a,ap1b,tp1a,tp1b,tp2a,tp2b,tp3a,tp3b;if(plane=='YZ'){ap1a=ap1.y,ap1b=ap1.z;tp1a=tp1.y,tp1b=tp1.z;tp2a=tp2.y,tp2b=tp2.z;tp3a=tp3.y,tp3b=tp3.z;}else if(plane=='XZ'){ap1a=ap1.z,ap1b=ap1.x;tp1a=tp1.z,tp1b=tp1.x;tp2a=tp2.z,tp2b=tp2.x;tp3a=tp3.z,tp3b=tp3.x;}else{ap1a=ap1.x,ap1b=ap1.y;tp1a=tp1.x,tp1b=tp1.y;tp2a=tp2.x,tp2b=tp2.y;tp3a=tp3.x,tp3b=tp3.y;}
b0=((tp2a-tp1a)*(tp3b-tp1b)-(tp3a-tp1a)*(tp2b-tp1b));if(b0!=0){b1=(((tp2a-ap1a)*(tp3b-ap1b)-(tp3a-ap1a)*(tp2b-ap1b))/b0);b2=(((tp3a-ap1a)*(tp1b-ap1b)-(tp1a-ap1a)*(tp3b-ap1b))/b0);b3=1-b1-b2;return((b1>0)&&(b2>0)&&(b3>0));}
else{return false;}},isKonvex:function(p,p1,p2,plane){var pa,pb,p1a,p1b,p2a,p2b;if(plane=='YZ'){pa=p.y,pb=p.z;p1a=p1.y,p1b=p1.z;p2a=p2.y,p2b=p2.z;}else if(plane=='XZ'){pa=p.z,pb=p.x;p1a=p1.z,p1b=p1.x;p2a=p2.z,p2b=p2.x;}else{pa=p.x,pb=p.y;p1a=p1.x,p1b=p1.y;p2a=p2.x,p2b=p2.y;}
var l=((p1a-pa)*(p2b-pb)-(p1b-pb)*(p2a-pa));if(l<0){return false;}else{return true;}},identifyPlane:function(p1,p2,p3){var v1x,v1y,v1z;var v2x,v2y,v2z;var v3x,v3y,v3z;v1x=p2.x-p1.x,v1y=p2.y-p1.y,v1z=p2.z-p1.z;v2x=p3.x-p1.x,v2y=p3.y-p1.y,v2z=p3.z-p1.z;v3x=v1y*v2z-v1z*v2y;v3y=v1z*v2x-v1x*v2z;v3z=v1x*v2y-v1y*v2x;var angle=Math.max(Math.abs(v3x),Math.abs(v3y),Math.abs(v3z));if(angle==Math.abs(v3x)){return'YZ';}else if(angle==Math.abs(v3y)){return'XZ';}else if(angle==Math.abs(v3z)){return'XY';}else{return'fehler';}}};x3dom.X3DCanvas=function(x3dElem,canvasIdx){var that=this;this.canvasIdx=canvasIdx;this.initContext=function(canvas){x3dom.debug.logInfo("Initializing X3DCanvas for ["+canvas.id+"]");var gl=x3dom.gfx_webgl(canvas);if(!gl){x3dom.debug.logError("No 3D context found...");this.x3dElem.removeChild(canvas);return null;}
return gl;};this.initFlashContext=function(object){x3dom.debug.logInfo("Initializing X3DObject for ["+object.id+"]");var gl=x3dom.gfx_flash(object);return gl;};this.appendParam=function(node,name,value){var param=document.createElement('param');param.setAttribute('name',name);param.setAttribute('value',value);node.appendChild(param);};this.detectFlash=function(required,max)
{var required_version=required;var max_version=max;var available_version=0;if(typeof(navigator.plugins["Shockwave Flash"])=="object")
{var description=navigator.plugins["Shockwave Flash"].description;available_version=description.substr(16,(description.indexOf(".",16)-16));}
else if(typeof(ActiveXObject)=="function"){for(var i=10;i<(max_version+1);i++){try{if(typeof(new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i))=="object"){available_version=i+1;}}
catch(error){}}}
return[available_version,required_version];};this.createInitFailedDiv=function(x3dElem){var div=document.createElement('div');div.style.width=x3dElem.getAttribute("width");;div.style.height=x3dElem.getAttribute("height");;div.style.backgroundColor="#C00";div.style.color="#FFF";div.style.fontSize="20px";div.style.fontWidth="bold";div.style.padding="10px 10px 10px 10px";div.style.display="inline-block";div.style.fontFamily="Helvetica";div.style.textAlign="center";div.appendChild(document.createTextNode('Your Browser does not support X3DOM'));div.appendChild(document.createElement('br'));div.appendChild(document.createTextNode('Read more about Browser support on:'));div.appendChild(document.createElement('br'));var link=document.createElement('a');link.setAttribute('href','http://www.x3dom.org/?page_id=9');link.appendChild(document.createTextNode('X3DOM | Browser Support'));div.appendChild(link);x3dElem.appendChild(div);x3dom.debug.logError("Your Browser does not support X3DOM!");}
this.createFlashObject=function(x3dElem){var result=this.detectFlash(11,11);if(!result[0]||result[0]<result[1]){return null;}else{x3dom.debug.logInfo("Creating FlashObject for (X)3D element...");var id=x3dElem.getAttribute("id");if(id!==null){id="x3dom-"+id+"-object";}else{var index=new Date().getTime();id="x3dom-"+index+"-object";}
var swf_path=x3dElem.getAttribute("swfpath");if(swf_path===null){swf_path="x3dom.swf";}
var width=x3dElem.getAttribute("width");if(width==null){width=550;}else{var idx=width.indexOf("px");if(idx!=-1){width=width.substr(0,idx);}}
var height=x3dElem.getAttribute("height");if(height==null){height=400;}else{var idx=height.indexOf("px");if(idx!=-1){height=height.substr(0,idx);}}
var obj=document.createElement('object');obj.setAttribute('width',width);obj.setAttribute('height',height);obj.setAttribute('id',id);this.appendParam(obj,'menu','false');this.appendParam(obj,'quality','high');this.appendParam(obj,'wmode','gpu');this.appendParam(obj,'allowScriptAccess','always');this.appendParam(obj,'flashvars','width='+width+'&height='+height+'&canvasIdx='+this.canvasIdx);this.appendParam(obj,'movie',swf_path);x3dElem.appendChild(obj);if(navigator.appName=="Microsoft Internet Explorer")
obj.setAttribute('classid','clsid:d27cdb6e-ae6d-11cf-96b8-444553540000');else{obj.setAttribute('type','application/x-shockwave-flash');obj.setAttribute('data',swf_path);}
return obj;}};this.createHTMLCanvas=function(x3dElem)
{x3dom.debug.logInfo("Creating canvas for (X)3D element...");var canvas=document.createElement('canvas');canvas.setAttribute("class","x3dom-canvas");var userStyle=x3dElem.getAttribute("style");if(userStyle){x3dom.debug.logInfo("Inline X3D styles detected");}
var evtArr=["onmousedown","onmousemove","onmouseout","onmouseover","onmouseup","onclick","ondblclick","onkeydown","onkeypress","onkeyup","ontouchstart","ontouchmove","ontouchend","ontouchcancel","ontouchleave","ontouchenter","ongesturestart","ongesturechange","ongestureend","MozTouchDown","MozTouchMove","MozTouchUp"];for(var i=0;i<evtArr.length;i++)
{var evtName=evtArr[i];var userEvt=x3dElem.getAttribute(evtName);if(userEvt){x3dom.debug.logInfo(evtName+", "+userEvt);canvas.setAttribute(evtName,userEvt);}}
if(!x3dElem.__addEventListener&&!x3dElem.__removeEventListener)
{x3dElem.__addEventListener=x3dElem.addEventListener;x3dElem.__removeEventListener=x3dElem.removeEventListener;x3dElem.addEventListener=function(type,func,phase){var j,found=false;for(j=0;j<evtArr.length&&!found;j++){if(evtArr[j]===type){found=true;}}
if(found){x3dom.debug.logInfo('addEventListener for div.on'+type);that.canvas.addEventListener(type,func,phase);}else{x3dom.debug.logInfo('addEventListener for X3D.on'+type);this.__addEventListener(type,func,phase);}};x3dElem.removeEventListener=function(type,func,phase){var j,found=false;for(j=0;j<evtArr.length&&!found;j++){if(evtArr[j]===type){found=true;}}
if(found){x3dom.debug.logInfo('removeEventListener for div.on'+type);that.canvas.removeEventListener(type,func,phase);}else{x3dom.debug.logInfo('removeEventListener for X3D.on'+type);this.__removeEventListener(type,func,phase);}};}
x3dElem.appendChild(canvas);var id=x3dElem.getAttribute("id");if(id!==null){canvas.id="x3dom-"+id+"-canvas";}else{var index=new Date().getTime();canvas.id="x3dom-"+index+"-canvas";}
var w=2;var h=2;if((w=x3dElem.getAttribute("width"))!==null){canvas.style.width=w;canvas.setAttribute("width",w);}
if((h=x3dElem.getAttribute("height"))!==null){canvas.style.height=h;canvas.setAttribute("height",h);}
canvas.setAttribute("tabindex","0");return canvas;};var _old_dim=[0,0];this.watchForResize=function(){var new_dim=[x3dom.getStyle(that.canvas,"width"),x3dom.getStyle(that.canvas,"height")];if((_old_dim[0]!=new_dim[0])||(_old_dim[1]!=new_dim[1])){_old_dim=new_dim;that.x3dElem.setAttribute("width",new_dim[0]);that.x3dElem.setAttribute("height",new_dim[1]);}};this.createStatDiv=function(){var statDiv=document.createElement('div');statDiv.setAttribute("class","x3dom-statdiv");statDiv.innerHTML="0 fps";this.x3dElem.appendChild(statDiv);statDiv.oncontextmenu=statDiv.onmousedown=function(evt){evt.preventDefault();evt.stopPropagation();evt.returnValue=false;return false;};return statDiv;};this.createProgressDiv=function(){var progressDiv=document.createElement('div');progressDiv.setAttribute("class","x3dom-progress");var _text=document.createElement('strong');_text.appendChild(document.createTextNode('Loading...'));progressDiv.appendChild(_text);var _inner=document.createElement('span');_inner.setAttribute('style',"width: 25%;");_inner.appendChild(document.createTextNode(' '));progressDiv.appendChild(_inner);this.x3dElem.appendChild(progressDiv);progressDiv.oncontextmenu=progressDiv.onmousedown=function(evt){evt.preventDefault();evt.stopPropagation();evt.returnValue=false;return false;};return progressDiv;};this.isFlashReady=false;this.x3dElem=x3dElem;this.backend='none';if(this.x3dElem.getAttribute('backend')=='flash'){this.backend='flash';this.canvas=this.createFlashObject(x3dElem);if(this.canvas!=null){this.canvas.parent=this;this.gl=this.initFlashContext(this.canvas);}else{this.createInitFailedDiv(x3dElem);return null;}}else{this.backend='webgl';this.canvas=this.createHTMLCanvas(x3dElem);this.canvas.parent=this;this.gl=this.initContext(this.canvas);if(this.gl==null)
{x3dom.debug.logInfo("Fallback to Flash Renderer");this.backend='flash';this.canvas=this.createFlashObject(x3dElem);if(this.canvas!=null){this.canvas.parent=this;this.gl=this.initFlashContext(this.canvas);}else{this.createInitFailedDiv(x3dElem);return null;}}}
x3dom.caps.BACKEND=this.backend;this.fps_t0=new Date().getTime();this.doc=null;x3dElem.__setAttribute=x3dElem.setAttribute;x3dElem.setAttribute=function(attrName,newVal){this.__setAttribute(attrName,newVal);switch(attrName){case"width":that.canvas.setAttribute("width",newVal);if(that.doc._viewarea){that.doc._viewarea._width=parseInt(that.canvas.getAttribute("width"),0);}
break;case"height":that.canvas.setAttribute("height",newVal);if(that.doc._viewarea){that.doc._viewarea._height=parseInt(that.canvas.getAttribute("height"),0);}
break;default:}
that.doc.needRender=true;};var runtimeEnabled=x3dElem.getAttribute("runtimeEnabled");if(runtimeEnabled!==null){this.hasRuntime=(runtimeEnabled.toLowerCase()=="true");}else{this.hasRuntime=x3dElem.hasRuntime;}
if(this.gl===null){this.hasRuntime=false;}
this.showStat=x3dElem.getAttribute("showStat");this.statDiv=this.createStatDiv();this.statDiv.style.display=(this.showStat!==null&&this.showStat=="true")?"inline":"none";this.showProgress=x3dElem.getAttribute("showProgress");this.progressDiv=this.createProgressDiv();this.progressDiv.style.display=(this.showProgress==null||this.showProgress=="true")?"inline":"none";this.showTouchpoints=x3dElem.getAttribute("showTouchpoints");this.showTouchpoints=this.showTouchpoints?!(this.showTouchpoints.toLowerCase()=="false"):true;if(this.canvas!==null&&this.gl!==null&&this.hasRuntime&&this.backend!=="flash"){this.canvas.mouse_dragging=false;this.canvas.mouse_button=0;this.canvas.mouse_drag_x=0;this.canvas.mouse_drag_y=0;this.canvas.isMulti=false;this.canvas.oncontextmenu=function(evt){evt.preventDefault();evt.stopPropagation();evt.returnValue=false;return false;};this.canvas.addEventListener('mousedown',function(evt){if(!this.isMulti){this.focus();switch(evt.button){case 0:this.mouse_button=1;break;case 1:this.mouse_button=4;break;case 2:this.mouse_button=2;break;default:this.mouse_button=0;break;}
var pos=mousePosition(evt);this.mouse_drag_x=pos.x;this.mouse_drag_y=pos.y;this.mouse_dragging=true;if(evt.shiftKey){this.mouse_button=1;}
if(evt.ctrlKey){this.mouse_button=4;}
if(evt.altKey){this.mouse_button=2;}
this.parent.doc.onMousePress(that.gl,this.mouse_drag_x,this.mouse_drag_y,this.mouse_button);this.parent.doc.needRender=true;window.status=this.id+' DOWN: '+pos.x+", "+pos.y;evt.returnValue=true;}},false);this.canvas.addEventListener('mouseup',function(evt){if(!this.isMulti){this.mouse_button=0;this.mouse_dragging=false;this.parent.doc.onMouseRelease(that.gl,this.mouse_drag_x,this.mouse_drag_y,this.mouse_button);this.parent.doc.needRender=true;evt.returnValue=true;}},false);this.canvas.addEventListener('mouseover',function(evt){if(!this.isMulti){this.mouse_button=0;this.mouse_dragging=false;this.parent.doc.onMouseOver(that.gl,this.mouse_drag_x,this.mouse_drag_y,this.mouse_button);this.parent.doc.needRender=true;evt.returnValue=true;}},false);this.canvas.addEventListener('mouseout',function(evt){if(!this.isMulti){this.mouse_button=0;this.mouse_dragging=false;this.parent.doc.onMouseOut(that.gl,this.mouse_drag_x,this.mouse_drag_y,this.mouse_button);this.parent.doc.needRender=true;evt.returnValue=true;}},false);this.canvas.addEventListener('dblclick',function(evt){if(!this.isMulti){this.mouse_button=0;var pos=mousePosition(evt);this.mouse_drag_x=pos.x;this.mouse_drag_y=pos.y;this.mouse_dragging=false;this.parent.doc.onDoubleClick(that.gl,this.mouse_drag_x,this.mouse_drag_y);this.parent.doc.needRender=true;window.status=this.id+' DBL: '+pos.x+", "+pos.y;evt.returnValue=true;}},false);this.canvas.addEventListener('mousemove',function(evt){if(!this.isMulti){if(evt.shiftKey){this.mouse_button=1;}
if(evt.ctrlKey){this.mouse_button=4;}
if(evt.altKey){this.mouse_button=2;}
var pos=mousePosition(evt);this.mouse_drag_x=pos.x;this.mouse_drag_y=pos.y;if(this.mouse_dragging){this.parent.doc.onDrag(that.gl,this.mouse_drag_x,this.mouse_drag_y,this.mouse_button);}
else{this.parent.doc.onMove(that.gl,this.mouse_drag_x,this.mouse_drag_y,this.mouse_button);}
this.parent.doc.needRender=true;evt.preventDefault();evt.stopPropagation();evt.returnValue=false;}},false);this.canvas.addEventListener('DOMMouseScroll',function(evt){if(!this.isMulti){this.mouse_drag_y+=2*evt.detail;this.parent.doc.onDrag(that.gl,this.mouse_drag_x,this.mouse_drag_y,2);this.parent.doc.needRender=true;window.status=this.id+' SCROLL: '+evt.detail;evt.returnValue=true;}},false);this.canvas.addEventListener('mousewheel',function(evt){if(!this.isMulti){this.mouse_drag_y-=0.1*evt.wheelDeltaY;this.parent.doc.onDrag(that.gl,this.mouse_drag_x,this.mouse_drag_y,2);this.parent.doc.needRender=true;window.status=this.id+' SCROLL: '+evt.detail;evt.returnValue=true;}},false);this.canvas.addEventListener('keypress',function(evt){var keysEnabled=this.parent.x3dElem.getAttribute("keysEnabled");if(!keysEnabled||keysEnabled.toLowerCase()==="true"){this.parent.doc.onKeyPress(evt.charCode);}
this.parent.doc.needRender=true;evt.returnValue=true;},true);this.canvas.addEventListener('keyup',function(evt){var keysEnabled=this.parent.x3dElem.getAttribute("keysEnabled");if(!keysEnabled||keysEnabled.toLowerCase()==="true"){this.parent.doc.onKeyUp(evt.keyCode);}
this.parent.doc.needRender=true;evt.returnValue=true;},true);this.canvas.addEventListener('keydown',function(evt){var keysEnabled=this.parent.x3dElem.getAttribute("keysEnabled");if(!keysEnabled||keysEnabled.toLowerCase()==="true"){this.parent.doc.onKeyDown(evt.keyCode);}
this.parent.doc.needRender=true;evt.returnValue=true;},true);var touches={numTouches:0,firstTouchTime:new Date().getTime(),firstTouchPoint:new x3dom.fields.SFVec2f(0,0),lastDrag:new x3dom.fields.SFVec2f(),lastMiddle:new x3dom.fields.SFVec2f(),lastDistance:new x3dom.fields.SFVec2f(),lastSquareDistance:0,lastAngle:0,lastLayer:new Array(),calcAngle:function(vector)
{var rotation=vector.normalize().dot(new x3dom.fields.SFVec2f(1,0));rotation=Math.acos(rotation);if(vector.y<0)
rotation=Math.PI+(Math.PI-rotation);return rotation;},visMarker:this.showTouchpoints,visMarkerBag:new Array(),visualizeTouches:function(evt,cleanup)
{if(!this.visMarker)
return;var touchBag=[];var marker=null;for(var i=0;i<evt.touches.length;i++){var id=evt.touches[i].identifier||evt.touches[i].streamId;var index=this.visMarkerBag.indexOf(id);if(this.visMarkerBag.indexOf(id)>=0){marker=document.getElementById("visMarker"+id);marker.style.left=(evt.touches[i].clientX)+"px";marker.style.top=(evt.touches[i].clientY)+"px";}
else{marker=document.createElement("div");marker.appendChild(document.createTextNode("#"+id));marker.id="visMarker"+id;marker.className="x3dom-touch-marker";document.body.appendChild(marker);index=this.visMarkerBag.length;this.visMarkerBag[index]=id;}
touchBag.push(id);}
for(var j=this.visMarkerBag.length-1;j>=0;j--){var oldId=this.visMarkerBag[j];if(touchBag.indexOf(oldId)<0){this.visMarkerBag.splice(j,1);marker=document.getElementById("visMarker"+oldId);document.body.removeChild(marker);}}}};var mozilla_ids=[];var mozilla_touches={touches:[],preventDefault:function(){}};var touchStartHandler=function(evt,doc)
{this.isMulti=true;evt.preventDefault();touches.visualizeTouches(evt);if(doc==null)
doc=this.parent.doc;touches.lastLayer=[];for(var i=0;i<evt.touches.length;i++){var pos=mousePosition(evt.touches[i]);touches.lastLayer.push(new Array(evt.touches[i].identifier,new x3dom.fields.SFVec2f(pos.x,pos.y)));}
if(touches.numTouches<1&&evt.touches.length==1){touches.numTouches=1;touches.lastDrag=new x3dom.fields.SFVec2f(evt.touches[0].screenX,evt.touches[0].screenY);}else if(touches.numTouches<2&&evt.touches.length>=2){touches.numTouches=2;var touch0=new x3dom.fields.SFVec2f(evt.touches[0].screenX,evt.touches[0].screenY);var touch1=new x3dom.fields.SFVec2f(evt.touches[1].screenX,evt.touches[1].screenY);var distance=touch1.subtract(touch0);var middle=distance.multiply(0.5).add(touch0);var squareDistance=distance.dot(distance);touches.lastDistance=distance;touches.lastMiddle=middle;touches.lastSquareDistance=squareDistance;touches.lastAngle=touches.calcAngle(distance);}
var min=x3dom.fields.SFVec3f.MAX();var max=x3dom.fields.SFVec3f.MIN();if(doc._scene.getVolume(min,max,true)){doc._scene._lastMin=min;doc._scene._lastMax=max;}
for(var i=0;i<evt.touches.length;i++){var pos=mousePosition(evt.touches[i]);doc.onPick(that.gl,pos.x,pos.y);doc._viewarea.prepareEvents(pos.x,pos.y,1,"onmousedown");doc._viewarea._pickingInfo.lastClickObj=doc._viewarea._pickingInfo.pickObj;doc.needRender=true;}};var touchStartHandlerMoz=function(evt)
{this.isMulti=true;evt.preventDefault();var new_id=true;for(var i=0;i<mozilla_ids.length;++i)
if(mozilla_ids[i]==evt.streamId)
new_id=false;if(new_id==true){evt.identifier=evt.streamId;mozilla_ids.push(evt.streamId);mozilla_touches.touches.push(evt);}
touchStartHandler(mozilla_touches,this.parent.doc);};var touchMoveHandler=function(evt,doc)
{evt.preventDefault();touches.visualizeTouches(evt);if(doc==null)
doc=this.parent.doc;if(evt.touches.length==1){var currentDrag=new x3dom.fields.SFVec2f(evt.touches[0].screenX,evt.touches[0].screenY);var deltaDrag=currentDrag.subtract(touches.lastDrag);touches.lastDrag=currentDrag;var mx=x3dom.fields.SFMatrix4f.rotationY(deltaDrag.x/100);var my=x3dom.fields.SFMatrix4f.rotationX(deltaDrag.y/100);var rotMatrix=mx.mult(my);doc.onMoveView(that.gl,null,rotMatrix);doc.needRender=true;}else if(evt.touches.length>=2){var touch0=new x3dom.fields.SFVec2f(evt.touches[0].screenX,evt.touches[0].screenY);var touch1=new x3dom.fields.SFVec2f(evt.touches[1].screenX,evt.touches[1].screenY);var distance=touch1.subtract(touch0);var middle=distance.multiply(0.5).add(touch0);var squareDistance=distance.dot(distance);var deltaMiddle=middle.subtract(touches.lastMiddle);var deltaZoom=squareDistance-touches.lastSquareDistance;var deltaMove=new x3dom.fields.SFVec3f(deltaMiddle.x/screen.width,-deltaMiddle.y/screen.height,deltaZoom/(screen.width*screen.height*0.2));var rotation=touches.calcAngle(distance);var angleDelta=touches.lastAngle-rotation;touches.lastAngle=rotation;var rotMatrix=x3dom.fields.SFMatrix4f.rotationZ(angleDelta);touches.lastMiddle=middle;touches.lastDistance=distance;touches.lastSquareDistance=squareDistance;doc.onMoveView(that.gl,deltaMove,rotMatrix);doc.needRender=true;}};var touchMoveHandlerMoz=function(evt)
{evt.preventDefault();for(var i=0;i<mozilla_ids.length;++i)
if(mozilla_ids[i]==evt.streamId)
mozilla_touches.touches[i]=evt;touchMoveHandler(mozilla_touches,this.parent.doc);};var touchEndHandler=function(evt,doc)
{this.isMulti=false;evt.preventDefault();touches.visualizeTouches(evt);if(doc==null)
doc=this.parent.doc;if(touches.numTouches==2&&evt.touches.length==1)
touches.lastDrag=new x3dom.fields.SFVec2f(evt.touches[0].screenX,evt.touches[0].screenY);var dblClick=false;if(evt.touches.length<2){if(touches.numTouches==1)
dblClick=true;touches.numTouches=evt.touches.length;}
for(var i=0;i<touches.lastLayer.length;i++){var pos=touches.lastLayer[i][1];doc.onPick(that.gl,pos.x,pos.y);doc._viewarea.prepareEvents(pos.x,pos.y,1,"onmouseup");doc._viewarea._pickingInfo.lastClickObj=doc._viewarea._pickingInfo.pickObj;if(doc._viewarea._pickingInfo.pickObj&&doc._viewarea._pickingInfo.pickObj===doc._viewarea._pickingInfo.lastClickObj){doc._viewarea.prepareEvents(pos.x,pos.y,1,"onclick");}}
if(dblClick){var now=new Date().getTime();var dist=touches.firstTouchPoint.subtract(touches.lastDrag).length();if(dist<18&&now-touches.firstTouchTime<180)
doc.onDoubleClick(that.gl,0,0);touches.firstTouchTime=now;touches.firstTouchPoint=touches.lastDrag;}
doc.needRender=true;};var touchEndHandlerMoz=function(evt)
{this.isMulti=false;evt.preventDefault();var remove_index=-1;for(var i=0;i<mozilla_ids.length;++i)
if(mozilla_ids[i]==evt.streamId)
remove_index=i;if(remove_index!=-1)
{mozilla_ids.splice(remove_index,1);mozilla_touches.touches.splice(remove_index,1);}
touchEndHandler(mozilla_touches,this.parent.doc);};this.canvas.addEventListener('MozTouchDown',touchStartHandlerMoz,true);this.canvas.addEventListener('MozTouchMove',touchMoveHandlerMoz,true);this.canvas.addEventListener('MozTouchUp',touchEndHandlerMoz,true);this.canvas.addEventListener('touchstart',touchStartHandler,true);this.canvas.addEventListener('touchmove',touchMoveHandler,true);this.canvas.addEventListener('touchend',touchEndHandler,true);}};x3dom.X3DCanvas.prototype.tick=function()
{var d=new Date().getTime();var fps=1000.0/(d-this.fps_t0);this.fps_t0=d;try{this.doc.advanceTime(d/1000);var animD=new Date().getTime()-d;if(this.doc.needRender){if(this.x3dElem.runtime.isReady==true){this.x3dElem.runtime.enterFrame();}else{this.x3dElem.runtime.ready();this.x3dElem.runtime.isReady=true;this.x3dElem.runtime.enterFrame();}
if(this.statDiv){this.statDiv.textContent=fps.toFixed(2)+' fps';this.statDiv.appendChild(document.createElement("br"));this.statDiv.appendChild(document.createTextNode("anim: "+animD));}
if(this.backend=='flash'){if(this.isFlashReady){this.canvas.setFPS({fps:fps});this.doc.needRender=false;this.doc.render(this.gl);}}else{this.doc.needRender=false;this.doc.render(this.gl);}}
if(this.statDiv||this.progressDiv){if(this.statDiv&&this.doc.downloadCount){if(this.doc.needRender)
{this.statDiv.appendChild(document.createElement("br"));this.statDiv.appendChild(document.createTextNode("#Loading: "+this.doc.downloadCount));}
else{this.statDiv.textContent="#Loading: "+this.doc.downloadCount;}}
if(this.doc.properties.getProperty("showProgress")!=='false'){if(this.progressDiv){this.progressDiv.childNodes[0].textContent='Loading: '+(+this.doc.downloadCount);if(this.doc.downloadCount>0){this.progressDiv.style.display='inline';}else{this.progressDiv.style.display='none';}
window.myThat=this;window.myStopProgress=function stopProgress(){window.myThat.doc.downloadCount=0;window.myThat.progressDiv.style.display='none';};window.setTimeout("window.myStopProgress()",1500);}}else{this.progressDiv.style.display='none';}}}catch(e){x3dom.debug.logException(e);throw e;}};x3dom.X3DCanvas.prototype.load=function(uri,sceneElemPos,settings){this.doc=new x3dom.X3DDocument(this.canvas,this.gl,settings);var x3dCanvas=this;this.doc.onload=function(){x3dom.debug.logInfo("loaded '"+uri+"'");if(x3dCanvas.hasRuntime){(function mainloop(){x3dCanvas.watchForResize();x3dCanvas.tick();window.requestAnimFrame(mainloop,x3dCanvas);})();}else{x3dCanvas.tick();}};this.x3dElem.render=function(){if(x3dCanvas.hasRuntime){x3dCanvas.doc.needRender=true;}else{x3dCanvas.doc.render(x3dCanvas.gl);}};this.x3dElem.context=x3dCanvas.gl.ctx3d;this.doc.onerror=function(){alert('Failed to load X3D document');};this.doc.load(uri,sceneElemPos);};function mousePosition(evt){var convertPoint=window.webkitConvertPointFromNodeToPage;var x=0,y=0;if("getBoundingClientRect"in document.documentElement){var box=evt.target.offsetParent.getBoundingClientRect();var scrolleft=window.pageXOffset||document.body.scrollLeft;var scrolltop=window.pageYOffset||document.body.scrollTop;var elem=evt.target.offsetParent;var paddingLeft=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('padding-left'));var borderLeftWidth=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('border-left-width'));var paddingTop=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('padding-top'));var borderTopWidth=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('border-top-width'));x=evt.pageX-(box.left+paddingLeft+borderLeftWidth+scrolleft);y=evt.pageY-(box.top+paddingTop+borderTopWidth+scrolltop);return new x3dom.fields.SFVec2f(x,y);}else if(convertPoint){var zeroPoint=new WebKitPoint(0,0);var point=convertPoint(evt.target,zeroPoint);x=Math.round(point.x);y=Math.round(point.y);return new x3dom.fields.SFVec2f(x,y);}else{x3dom.debug.logError('NO getBoundingClientRect, NO webkitConvertPointFromNodeToPage');}
return new x3dom.fields.SFVec2f(x,y);}
x3dom.runtime={};x3dom.Runtime=function(doc,canvas){this.doc=doc;this.canvas=canvas;this.isReady=false;};x3dom.Runtime.prototype.initialize=function(doc,canvas){this.doc=doc;this.canvas=canvas;this.config={};this.isReady=false;};x3dom.Runtime.prototype.ready=function(){x3dom.debug.logInfo('System ready.');};x3dom.Runtime.prototype.enterFrame=function(){},x3dom.Runtime.prototype.getActiveBindable=function(typeName){var stacks;var i,current,result;var type;stacks=this.canvas.doc._bindableBag._stacks;result=[];type=x3dom.nodeTypesLC[typeName.toLowerCase()];if(!type){x3dom.debug.logError('No node of type "'+typeName+'" found');return null;}
for(i=0;i<stacks.length;i++){current=stacks[i].getActive();if(current._xmlNode!==undefined&&x3dom.isa(current,type)){result.push(current);}}
return result[0]?result[0]._xmlNode:null;};x3dom.Runtime.prototype.nextView=function(){var stack=this.canvas.doc._scene.getViewpoint()._stack;if(stack){stack.switchTo('next');}else{x3dom.debug.logError('No valid ViewBindable stack.');}};x3dom.Runtime.prototype.prevView=function(){var stack=this.canvas.doc._scene.getViewpoint()._stack;if(stack){stack.switchTo('prev');}else{x3dom.debug.logError('No valid ViewBindable stack.');}};x3dom.Runtime.prototype.viewpoint=function(){return this.canvas.doc._scene.getViewpoint();};x3dom.Runtime.prototype.viewMatrix=function(){return this.canvas.doc._viewarea.getViewMatrix();};x3dom.Runtime.prototype.projectionMatrix=function(){return this.canvas.doc._viewarea.getProjectionMatrix();};x3dom.Runtime.prototype.getWorldToCameraCoordinatesMatrix=function(){return this.canvas.doc._viewarea.getWCtoCCMatrix();};x3dom.Runtime.prototype.getCameraToWorldCoordinatesMatrix=function(){return this.canvas.doc._viewarea.getCCtoWCMatrix();};x3dom.Runtime.prototype.getViewingRay=function(x,y){return this.canvas.doc._viewarea.calcViewRay(x,y);};x3dom.Runtime.prototype.getWidth=function(){return this.canvas.doc._viewarea._width;};x3dom.Runtime.prototype.getHeight=function(){return this.canvas.doc._viewarea._height;};x3dom.Runtime.prototype.calcCanvasPos=function(wx,wy,wz){var pnt=new x3dom.fields.SFVec3f(wx,wy,wz);var mat=this.canvas.doc._viewarea.getWCtoCCMatrix();var pos=mat.multFullMatrixPnt(pnt);var w=this.canvas.doc._viewarea._width;var h=this.canvas.doc._viewarea._height;var x=Math.round((pos.x+1)*(w-1)/2);var y=Math.round((h-1)*(1-pos.y)/2);return[x,y];};x3dom.Runtime.prototype.calcPagePos=function(wx,wy,wz){var cavasPos=this.canvas.canvas.offsetParent.getBoundingClientRect();var mousePos=this.calcCanvasPos(wx,wy,wz);var scrolleft=window.pageXOffset||document.body.scrollLeft;var scroltop=window.pageYOffset||document.body.scrollTop;var elem=this.canvas.canvas.offsetParent;var paddingLeft=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('padding-left'));var borderLeftWidth=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('border-left-width'));var paddingTop=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('padding-top'));var borderTopWidth=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('border-top-width'));var mousePos=this.calcCanvasPos(wx,wy,wz);var x=cavasPos.left+paddingLeft+borderLeftWidth+scrolleft+mousePos[0];var y=cavasPos.top+paddingTop+borderTopWidth+scroltop+mousePos[1];return[x,y];};x3dom.Runtime.prototype.calcClientPos=function(wx,wy,wz){var cavasPos=this.canvas.canvas.offsetParent.getBoundingClientRect();var elem=this.canvas.canvas.offsetParent;var paddingLeft=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('padding-left'));var borderLeftWidth=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('border-left-width'));var paddingTop=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('padding-top'));var borderTopWidth=parseFloat(document.defaultView.getComputedStyle(elem,null).getPropertyValue('border-top-width'));var mousePos=this.calcCanvasPos(wx,wy,wz);var x=cavasPos.left+paddingLeft+borderLeftWidth+mousePos[0];var y=cavasPos.top+paddingTop+borderTopWidth+mousePos[1];return[x,y];};x3dom.Runtime.prototype.lightMatrix=function(){this.canvas.doc._viewarea.getLightMatrix();};x3dom.Runtime.prototype.resetView=function(){this.canvas.doc._viewarea.resetView();};x3dom.Runtime.prototype.lightView=function(){if(this.canvas.doc._nodeBag.lights.length>0){this.canvas.doc._viewarea.animateTo(this.canvas.doc._viewarea.getLightMatrix()[0],this.canvas.doc._scene.getViewpoint());return true;}else{x3dom.debug.logInfo("No lights to navigate to");return false;}};x3dom.Runtime.prototype.uprightView=function(){this.canvas.doc._viewarea.uprightView();};x3dom.Runtime.prototype.showAll=function(axis){this.canvas.doc._viewarea.showAll(axis);};x3dom.Runtime.prototype.showObject=function(obj){var min=x3dom.fields.SFVec3f.MAX();var max=x3dom.fields.SFVec3f.MIN();if(obj&&obj._x3domNode&&obj._x3domNode.getVolume(min,max,true))
{var mat=obj._x3domNode.getCurrentTransform();min=mat.multMatrixPnt(min);max=mat.multMatrixPnt(max);var focalLen=(this.canvas.doc._viewarea._width<this.canvas.doc._viewarea._height)?this.canvas.doc._viewarea._width:this.canvas.doc._viewarea._height;var n0=new x3dom.fields.SFVec3f(0,0,1);var percArea=1.0;var viewpoint=this.canvas.doc._scene.getViewpoint();var fov=viewpoint.getFieldOfView()/2.0;var ta=Math.tan(fov);if(Math.abs(ta)>x3dom.fields.Eps){focalLen/=ta;}
var w=this.canvas.doc._viewarea._width-1;var h=this.canvas.doc._viewarea._height-1;var frame=0.25;var minScreenPos=new x3dom.fields.SFVec2f(frame*w,frame*h);frame=0.75;var maxScreenPos=new x3dom.fields.SFVec2f(frame*w,frame*h);var dia2=max.subtract(min).multiply(0.5);var rw=dia2.length();var pc=min.add(dia2);var vc=maxScreenPos.subtract(minScreenPos).multiply(0.5);var rs=1.5*vc.length();vc=vc.add(minScreenPos);var dist=1.0;if(rs>x3dom.fields.Eps){dist=(rw/rs)*Math.sqrt(vc.x*vc.x+vc.y*vc.y+focalLen*focalLen);}
n0=mat.multMatrixVec(n0).normalize();n0=n0.multiply(percArea*dist);var p0=pc.add(n0);var qDir=x3dom.fields.Quaternion.rotateFromTo(new x3dom.fields.SFVec3f(0,0,1),n0);var R=qDir.toMatrix();var T=x3dom.fields.SFMatrix4f.translation(p0.negate());var M=x3dom.fields.SFMatrix4f.translation(p0);M=M.mult(R).mult(T).mult(M);var viewmat=M.inverse();this.canvas.doc._viewarea.animateTo(viewmat,viewpoint);}};x3dom.Runtime.prototype.getCenter=function(domNode){if(domNode&&domNode._x3domNode&&(this.isA(domNode,"X3DShapeNode")||this.isA(domNode,"X3DGeometryNode")))
{return domNode._x3domNode.getCenter();}
return null;};x3dom.Runtime.prototype.getCurrentTransform=function(domNode){if(domNode&&domNode._x3domNode)
{return domNode._x3domNode.getCurrentTransform();}
return null;};x3dom.Runtime.prototype.debug=function(show){if(show===true){this.canvas.doc._viewarea._visDbgBuf=true;x3dom.debug.logContainer.style.display="block";}
if(show===false){this.canvas.doc._viewarea._visDbgBuf=false;x3dom.debug.logContainer.style.display="none";}
else{if(this.canvas.doc._viewarea._visDbgBuf===undefined)
this.canvas.doc._viewarea._visDbgBuf=true;else
this.canvas.doc._viewarea._visDbgBuf=!this.canvas.doc._viewarea._visDbgBuf;x3dom.debug.logContainer.style.display=(this.canvas.doc._viewarea._visDbgBuf===true)?"block":"none";}
this.canvas.doc.needRender=true;return this.canvas.doc._viewarea._visDbgBuf;};x3dom.Runtime.prototype.navigationType=function(){return this.canvas.doc._scene.getNavigationInfo().getType();};x3dom.Runtime.prototype.examine=function(){this.canvas.doc._scene.getNavigationInfo().setType("examine");};x3dom.Runtime.prototype.fly=function(){this.canvas.doc._scene.getNavigationInfo().setType("fly");};x3dom.Runtime.prototype.lookAt=function(){this.canvas.doc._scene.getNavigationInfo().setType("lookat");};x3dom.Runtime.prototype.lookAround=function(){this.canvas.doc._scene.getNavigationInfo().setType("lookaround");};x3dom.Runtime.prototype.walk=function(){this.canvas.doc._scene.getNavigationInfo().setType("walk");};x3dom.Runtime.prototype.game=function(){this.canvas.doc._scene.getNavigationInfo().setType("game");};x3dom.Runtime.prototype.resetExamin=function(){this.canvas.doc._viewarea._rotMat=x3dom.fields.SFMatrix4f.identity();this.canvas.doc._viewarea._transMat=x3dom.fields.SFMatrix4f.identity();this.canvas.doc._viewarea._movement=new x3dom.fields.SFVec3f(0,0,0);this.canvas.doc.needRender=true;};x3dom.Runtime.prototype.togglePoints=function(){if(this.canvas.doc._viewarea._points===undefined)
this.canvas.doc._viewarea._points=0;this.canvas.doc._viewarea._points=++this.canvas.doc._viewarea._points%2;this.canvas.doc.needRender=true;};x3dom.Runtime.prototype.pickMode=function(options){if(options&&options.internal===true){return this.canvas.doc._scene._vf.pickMode;}
return this.canvas.doc._scene._vf.pickMode.toLowerCase();};x3dom.Runtime.prototype.changePickMode=function(type,options){type=type.toLowerCase();switch(type){case'idbuf':type='idBuf';break;case'textcoord':type='textCoord';break;case'color':type='color';break;case'box':type='box';break;default:x3dom.debug.logWarning("Switch pickMode to "+type+' unknown intersect type');type=undefined;}
if(type!==undefined){this.canvas.doc._scene._vf.pickMode=type;x3dom.debug.logInfo("Switched pickMode to '"+type+"'.");return false;}
return true;};x3dom.Runtime.prototype.speed=function(newSpeed){if(newSpeed){this.canvas.doc._scene.getNavigationInfo()._vf.speed=newSpeed;x3dom.debug.logInfo("Changed navigation speed to "+this.canvas.doc._scene.getNavigationInfo()._vf.speed);}
return this.canvas.doc._scene.getNavigationInfo()._vf.speed;};x3dom.Runtime.prototype.statistics=function(mode){var statDiv=this.canvas.statDiv;if(statDiv){if(mode===true){statDiv.style.display='inline';return true;}
if(mode===false){statDiv.style.display='none';return false;}
return statDiv.style.display!='none'}};x3dom.Runtime.prototype.processIndicator=function(mode){var processDiv=this.canvas.processDiv;if(processDiv){if(mode===true){processDiv.style.display='inline';return true;}
if(mode===false){processDiv.style.display='none';return false;}
return processDiv.style.display!='none'}},x3dom.Runtime.prototype.properties=function(){return this.canvas.doc.properties;};x3dom.Runtime.prototype.backendName=function(){return this.canvas.backend;};x3dom.Runtime.prototype.isA=function(domNode,nodeType){var inherits=false;if(nodeType&&domNode&&domNode._x3domNode){if(nodeType===""){nodeType="X3DNode";}
inherits=x3dom.isa(domNode._x3domNode,x3dom.nodeTypesLC[nodeType.toLowerCase()]);}
return inherits;};x3dom.detectActiveX=function(){var isInstalled=false;if(window.ActiveXObject){var control=null;try{control=new ActiveXObject('AVALONATX.InstantPluginATXCtrl.1');}catch(e){}
if(control){isInstalled=true;}}
return isInstalled;};x3dom.rerouteSetAttribute=function(node,browser){node._setAttribute=node.setAttribute;node.setAttribute=function(name,value){var id=node.getAttribute("_x3domNode");var anode=browser.findNode(id);if(anode)
return anode.parseField(name,value);else
return 0;};for(var i=0;i<node.childNodes.length;i++){var child=node.childNodes[i];x3dom.rerouteSetAttribute(child,browser);}};x3dom.insertActiveX=function(x3d){if(typeof x3dom.atxCtrlCounter=='undefined'){x3dom.atxCtrlCounter=0;}
var height=x3d.getAttribute("height");var width=x3d.getAttribute("width");var parent=x3d.parentNode;var divelem=document.createElement("div");divelem.setAttribute("id","x3dplaceholder");var inserted=parent.insertBefore(divelem,x3d);var hiddenx3d=document.createElement("div");hiddenx3d.style.display="none";parent.appendChild(hiddenx3d);parent.removeChild(x3d);hiddenx3d.appendChild(x3d);var atx=document.createElement("object");var containerName="Avalon"+x3dom.atxCtrlCounter;x3dom.atxCtrlCounter++;atx.setAttribute("id",containerName);atx.setAttribute("classid","CLSID:F3254BA0-99FF-4D14-BD81-EDA9873A471E");atx.setAttribute("width",width?width:"500");atx.setAttribute("height",height?height:"500");inserted.appendChild(atx);var atxctrl=document.getElementById(containerName);var browser=atxctrl.getBrowser();var scene=browser.importDocument(x3d);browser.replaceWorld(scene);x3d.getBrowser=function(){return atxctrl.getBrowser();};x3dom.rerouteSetAttribute(x3d,browser);};x3dom.userAgentFeature={supportsDOMAttrModified:false};(function loadX3DOM(){var onload=function(){var i,j;var x3ds=document.getElementsByTagName('X3D');var w3sg=document.getElementsByTagName('webSG');var params;var settings=new x3dom.Properties();var validParams=array_to_object(['showLog','showStat','showProgress','PrimitiveQuality','component','loadpath','disableDoubleClick','maxActiveDownloads']);var components,prefix;var showLoggingConsole=false;for(i=0;i<x3ds.length;i++){settings.setProperty("showLog",x3ds[i].getAttribute("showLog")||'false');settings.setProperty("showStat",x3ds[i].getAttribute("showStat")||'false');settings.setProperty("showProgress",x3ds[i].getAttribute("showProgress")||'true');settings.setProperty("PrimitiveQuality",x3ds[i].getAttribute("PrimitiveQuality")||'High');params=x3ds[i].getElementsByTagName('PARAM');for(j=0;j<params.length;j++){if(params[j].getAttribute('name')in validParams){settings.setProperty(params[j].getAttribute('name'),params[j].getAttribute('value'));}else{}}
if(settings.getProperty('showLog')==='true'){showLoggingConsole=true;}
if(typeof X3DOM_SECURITY_OFF!='undefined'&&X3DOM_SECURITY_OFF===true){components=settings.getProperty('components',x3ds[i].getAttribute("components"));if(components){prefix=settings.getProperty('loadpath',x3ds[i].getAttribute("loadpath"))
components=components.trim().split(',');for(j=0;j<components.length;j++){x3dom.loadJS(components[j]+".js",prefix);}}}
if(typeof X3DOM_SECURITY_OFF!='undefined'&&X3DOM_SECURITY_OFF===true){if(x3ds[i].getAttribute("src")){var _scene=document.createElement("scene");var _inl=document.createElement("Inline");_inl.setAttribute("url",x3ds[i].getAttribute("src"));_scene.appendChild(_inl);x3ds[i].appendChild(_scene);}}}
if(showLoggingConsole==true){x3dom.debug.activate(true);}else{x3dom.debug.activate(false);}
x3ds=Array.map(x3ds,function(n){n.runtime=new x3dom.Runtime();n.hasRuntime=true;return n;});w3sg=Array.map(w3sg,function(n){n.hasRuntime=false;return n;});for(i=0;i<w3sg.length;i++){x3ds.push(w3sg[i]);}
if(x3dom.versionInfo!==undefined){x3dom.debug.logInfo("X3DOM version "+x3dom.versionInfo.version+", "+"Revison <a href='https://github.com/x3dom/x3dom/tree/"+x3dom.versionInfo.revision+"'>"
+x3dom.versionInfo.revision+"</a>, "+"Date "+x3dom.versionInfo.date);}
x3dom.debug.logInfo("Found "+(x3ds.length-w3sg.length)+" X3D and "+
w3sg.length+" (experimental) WebSG nodes...");var x3d_element;var x3dcanvas;var altDiv,altP,aLnk,altImg,altImgObj;var t0,t1;for(i=0;i<x3ds.length;i++)
{x3d_element=x3ds[i];if(x3dom.detectActiveX()){x3dom.insertActiveX(x3d_element);continue;}
x3dcanvas=new x3dom.X3DCanvas(x3d_element,i);if(x3dcanvas.gl===null){altDiv=document.createElement("div");altDiv.setAttribute("class","x3dom-nox3d");altP=document.createElement("p");altP.appendChild(document.createTextNode("WebGL is not yet supported in your browser. "));aLnk=document.createElement("a");aLnk.setAttribute("href","http://www.x3dom.org/?page_id=9");aLnk.appendChild(document.createTextNode("Follow link for a list of supported browsers... "));altDiv.appendChild(altP);altDiv.appendChild(aLnk);x3dcanvas.x3dElem.appendChild(altDiv);if(x3dcanvas.statDiv){x3d_element.removeChild(x3dcanvas.statDiv);}
altImg=x3ds[i].getAttribute("altImg")||null;if(altImg){altImgObj=new Image();altImgObj.src=altImg;x3d_element.style.backgroundImage="url("+altImg+")";}
continue;}
t0=new Date().getTime();x3ds[i].runtime=new x3dom.Runtime(x3ds[i],x3dcanvas);x3ds[i].runtime.initialize(x3ds[i],x3dcanvas);if(x3dom.runtime.ready){x3ds[i].runtime.ready=x3dom.runtime.ready;}
x3dcanvas.load(x3ds[i],i,settings);if(settings.getProperty('showStat')==='true'){x3ds[i].runtime.statistics(true);}else{x3ds[i].runtime.statistics(false);}
if(settings.getProperty('showProgress')==='true'){if(settings.getProperty('showProgress')==='bar'){x3dcanvas.progressDiv.setAttribute("class","x3dom-progress bar");}
x3ds[i].runtime.processIndicator(true);}else{x3ds[i].runtime.processIndicator(false);}
x3dom.canvases.push(x3dcanvas);t1=new Date().getTime()-t0;x3dom.debug.logInfo("Time for setup and init of GL element no. "+i+": "+t1+" ms.");}
var ready=(function(eventType){var evt=null;if(document.createEvent){evt=document.createEvent("Events");evt.initEvent(eventType,true,true);document.dispatchEvent(evt);}else if(document.createEventObject){evt=document.createEventObject();document.body.fireEvent('on'+eventType,evt);}})('load');};var onunload=function(){for(var i=0;i<x3dom.canvases.length;i++){x3dom.canvases[i].doc.shutdown(x3dom.canvases[i].gl);}};if(navigator.userAgent.indexOf("Chrome")!=-1){document.__getElementsByTagName=document.getElementsByTagName;document.getElementsByTagName=function(tag){var obj=new Array();var elems=this.__getElementsByTagName("*");if(tag=="*"){obj=elems;}else{tag=tag.toUpperCase();for(var i=0;i<elems.length;i++){var tagName=elems[i].tagName.toUpperCase();if(tagName===tag){obj.push(elems[i]);}}}
return obj;};document.__getElementById=document.getElementById;document.getElementById=function(id){var obj=this.__getElementById(id);if(!obj){var elems=this.__getElementsByTagName("*");for(var i=0;i<elems.length&&!obj;i++){if(elems[i].getAttribute("id")===id){obj=elems[i];}}}
return obj;};}else{document.__getElementById=document.getElementById;document.getElementById=function(id){var obj=this.__getElementById(id);if(!obj){var elems=this.getElementsByTagName("*");for(var i=0;i<elems.length&&!obj;i++){if(elems[i].getAttribute("id")===id){obj=elems[i];}}}
return obj;};}
if(window.addEventListener){window.addEventListener('load',onload,false);window.addEventListener('unload',onunload,false);window.addEventListener('reload',onunload,false);}else if(window.attachEvent){window.attachEvent('onload',onload);window.attachEvent('onunload',onunload);window.attachEvent('onreload',onunload);}})();x3dom.gfx_webgl=(function(){function Context(ctx3d,canvas,name){this.ctx3d=ctx3d;this.canvas=canvas;this.name=name;this.cached_shader_programs={};this.cached_shaders={};this.IG_PositionBuffer=null;}
Context.prototype.getName=function(){return this.name;};function setupContext(canvas){var validContextNames=['moz-webgl','webkit-3d','experimental-webgl','webgl'];var ctx=null;var ctxAttribs={alpha:true,depth:true,stencil:true,antialias:true,premultipliedAlpha:false};for(var i=0;i<validContextNames.length;i++){try{ctx=canvas.getContext(validContextNames[i],ctxAttribs);if(ctx){var newCtx=new Context(ctx,canvas,'webgl');try{if(ctx.getString){x3dom.debug.logInfo("\nVendor: "+ctx.getString(ctx.VENDOR)+", "+"Renderer: "+ctx.getString(ctx.RENDERER)+", "+"Version: "+ctx.getString(ctx.VERSION)+", "+"ShadingLangV.: "+ctx.getString(ctx.SHADING_LANGUAGE_VERSION)+", "+"\nExtensions: "+ctx.getString(ctx.EXTENSIONS));}
else{x3dom.debug.logInfo("\nVendor: "+ctx.getParameter(ctx.VENDOR)+", "+"Renderer: "+ctx.getParameter(ctx.RENDERER)+", "+"Version: "+ctx.getParameter(ctx.VERSION)+", "+"ShadingLangV.: "+ctx.getParameter(ctx.SHADING_LANGUAGE_VERSION)
+", "+"\nExtensions: "+ctx.getSupportedExtensions());x3dom.caps.VENDOR=ctx.getParameter(ctx.VENDOR);x3dom.caps.VERSION=ctx.getParameter(ctx.VERSION);x3dom.caps.RENDERER=ctx.getParameter(ctx.RENDERER);x3dom.caps.SHADING_LANGUAGE_VERSION=ctx.getParameter(ctx.SHADING_LANGUAGE_VERSION);x3dom.caps.RED_BITS=ctx.getParameter(ctx.RED_BITS);x3dom.caps.GREEN_BITS=ctx.getParameter(ctx.GREEN_BITS);x3dom.caps.BLUE_BITS=ctx.getParameter(ctx.BLUE_BITS);x3dom.caps.ALPHA_BITS=ctx.getParameter(ctx.ALPHA_BITS);x3dom.caps.DEPTH_BITS=ctx.getParameter(ctx.DEPTH_BITS);x3dom.caps.MAX_VERTEX_ATTRIBS=ctx.getParameter(ctx.MAX_VERTEX_ATTRIBS);x3dom.caps.MAX_VERTEX_TEXTURE_IMAGE_UNITS=ctx.getParameter(ctx.MAX_VERTEX_TEXTURE_IMAGE_UNITS);x3dom.caps.MAX_VARYING_VECTORS=ctx.getParameter(ctx.MAX_VARYING_VECTORS);x3dom.caps.MAX_VERTEX_UNIFORM_VECTORS=ctx.getParameter(ctx.MAX_VERTEX_UNIFORM_VECTORS);x3dom.caps.MAX_COMBINED_TEXTURE_IMAGE_UNITS=ctx.getParameter(ctx.MAX_COMBINED_TEXTURE_IMAGE_UNITS);x3dom.caps.MAX_TEXTURE_SIZE=ctx.getParameter(ctx.MAX_TEXTURE_SIZE);x3dom.caps.MAX_CUBE_MAP_TEXTURE_SIZE=ctx.getParameter(ctx.MAX_CUBE_MAP_TEXTURE_SIZE);x3dom.caps.COMPRESSED_TEXTURE_FORMATS=ctx.getParameter(ctx.COMPRESSED_TEXTURE_FORMATS);x3dom.caps.MAX_RENDERBUFFER_SIZE=ctx.getParameter(ctx.MAX_RENDERBUFFER_SIZE);x3dom.caps.MAX_VIEWPORT_DIMS=ctx.getParameter(ctx.MAX_VIEWPORT_DIMS);x3dom.caps.ALIASED_LINE_WIDTH_RANGE=ctx.getParameter(ctx.ALIASED_LINE_WIDTH_RANGE);x3dom.caps.ALIASED_POINT_SIZE_RANGE=ctx.getParameter(ctx.ALIASED_POINT_SIZE_RANGE);x3dom.caps.EXTENSIONS=ctx.getSupportedExtensions();x3dom.caps.MOBILE=(function(a){if(/android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))){return true}else{return false}})(navigator.userAgent||navigator.vendor||window.opera);if(x3dom.caps.RENDERER.indexOf("PowerVR")>=0||navigator.appVersion.indexOf("Mobile")>-1||x3dom.caps.MAX_VARYING_VECTORS<=8||x3dom.caps.MAX_VERTEX_TEXTURE_IMAGE_UNITS<2)
{x3dom.caps.MOBILE=true;}
if(x3dom.caps.MOBILE){x3dom.debug.logWarning("Detected mobile graphics card! Using low quality shaders without ImageGeometry support!");}}}
catch(ex){x3dom.debug.logWarning("Your browser probably supports an older WebGL version. "+"Please try the old mobile runtime instead:\n"+"http://www.x3dom.org/x3dom/src_mobile/x3dom.js");newCtx=null;}
return newCtx;}}
catch(e){}}
return null;}
var g_shaders={};g_shaders['vs-x3d-bg-texture']={type:"vertex",data:"attribute vec3 position;"+"varying vec2 fragTexCoord;"+""+"void main(void) {"+" vec2 texCoord = (position.xy + 1.0) * 0.5;"+" fragTexCoord = texCoord;"+" gl_Position = vec4(position.xy, 0.0, 1.0);"+"}"};g_shaders['vs-x3d-bg-texture-bgnd']={type:"vertex",data:"attribute vec3 position;"+"attribute vec2 texcoord;"+"uniform mat4 modelViewProjectionMatrix;"+"varying vec2 fragTexCoord;"+""+"void main(void) {"+" fragTexCoord = texcoord;"+" gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);"+"}"};g_shaders['fs-x3d-bg-texture']={type:"fragment",data:"#ifdef GL_ES \n"+" precision highp float; \n"+"#endif \n"+"\n"+"uniform sampler2D tex;\n"+"varying vec2 fragTexCoord;\n"+"\n"+"void main(void) {\n"+" gl_FragColor = texture2D(tex, fragTexCoord);\n"+"}"};g_shaders['vs-x3d-bg-textureCube']={type:"vertex",data:"attribute vec3 position;"+"uniform mat4 modelViewProjectionMatrix;"+"varying vec3 fragNormal;"+""+"void main(void) {"+" fragNormal = normalize(position);"+" gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);"+"}"};g_shaders['fs-x3d-bg-textureCube']={type:"fragment",data:"#ifdef GL_ES \n"+" precision highp float; \n"+"#endif \n"+"\n"+"uniform samplerCube tex;"+"varying vec3 fragNormal;"+" "+"float magn(float val) {"+" return ((val >= 0.0) ? val : -1.0 * val);"+"}"+" "+"void main(void) {"+" vec3 normal = -reflect(normalize(fragNormal), vec3(0.0,0.0,1.0));"+" if (magn(normal.y) >= magn(normal.x) && magn(normal.y) >= magn(normal.z))"+" normal.xz = -normal.xz;"+" gl_FragColor = textureCube(tex, normal);"+"}"};g_shaders['vs-x3d-vertexcolorUnlit']={type:"vertex",data:"attribute vec3 position;"+"attribute vec3 color;"+"varying vec3 fragColor;"+"uniform mat4 modelViewProjectionMatrix;"+""+"void main(void) {"+" gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);"+" gl_PointSize = 2.0;"+" fragColor = color;"+"}"};g_shaders['fs-x3d-vertexcolorUnlit']={type:"fragment",data:"#ifdef GL_ES \n"+" precision highp float; \n"+"#endif \n"+"\n"+"uniform vec3 diffuseColor;"+"uniform float alpha;"+"uniform float lightOn;"+"varying vec3 fragColor;"+""+"void main(void) {"+" gl_FragColor = vec4(fragColor, alpha);"+"}"};g_shaders['vs-x3d-default']={type:"vertex",data:"attribute vec3 position;"+"uniform mat4 modelViewProjectionMatrix;"+"void main(void) {"+" gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);"+"}"};g_shaders['fs-x3d-default']={type:"fragment",data:"#ifdef GL_ES \n"+" precision highp float; \n"+"#endif \n"+"\n"+"struct Material {"+" vec3 diffuseColor;"+" vec3 specularColor;"+" vec3 emissiveColor;"+" float shininess;"+" float transparency;"+" float ambientIntensity;"+"};"+"uniform Material material;"+"void main(void) {"+" gl_FragColor = vec4(material.emissiveColor, 1.0);"+"}"};g_shaders['vs-x3d-texcoordUnlit']={type:"vertex",data:"attribute vec3 position;"+"attribute vec2 texcoord;"+"varying vec3 fragColor;"+"uniform mat4 modelViewProjectionMatrix;"+""+"void main(void) {"+" gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);"+" fragColor = vec3(abs(texcoord.x), abs(texcoord.y), 0.0);"+"}"};g_shaders['fs-x3d-texcoordUnlit']={type:"fragment",data:"#ifdef GL_ES \n"+" precision highp float; \n"+"#endif \n"+"\n"+"uniform float alpha;"+"varying vec3 fragColor;"+""+"void main(void) {"+" gl_FragColor = vec4(fragColor, alpha);"+"}"};g_shaders['vs-x3d-pick']={type:"vertex",data:"attribute vec3 position;"+"uniform vec3 bgCenter;"+"uniform vec3 bgSize;"+"uniform float bgPrecisionMax;"+"uniform mat4 modelMatrix;"+"uniform mat4 modelViewProjectionMatrix;"+"uniform vec3 wcMin;"+"uniform vec3 wcMax;"+"varying vec3 worldCoord;"+"void main(void) {"+" vec3 pos = bgCenter + bgSize * position / bgPrecisionMax;"+" vec3 dia = wcMax - wcMin;"+" worldCoord = (modelMatrix * vec4(pos, 1.0)).xyz;"+" worldCoord = (worldCoord - wcMin) / dia;"+" gl_Position = modelViewProjectionMatrix * vec4(pos, 1.0);"+"}"};g_shaders['vs-x3d-pickBLG']={type:"vertex",data:"attribute vec3 position;"+"uniform vec3 BLG_bboxMin;"+"uniform vec3 BLG_bboxMax;"+"uniform float bgPrecisionMax;"+"uniform mat4 modelMatrix;"+"uniform mat4 modelViewProjectionMatrix;"+"uniform vec3 wcMin;"+"uniform vec3 wcMax;"+"varying vec3 worldCoord;"+"void main(void) {"+" vec3 pos = position / bgPrecisionMax;"+" pos = pos * (BLG_bboxMax - BLG_bboxMin) + BLG_bboxMin;"+" vec3 dia = wcMax - wcMin;"+" worldCoord = (modelMatrix * vec4(pos, 1.0)).xyz;"+" worldCoord = (worldCoord - wcMin) / dia;"+" gl_Position = modelViewProjectionMatrix * vec4(pos, 1.0);"+"}"};g_shaders['vs-x3d-pickIG']={type:"vertex",data:"attribute vec3 position;"+"uniform mat4 modelMatrix;"+"uniform mat4 modelViewProjectionMatrix;"+"uniform vec3 wcMin;"+"uniform vec3 wcMax;"+"varying vec3 worldCoord;"+"uniform float indexed;"+"uniform float imageGeometry;"+"uniform vec3 IG_bboxMin;"+"uniform vec3 IG_bboxMax;"+"uniform float IG_coordTextureWidth;"+"uniform float IG_coordTextureHeight;"+"uniform float IG_indexTextureWidth;"+"uniform float IG_indexTextureHeight;"+"uniform sampler2D IG_indexTexture;"+"uniform sampler2D IG_coordinateTexture;"+"uniform float IG_implicitMeshSize;"+"void main(void) {"+" if(imageGeometry == 1.0) { "+" vec2 IG_texCoord;"+" if(indexed == 1.0) {"+" vec2 halfPixel = vec2(0.5/IG_indexTextureWidth,0.5/IG_indexTextureHeight);"+" IG_texCoord = vec2(position.x*(IG_implicitMeshSize/IG_indexTextureWidth), position.y*(IG_implicitMeshSize/IG_indexTextureHeight)) + halfPixel;"+" vec2 IG_index = texture2D( IG_indexTexture, IG_texCoord ).rg;"+" IG_texCoord = IG_index * 0.996108948;"+" } else { "+" vec2 halfPixel = vec2(0.5/IG_coordTextureWidth, 0.5/IG_coordTextureHeight);"+" IG_texCoord = vec2(position.x*(IG_implicitMeshSize/IG_coordTextureWidth), position.y*(IG_implicitMeshSize/IG_coordTextureHeight)) + halfPixel;"+" }"+" vec3 pos = texture2D( IG_coordinateTexture, IG_texCoord ).rgb;"+" pos = pos * (IG_bboxMax - IG_bboxMin) + IG_bboxMin;"+" worldCoord = (modelMatrix * vec4(pos, 1.0)).xyz;"+" gl_Position = modelViewProjectionMatrix * vec4(pos, 1.0);"+" } else { "+" worldCoord = (modelMatrix * vec4(position, 1.0)).xyz;"+" gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);"+" }"+" vec3 dia = wcMax - wcMin;"+" worldCoord = worldCoord - wcMin;"+" worldCoord.x /= dia.x;"+" worldCoord.y /= dia.y;"+" worldCoord.z /= dia.z;"+"}"};g_shaders['fs-x3d-pick']={type:"fragment",data:"#ifdef GL_ES \n"+" precision highp float; \n"+"#endif \n"+"\n"+"uniform float alpha;"+"varying vec3 worldCoord;"+"void main(void) {"+" gl_FragColor = vec4(worldCoord, alpha);"+"}"};g_shaders['vs-x3d-shadow']={type:"vertex",data:"attribute vec3 position;"+"uniform mat4 modelViewProjectionMatrix;"+"varying vec4 projCoord;"+"void main(void) {"+" projCoord = modelViewProjectionMatrix * vec4(position, 1.0);"+" gl_Position = projCoord;"+"}"};g_shaders['fs-x3d-shadow']={type:"fragment",data:"#ifdef GL_ES \n"+" precision highp float; \n"+"#endif \n"+"\n"+"varying vec4 projCoord;"+"void main(void) {"+" vec3 proj = (projCoord.xyz / projCoord.w);"+" vec4 outVal = vec4(0.0);"+" float toFixed = 255.0 / 256.0;"+" outVal.r = fract(proj.z * toFixed);"+" outVal.g = fract(proj.z * toFixed * 255.0);"+" outVal.b = fract(proj.z * toFixed * 255.0 * 255.0);"+" outVal.a = fract(proj.z * toFixed * 255.0 * 255.0 * 255.0);"+" gl_FragColor = outVal;"+"}"};function getDefaultShaderProgram(gl,suffix)
{var prog=gl.createProgram();var vs=gl.createShader(gl.VERTEX_SHADER);var fs=gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(vs,g_shaders['vs-x3d-'+suffix].data);gl.shaderSource(fs,g_shaders['fs-x3d-'+suffix].data);gl.compileShader(vs);if(!gl.getShaderParameter(vs,gl.COMPILE_STATUS)){x3dom.debug.logError("VertexShader "+gl.getShaderInfoLog(vs));}
gl.compileShader(fs);if(!gl.getShaderParameter(fs,gl.COMPILE_STATUS)){x3dom.debug.logError("FragmentShader "+gl.getShaderInfoLog(fs));}
gl.attachShader(prog,vs);gl.attachShader(prog,fs);gl.linkProgram(prog);var msg=gl.getProgramInfoLog(prog);if(msg){if(msg.indexOf("warning")>=0)
x3dom.debug.logWarning(msg);else
x3dom.debug.logError(msg);}
return wrapShaderProgram(gl,prog);}
function scaleImage(image)
{if(!isPowerOfTwo(image.width)||!isPowerOfTwo(image.height)){var canvas=document.createElement("canvas");canvas.width=nextHighestPowerOfTwo(image.width);canvas.height=nextHighestPowerOfTwo(image.height);var ctx=canvas.getContext("2d");ctx.drawImage(image,0,0,image.width,image.height,0,0,canvas.width,canvas.height);image=canvas;}
return image;}
function isPowerOfTwo(x)
{return((x&(x-1))===0);}
function nextHighestPowerOfTwo(x)
{--x;for(var i=1;i<32;i<<=1){x=x|x>>i;}
return(x+1);}
function nextBestPowerOfTwo(x)
{var log2x=Math.log(x)/Math.log(2);return Math.pow(2,Math.round(log2x));}
function getArrayBufferView(type,buffer)
{var array=null;switch(type)
{case"Int8":array=new Int8Array(buffer);break;case"Uint8":array=new Uint8Array(buffer);break;case"Int16":array=new Int16Array(buffer);break;case"Uint16":array=new Uint16Array(buffer);break;case"Int32":array=new Int32Array(buffer);break;case"Uint32":array=new Uint32Array(buffer);break;case"Float32":array=new Float32Array(buffer);break;case"Float64":array=new Float64Array(buffer);break;default:x3dom.debug.logError("Can't create typed array view of type "+type+", trying Float32...");array=new Float32Array(buffer);break;}
return array;}
function getVertexAttribType(type,gl)
{var dataType=gl.NONE;switch(type)
{case"Int8":dataType=gl.BYTE;break;case"Uint8":dataType=gl.UNSIGNED_BYTE;break;case"Int16":dataType=gl.SHORT;break;case"Uint16":dataType=gl.UNSIGNED_SHORT;break;case"Int32":dataType=gl.INT;break;case"Uint32":dataType=gl.UNSIGNED_INT;break;case"Float32":dataType=gl.FLOAT;break;case"Float64":default:x3dom.debug.logError("Can't find GL data type for "+type+", getting FLOAT...");dataType=gl.FLOAT;break;}
return dataType;}
function getDataTypeSize(type)
{switch(type)
{case"Int8":case"Uint8":return 1;case"Int16":case"Uint16":return 2;case"Int32":case"Uint32":case"Float32":return 4;case"Float64":default:return 8;}}
Context.prototype.getShaderProgram=function(gl,ids)
{var shader=[];var prog=null;var debug=[];if(this.cached_shader_programs[ids[0]+ids[1]]){prog=this.cached_shader_programs[ids[0]+ids[1]];}
else
{for(var id=0;id<2;id++)
{if(!g_shaders[ids[id]]){x3dom.debug.logError('Cannot find shader '+ids[id]);return;}
if(this.cached_shaders[ids[id]]){shader[id]=this.cached_shaders[ids[id]];}else{if(g_shaders[ids[id]].type=='vertex'){shader[id]=gl.createShader(gl.VERTEX_SHADER);}
else if(g_shaders[ids[id]].type=='fragment'){shader[id]=gl.createShader(gl.FRAGMENT_SHADER);}
else{x3dom.debug.logError('Invalid shader type '+g_shaders[id].type);return;}
gl.shaderSource(shader[id],g_shaders[ids[id]].data);gl.compileShader(shader[id]);if(!gl.getShaderParameter(shader[id],gl.COMPILE_STATUS)){if(id==0){x3dom.debug.logError("VertexShader "+gl.getShaderInfoLog(shader[id]));}else{x3dom.debug.logError("FragmentShader "+gl.getShaderInfoLog(shader[id]));}}
this.cached_shaders[ids[id]]=shader[id];}}
prog=gl.createProgram();gl.attachShader(prog,shader[0]);gl.attachShader(prog,shader[1]);gl.linkProgram(prog);var msg=gl.getProgramInfoLog(prog);if(msg){if(msg.indexOf("warning")>=0)
x3dom.debug.logWarning(msg);else
x3dom.debug.logError(msg);}
this.cached_shader_programs[ids[0]+ids[1]]=wrapShaderProgram(gl,prog);prog=this.cached_shader_programs[ids[0]+ids[1]];}
return prog;};function wrapShaderProgram(gl,sp)
{var shader={};shader.bind=function(){gl.useProgram(sp);};var loc=null,obj=null;var i=0;var glErr;var numUniforms=gl.getProgramParameter(sp,gl.ACTIVE_UNIFORMS);for(i=0;i<numUniforms;++i){try{obj=gl.getActiveUniform(sp,i);}
catch(eu){}
glErr=gl.getError();if(glErr!==0){x3dom.debug.logError("GL-Error (on searching uniforms): "+glErr);}
loc=gl.getUniformLocation(sp,obj.name);var objName=obj.name;if(obj.name.lastIndexOf("[0]")==obj.name.length-3){objName=obj.name.substr(0,obj.name.length-3);}
switch(obj.type){case gl.SAMPLER_2D:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniform1i(loc,val);};})(loc));break;case gl.SAMPLER_CUBE:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniform1i(loc,val);};})(loc));break;case gl.BOOL:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniform1i(loc,val);};})(loc));break;case gl.FLOAT:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniform1f(loc,val);};})(loc));break;case gl.FLOAT_VEC2:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniform2f(loc,val[0],val[1]);};})(loc));break;case gl.FLOAT_VEC3:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniform3f(loc,val[0],val[1],val[2]);};})(loc));break;case gl.FLOAT_VEC4:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniform4f(loc,val[0],val[1],val[2],val[3]);};})(loc));break;case gl.FLOAT_MAT2:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniformMatrix2fv(loc,false,new Float32Array(val));};})(loc));break;case gl.FLOAT_MAT3:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniformMatrix3fv(loc,false,new Float32Array(val));};})(loc));break;case gl.FLOAT_MAT4:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniformMatrix4fv(loc,false,new Float32Array(val));};})(loc));break;case gl.INT:shader.__defineSetter__(objName,(function(loc){return function(val){gl.uniform1i(loc,val);};})(loc));break;default:x3dom.debug.logWarning('GLSL program variable '+obj.name+' has unknown type '+obj.type);}}
var numAttribs=gl.getProgramParameter(sp,gl.ACTIVE_ATTRIBUTES);for(i=0;i<numAttribs;++i){try{obj=gl.getActiveAttrib(sp,i);}
catch(ea){}
glErr=gl.getError();if(glErr!==0){x3dom.debug.logError("GL-Error (on searching attributes): "+glErr);}
loc=gl.getAttribLocation(sp,obj.name);shader[obj.name]=loc;}
return shader;}
function useLightingFunc(viewarea)
{var result=[0,false];var slights=viewarea.getLights();var numLights=slights.length;if(numLights>0){if(numLights>8){result[0]=8;}else{result[0]=numLights;}}
for(var i=0;i<numLights;i++){if(slights[i]._vf.shadowIntensity>0.0){result[1]=true;}}
var nav=viewarea._scene.getNavigationInfo();if(nav._vf.headlight){result[0]+=1;}
return result;}
Context.prototype.generateVSMobile=function(viewarea,shape)
{var texture=(shape._cf.appearance.node._cf.texture.node||x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text))?1:0;var textureTransform=(shape._cf.appearance.node._cf.textureTransform.node!==null)?1:0;var sphereMapping=(shape._cf.geometry.node._cf.texCoord!==undefined&&shape._cf.geometry.node._cf.texCoord.node!==null&&shape._cf.geometry.node._cf.texCoord.node._vf.mode)?(shape._cf.geometry.node._cf.texCoord.node._vf.mode.toLowerCase()=="sphere")?1:0:0;var cubeMap=(shape._cf.appearance.node._cf.texture.node)?x3dom.isa(shape._cf.appearance.node._cf.texture.node,x3dom.nodeTypes.X3DEnvironmentTextureNode)?1:0:0;var blending=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text)||cubeMap||(shape._cf.appearance.node._cf.texture.node&&(shape._cf.appearance.node._cf.texture.node._vf.origChannelCount==1||shape._cf.appearance.node._cf.texture.node._vf.origChannelCount==2)))?1:0;var vertexColor=(shape._cf.geometry.node._mesh._colors[0].length>0||shape._cf.geometry.node.getColorTexture()||(shape._cf.geometry.node._vf.color!==undefined&&shape._cf.geometry.node._vf.color.length>0))?shape._cf.geometry.node._mesh._numColComponents:0;var lights=(viewarea.getLights().length)+(viewarea._scene.getNavigationInfo()._vf.headlight);var solid=(shape.isSolid())?1:0;var fog=(viewarea._scene.getFog()._vf.visibilityRange>0)?1:0;var imageGeometry=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.ImageGeometry))?1:0;var bitLODGeometry=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BitLODGeometry))?1:0;var iG_Precision=(imageGeometry)?shape._cf.geometry.node.numCoordinateTextures():0;var iG_Indexed=(imageGeometry&&shape._cf.geometry.node.getIndexTexture()!=null)?1.0:0.0;var requireBBox=(shape._cf.geometry.node._vf.coordType!==undefined&&shape._cf.geometry.node._vf.coordType!="Float32");var requireBBoxNor=(shape._cf.geometry.node._vf.normalType!==undefined&&shape._cf.geometry.node._vf.normalType!="Float32");var requireBBoxCol=(shape._cf.geometry.node._vf.colorType!==undefined&&shape._cf.geometry.node._vf.colorType!="Float32");var requireBBoxTex=(shape._cf.geometry.node._vf.texCoordType!==undefined&&shape._cf.geometry.node._vf.texCoordType!="Float32");var polarNormal=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BitLODGeometry)&&shape._cf.geometry.node.hasPolarNormals())?1:0;var shaderIdentifier="vs-x3d-mobil-"+vertexColor+
texture+
textureTransform+
sphereMapping+
blending+
cubeMap+
solid+
fog+
lights+
imageGeometry+
iG_Precision+
iG_Indexed+
requireBBox+
requireBBoxNor+
requireBBoxCol+
requireBBoxTex+
bitLODGeometry+
polarNormal;if(!g_shaders[shaderIdentifier]){var shader="";shader+="attribute vec3 position;\n";if(polarNormal){shader+="attribute vec2 normal;\n";}else{shader+="attribute vec3 normal;\n";}
shader+="uniform mat4 modelViewMatrix;\n";shader+="uniform mat4 normalMatrix;\n";shader+="uniform mat4 modelViewProjectionMatrix;\n";shader+="uniform vec3 diffuseColor;\n";shader+="uniform vec3 specularColor;\n";shader+="uniform vec3 emissiveColor;\n";shader+="uniform float shininess;\n";shader+="uniform float transparency;\n";shader+="uniform float ambientIntensity;\n";shader+="varying vec4 fragColor;\n";if(requireBBox){shader+="uniform vec3 bgCenter;\n";shader+="uniform vec3 bgSize;\n";shader+="uniform float bgPrecisionMax;\n";}
if(requireBBoxNor){shader+="uniform float bgPrecisionNorMax;\n";}
if(requireBBoxCol){shader+="uniform float bgPrecisionColMax;\n";}
if(requireBBoxTex){shader+="uniform float bgPrecisionTexMax;\n";}
if(imageGeometry){shader+="uniform vec3 IG_bboxMin;\n";shader+="uniform vec3 IG_bboxMax;\n";shader+="uniform float IG_coordTextureWidth;";shader+="uniform float IG_coordTextureHeight;";shader+="uniform sampler2D IG_normalTexture;";shader+="uniform float IG_implicitMeshSize;";for(var i=0;i<iG_Precision;i++){shader+="uniform sampler2D IG_coordinateTexture"+i+";";}
if(iG_Indexed){shader+="uniform sampler2D IG_indexTexture;";shader+="uniform float IG_indexTextureWidth;";shader+="uniform float IG_indexTextureHeight;";}}
if(fog){shader+="uniform vec3 fogColor;\n"+"uniform float fogType;\n"+"uniform float fogRange;\n"+"float calcFog(in vec3 eye) {\n"+" float f0 = 0.0;\n"+" if(fogType == 0.0) {\n"+" if(length(eye) < fogRange){\n"+" f0 = (fogRange-length(eye)) / fogRange;\n"+" }\n"+" }else{\n"+" if(length(eye) < fogRange){\n"+" f0 = exp(-length(eye) / (fogRange-length(eye) ) );\n"+" }\n"+" }\n"+" f0 = clamp(f0, 0.0, 1.0);\n"+" return f0;\n"+"}";}
if(lights){for(var l=0;l<lights;l++){shader+="uniform float Light"+l+"_On;\n";shader+="uniform float Light"+l+"_Type;\n";shader+="uniform vec3 Light"+l+"_Location;\n";shader+="uniform vec3 Light"+l+"_Direction;\n";shader+="uniform vec3 Light"+l+"_Color;\n";shader+="uniform vec3 Light"+l+"_Attenuation;\n";shader+="uniform float Light"+l+"_Intensity;\n";shader+="uniform float Light"+l+"_AmbientIntensity;\n";shader+="uniform float Light"+l+"_BeamWidth;\n";shader+="uniform float Light"+l+"_CutOffAngle;\n";shader+="uniform float Light"+l+"_ShadowIntensity;\n";}
shader+="void lighting(in float lType, in vec3 lLocation, in vec3 lDirection, in vec3 lColor, in vec3 lAttenuation,"+" in float lIntensity, in float lAmbientIntensity, in float lBeamWidth, in float lCutOffAngle,"+" in vec3 N, in vec3 V, inout vec3 ambient, inout vec3 diffuse, inout vec3 specular) {"+" vec3 L;\n"+" float spot = 1.0, attentuation = 1.0;\n"+" if(lType == 0.0) {\n"+" L = -normalize(lDirection);\n"+" }else{\n"+" L = normalize(lLocation - (-V));"+" float distance = length(L);"+" L /= distance;\n"+" attentuation = 1.0 / (lAttenuation.x + lAttenuation.y * distance + lAttenuation.z * (distance * distance));"+" attentuation *= max(0.0, dot(N, L));"+" if(lType == 2.0) {"+" float spotAngle = acos(max(0.0, dot(-L, normalize(lDirection))));"+" if(spotAngle >= lCutOffAngle) spot = 0.0;"+" else if(spotAngle <= lBeamWidth) spot = 1.0;"+" else spot = (spotAngle - lCutOffAngle ) / (lBeamWidth - lCutOffAngle);"+" }"+" }"+" vec3 H = normalize( L + V );\n"+" float NdotL = max(0.0, dot(N, L));\n"+" float NdotH = max(0.0, dot(N, H));\n"+" float ambientFactor = lAmbientIntensity * ambientIntensity;"+" float diffuseFactor = lIntensity * NdotL;"+" float specularFactor = lIntensity * NdotL * pow(NdotH, shininess*128.0);"+" ambient += lColor * ambientFactor * attentuation * spot;"+" diffuse += lColor * diffuseFactor * attentuation * spot;"+" specular += lColor * specularFactor * attentuation * spot;"+"}";}
if(vertexColor){if(imageGeometry){shader+="uniform sampler2D IG_colorTexture;";}else{if(vertexColor==3){shader+="attribute vec3 color;";}else{shader+="attribute vec4 color;";}}}
if(texture){if(imageGeometry){shader+="uniform sampler2D IG_texCoordTexture;";}else{shader+="attribute vec2 texcoord;\n";}
shader+="varying vec2 fragTexcoord;\n";if(textureTransform){shader+="uniform mat4 texTrafoMatrix;\n";}
if(!blending){shader+="varying vec3 fragAmbient;\n";shader+="varying vec3 fragDiffuse;\n";}
if(cubeMap){shader+="varying vec3 fragViewDir;\n";shader+="varying vec3 fragNormal;\n";shader+="uniform mat4 viewMatrix;\n";}}
shader+="void main(void) {\n";if(imageGeometry){if(iG_Indexed){shader+="vec2 halfPixel = vec2(0.5/IG_indexTextureWidth,0.5/IG_indexTextureHeight);";shader+="vec2 IG_texCoord = vec2(position.x*(IG_implicitMeshSize/IG_indexTextureWidth), position.y*(IG_implicitMeshSize/IG_indexTextureHeight)) + halfPixel;";shader+="vec2 IG_index = texture2D( IG_indexTexture, IG_texCoord ).rg;";shader+="halfPixel = vec2(0.5/IG_coordTextureWidth,0.5/IG_coordTextureHeight);";shader+="IG_texCoord = (IG_index * 0.996108948) + halfPixel;";}else{shader+="vec2 halfPixel = vec2(0.5/IG_coordTextureWidth, 0.5/IG_coordTextureHeight);";shader+="vec2 IG_texCoord = vec2(position.x*(IG_implicitMeshSize/IG_coordTextureWidth), position.y*(IG_implicitMeshSize/IG_coordTextureHeight)) + halfPixel;";}
shader+="vec3 temp = vec3(0.0, 0.0, 0.0);";shader+="vec3 vertPosition = vec3(0.0, 0.0, 0.0);";for(var i=0;i<iG_Precision;i++)
{shader+="temp = 255.0 * texture2D( IG_coordinateTexture"+i+", IG_texCoord ).rgb;";shader+="vertPosition *= IG_implicitMeshSize;";shader+="vertPosition += temp;";}
shader+="vertPosition /= (pow(2.0, 8.0 * "+iG_Precision+".0) - 1.0);";shader+="vertPosition = vertPosition * (IG_bboxMax - IG_bboxMin) + IG_bboxMin;";shader+="vec3 vertNormal = texture2D( IG_normalTexture, IG_texCoord ).rgb;";shader+="vertNormal = vertNormal * 2.0 - 1.0;";if(texture){shader+="vec4 IG_doubleTexCoords = texture2D( IG_texCoordTexture, IG_texCoord );";shader+="vec2 vertTexCoord;";shader+="vertTexCoord.r = (IG_doubleTexCoords.r * 0.996108948) + (IG_doubleTexCoords.b * 0.003891051);";shader+="vertTexCoord.g = (IG_doubleTexCoords.g * 0.996108948) + (IG_doubleTexCoords.a * 0.003891051);";}
if(vertexColor==3){shader+="vec3 vertColor = texture2D( IG_colorTexture, IG_texCoord ).rgb;";}else if(vertexColor==4){shader+="vec4 vertColor = texture2D( IG_colorTexture, IG_texCoord ).rgba;";}}else{if(polarNormal){shader+="float PI = 2.0 * asin(1.0);\n";shader+="float theta = normal.x*PI;\n";shader+="float phi = normal.y*PI*2.0 - PI;\n";shader+="vec3 vertNormal;\n";shader+="vertNormal.x = sin(theta) * cos(phi);\n";shader+="vertNormal.y = sin(theta) * sin(phi);\n";shader+="vertNormal.z = cos(theta);\n";}else{shader+="vec3 vertNormal = normal;\n";if(requireBBoxNor){shader+="vertNormal = vertNormal / bgPrecisionNorMax;\n";}}
shader+="vec3 vertPosition = position;";if(bitLODGeometry){shader+="vertPosition = (vertPosition / bgPrecisionMax) * 2.0 - 1.0;\n";shader+="vertPosition = bgCenter + bgSize * vertPosition;\n";}else if(requireBBox){shader+="vertPosition = bgCenter + bgSize * vertPosition / bgPrecisionMax;\n";}
if(vertexColor==3){shader+="vec3 vertColor = color;";}else if(vertexColor==4){shader+="vec4 vertColor = color;";}
if(requireBBoxCol&&vertexColor>=3){shader+="vertColor = vertColor / bgPrecisionColMax;\n";}
if(texture){shader+="vec2 vertTexCoord = texcoord;";if(requireBBoxTex){shader+="vertTexCoord = vertTexCoord / bgPrecisionTexMax;\n";}}}
shader+="vec3 positionMV = (modelViewMatrix * vec4(vertPosition, 1.0)).xyz;\n";shader+="vec3 normalMV = normalize( (normalMatrix * vec4(vertNormal, 0.0)).xyz );\n";shader+="vec3 eye = -positionMV;\n";shader+="vec3 rgb = diffuseColor;\n";shader+="float alpha = 1.0 - transparency;\n";if(vertexColor){shader+="rgb = vertColor.rgb;\n";if(vertexColor==4){shader+="alpha = vertColor.a;\n";}}
if(texture){if(cubeMap){shader+="fragViewDir = viewMatrix[3].xyz;\n";shader+="fragNormal = normalMV;\n";}else if(sphereMapping){shader+=" fragTexcoord = 0.5 + normalMV.xy / 2.0;\n";}else if(textureTransform){shader+=" fragTexcoord = (texTrafoMatrix * vec4(vertTexCoord, 1.0, 1.0)).xy;\n";}else{shader+=" fragTexcoord = vertTexCoord;\n";}}
if(lights){shader+="vec3 ambient = vec3(0.07, 0.07, 0.07);\n";shader+="vec3 diffuse = vec3(0.0, 0.0, 0.0);\n";shader+="vec3 specular = vec3(0.0, 0.0, 0.0);\n";if(!solid){shader+="if (dot(normalMV, eye) < 0.0) {\n";shader+=" normalMV *= -1.0;\n";shader+="}\n";}
for(var i=0;i<lights;i++){shader+=" lighting(Light"+i+"_Type,"+"Light"+i+"_Location,"+"Light"+i+"_Direction,"+"Light"+i+"_Color,"+"Light"+i+"_Attenuation,"+"Light"+i+"_Intensity,"+"Light"+i+"_AmbientIntensity,"+"Light"+i+"_BeamWidth,"+"Light"+i+"_CutOffAngle,"+"normalMV, eye, ambient, diffuse, specular);\n";}
if(texture&&!blending){shader+="fragAmbient = ambient;\n";shader+="fragDiffuse = diffuse;\n";shader+="fragColor.rgb = (emissiveColor + specular*specularColor);\n";shader+="fragColor.a = alpha;\n";}else{shader+="fragColor.rgb = (emissiveColor + ambient*rgb + diffuse*rgb + specular*specularColor);\n";shader+="fragColor.a = alpha;\n";}}else{if(texture&&!blending){shader+="fragAmbient = vec3(1.0);\n";shader+="fragDiffuse = vec3(1.0);\n";shader+="fragColor.rgb = vec3(0.0);\n";shader+="fragColor.a = alpha;\n";}else{shader+="fragColor.rgb = rgb + emissiveColor;\n;\n";shader+="fragColor.a = alpha;\n";}}
if(fog){shader+="float f0 = calcFog(-positionMV);\n";shader+="fragColor.rgb = fogColor * (1.0-f0) + f0 * (fragColor.rgb);\n";}
shader+="gl_Position = modelViewProjectionMatrix * vec4(vertPosition, 1.0);\n";shader+="}\n";g_shaders[shaderIdentifier]={};g_shaders[shaderIdentifier].type="vertex";g_shaders[shaderIdentifier].data=shader;}
return shaderIdentifier;};Context.prototype.generateFSMobile=function(viewarea,shape)
{var texture=(shape._cf.appearance.node._cf.texture.node||x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text))?1:0;var cubeMap=(shape._cf.appearance.node._cf.texture.node)?x3dom.isa(shape._cf.appearance.node._cf.texture.node,x3dom.nodeTypes.X3DEnvironmentTextureNode)?1:0:0;var blending=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text)||cubeMap||(shape._cf.appearance.node._cf.texture.node&&(shape._cf.appearance.node._cf.texture.node._vf.origChannelCount==1||shape._cf.appearance.node._cf.texture.node._vf.origChannelCount==2)))?1:0;var shaderIdentifier="fs-x3d-mobil-"+texture+
cubeMap+
blending;if(!g_shaders[shaderIdentifier]){var shader="";shader+="#ifdef GL_ES \n";shader+=" precision highp float;\n";shader+="#endif\n";shader+="\n";if(texture){if(cubeMap){shader+="uniform samplerCube tex;\n";shader+="varying vec3 fragViewDir;\n";shader+="varying vec3 fragNormal;\n";shader+="uniform mat4 modelViewMatrixInverse;\n";}else{shader+="uniform sampler2D tex; \n";shader+="varying vec2 fragTexcoord; \n";}
if(!blending){shader+="varying vec3 fragAmbient;\n";shader+="varying vec3 fragDiffuse;\n";}}
shader+="varying vec4 fragColor;\n";shader+="void main(void) {\n";shader+="vec4 color = fragColor;\n";if(texture){if(cubeMap){shader+="vec3 normal = normalize(fragNormal);\n";shader+="vec3 viewDir = normalize(fragViewDir);\n";shader+="vec3 reflected = reflect(viewDir, normal);\n"
shader+="reflected = (modelViewMatrixInverse * vec4(reflected,0.0)).xyz;\n"
shader+="vec4 texColor = textureCube(tex, reflected);\n";}else{shader+="vec4 texColor = texture2D(tex, vec2(fragTexcoord.s, 1.0-fragTexcoord.t));\n";}
if(blending){if(cubeMap){shader+="color.rgb = mix(color.rgb, texColor.rgb, vec3(0.75));\n";shader+="color.a = texColor.a;\n";}else{shader+="color.rgb *= texColor.rgb;\n";shader+="color.a *= texColor.a;\n";}}else{shader+="color.rgb += fragAmbient*texColor.rgb + fragDiffuse*texColor.rgb;\n";shader+="color.a *= texColor.a;\n";}}
shader+="if (color.a <= 0.1) discard;\n";shader+="gl_FragColor = color;\n";shader+="}\n";g_shaders[shaderIdentifier]={};g_shaders[shaderIdentifier].type="fragment";g_shaders[shaderIdentifier].data=shader;}
return shaderIdentifier;};Context.prototype.generateVS=function(viewarea,shape)
{var shader=(shape._cf.appearance.node._shader&&x3dom.isa(shape._cf.appearance.node._shader,x3dom.nodeTypes.CommonSurfaceShader))?1:0;var texture=(shape._cf.appearance.node._cf.texture.node||shader||x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text))?1:0;var normalMap=(shader&&shape._cf.appearance.node._shader.getNormalMap())?1:0;var textureTransform=(shape._cf.appearance.node._cf.textureTransform.node!==null)?1:0;var sphereMapping=(shape._cf.geometry.node._cf.texCoord!==undefined&&shape._cf.geometry.node._cf.texCoord.node!==null&&shape._cf.geometry.node._cf.texCoord.node._vf.mode)?(shape._cf.geometry.node._cf.texCoord.node._vf.mode.toLowerCase()=="sphere")?1:0:0;var cubeMap=(shape._cf.appearance.node._cf.texture.node)?x3dom.isa(shape._cf.appearance.node._cf.texture.node,x3dom.nodeTypes.X3DEnvironmentTextureNode)?1:0:0;var vertexColor=(shape._cf.geometry.node._mesh._colors[0].length>0||shape._cf.geometry.node.getColorTexture()||(shape._cf.geometry.node._vf.color!==undefined&&shape._cf.geometry.node._vf.color.length>0))?shape._cf.geometry.node._mesh._numColComponents:0;var lights=(viewarea.getLights().length)+(viewarea._scene.getNavigationInfo()._vf.headlight);var shadow=(viewarea.getLightsShadow())?1:0;var fog=(viewarea._scene.getFog()._vf.visibilityRange>0)?1:0;var imageGeometry=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.ImageGeometry))?1:0;var bitLODGeometry=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BitLODGeometry))?1:0;var iG_Precision=(imageGeometry)?shape._cf.geometry.node.numCoordinateTextures():0;var iG_Indexed=(imageGeometry&&shape._cf.geometry.node.getIndexTexture()!=null)?1:0;var requireBBox=(shape._cf.geometry.node._vf.coordType!==undefined&&shape._cf.geometry.node._vf.coordType!="Float32");var requireBBoxNor=(shape._cf.geometry.node._vf.normalType!==undefined&&shape._cf.geometry.node._vf.normalType!="Float32");var requireBBoxCol=(shape._cf.geometry.node._vf.colorType!==undefined&&shape._cf.geometry.node._vf.colorType!="Float32");var requireBBoxTex=(shape._cf.geometry.node._vf.texCoordType!==undefined&&shape._cf.geometry.node._vf.texCoordType!="Float32");var polarNormal=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BitLODGeometry)&&shape._cf.geometry.node.hasPolarNormals())?1:0;var shaderIdentifier="vs-x3d-"+vertexColor+
texture+
normalMap+
textureTransform+
sphereMapping+
cubeMap+
fog+
lights+
shadow+
imageGeometry+
bitLODGeometry+
iG_Precision+
iG_Indexed+
requireBBox+
requireBBoxNor+
requireBBoxCol+
requireBBoxTex+
polarNormal;if(!g_shaders[shaderIdentifier]){var shader="";shader+="attribute vec3 position;\n";if(polarNormal){shader+="attribute vec2 normal;\n";}else{shader+="attribute vec3 normal;\n";}
shader+="uniform mat4 modelViewMatrix;\n";shader+="uniform mat4 normalMatrix;\n";shader+="uniform mat4 modelViewProjectionMatrix;\n";shader+="varying vec3 fragNormal;\n";if(requireBBox){shader+="uniform vec3 bgCenter;\n";shader+="uniform vec3 bgSize;\n";shader+="uniform float bgPrecisionMax;\n";}
if(requireBBoxNor){shader+="uniform float bgPrecisionNorMax;\n";}
if(requireBBoxCol){shader+="uniform float bgPrecisionColMax;\n";}
if(requireBBoxTex){shader+="uniform float bgPrecisionTexMax;\n";}
if(imageGeometry){shader+="uniform vec3 IG_bboxMin;\n";shader+="uniform vec3 IG_bboxMax;\n";shader+="uniform float IG_coordTextureWidth;\n";shader+="uniform float IG_coordTextureHeight;\n";shader+="uniform float IG_implicitMeshSize;\n";if(iG_Indexed){shader+="uniform sampler2D IG_indexTexture;\n";shader+="uniform float IG_indexTextureWidth;\n";shader+="uniform float IG_indexTextureHeight;\n";}
for(var i=0;i<iG_Precision;i++){shader+="uniform sampler2D IG_coordinateTexture"+i+"\n;";}
shader+="uniform sampler2D IG_normalTexture;\n";shader+="uniform sampler2D IG_texCoordTexture;\n";shader+="uniform sampler2D IG_colorTexture;\n";}
if(bitLODGeometry){shader+="uniform vec3 BLG_bboxMin;\n";shader+="uniform vec3 BLG_bboxMax;\n";}
if(vertexColor){if(vertexColor==3.0){shader+="attribute vec3 color;\n";shader+="varying vec3 fragColor;\n";}else{shader+="attribute vec4 color;\n";shader+="varying vec4 fragColor;\n";}}
if(texture){shader+="attribute vec2 texcoord;\n";shader+="varying vec2 fragTexcoord;\n";if(textureTransform){shader+="uniform mat4 texTrafoMatrix;\n";}
if(normalMap){shader+="attribute vec3 tangent;\n";shader+="attribute vec3 binormal;\n";shader+="varying vec3 fragTangent;\n";shader+="varying vec3 fragBinormal;\n";}
if(cubeMap){shader+="varying vec3 fragViewDir;\n";shader+="uniform mat4 viewMatrix;\n";}}
if(lights||fog){shader+="uniform vec3 eyePosition;\n";if(fog){shader+="varying vec3 fragEyePosition;\n";}
shader+="varying vec3 fragPosition;\n";if(shadow){shader+="uniform mat4 matPV;\n";shader+="varying vec4 projCoord;\n";}}
shader+="void main(void) {\n";if(imageGeometry){if(iG_Indexed){shader+="vec2 halfPixel = vec2(0.5/IG_indexTextureWidth,0.5/IG_indexTextureHeight);\n";shader+="vec2 IG_texCoord = vec2(position.x*(IG_implicitMeshSize/IG_indexTextureWidth), position.y*(IG_implicitMeshSize/IG_indexTextureHeight)) + halfPixel;\n";shader+="vec2 IG_index = texture2D( IG_indexTexture, IG_texCoord ).rg;\n";shader+="halfPixel = vec2(0.5/IG_coordTextureWidth,0.5/IG_coordTextureHeight);\n";shader+="IG_texCoord = (IG_index * 0.996108948) + halfPixel;\n";}else{shader+="vec2 halfPixel = vec2(0.5/IG_coordTextureWidth, 0.5/IG_coordTextureHeight);\n";shader+="vec2 IG_texCoord = vec2(position.x*(IG_implicitMeshSize/IG_coordTextureWidth), position.y*(IG_implicitMeshSize/IG_coordTextureHeight)) + halfPixel;\n";}
shader+="vec3 temp = vec3(0.0, 0.0, 0.0);\n";shader+="vec3 vertPosition = vec3(0.0, 0.0, 0.0);\n";for(var i=0;i<iG_Precision;i++)
{shader+="temp = 255.0 * texture2D( IG_coordinateTexture"+i+", IG_texCoord ).rgb;\n";shader+="vertPosition *= 256.0;\n";shader+="vertPosition += temp;\n";}
shader+="vertPosition /= (pow(2.0, 8.0 * "+iG_Precision+".0) - 1.0);\n";shader+="vertPosition = vertPosition * (IG_bboxMax - IG_bboxMin) + IG_bboxMin;\n";shader+="vec3 vertNormal = texture2D( IG_normalTexture, IG_texCoord ).rgb;\n";shader+="vertNormal = vertNormal * 2.0 - 1.0;\n";if(texture){shader+="vec4 IG_doubleTexCoords = texture2D( IG_texCoordTexture, IG_texCoord );\n";shader+="vec2 vertTexCoord;";shader+="vertTexCoord.r = (IG_doubleTexCoords.r * 0.996108948) + (IG_doubleTexCoords.b * 0.003891051);\n";shader+="vertTexCoord.g = (IG_doubleTexCoords.g * 0.996108948) + (IG_doubleTexCoords.a * 0.003891051);\n";}
if(vertexColor){shader+="fragColor = texture2D( IG_colorTexture, IG_texCoord ).rgb;\n";}
shader+="gl_PointSize = 2.0;\n";}else{if(polarNormal){shader+="float PI = 2.0 * asin(1.0);\n";shader+="float theta = normal.x*PI;\n";shader+="float phi = normal.y*PI*2.0 - PI;\n";shader+="vec3 vertNormal;\n";shader+="vertNormal.x = sin(theta) * cos(phi);\n";shader+="vertNormal.y = sin(theta) * sin(phi);\n";shader+="vertNormal.z = cos(theta);\n";}else{shader+="vec3 vertNormal = normal;\n";if(requireBBoxNor){shader+="vertNormal = vertNormal / bgPrecisionNorMax;\n";}}
if(texture){shader+="vec2 vertTexCoord = texcoord;\n";if(requireBBoxTex){shader+="vertTexCoord = vertTexCoord / bgPrecisionTexMax;\n";}}
shader+="vec3 vertPosition = position;\n";if(bitLODGeometry)
{shader+="vertPosition = vertPosition / bgPrecisionMax;\n";shader+="vertPosition = vertPosition * (BLG_bboxMax - BLG_bboxMin) + BLG_bboxMin;\n";}
else if(requireBBox){shader+="vertPosition = bgCenter + bgSize * vertPosition / bgPrecisionMax;\n";}
shader+="gl_PointSize = 2.0;\n";if(vertexColor){if(requireBBoxCol){shader+="fragColor = color / bgPrecisionColMax;\n";}
else{shader+="fragColor = color;\n";}}}
shader+="fragNormal = (normalMatrix * vec4(vertNormal, 0.0)).xyz;\n";if(lights||fog){shader+="fragPosition = (modelViewMatrix * vec4(vertPosition, 1.0)).xyz;\n";if(fog){shader+="fragEyePosition = eyePosition - fragPosition;\n";}
if(shadow){shader+="projCoord = matPV * vec4(vertPosition+0.5*normalize(vertNormal), 1.0);\n";}}
if(texture){if(cubeMap){shader+="fragViewDir = (viewMatrix[3].xyz);\n";}else if(sphereMapping){shader+=" fragTexcoord = 0.5 + fragNormal.xy / 2.0;\n";}else if(textureTransform){shader+=" fragTexcoord = (texTrafoMatrix * vec4(vertTexCoord, 1.0, 1.0)).xy;\n";}else{shader+=" fragTexcoord = vertTexCoord;\n";}
if(normalMap){shader+="fragTangent = (normalMatrix * vec4(tangent, 0.0)).xyz;\n";shader+="fragBinormal = (normalMatrix * vec4(binormal, 0.0)).xyz;\n";}}
shader+="gl_Position = modelViewProjectionMatrix * vec4(vertPosition, 1.0);\n";shader+="}";g_shaders[shaderIdentifier]={};g_shaders[shaderIdentifier].type="vertex";g_shaders[shaderIdentifier].data=shader;}
return shaderIdentifier;};Context.prototype.generateFS=function(viewarea,shape)
{var vertexColor=(shape._cf.geometry.node._mesh._colors[0].length>0||shape._cf.geometry.node.getColorTexture()||(shape._cf.geometry.node._vf.color!==undefined&&shape._cf.geometry.node._vf.color.length>0))?shape._cf.geometry.node._mesh._numColComponents:0;var lights=(viewarea.getLights().length)+(viewarea._scene.getNavigationInfo()._vf.headlight);var shadows=(viewarea.getLightsShadow())?1:0;var fogs=(viewarea._scene.getFog()._vf.visibilityRange>0)?1:0;var solid=(shape.isSolid())?1:0;var texture=(shape._cf.appearance.node._cf.texture.node||x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text))?1:0;var cubeMap=(shape._cf.appearance.node._cf.texture.node)?x3dom.isa(shape._cf.appearance.node._cf.texture.node,x3dom.nodeTypes.X3DEnvironmentTextureNode)?1:0:0;var blending=(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text)||cubeMap||(shape._cf.appearance.node._cf.texture.node&&(shape._cf.appearance.node._cf.texture.node._vf.origChannelCount==1.0||shape._cf.appearance.node._cf.texture.node._vf.origChannelCount==2.0)))?1:0;var text=x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text);var shader=(shape._cf.appearance.node._shader&&x3dom.isa(shape._cf.appearance.node._shader,x3dom.nodeTypes.CommonSurfaceShader))?1:0;var shaderDiffuse=(shader&&shape._cf.appearance.node._shader.getDiffuseMap())?1:0;var shaderNormal=(shader&&shape._cf.appearance.node._shader.getNormalMap())?1:0;var shaderSpec=(shader&&shape._cf.appearance.node._shader.getSpecularMap())?1:0;var shaderIdentifier="fs-x3d-"+vertexColor+
texture+
cubeMap+
fogs+
lights+
shadows+
blending+
shader+
shaderDiffuse+
shaderNormal+
shaderSpec;if(!g_shaders[shaderIdentifier]){var fog="struct Fog {"+" vec3 color;"+" float fogType;"+" float visibilityRange;"+"};"+"uniform Fog fog;"+"float calcFog() {"+" float f0 = 0.0;"+" if(fog.fogType == 0.0) {"+" if(length(fragEyePosition) < fog.visibilityRange){"+" f0 = (fog.visibilityRange-length(fragEyePosition)) / fog.visibilityRange;"+" }"+" }else{"+" if(length(fragEyePosition) < fog.visibilityRange){"+" f0 = exp(-length(fragEyePosition) / (fog.visibilityRange-length(fragEyePosition) ) );"+" }"+" }"+" f0 = clamp(f0, 0.0, 1.0);"+" return f0;"+"}";var light="struct Light {\n"+" float on;\n"+" float type;\n"+" vec3 location;\n"+" vec3 direction;\n"+" vec3 color;\n"+" vec3 attenuation;\n"+" float intensity;\n"+" float ambientIntensity;\n"+" float beamWidth;\n"+" float cutOffAngle;\n"+" float shadowIntensity;\n"+"};\n"+"const int NUMLIGHTS = "+lights+";\n"+"uniform Light light[9];\n"+"void lighting(in Light light, in vec3 N, in vec3 V, inout vec3 ambient, inout vec3 diffuse, inout vec3 specular){"+" vec3 L;\n"+" float spot = 1.0, attentuation = 1.0;\n"+" if(light.type == 0.0) {\n"+" L = -normalize(light.direction);\n"+" }else{\n"+" L = normalize(light.location - fragPosition);"+" float distance = length(L);"+" L /= distance;\n"+" attentuation = 1.0 / (light.attenuation.x + light.attenuation.y * distance + light.attenuation.z * distance * distance);"+" attentuation *= max(0.0, dot(N, L));"+" if(light.type == 2.0) {"+" float spotAngle = acos(max(0.0, dot(-L, normalize(light.direction))));"+" if(spotAngle >= light.cutOffAngle) spot = 0.0;"+" else if(spotAngle <= light.beamWidth) spot = 1.0;"+" else spot = (spotAngle - light.cutOffAngle ) / (light.beamWidth - light.cutOffAngle);"+" }"+" }"+" vec3 H = normalize( L + V );\n"+" float NdotL = max(0.0, dot(N, L));\n"+" float NdotH = max(0.0, dot(N, H));\n"+" float ambientFactor = light.ambientIntensity * material.ambientIntensity;"+" float diffuseFactor = light.intensity * NdotL;"+" float specularFactor = light.intensity * NdotL * pow(NdotH, material.shininess*128.0);"+" ambient += light.color * ambientFactor * attentuation * spot;"+" diffuse += light.color * diffuseFactor * attentuation * spot;"+" specular += light.color * specularFactor * attentuation * spot;"+"}";var shadow="uniform sampler2D sh_tex;"+"varying vec4 projCoord;"+"float PCF_Filter(Light light, vec3 projectiveBiased, float filterWidth)"+"{"+" float stepSize = 2.0 * filterWidth / 3.0;"+" float blockerCount = 0.0;"+" projectiveBiased.x -= filterWidth;"+" projectiveBiased.y -= filterWidth;"+" for (float i=0.0; i<3.0; i++)"+" {"+" for (float j=0.0; j<3.0; j++)"+" {"+" projectiveBiased.x += (j*stepSize);"+" projectiveBiased.y += (i*stepSize);"+" vec4 zCol = texture2D(sh_tex, (1.0+projectiveBiased.xy)*0.5);"+" float fromFixed = 256.0 / 255.0;"+" float z = zCol.r * fromFixed;"+" z += zCol.g * fromFixed / (255.0);"+" z += zCol.b * fromFixed / (255.0 * 255.0);"+" z += zCol.a * fromFixed / (255.0 * 255.0 * 255.0);"+" if (z < projectiveBiased.z) blockerCount += 1.0;"+" projectiveBiased.x -= (j*stepSize);"+" projectiveBiased.y -= (i*stepSize);"+" }"+" }"+" float result = 1.0 - light.shadowIntensity * blockerCount / 9.0;"+" return result;"+"}";var material="struct Material { \n"+" vec3 diffuseColor; \n"+" vec3 specularColor; \n"+" vec3 emissiveColor; \n"+" float shininess; \n"+" float transparency; \n"+" float ambientIntensity; \n"+"}; \n"+"uniform Material material; \n";var shader="";shader+="#ifdef GL_ES \n";shader+=" precision highp float; \n";shader+="#endif \n";shader+="\n";shader+=material;shader+="uniform mat4 modelMatrix;";shader+="uniform mat4 modelViewMatrix;";if(vertexColor){if(vertexColor==3){shader+="varying vec3 fragColor; \n";}else{shader+="varying vec4 fragColor; \n";}}
if(texture||shader){shader+="varying vec2 fragTexcoord; \n";if((texture||shaderDiffuse)&&!cubeMap){shader+="uniform sampler2D tex; \n";}else if(cubeMap){shader+="uniform samplerCube tex;\n";shader+="varying vec3 fragViewDir;\n";shader+="uniform mat4 modelViewMatrixInverse;\n";}
if(shaderNormal){shader+="uniform sampler2D bump; \n";shader+="varying vec3 fragTangent; \n";shader+="varying vec3 fragBinormal; \n";}
if(shaderSpec){shader+="uniform sampler2D spec; \n";}}
if(lights){shader+="uniform float solid; \n";shader+="varying vec3 fragNormal; \n";shader+="varying vec3 fragPosition; \n";shader+=light;if(shadows){shader+=shadow;}}
if(fogs){shader+="varying vec3 fragEyePosition; \n";shader+=fog;}
shader+="void main(void) { \n";shader+="vec3 rgb = material.diffuseColor; \n";shader+="float alpha = 1.0 - material.transparency;\n";if(vertexColor){shader+="rgb = fragColor.rgb;\n";if(vertexColor==4){shader+="alpha = fragColor.a;\n";}}
if(lights){shader+="vec3 ambient = vec3(0.07, 0.07, 0.07);\n";shader+="vec3 diffuse = vec3(0.0, 0.0, 0.0);\n";shader+="vec3 specular = vec3(0.0, 0.0, 0.0);\n";if(shadows){shader+="float shadowed = 1.0;\n";shader+="float oneShadowAlreadyExists = 0.0;\n";}
shader+="vec3 eye = normalize(-fragPosition);\n";shader+="vec3 normal = normalize(fragNormal);\n";if(shaderNormal){shader+="vec3 t = normalize( fragTangent );\n";shader+="vec3 b = normalize( fragBinormal );\n";shader+="vec3 n = normalize( fragNormal );\n";shader+="mat3 tangentToWorld = mat3(t, b, n);\n";shader+="normal = texture2D( bump, vec2(fragTexcoord.x, 1.0-fragTexcoord.y) ).rgb;\n";shader+="normal = 2.0 * normal - 1.0;\n";shader+="normal = normalize( normal * tangentToWorld );\n";shader+="normal.y = -normal.y;";shader+="normal.x = -normal.x;";}
shader+="if (solid == 0.0 && dot(normal, eye) < 0.0) {\n";shader+=" normal *= -1.0;\n";shader+="}\n";shader+="for(int i=0; i<NUMLIGHTS; i++) {\n";shader+=" lighting(light[i], normal, eye, ambient, diffuse, specular);\n";if(shadows){shader+=" if(light[i].shadowIntensity > 0.0 && oneShadowAlreadyExists == 0.0){\n";shader+=" vec3 projectiveBiased = projCoord.xyz / projCoord.w;\n";shader+=" shadowed = PCF_Filter(light[i], projectiveBiased, 0.002);\n";shader+=" oneShadowAlreadyExists = 1.0;\n";shader+=" }\n";}
shader+="}\n";if(shaderSpec){shader+="specular *= texture2D( spec, vec2(fragTexcoord.x, 1.0-fragTexcoord.y) ).rgb;\n";}
if(texture||shaderDiffuse){if(cubeMap){shader+="vec3 viewDir = normalize(fragViewDir);\n";shader+="vec3 reflected = reflect(viewDir, normal);\n"
shader+="reflected = (modelViewMatrixInverse * vec4(reflected,0.0)).xyz;\n"
shader+="vec4 texColor = textureCube(tex, reflected);\n";shader+="alpha *= texColor.a;\n";}else{shader+="vec2 texCoord = vec2(fragTexcoord.x, 1.0-fragTexcoord.y);\n";shader+="vec4 texColor = texture2D(tex, texCoord);\n";shader+="alpha *= texColor.a;\n";}
if(blending){shader+="rgb = (material.emissiveColor + ambient*rgb + diffuse*rgb + specular*material.specularColor);\n";if(cubeMap){shader+="rgb = mix(rgb, texColor.rgb, vec3(0.75));\n";}else{shader+="rgb *= texColor.rgb;\n";}}else{shader+="rgb = (material.emissiveColor + ambient*texColor.rgb + diffuse*texColor.rgb + specular*material.specularColor);\n";}}else{shader+="rgb = (material.emissiveColor + ambient*rgb + diffuse*rgb + specular*material.specularColor);\n";}
if(shadows){shader+="rgb *= shadowed;\n";}}else{if(texture){shader+="vec2 texCoord = vec2(fragTexcoord.x, 1.0-fragTexcoord.y);\n";shader+="vec4 texColor = texture2D(tex, texCoord);\n";shader+="rgb = texColor.rgb;\n";shader+="alpha *= texColor.a;\n";}else if(vertexColor){shader+="rgb = fragColor.rgb;\n";if(vertexColor==4){shader+="alpha = fragColor.a;\n";}}else{shader+="rgb = material.diffuseColor + material.emissiveColor;\n";}}
if(fogs){shader+="float f0 = calcFog();\n";shader+="rgb = fog.color * (1.0-f0) + f0 * (rgb);\n";}
if(text){shader+="if (alpha <= 0.5) discard;\n";}else{shader+="if (alpha <= 0.1) discard;\n";}
shader+="gl_FragColor = vec4(rgb, alpha);\n";shader+="}\n";g_shaders[shaderIdentifier]={};g_shaders[shaderIdentifier].type="fragment";g_shaders[shaderIdentifier].data=shader;}
return shaderIdentifier;};Context.prototype.setupShape=function(gl,shape,viewarea)
{var i,q=0;var tex=null;var IG_texUnit=1;var vertices,positionBuffer;if(shape._webgl!==undefined)
{var oldLightsAndShadow=shape._webgl.lightsAndShadow;shape._webgl.lightsAndShadow=useLightingFunc(viewarea);var needFullReInit=(shape._webgl.lightsAndShadow[0]!=oldLightsAndShadow[0]||shape._webgl.lightsAndShadow[1]!=oldLightsAndShadow[1]||shape._dirty.shader);if(shape._dirty.colors===true&&shape._webgl.shader.color===undefined&&shape._cf.geometry.node._mesh._colors[0].length)
{needFullReInit=true;}
if(shape._dirty.texture===true||needFullReInit)
{tex=shape._cf.appearance.node._cf.texture.node;if((shape._webgl.texture!==undefined&&tex)&&!needFullReInit)
{shape.updateTexture(tex,0,"false");shape._dirty.texture=false;}
else
{needFullReInit=true;var spOld=shape._webgl.shader;var inc=0;for(inc=0;shape._webgl.texture!==undefined&&inc<shape._webgl.texture.length;inc++)
{if(shape._webgl.texture[inc])
{gl.deleteTexture(shape._webgl.texture[inc]);}}
for(q=0;q<shape._webgl.positions.length;q++)
{if(spOld.position!==undefined)
{gl.deleteBuffer(shape._webgl.buffers[5*q+1]);gl.deleteBuffer(shape._webgl.buffers[5*q+0]);}
if(spOld.normal!==undefined)
{gl.deleteBuffer(shape._webgl.buffers[5*q+2]);}
if(spOld.texcoord!==undefined)
{gl.deleteBuffer(shape._webgl.buffers[5*q+3]);}
if(spOld.color!==undefined)
{gl.deleteBuffer(shape._webgl.buffers[5*q+4]);}}
for(inc=0;inc<shape._webgl.dynamicFields.length;inc++)
{var h_attrib=shape._webgl.dynamicFields[inc];if(spOld[h_attrib.name]!==undefined)
{gl.deleteBuffer(h_attrib.buf);}}}}
for(q=0;q<shape._webgl.positions.length;q++)
{if(!needFullReInit&&shape._dirty.positions===true)
{if(shape._webgl.shader.position!==undefined)
{shape._webgl.positions[q]=shape._cf.geometry.node._mesh._positions[q];gl.deleteBuffer(shape._webgl.buffers[5*q+1]);positionBuffer=gl.createBuffer();shape._webgl.buffers[5*q+1]=positionBuffer;gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,shape._webgl.buffers[5*q+0]);vertices=new Float32Array(shape._webgl.positions[q]);gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);gl.vertexAttribPointer(shape._webgl.shader.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);vertices=null;}
shape._dirty.positions=false;}
if(!needFullReInit&&shape._dirty.colors===true)
{if(shape._webgl.shader.color!==undefined)
{shape._webgl.colors[q]=shape._cf.geometry.node._mesh._colors[q];gl.deleteBuffer(shape._webgl.buffers[5*q+4]);colorBuffer=gl.createBuffer();shape._webgl.buffers[5*q+4]=colorBuffer;colors=new Float32Array(shape._webgl.colors[q]);gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer);gl.bufferData(gl.ARRAY_BUFFER,colors,gl.STATIC_DRAW);gl.vertexAttribPointer(shape._webgl.shader.color,3,shape._webgl.colorType,false,shape._colorStrideOffset[0],shape._colorStrideOffset[1]);colors=null;}
shape._dirty.colors=false;}
if(!needFullReInit&&shape._dirty.normals===true)
{if(shape._webgl.shader.normal!==undefined)
{shape._webgl.normals[q]=shape._cf.geometry.node._mesh._normals[q];gl.deleteBuffer(shape._webgl.buffers[5*q+2]);normalBuffer=gl.createBuffer();shape._webgl.buffers[5*q+2]=normalBuffer;normals=new Float32Array(shape._webgl.normals[q]);gl.bindBuffer(gl.ARRAY_BUFFER,normalBuffer);gl.bufferData(gl.ARRAY_BUFFER,normals,gl.STATIC_DRAW);gl.vertexAttribPointer(shape._webgl.shader.normal,3,shape._webgl.normalType,false,shape._normalStrideOffset[0],shape._normalStrideOffset[1]);normals=null;}
shape._dirty.normals=false;}
if(!needFullReInit&&shape._dirty.texCoords===true)
{if(shape._webgl.shader.texcoord!==undefined)
{shape._webgl.texcoords[q]=shape._cf.geometry.node._mesh._texCoords[q];gl.deleteBuffer(shape._webgl.buffers[5*q+3]);texCoordBuffer=gl.createBuffer();shape._webgl.buffers[5*q+3]=texCoordBuffer;texCoords=new Float32Array(shape._webgl.texcoords[q]);gl.bindBuffer(gl.ARRAY_BUFFER,texCoordBuffer);gl.bufferData(gl.ARRAY_BUFFER,texCoords,gl.STATIC_DRAW);gl.vertexAttribPointer(shape._webgl.shader.texCoord,3,shape._webgl.texCoordType,false,shape._texCoordStrideOffset[0],shape._texCoordStrideOffset[1]);texCoords=null;}
shape._dirty.texCoords=false;}}
if(shape._webgl.imageGeometry)
{var texNode=null;IG_texUnit=1;if((texNode=shape._cf.geometry.node.getIndexTexture())&&shape._cf.geometry.node._dirty.index==true){shape.updateTexture(texNode,IG_texUnit++,'index');}
for(i=0;i<shape._webgl.imageGeometry&&shape._cf.geometry.node._dirty.coord==true;i++){if((texNode=shape._cf.geometry.node.getCoordinateTexture(i))){shape.updateTexture(texNode,IG_texUnit++,'coord');}}
if((texNode=shape._cf.geometry.node.getNormalTexture(0))&&shape._cf.geometry.node._dirty.normal==true){shape.updateTexture(texNode,IG_texUnit++,'normal');}
if((texNode=shape._cf.geometry.node.getTexCoordTexture())&&shape._cf.geometry.node._dirty.texCoord==true){shape.updateTexture(texNode,IG_texUnit++,'texCoord');}
if((texNode=shape._cf.geometry.node.getColorTexture())&&shape._cf.geometry.node._dirty.color==true){shape.updateTexture(texNode,IG_texUnit++,'color');}
shape._cf.geometry.node._dirty.coord=false;shape._cf.geometry.node._dirty.normal=false;shape._cf.geometry.node._dirty.texCoord=false;shape._cf.geometry.node._dirty.color=false;shape._cf.geometry.node._dirty.index=false;}
if(!needFullReInit){return;}}
else if(!(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text)||x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BinaryGeometry)||x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BitLODGeometry))&&(!shape._cf.geometry.node||shape._cf.geometry.node._mesh._positions[0].length<1))
{if(x3dom.caps.MAX_VERTEX_TEXTURE_IMAGE_UNITS<2&&x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.ImageGeometry)){x3dom.debug.logError("Can't render ImageGeometry nodes with only "+
x3dom.caps.MAX_VERTEX_TEXTURE_IMAGE_UNITS+" vertex texture units. Please upgrade your GPU!");}
else{x3dom.debug.logError("NO VALID MESH OR NO VERTEX POSITIONS SET!");}
return;}
shape._dirty.positions=false;shape._dirty.normals=false;shape._dirty.texcoords=false;shape._dirty.colors=false;shape._dirty.indexes=false;shape._dirty.texture=false;shape._dirty.material=false;shape._dirty.shader=false;if(shape._cleanupGLObjects==null)
{shape._cleanupGLObjects=function(force)
{if(this._webgl&&((arguments.length>0&&force)||this._parentNodes.length==0))
{var sp=this._webgl.shader;for(var cnt=0;this._webgl.texture!==undefined&&cnt<this._webgl.texture.length;cnt++)
{if(this._webgl.texture[cnt]){gl.deleteTexture(this._webgl.texture[cnt]);}}
for(var q=0;q<this._webgl.positions.length;q++)
{if(sp.position!==undefined){gl.deleteBuffer(this._webgl.buffers[5*q+1]);gl.deleteBuffer(this._webgl.buffers[5*q+0]);}
if(sp.normal!==undefined){gl.deleteBuffer(this._webgl.buffers[5*q+2]);}
if(sp.texcoord!==undefined){gl.deleteBuffer(this._webgl.buffers[5*q+3]);}
if(sp.color!==undefined){gl.deleteBuffer(this._webgl.buffers[5*q+4]);}}
for(var df=0;df<this._webgl.dynamicFields.length;df++)
{var attrib=this._webgl.dynamicFields[df];if(sp[attrib.name]!==undefined){gl.deleteBuffer(attrib.buf);}}
delete this._webgl;}};}
if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text))
{var fontStyleNode=shape._cf.geometry.node._cf.fontStyle.node;var font_family=['SERIF'];var font_size=32;var font_style="PLAIN";var font_spacing=1.0;var font_horizontal=true;var font_justify='BEGIN';var font_language="";var font_leftToRight=true;var font_topToBottom=true;if(fontStyleNode!==null){var fonts=fontStyleNode._vf.family.toString();fonts=fonts.trim().replace(/\'/g,'').replace(/\,/,' ');fonts=fonts.split(" ");font_family=Array.map(fonts,function(s){if(s=='SANS'){return'sans-serif';}
else if(s=='SERIF'){return'serif';}
else if(s=='TYPEWRITER'){return'monospace';}
else{return''+s+'';}}).join(",");font_style=fontStyleNode._vf.style.toString().replace(/\'/g,'');switch(font_style.toUpperCase()){case'PLAIN':font_style='normal';break;case'BOLD':font_style='bold';break;case'ITALIC':font_style='italic';break;case'BOLDITALIC':font_style='italic bold';break;default:font_style='normal';}
font_leftToRight=fontStyleNode._vf.leftToRight?'ltr':'rtl';font_topToBottom=fontStyleNode._vf.topToBottom;font_justify=fontStyleNode._vf.justify[0].toString().replace(/\'/g,'');switch(font_justify.toUpperCase()){case'BEGIN':font_justify='left';break;case'END':font_justify='right';break;case'FIRST':font_justify='left';break;case'MIDDLE':font_justify='center';break;default:font_justify='left';break;}
font_size=fontStyleNode._vf.size;font_spacing=fontStyleNode._vf.spacing;font_horizontal=fontStyleNode._vf.horizontal;font_language=fontStyleNode._vf.language;}
var paragraph=shape._cf.geometry.node._vf.string;var textX,textY;var text_canvas=document.createElement('canvas');text_canvas.dir=font_leftToRight;var textHeight=font_size;var textAlignment=font_justify;document.body.appendChild(text_canvas);var text_ctx=text_canvas.getContext('2d');text_ctx.font=font_style+" "+font_size+"px "+font_family;var maxWidth=text_ctx.measureText(paragraph[0]).width;for(var i=1;i<paragraph.length;i++){if(text_ctx.measureText(paragraph[i]).width>maxWidth)
maxWidth=text_ctx.measureText(paragraph[i]).width;}
text_canvas.width=maxWidth;text_canvas.height=textHeight*paragraph.length;switch(textAlignment){case"left":textX=0;break;case"center":textX=text_canvas.width/2;break;case"right":textX=text_canvas.width;break;}
var txtW=text_canvas.width;var txtH=text_canvas.height;text_ctx.fillStyle='rgba(0,0,0,0)';text_ctx.fillRect(0,0,text_ctx.canvas.width,text_ctx.canvas.height);text_ctx.fillStyle='white';text_ctx.lineWidth=2.5;text_ctx.strokeStyle='grey';text_ctx.textBaseline='top';text_ctx.font=font_style+" "+font_size+"px "+font_family;text_ctx.textAlign=textAlignment;for(var i=0;i<paragraph.length;i++){textY=i*textHeight;text_ctx.fillText(paragraph[i],textX,textY);}
var ids=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,ids);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,text_canvas);document.body.removeChild(text_canvas);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D,null);var w=txtW/100.0;var h=txtH/100.0;var v0=1,u0=0;var u=1,v=0;shape._cf.geometry.node._mesh._positions[0]=[-w,-h,0,w,-h,0,w,h,0,-w,h,0];shape._cf.geometry.node._mesh._normals[0]=[0,0,1,0,0,1,0,0,1,0,0,1];shape._cf.geometry.node._mesh._texCoords[0]=[u0,v,u,v,u,v0,u0,v0];shape._cf.geometry.node._mesh._colors[0]=[];shape._cf.geometry.node._mesh._indices[0]=[0,1,2,2,3,0];shape._cf.geometry.node._mesh._invalidate=true;shape._cf.geometry.node._mesh._numFaces=2;shape._cf.geometry.node._mesh._numCoords=4;shape._webgl={positions:shape._cf.geometry.node._mesh._positions,normals:shape._cf.geometry.node._mesh._normals,texcoords:shape._cf.geometry.node._mesh._texCoords,colors:shape._cf.geometry.node._mesh._colors,indexes:shape._cf.geometry.node._mesh._indices,texture:[ids],textureFilter:[gl.LINEAR],coordType:gl.FLOAT,normalType:gl.FLOAT,texCoordType:gl.FLOAT,colorType:gl.FLOAT,lightsAndShadow:useLightingFunc(viewarea),imageGeometry:0,indexedImageGeometry:0,binaryGeometry:0,bitLODGeometry:0};shape._webgl.primType=gl.TRIANGLES;if(x3dom.caps.MOBILE){shape._webgl.shader=this.getShaderProgram(gl,[this.generateVSMobile(viewarea,shape),this.generateFSMobile(viewarea,shape)]);}else{shape._webgl.shader=this.getShaderProgram(gl,[this.generateVS(viewarea,shape),this.generateFS(viewarea,shape)]);}}
else
{var context=this;tex=shape._cf.appearance.node._cf.texture.node;shape.updateTexture=function(tex,unit,saveSize)
{var that=this;var texture;var childTex=(tex._video!==undefined&&tex._video!==null&&tex._needPerFrameUpdate!==undefined&&tex._needPerFrameUpdate===true);if(this._webgl.texture===undefined){this._webgl.texture=[];}
if(this._webgl.textureFilter===undefined){that._webgl.textureFilter=[];that._webgl.textureFilter[unit]=gl.LINEAR;}
if(tex._isCanvas&&tex._canvas){texture=gl.createTexture();that._webgl.texture[unit]=texture;gl.bindTexture(gl.TEXTURE_2D,texture);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,tex._canvas);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D,null);}
else if(x3dom.isa(tex,x3dom.nodeTypes.RenderedTexture))
{that._webgl.texture[unit]=tex._webgl.fbo.tex;gl.bindTexture(gl.TEXTURE_2D,tex._webgl.fbo.tex);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D,null);}
else if(x3dom.isa(tex,x3dom.nodeTypes.PixelTexture))
{var pixels=new Uint8Array(tex._vf.image.toGL());var format=gl.NONE;switch(tex._vf.image.comp)
{case 1:format=gl.LUMINANCE;break;case 2:format=gl.LUMINANCE_ALPHA;break;case 3:format=gl.RGB;break;case 4:format=gl.RGBA;break;}
texture=gl.createTexture();that._webgl.texture[unit]=texture;gl.bindTexture(gl.TEXTURE_2D,texture);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.pixelStorei(gl.UNPACK_ALIGNMENT,1);gl.texImage2D(gl.TEXTURE_2D,0,format,tex._vf.image.width,tex._vf.image.height,0,format,gl.UNSIGNED_BYTE,pixels);}
else if(x3dom.isa(tex,x3dom.nodeTypes.MultiTexture))
{for(var cnt=0;cnt<tex.size();cnt++)
{var singleTex=tex.getTexture(cnt);if(!singleTex){break;}
that.updateTexture(singleTex,cnt,"false");}}
else if(x3dom.isa(tex,x3dom.nodeTypes.MovieTexture)||childTex)
{texture=gl.createTexture();if(!childTex)
{tex._video=document.createElement('video');tex._video.setAttribute('autobuffer','true');var p=document.getElementsByTagName('body')[0];p.appendChild(tex._video);tex._video.style.visibility="hidden";}
for(var i=0;i<tex._vf.url.length;i++)
{var videoUrl=tex._nameSpace.getURL(tex._vf.url[i]);x3dom.debug.logInfo('Adding video file: '+videoUrl);var src=document.createElement('source');src.setAttribute('src',videoUrl);tex._video.appendChild(src);}
var updateMovie=function()
{that._nameSpace.doc.needRender=true;if(saveSize=="index"||saveSize=="coord"||saveSize=="normal"||saveSize=="texCoord"){that._webgl.textureFilter[unit]=gl.NEAREST;}
gl.bindTexture(gl.TEXTURE_2D,texture);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,tex._video);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,that._webgl.textureFilter[unit]);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,that._webgl.textureFilter[unit]);gl.bindTexture(gl.TEXTURE_2D,null);};var startVideo=function()
{that._nameSpace.doc.needRender=true;that._webgl.texture[unit]=texture;if(saveSize=="coord"){that._webgl.coordTextureWidth=tex._video.clientWidth;that._webgl.coordTextureHeight=tex._video.clientHeight;}else if(saveSize=="index"){that._webgl.indexTextureWidth=tex._video.clientWidth;that._webgl.indexTextureHeight=tex._video.clientHeight;}
x3dom.debug.logInfo(texture+" video tex url: "+tex._vf.url[0]);tex._video.play();tex._intervalID=setInterval(updateMovie,16);};var videoDone=function()
{clearInterval(tex._intervalID);if(tex._vf.loop===true)
{tex._video.play();tex._intervalID=setInterval(updateMovie,16);}};tex._video.addEventListener("canplaythrough",startVideo,true);tex._video.addEventListener("ended",videoDone,true);}
else if(x3dom.isa(tex,x3dom.nodeTypes.X3DEnvironmentTextureNode))
{texture=context.loadCubeMap(gl,tex.getTexUrl(),that._nameSpace.doc,false);that._webgl.texture[unit]=texture;}
else
{var t00=new Date().getTime();texture=gl.createTexture();var image=new Image();image.crossOrigin='';image.src=tex._nameSpace.getURL(tex._vf.url[0]);that._nameSpace.doc.downloadCount+=1;image.onload=function()
{x3dom.ImageLoadManager.activeDownloads--;that._nameSpace.doc.needRender=true;that._nameSpace.doc.downloadCount-=1;if(tex._vf.scale){image=scaleImage(image);}
that._webgl.texture[unit]=texture;if(saveSize=="coord"){that._webgl.coordTextureWidth=image.width;that._webgl.coordTextureHeight=image.height;}else if(saveSize=="index"){that._webgl.indexTextureWidth=image.width;that._webgl.indexTextureHeight=image.height;}
if(saveSize=="index"||saveSize=="coord"||saveSize=="normal"||saveSize=="texCoord"||saveSize=="color"){that._webgl.textureFilter[unit]=gl.NEAREST;}else{that._webgl.textureFilter[unit]=gl.LINEAR;}
gl.bindTexture(gl.TEXTURE_2D,texture);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,image);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,that._webgl.textureFilter[unit]);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,that._webgl.textureFilter[unit]);gl.bindTexture(gl.TEXTURE_2D,null);tex._complete=true;var t11=new Date().getTime()-t00;};image.onerror=function()
{that._nameSpace.doc.downloadCount-=1;x3dom.debug.logError("Can't load tex url: "+tex._vf.url[0]+" (at unit "+unit+").");};}};var indexed=0,numCoordinateTextures=0;if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.ImageGeometry)&&!x3dom.caps.MOBILE)
{numCoordinateTextures=shape._cf.geometry.node.numCoordinateTextures();indexed=(shape._cf.geometry.node.getIndexTexture()!=null)?1.0:0.0;}
viewarea._scene._webgl.imageGeometry=numCoordinateTextures;viewarea._scene._webgl.bitLODGeometry=x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BitLODGeometry);shape._webgl={positions:shape._cf.geometry.node._mesh._positions,normals:shape._cf.geometry.node._mesh._normals,texcoords:shape._cf.geometry.node._mesh._texCoords,colors:shape._cf.geometry.node._mesh._colors,indexes:shape._cf.geometry.node._mesh._indices,coordType:gl.FLOAT,normalType:gl.FLOAT,texCoordType:gl.FLOAT,colorType:gl.FLOAT,lightsAndShadow:useLightingFunc(viewarea),imageGeometry:numCoordinateTextures,indexedImageGeometry:indexed,binaryGeometry:0,bitLODGeometry:0};if(tex){shape.updateTexture(tex,0,"false");}
if(shape._webgl.imageGeometry){var IG_texUnit=1;var indexTexture=shape._cf.geometry.node.getIndexTexture();if(indexTexture){shape.updateTexture(indexTexture,IG_texUnit++,'index');}
for(i=0;i<numCoordinateTextures;i++){var coordinateTexture=shape._cf.geometry.node.getCoordinateTexture(i);if(coordinateTexture){shape.updateTexture(coordinateTexture,IG_texUnit++,'coord');}}
var normalTexture=shape._cf.geometry.node.getNormalTexture(0);if(normalTexture){shape.updateTexture(normalTexture,IG_texUnit++,"normal");}
var texCoordTexture=shape._cf.geometry.node.getTexCoordTexture();if(texCoordTexture){shape.updateTexture(texCoordTexture,IG_texUnit++,"texCoord");}
var colorTexture=shape._cf.geometry.node.getColorTexture();if(colorTexture){shape.updateTexture(colorTexture,IG_texUnit++,"color");}
shape._cf.geometry.node._dirty.coord=false;shape._cf.geometry.node._dirty.normal=false;shape._cf.geometry.node._dirty.texCoord=false;shape._cf.geometry.node._dirty.color=false;shape._cf.geometry.node._dirty.index=false;}
if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.PointSet)||x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Polypoint2D))
{shape._webgl.primType=gl.POINTS;if(shape._webgl.colors[0].length){shape._webgl.shader=this.getShaderProgram(gl,['vs-x3d-vertexcolorUnlit','fs-x3d-vertexcolorUnlit']);}
else{shape._webgl.shader=this.getShaderProgram(gl,['vs-x3d-default','fs-x3d-default']);}}
else if((x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.IndexedLineSet))||(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Circle2D))||(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Arc2D))||(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Polyline2D)))
{shape._webgl.primType=gl.LINES;if(shape._webgl.colors[0].length){shape._webgl.shader=this.getShaderProgram(gl,['vs-x3d-vertexcolorUnlit','fs-x3d-vertexcolorUnlit']);}
else{shape._webgl.shader=this.getShaderProgram(gl,['vs-x3d-default','fs-x3d-default']);}}
else
{if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.ImageGeometry)){shape._webgl.primType=[];for(var i=0;i<shape._cf.geometry.node._vf.primType.length;i++){if(shape._cf.geometry.node._vf.primType[i].toUpperCase()=='POINTS'){shape._webgl.primType.push(gl.POINTS);}else if(shape._cf.geometry.node._vf.primType[i].toUpperCase()=='TRIANGLESTRIP'){shape._webgl.primType.push(gl.TRIANGLE_STRIP);}else{shape._webgl.primType.push(gl.TRIANGLES);}}}else if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.IndexedTriangleStripSet)&&shape._cf.geometry.node._mesh._primType.toUpperCase()=='TRIANGLESTRIP'){shape._webgl.primType=gl.TRIANGLE_STRIP;}else{shape._webgl.primType=gl.TRIANGLES;}
if(shape._cf.appearance.node._shader!==null){if(x3dom.isa(shape._cf.appearance.node._shader,x3dom.nodeTypes.CommonSurfaceShader)){var texCnt=0;var cssMode=0;var cssShader=shape._cf.appearance.node._shader;var diffuseTex=cssShader.getDiffuseMap();var normalTex=cssShader.getNormalMap();var specularTex=cssShader.getSpecularMap();if(diffuseTex!=null){shape.updateTexture(diffuseTex,texCnt++,"false");}
if(normalTex!=null){shape.updateTexture(normalTex,texCnt++,"false");}
if(specularTex!=null){shape.updateTexture(specularTex,texCnt++,"false");}
if(x3dom.caps.MOBILE){x3dom.debug.logWarning("No mobile shader for CommonSurfaceShader! Using high quality shader!");}
shape._webgl.shader=this.getShaderProgram(gl,[this.generateVS(viewarea,shape),this.generateFS(viewarea,shape)]);}
else{var hackID='HACK'+shape._objectID;g_shaders['vs-x3d-'+hackID]={};g_shaders['vs-x3d-'+hackID].type="vertex";g_shaders['vs-x3d-'+hackID].data=shape._cf.appearance.node._shader._vertex._vf.url[0];g_shaders['fs-x3d-'+hackID]={};g_shaders['fs-x3d-'+hackID].type="fragment";g_shaders['fs-x3d-'+hackID].data=shape._cf.appearance.node._shader._fragment._vf.url[0];shape._webgl.shader=getDefaultShaderProgram(gl,hackID);}}
else
{if(x3dom.caps.MOBILE){shape._webgl.shader=this.getShaderProgram(gl,[this.generateVSMobile(viewarea,shape),this.generateFSMobile(viewarea,shape)]);}else{shape._webgl.shader=this.getShaderProgram(gl,[this.generateVS(viewarea,shape),this.generateFS(viewarea,shape)]);}}}}
var sp=shape._webgl.shader;var currAttribs=0;shape._webgl.buffers=[];shape._webgl.dynamicFields=[];if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BinaryGeometry))
{var t00=new Date().getTime();shape._webgl.primType=[];for(var primCnt=0;primCnt<shape._cf.geometry.node._vf.primType.length;++primCnt)
{switch(shape._cf.geometry.node._vf.primType[primCnt].toUpperCase())
{case'POINTS':shape._webgl.primType.push(gl.POINTS);break;case'LINES':shape._webgl.primType.push(gl.LINES);break;case'TRIANGLESTRIP':shape._webgl.primType.push(gl.TRIANGLE_STRIP);break;case'TRIANGLES':default:shape._webgl.primType.push(gl.TRIANGLES);break;}}
shape._webgl.binaryGeometry=-1;shape._webgl.internalDownloadCount=0;if(shape._cf.geometry.node._vf.index.length>0)
{var xmlhttp0=new XMLHttpRequest();xmlhttp0.open("GET",encodeURI(shape._nameSpace.getURL(shape._cf.geometry.node._vf.index)),true);xmlhttp0.responseType="arraybuffer";shape._nameSpace.doc.downloadCount+=1;shape._webgl.internalDownloadCount+=1;xmlhttp0.send(null);xmlhttp0.onload=function()
{var XHR_buffer=xmlhttp0.response;var indicesBuffer=gl.createBuffer();shape._webgl.buffers[0]=indicesBuffer;var indexArray=getArrayBufferView("Uint16",XHR_buffer);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indicesBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexArray,gl.STATIC_DRAW);shape._webgl.binaryGeometry=1;var geoNode=shape._cf.geometry.node;if(geoNode._vf.vertexCount[0]==0)
geoNode._vf.vertexCount[0]=indexArray.length;geoNode._mesh._numFaces=0;for(var i=0;i<geoNode._vf.vertexCount.length;i++){if(shape._webgl.primType[i]==gl.TRIANGLE_STRIP)
geoNode._mesh._numFaces+=geoNode._vf.vertexCount[i]-2;else
geoNode._mesh._numFaces+=geoNode._vf.vertexCount[i]/3;}
indexArray=null;shape._nameSpace.doc.downloadCount-=1;shape._webgl.internalDownloadCount-=1;if(shape._webgl.internalDownloadCount==0)
shape._nameSpace.doc.needRender=true;var t11=new Date().getTime()-t00;x3dom.debug.logInfo("XHR0/ index load time: "+t11+" ms");};}
if(shape._cf.geometry.node._hasStrideOffset&&shape._cf.geometry.node._vf.coord.length>0)
{var xmlhttp=new XMLHttpRequest();xmlhttp.open("GET",encodeURI(shape._nameSpace.getURL(shape._cf.geometry.node._vf.coord)),true);xmlhttp.responseType="arraybuffer";shape._nameSpace.doc.downloadCount+=1;shape._webgl.internalDownloadCount+=1;xmlhttp.send(null);xmlhttp.onload=function()
{var XHR_buffer=xmlhttp.response;var geoNode=shape._cf.geometry.node;var attribTypeStr=geoNode._vf.coordType;shape._webgl.coordType=getVertexAttribType(attribTypeStr,gl);shape._webgl.normalType=shape._webgl.coordType;shape._webgl.texCoordType=shape._webgl.coordType;shape._webgl.colorType=shape._webgl.coordType;var attributes=getArrayBufferView(attribTypeStr,XHR_buffer);var dataLen=shape._coordStrideOffset[0]/getDataTypeSize(attribTypeStr);if(dataLen)
geoNode._mesh._numCoords=attributes.length/dataLen;var buffer=gl.createBuffer();shape._webgl.buffers[1]=buffer;gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,attributes,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);gl.enableVertexAttribArray(sp.position);if(shape._cf.geometry.node._vf.normal.length>0)
{shape._webgl.buffers[2]=buffer;gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,attributes,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.normal,3,shape._webgl.normalType,false,shape._normalStrideOffset[0],shape._normalStrideOffset[1]);gl.enableVertexAttribArray(sp.normal);}
if(shape._cf.geometry.node._vf.texCoord.length>0)
{shape._webgl.buffers[3]=buffer;gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,attributes,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.texcoord,2,shape._webgl.texCoordType,false,shape._texCoordStrideOffset[0],shape._texCoordStrideOffset[1]);gl.enableVertexAttribArray(sp.texcoord);}
if(shape._cf.geometry.node._vf.color.length>0)
{shape._webgl.buffers[4]=buffer;gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,attributes,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.color,3,shape._webgl.colorType,false,shape._colorStrideOffset[0],shape._colorStrideOffset[1]);gl.enableVertexAttribArray(sp.color);}
attributes=null;shape._nameSpace.doc.downloadCount-=1;shape._webgl.internalDownloadCount-=1;if(shape._webgl.internalDownloadCount==0)
shape._nameSpace.doc.needRender=true;var t11=new Date().getTime()-t00;x3dom.debug.logInfo("XHR/ interleaved array load time: "+t11+" ms");};}
if(!shape._cf.geometry.node._hasStrideOffset&&shape._cf.geometry.node._vf.coord.length>0)
{var xmlhttp1=new XMLHttpRequest();xmlhttp1.open("GET",encodeURI(shape._nameSpace.getURL(shape._cf.geometry.node._vf.coord)),true);xmlhttp1.responseType="arraybuffer";shape._nameSpace.doc.downloadCount+=1;shape._webgl.internalDownloadCount+=1;xmlhttp1.send(null);xmlhttp1.onload=function()
{var XHR_buffer=xmlhttp1.response;positionBuffer=gl.createBuffer();shape._webgl.buffers[1]=positionBuffer;gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);var attribTypeStr=shape._cf.geometry.node._vf.coordType;shape._webgl.coordType=getVertexAttribType(attribTypeStr,gl);var vertices=getArrayBufferView(attribTypeStr,XHR_buffer);gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);gl.vertexAttribPointer(sp.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);gl.enableVertexAttribArray(sp.position);shape._cf.geometry.node._mesh._numCoords=vertices.length/3;if((attribTypeStr=="Float32")&&(shape._vf.bboxSize.x<0||shape._vf.bboxSize.y<0||shape._vf.bboxSize.z<0))
{var min=new x3dom.fields.SFVec3f(vertices[0],vertices[1],vertices[2]);var max=new x3dom.fields.SFVec3f(vertices[0],vertices[1],vertices[2]);for(var i=3;i<vertices.length;i+=3)
{if(min.x>vertices[i+0]){min.x=vertices[i+0];}
if(min.y>vertices[i+1]){min.y=vertices[i+1];}
if(min.z>vertices[i+2]){min.z=vertices[i+2];}
if(max.x<vertices[i+0]){max.x=vertices[i+0];}
if(max.y<vertices[i+1]){max.y=vertices[i+1];}
if(max.z<vertices[i+2]){max.z=vertices[i+2];}}
shape._vf.bboxCenter.setValues(min.add(max).multiply(0.5));shape._vf.bboxSize.setValues(max.subtract(min));}
vertices=null;shape._nameSpace.doc.downloadCount-=1;shape._webgl.internalDownloadCount-=1;if(shape._webgl.internalDownloadCount==0)
shape._webgl.shape._nameSpace.doc.needRender=true;var t11=new Date().getTime()-t00;x3dom.debug.logInfo("XHR1/ coord load time: "+t11+" ms");};}
if(!shape._cf.geometry.node._hasStrideOffset&&shape._cf.geometry.node._vf.normal.length>0)
{var xmlhttp2=new XMLHttpRequest();xmlhttp2.open("GET",encodeURI(shape._nameSpace.getURL(shape._cf.geometry.node._vf.normal)),true);xmlhttp2.responseType="arraybuffer";shape._nameSpace.doc.downloadCount+=1;shape._webgl.internalDownloadCount+=1;xmlhttp2.send(null);xmlhttp2.onload=function()
{var XHR_buffer=xmlhttp2.response;var normalBuffer=gl.createBuffer();shape._webgl.buffers[2]=normalBuffer;var attribTypeStr=shape._cf.geometry.node._vf.normalType;shape._webgl.normalType=getVertexAttribType(attribTypeStr,gl);var normals=getArrayBufferView(attribTypeStr,XHR_buffer);gl.bindBuffer(gl.ARRAY_BUFFER,normalBuffer);gl.bufferData(gl.ARRAY_BUFFER,normals,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.normal,3,shape._webgl.normalType,false,shape._normalStrideOffset[0],shape._normalStrideOffset[1]);gl.enableVertexAttribArray(sp.normal);normals=null;shape._nameSpace.doc.downloadCount-=1;shape._webgl.internalDownloadCount-=1;if(shape._webgl.internalDownloadCount==0)
shape._nameSpace.doc.needRender=true;var t11=new Date().getTime()-t00;x3dom.debug.logInfo("XHR2/ normal load time: "+t11+" ms");};}
if(!shape._cf.geometry.node._hasStrideOffset&&shape._cf.geometry.node._vf.texCoord.length>0)
{var xmlhttp3=new XMLHttpRequest();xmlhttp3.open("GET",encodeURI(shape._nameSpace.getURL(shape._cf.geometry.node._vf.texCoord)),true);xmlhttp3.responseType="arraybuffer";shape._nameSpace.doc.downloadCount+=1;shape._webgl.internalDownloadCount+=1;xmlhttp3.send(null);xmlhttp3.onload=function()
{var XHR_buffer=xmlhttp3.response;var texcBuffer=gl.createBuffer();shape._webgl.buffers[3]=texcBuffer;var attribTypeStr=shape._cf.geometry.node._vf.texCoordType;shape._webgl.texCoordType=getVertexAttribType(attribTypeStr,gl);var texCoords=getArrayBufferView(attribTypeStr,XHR_buffer);gl.bindBuffer(gl.ARRAY_BUFFER,texcBuffer);gl.bufferData(gl.ARRAY_BUFFER,texCoords,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.texcoord,2,shape._webgl.texCoordType,false,shape._texCoordStrideOffset[0],shape._texCoordStrideOffset[1]);gl.enableVertexAttribArray(sp.texcoord);texCoords=null;shape._nameSpace.doc.downloadCount-=1;shape._webgl.internalDownloadCount-=1;if(shape._webgl.internalDownloadCount==0)
shape._nameSpace.doc.needRender=true;var t11=new Date().getTime()-t00;x3dom.debug.logInfo("XHR3/ texCoord load time: "+t11+" ms");};}
if(!shape._cf.geometry.node._hasStrideOffset&&shape._cf.geometry.node._vf.color.length>0)
{var xmlhttp4=new XMLHttpRequest();xmlhttp4.open("GET",encodeURI(shape._nameSpace.getURL(shape._cf.geometry.node._vf.color)),true);xmlhttp4.responseType="arraybuffer";shape._nameSpace.doc.downloadCount+=1;shape._webgl.internalDownloadCount+=1;xmlhttp4.send(null);xmlhttp4.onload=function()
{var XHR_buffer=xmlhttp4.response;var colorBuffer=gl.createBuffer();shape._webgl.buffers[4]=colorBuffer;var attribTypeStr=shape._cf.geometry.node._vf.colorType;shape._webgl.colorType=getVertexAttribType(attribTypeStr,gl);var colors=getArrayBufferView(attribTypeStr,XHR_buffer);gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer);gl.bufferData(gl.ARRAY_BUFFER,colors,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.color,3,shape._webgl.colorType,false,shape._colorStrideOffset[0],shape._colorStrideOffset[1]);gl.enableVertexAttribArray(sp.color);colors=null;shape._nameSpace.doc.downloadCount-=1;shape._webgl.internalDownloadCount-=1;if(shape._webgl.internalDownloadCount==0)
shape._nameSpace.doc.needRender=true;var t11=new Date().getTime()-t00;x3dom.debug.logInfo("XHR4/ color load time: "+t11+" ms");};}}
else if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.BitLODGeometry))
{shape._webgl.bitLODGeometry=-1;var bitLODGeometry=shape._cf.geometry.node;var numComponents=bitLODGeometry.getNumComponents();if(numComponents)
{shape._webgl.primType=[];for(var p=0;p<bitLODGeometry.getNumPrimTypes();++p)
{switch(bitLODGeometry.getPrimType(p))
{case'POINTS':shape._webgl.primType.push(gl.POINTS);break;case'LINES':shape._webgl.primType.push(gl.LINES);break;case'TRIANGLESTRIP':shape._webgl.primType.push(gl.TRIANGLE_STRIP);break;case'TRIANGLES':default:shape._webgl.primType.push(gl.TRIANGLES);break;}}
if(bitLODGeometry.hasIndex())
{var xmlhttp0=new XMLHttpRequest();xmlhttp0.open("GET",encodeURI(shape._nameSpace.getURL(bitLODGeometry._vf.index)),true);xmlhttp0.responseType="arraybuffer";shape._nameSpace.doc.downloadCount+=1;xmlhttp0.send(null);xmlhttp0.onload=function()
{var XHR_buffer=xmlhttp0.response;var indicesBuffer=gl.createBuffer();shape._webgl.buffers[0]=indicesBuffer;var indexArray=getArrayBufferView("Uint16",XHR_buffer);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indicesBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexArray,gl.STATIC_DRAW);shape._webgl.bitLODGeometry=1;if(bitLODGeometry.getVertexCount(0)==0)
bitLODGeometry.setVertexCount(0,indexArray.length);bitLODGeometry._mesh._numFaces=0;for(var p=0;p<bitLODGeometry.getNumPrimTypes();p++){if(shape._webgl.primType[p]==gl.TRIANGLE_STRIP)
bitLODGeometry._mesh._numFaces+=bitLODGeometry.getVertexCount(p)-2;else
bitLODGeometry._mesh._numFaces+=bitLODGeometry.getVertexCount(p)/3;}
indexArray=null;shape._nameSpace.doc.downloadCount-=1;shape._nameSpace.doc.needRender=true;};}
shape._webgl.bitLODComposer=new x3dom.BitLODComposer();var that=this;function callBack(refinedBuffer)
{var attribTypeStr=bitLODGeometry._vf.coordType;shape._webgl.coordType=getVertexAttribType(attribTypeStr,gl);shape._webgl.normalType=shape._webgl.coordType;var attributes=getArrayBufferView(attribTypeStr,refinedBuffer);var dataLen=shape._coordStrideOffset[0]/getDataTypeSize(attribTypeStr);if(dataLen)
bitLODGeometry._mesh._numCoords=attributes.length/dataLen;var buffer=gl.createBuffer();shape._webgl.buffers[1]=buffer;gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,attributes,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);gl.enableVertexAttribArray(sp.position);shape._webgl.buffers[2]=buffer;gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,attributes,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.normal,2,shape._webgl.normalType,false,shape._normalStrideOffset[0],shape._normalStrideOffset[1]);gl.enableVertexAttribArray(sp.normal);attributes=null;shape._nameSpace.doc.needRender=true;shape._webgl.bitLODComposer.refine(refinedBuffer);};shape._webgl.bitLODComposer.run([3,2],[16,16],[6,2],bitLODGeometry.getComponentsURLs(),callBack,[0,64],96);}}
else if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.ImageGeometry))
{if(this.IG_PositionBuffer==null){this.IG_PositionBuffer=gl.createBuffer();}
shape._webgl.buffers[1]=this.IG_PositionBuffer;gl.bindBuffer(gl.ARRAY_BUFFER,this.IG_PositionBuffer);vertices=new Float32Array(shape._webgl.positions[0]);gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);gl.bindBuffer(gl.ARRAY_BUFFER,this.IG_PositionBuffer);gl.vertexAttribPointer(sp.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);gl.enableVertexAttribArray(sp.position);vertices=null;}
else
{for(q=0;q<shape._webgl.positions.length;q++)
{if(sp.position!==undefined)
{var indicesBuffer=gl.createBuffer();shape._webgl.buffers[5*q+0]=indicesBuffer;var indexArray=new Uint16Array(shape._webgl.indexes[q]);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indicesBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexArray,gl.STATIC_DRAW);indexArray=null;positionBuffer=gl.createBuffer();shape._webgl.buffers[5*q+1]=positionBuffer;gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);vertices=new Float32Array(shape._webgl.positions[q]);gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);gl.vertexAttribPointer(sp.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);gl.enableVertexAttribArray(sp.position);vertices=null;}
if(sp.normal!==undefined)
{var normalBuffer=gl.createBuffer();shape._webgl.buffers[5*q+2]=normalBuffer;var normals=new Float32Array(shape._webgl.normals[q]);gl.bindBuffer(gl.ARRAY_BUFFER,normalBuffer);gl.bufferData(gl.ARRAY_BUFFER,normals,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.normal,3,shape._webgl.normalType,false,shape._normalStrideOffset[0],shape._normalStrideOffset[1]);gl.enableVertexAttribArray(sp.normal);normals=null;}
if(sp.texcoord!==undefined)
{var texcBuffer=gl.createBuffer();shape._webgl.buffers[5*q+3]=texcBuffer;var texCoords=new Float32Array(shape._webgl.texcoords[q]);gl.bindBuffer(gl.ARRAY_BUFFER,texcBuffer);gl.bufferData(gl.ARRAY_BUFFER,texCoords,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.texcoord,shape._cf.geometry.node._mesh._numTexComponents,shape._webgl.texCoordType,false,shape._texCoordStrideOffset[0],shape._texCoordStrideOffset[1]);gl.enableVertexAttribArray(sp.texcoord);texCoords=null;}
if(sp.color!==undefined)
{var colorBuffer=gl.createBuffer();shape._webgl.buffers[5*q+4]=colorBuffer;var colors=new Float32Array(shape._webgl.colors[q]);gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer);gl.bufferData(gl.ARRAY_BUFFER,colors,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.color,shape._cf.geometry.node._mesh._numColComponents,shape._webgl.colorType,false,shape._colorStrideOffset[0],shape._colorStrideOffset[1]);gl.enableVertexAttribArray(sp.color);colors=null;}}
for(var df in shape._cf.geometry.node._mesh._dynamicFields)
{var attrib=shape._cf.geometry.node._mesh._dynamicFields[df];shape._webgl.dynamicFields[currAttribs]={buf:{},name:df,numComponents:attrib.numComponents};if(sp[df]!==undefined)
{var attribBuffer=gl.createBuffer();shape._webgl.dynamicFields[currAttribs++].buf=attribBuffer;var attribs=new Float32Array(attrib.value);gl.bindBuffer(gl.ARRAY_BUFFER,attribBuffer);gl.bufferData(gl.ARRAY_BUFFER,attribs,gl.STATIC_DRAW);gl.vertexAttribPointer(sp[df],attrib.numComponents,gl.FLOAT,false,0,0);attribs=null;}}}
shape._webgl._minFilterDic={NEAREST:gl.NEAREST,LINEAR:gl.LINEAR,NEAREST_MIPMAP_NEAREST:gl.NEAREST_MIPMAP_NEAREST,NEAREST_MIPMAP_LINEAR:gl.NEAREST_MIPMAP_LINEAR,LINEAR_MIPMAP_NEAREST:gl.LINEAR_MIPMAP_NEAREST,LINEAR_MIPMAP_LINEAR:gl.LINEAR_MIPMAP_LINEAR,AVG_PIXEL:gl.LINEAR,AVG_PIXEL_AVG_MIPMAP:gl.LINEAR_MIPMAP_LINEAR,AVG_PIXEL_NEAREST_MIPMAP:gl.LINEAR_MIPMAP_NEAREST,DEFAULT:gl.LINEAR_MIPMAP_LINEAR,FASTEST:gl.NEAREST,NEAREST_PIXEL:gl.NEAREST,NEAREST_PIXEL_AVG_MIPMAP:gl.NEAREST_MIPMAP_LINEAR,NEAREST_PIXEL_NEAREST_MIPMAP:gl.NEAREST_MIPMAP_NEAREST,NICEST:gl.LINEAR_MIPMAP_LINEAR};shape._webgl._magFilterDic={NEAREST:gl.NEAREST,LINEAR:gl.LINEAR,AVG_PIXEL:gl.LINEAR,DEFAULT:gl.LINEAR,FASTEST:gl.NEAREST,NEAREST_PIXEL:gl.NEAREST,NICEST:gl.LINEAR};shape._webgl._boundaryModesDic={CLAMP:gl.CLAMP_TO_EDGE,CLAMP_TO_EDGE:gl.CLAMP_TO_EDGE,CLAMP_TO_BOUNDARY:gl.CLAMP_TO_EDGE,MIRRORED_REPEAT:gl.MIRRORED_REPEAT,REPEAT:gl.REPEAT};};Context.prototype.setupScene=function(gl,bgnd){var sphere;var texture;if(bgnd._webgl!==undefined)
{if(!bgnd._dirty){return;}
if(bgnd._webgl.texture!==undefined&&bgnd._webgl.texture)
{gl.deleteTexture(bgnd._webgl.texture);}
if(bgnd._webgl.shader.position!==undefined)
{gl.deleteBuffer(bgnd._webgl.buffers[1]);gl.deleteBuffer(bgnd._webgl.buffers[0]);}
if(bgnd._webgl.shader.texcoord!==undefined)
{gl.deleteBuffer(bgnd._webgl.buffers[2]);}
bgnd._webgl={};}
bgnd._dirty=false;var url=bgnd.getTexUrl();var i=0;var w=1,h=1;if(url.length>0&&url[0].length>0)
{if(url.length>=6&&url[1].length>0&&url[2].length>0&&url[3].length>0&&url[4].length>0&&url[5].length>0)
{sphere=new x3dom.nodeTypes.Sphere();bgnd._webgl={positions:sphere._mesh._positions[0],indexes:sphere._mesh._indices[0],buffers:[{},{}]};bgnd._webgl.primType=gl.TRIANGLES;bgnd._webgl.shader=this.getShaderProgram(gl,['vs-x3d-bg-textureCube','fs-x3d-bg-textureCube']);bgnd._webgl.texture=this.loadCubeMap(gl,url,bgnd._nameSpace.doc,true);}
else{texture=gl.createTexture();var image=new Image();image.crossOrigin='';image.onload=function(){bgnd._nameSpace.doc.needRender=true;bgnd._nameSpace.doc.downloadCount-=1;bgnd._webgl.texture=texture;gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,true);gl.bindTexture(gl.TEXTURE_2D,texture);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,image);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.bindTexture(gl.TEXTURE_2D,null);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,false);};image.onerror=function()
{bgnd._nameSpace.doc.downloadCount-=1;x3dom.debug.logError("Can't load tex url: "+url[0]);};image.src=bgnd._nameSpace.getURL(url[0]);bgnd._nameSpace.doc.downloadCount+=1;bgnd._webgl={positions:[-w,-h,0,-w,h,0,w,-h,0,w,h,0],indexes:[0,1,2,3],buffers:[{},{}]};bgnd._webgl.primType=gl.TRIANGLE_STRIP;bgnd._webgl.shader=this.getShaderProgram(gl,['vs-x3d-bg-texture','fs-x3d-bg-texture']);}}
else
{if(bgnd.getSkyColor().length>1||bgnd.getGroundColor().length)
{sphere=new x3dom.nodeTypes.Sphere();texture=gl.createTexture();bgnd._webgl={positions:sphere._mesh._positions[0],texcoords:sphere._mesh._texCoords[0],indexes:sphere._mesh._indices[0],buffers:[{},{},{}],texture:texture,primType:gl.TRIANGLES};var N=nextHighestPowerOfTwo(bgnd.getSkyColor().length+bgnd.getGroundColor().length+2);N=(N<512)?512:N;var n=bgnd._vf.groundAngle.length;var tmp=[],arr=[];var colors=[],sky=[0];for(i=0;i<bgnd._vf.skyColor.length;i++){colors[i]=bgnd._vf.skyColor[i];}
for(i=0;i<bgnd._vf.skyAngle.length;i++){sky[i+1]=bgnd._vf.skyAngle[i];}
if(n>0){if(sky[sky.length-1]<Math.PI/2){sky[sky.length]=Math.PI/2-x3dom.fields.Eps;colors[colors.length]=colors[colors.length-1];}
for(i=n-1;i>=0;i--){if((i==n-1)&&(Math.PI-bgnd._vf.groundAngle[i]<=Math.PI/2)){sky[sky.length]=Math.PI/2;colors[colors.length]=bgnd._vf.groundColor[bgnd._vf.groundColor.length-1];}
sky[sky.length]=Math.PI-bgnd._vf.groundAngle[i];colors[colors.length]=bgnd._vf.groundColor[i+1];}
sky[sky.length]=Math.PI;colors[colors.length]=bgnd._vf.groundColor[0];}
else{if(sky[sky.length-1]<Math.PI){sky[sky.length]=Math.PI;colors[colors.length]=colors[colors.length-1];}}
for(i=0;i<sky.length;i++){sky[i]/=Math.PI;}
x3dom.debug.assert(sky.length==colors.length);var interp=new x3dom.nodeTypes.ColorInterpolator();interp._vf.key=new x3dom.fields.MFFloat(sky);interp._vf.keyValue=new x3dom.fields.MFColor(colors);for(i=0;i<N;i++){var fract=i/(N-1.0);interp._vf.set_fraction=fract;interp.fieldChanged("set_fraction");tmp[i]=interp._vf.value_changed;}
tmp.reverse();for(i=0;i<tmp.length;i++){arr[3*i+0]=Math.floor(tmp[i].r*255);arr[3*i+1]=Math.floor(tmp[i].g*255);arr[3*i+2]=Math.floor(tmp[i].b*255);}
var pixels=new Uint8Array(arr);var format=gl.RGB;N=(pixels.length)/3;gl.bindTexture(gl.TEXTURE_2D,texture);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);gl.pixelStorei(gl.UNPACK_ALIGNMENT,1);gl.texImage2D(gl.TEXTURE_2D,0,format,1,N,0,format,gl.UNSIGNED_BYTE,pixels);gl.bindTexture(gl.TEXTURE_2D,null);bgnd._webgl.shader=this.getShaderProgram(gl,['vs-x3d-bg-texture-bgnd','fs-x3d-bg-texture']);}
else
{bgnd._webgl={};}}
if(bgnd._webgl.shader)
{var sp=bgnd._webgl.shader;var positionBuffer=gl.createBuffer();bgnd._webgl.buffers[1]=positionBuffer;gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);var vertices=new Float32Array(bgnd._webgl.positions);gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);gl.vertexAttribPointer(sp.position,3,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(sp.position);var indicesBuffer=gl.createBuffer();bgnd._webgl.buffers[0]=indicesBuffer;var indexArray=new Uint16Array(bgnd._webgl.indexes);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indicesBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexArray,gl.STATIC_DRAW);vertices=null;indexArray=null;if(sp.texcoord!==undefined)
{var texcBuffer=gl.createBuffer();bgnd._webgl.buffers[2]=texcBuffer;var texcoords=new Float32Array(bgnd._webgl.texcoords);gl.bindBuffer(gl.ARRAY_BUFFER,texcBuffer);gl.bufferData(gl.ARRAY_BUFFER,texcoords,gl.STATIC_DRAW);gl.vertexAttribPointer(sp.texcoord,2,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(sp.texcoord);texcoords=null;}}
bgnd._webgl.render=function(gl,mat_view,mat_proj)
{var sp=bgnd._webgl.shader;var mat_scene=null;var projMatrix_22=mat_proj._22,projMatrix_23=mat_proj._23;if((sp!==undefined&&sp!==null)&&(sp.texcoord!==undefined&&sp.texcoord!==null)&&(bgnd._webgl.texture!==undefined&&bgnd._webgl.texture!==null))
{gl.clearDepth(1.0);gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT|gl.STENCIL_BUFFER_BIT);gl.frontFace(gl.CCW);gl.disable(gl.CULL_FACE);gl.disable(gl.DEPTH_TEST);gl.disable(gl.BLEND);sp.bind();if(!sp.tex){sp.tex=0;}
sp.alpha=1.0;mat_proj._22=100001/99999;mat_proj._23=200000/99999;mat_scene=mat_proj.mult(mat_view);sp.modelViewProjectionMatrix=mat_scene.toGL();mat_proj._22=projMatrix_22;mat_proj._23=projMatrix_23;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,bgnd._webgl.texture);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,bgnd._webgl.buffers[0]);gl.bindBuffer(gl.ARRAY_BUFFER,bgnd._webgl.buffers[1]);gl.vertexAttribPointer(sp.position,3,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(sp.position);gl.bindBuffer(gl.ARRAY_BUFFER,bgnd._webgl.buffers[2]);gl.vertexAttribPointer(sp.texcoord,2,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(sp.texcoord);try{gl.drawElements(bgnd._webgl.primType,bgnd._webgl.indexes.length,gl.UNSIGNED_SHORT,0);}
catch(e){x3dom.debug.logException("Render background: "+e);}
gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,null);gl.disableVertexAttribArray(sp.position);gl.disableVertexAttribArray(sp.texcoord);gl.clear(gl.DEPTH_BUFFER_BIT|gl.STENCIL_BUFFER_BIT);}
else if(!sp||!bgnd._webgl.texture||(bgnd._webgl.texture.textureCubeReady!==undefined&&bgnd._webgl.texture.textureCubeReady!==true))
{var bgCol=bgnd.getSkyColor().toGL();bgCol[3]=1.0-bgnd.getTransparency();gl.clearColor(bgCol[0],bgCol[1],bgCol[2],bgCol[3]);gl.clearDepth(1.0);gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT|gl.STENCIL_BUFFER_BIT);}
else
{gl.clearDepth(1.0);gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT|gl.STENCIL_BUFFER_BIT);gl.frontFace(gl.CCW);gl.disable(gl.CULL_FACE);gl.disable(gl.DEPTH_TEST);gl.disable(gl.BLEND);sp.bind();if(!sp.tex){sp.tex=0;}
if(bgnd._webgl.texture.textureCubeReady){mat_proj._22=100001/99999;mat_proj._23=200000/99999;mat_scene=mat_proj.mult(mat_view);sp.modelViewProjectionMatrix=mat_scene.toGL();mat_proj._22=projMatrix_22;mat_proj._23=projMatrix_23;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_CUBE_MAP,bgnd._webgl.texture);gl.texParameteri(gl.TEXTURE_CUBE_MAP,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_CUBE_MAP,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_CUBE_MAP,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_CUBE_MAP,gl.TEXTURE_MAG_FILTER,gl.LINEAR);}
else{gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,bgnd._webgl.texture);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,bgnd._webgl.buffers[0]);gl.bindBuffer(gl.ARRAY_BUFFER,bgnd._webgl.buffers[1]);gl.vertexAttribPointer(sp.position,3,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(sp.position);try{gl.drawElements(bgnd._webgl.primType,bgnd._webgl.indexes.length,gl.UNSIGNED_SHORT,0);}
catch(e){x3dom.debug.logException("Render background: "+e);}
gl.disableVertexAttribArray(sp.position);if(bgnd._webgl.texture.textureCubeReady){gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_CUBE_MAP,null);}
else{gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,null);}
gl.clear(gl.DEPTH_BUFFER_BIT|gl.STENCIL_BUFFER_BIT);}};};Context.prototype.setupFgnds=function(gl,scene)
{if(scene._fgnd!==undefined){return;}
var w=1,h=1;scene._fgnd={};scene._fgnd._webgl={positions:[-w,-h,0,-w,h,0,w,-h,0,w,h,0],indexes:[0,1,2,3],buffers:[{},{}]};scene._fgnd._webgl.primType=gl.TRIANGLE_STRIP;scene._fgnd._webgl.shader=this.getShaderProgram(gl,['vs-x3d-bg-texture','fs-x3d-bg-texture']);var sp=scene._fgnd._webgl.shader;var positionBuffer=gl.createBuffer();scene._fgnd._webgl.buffers[1]=positionBuffer;gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);var vertices=new Float32Array(scene._fgnd._webgl.positions);gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);gl.vertexAttribPointer(sp.position,3,gl.FLOAT,false,0,0);var indicesBuffer=gl.createBuffer();scene._fgnd._webgl.buffers[0]=indicesBuffer;var indexArray=new Uint16Array(scene._fgnd._webgl.indexes);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indicesBuffer);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexArray,gl.STATIC_DRAW);vertices=null;indexArray=null;scene._fgnd._webgl.render=function(gl,tex)
{scene._fgnd._webgl.texture=tex;gl.frontFace(gl.CCW);gl.disable(gl.CULL_FACE);gl.disable(gl.DEPTH_TEST);sp.bind();if(!sp.tex){sp.tex=0;}
gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,scene._fgnd._webgl.texture);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,scene._fgnd._webgl.buffers[0]);gl.bindBuffer(gl.ARRAY_BUFFER,scene._fgnd._webgl.buffers[1]);gl.vertexAttribPointer(sp.position,3,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(sp.position);try{gl.drawElements(scene._fgnd._webgl.primType,scene._fgnd._webgl.indexes.length,gl.UNSIGNED_SHORT,0);}
catch(e){x3dom.debug.logException("Render background: "+e);}
gl.disableVertexAttribArray(sp.position);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,null);};};Context.prototype.renderShadowPass=function(gl,scene,mat_light,mat_scene)
{gl.bindFramebuffer(gl.FRAMEBUFFER,scene._webgl.fboShadow.fbo);gl.viewport(0,0,scene._webgl.fboShadow.width,scene._webgl.fboShadow.height);gl.clearColor(1.0,1.0,1.0,1.0);gl.clearDepth(1.0);gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);gl.depthFunc(gl.LEQUAL);gl.enable(gl.DEPTH_TEST);gl.enable(gl.CULL_FACE);gl.disable(gl.BLEND);var sp=scene._webgl.shadowShader;sp.bind();var i,n=scene.drawableObjects.length;for(i=0;i<n;i++)
{var trafo=scene.drawableObjects[i][0];var shape=scene.drawableObjects[i][1];sp.modelViewMatrix=mat_light.mult(trafo).toGL();sp.modelViewProjectionMatrix=mat_scene.mult(trafo).toGL();for(var q=0;q<shape._webgl.positions.length;q++)
{if(shape._webgl.buffers[5*q+0])
{gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,shape._webgl.buffers[5*q+0]);}
if(sp.position!==undefined&&shape._webgl.buffers[5*q+1])
{gl.bindBuffer(gl.ARRAY_BUFFER,shape._webgl.buffers[5*q+1]);gl.vertexAttribPointer(sp.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);gl.enableVertexAttribArray(sp.position);}
try{if(shape._webgl.indexes&&shape._webgl.indexes[q]){if(shape._webgl.imageGeometry||shape._webgl.binaryGeometry<0||shape._webgl.bitLODGeometry<0){for(var v=0,offset=0;v<shape._cf.geometry.node._vf.vertexCount.length;v++){gl.drawArrays(shape._webgl.primType[v],offset,shape._cf.geometry.node._vf.vertexCount[v]);offset+=shape._cf.geometry.node._vf.vertexCount[v];}}
else if(shape._webgl.binaryGeometry>0||shape._webgl.bitLODGeometry>0){for(var v=0,offset=0;v<shape._cf.geometry.node._vf.vertexCount.length;v++){gl.drawElements(shape._webgl.primType[v],shape._cf.geometry.node._vf.vertexCount[v],gl.UNSIGNED_SHORT,2*offset);offset+=shape._cf.geometry.node._vf.vertexCount[v];}}
else if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.IndexedTriangleStripSet)&&shape._webgl.primType==gl.TRIANGLE_STRIP){var indOff=shape._cf.geometry.node._indexOffset;for(var io=1;io<indOff.length;io++){gl.drawElements(gl.TRIANGLE_STRIP,indOff[io]-indOff[io-1],gl.UNSIGNED_SHORT,2*indOff[io-1]);}}
else{gl.drawElements(shape._webgl.primType,shape._webgl.indexes[q].length,gl.UNSIGNED_SHORT,0);}}}
catch(e){x3dom.debug.logException(shape._DEF+" renderShadowPass(): "+e);}
if(sp.position!==undefined){gl.disableVertexAttribArray(sp.position);}}}
gl.flush();gl.bindFramebuffer(gl.FRAMEBUFFER,null);};Context.prototype.renderPickingPass=function(gl,scene,mat_view,mat_scene,min,max,pickMode,lastX,lastY)
{gl.bindFramebuffer(gl.FRAMEBUFFER,scene._webgl.fboPick.fbo);gl.viewport(0,0,scene._webgl.fboPick.width,scene._webgl.fboPick.height);gl.clearColor(0.0,0.0,0.0,1.0);gl.clearDepth(1.0);gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);gl.depthFunc(gl.LEQUAL);gl.enable(gl.DEPTH_TEST);gl.enable(gl.CULL_FACE);gl.disable(gl.BLEND);var sp=null;if(pickMode===0)
{if(scene._webgl.imageGeometry>0&&!x3dom.caps.MOBILE)
{sp=scene._webgl.pickShaderIG;}
else if(scene._webgl.bitLODGeometry!=0)
{sp=scene._webgl.pickShaderBLG;}
else
{sp=scene._webgl.pickShader;}}
else if(pickMode===1)
{sp=scene._webgl.pickColorShader;}
else if(pickMode===2)
{sp=scene._webgl.pickTexCoordShader;}
sp.bind();var bgCenter=new x3dom.fields.SFVec3f(0,0,0).toGL();var bgSize=new x3dom.fields.SFVec3f(1,1,1).toGL();for(var i=0;i<scene.drawableObjects.length;i++)
{var trafo=scene.drawableObjects[i][0];var shape=scene.drawableObjects[i][1];if(shape._objectID<1||shape._webgl===undefined){continue;}
if(i>0){var prev_shape=scene.drawableObjects[i-1][1];}
if(i<scene.drawableObjects.length-1){var next_shape=scene.drawableObjects[i+1][1];}
sp.modelMatrix=trafo.toGL();sp.modelViewProjectionMatrix=mat_scene.mult(trafo).toGL();sp.wcMin=min.toGL();sp.wcMax=max.toGL();sp.alpha=1.0-shape._objectID/255.0;sp.imageGeometry=0.0;if(shape._webgl.coordType!=gl.FLOAT)
{sp.bgCenter=shape._cf.geometry.node._vf.position.toGL();sp.bgSize=shape._cf.geometry.node._vf.size.toGL();sp.bgPrecisionMax=shape._cf.geometry.node.getPrecisionMax('coordType');}else{sp.bgCenter=bgCenter;sp.bgSize=bgSize;sp.bgPrecisionMax=1;}
if(shape._webgl.colorType!=gl.FLOAT){sp.bgPrecisionColMax=shape._cf.geometry.node.getPrecisionMax('colorType');}
if(shape._webgl.texCoordType!=gl.FLOAT){sp.bgPrecisionTexMax=shape._cf.geometry.node.getPrecisionMax('texCoordType');}
if(shape._webgl.bitLODGeometry!=0)
{sp.BLG_bboxMin=shape._cf.geometry.node.getMin().toGL();sp.BLG_bboxMax=shape._cf.geometry.node.getMax().toGL();}
if(shape._webgl.imageGeometry)
{sp.imageGeometry=1.0;sp.IG_bboxMin=shape._cf.geometry.node.getMin().toGL();sp.IG_bboxMax=shape._cf.geometry.node.getMax().toGL();sp.IG_coordTextureWidth=shape._webgl.coordTextureWidth;sp.IG_coordTextureHeight=shape._webgl.coordTextureHeight;sp.IG_implicitMeshSize=shape._cf.geometry.node._vf.implicitMeshSize.x;if(shape._webgl.indexedImageGeometry){sp.indexed=1.0;sp.IG_indexTextureWidth=shape._webgl.indexTextureWidth;sp.IG_indexTextureHeight=shape._webgl.indexTextureHeight;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,shape._webgl.texture[1]);gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D,shape._webgl.texture[2]);}else{sp.indexed=0.0;gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,shape._webgl.texture[1]);}
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);var texUnit=0;if(shape._cf.geometry.node.getIndexTexture()){if(!sp.IG_indexTexture){sp.IG_indexTexture=texUnit++;}}
if(shape._cf.geometry.node.getCoordinateTexture(0)){if(!sp.IG_coordinateTexture){sp.IG_coordinateTexture=texUnit++;}}}
for(var q=0;q<shape._webgl.positions.length;q++)
{if(!prev_shape||(prev_shape&&prev_shape._cf.geometry.node._mesh!==shape._cf.geometry.node._mesh))
{if(shape._webgl.buffers[5*q+0])
{gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,shape._webgl.buffers[5*q+0]);}
if(sp.position!==undefined&&shape._webgl.buffers[5*q+1])
{gl.bindBuffer(gl.ARRAY_BUFFER,shape._webgl.buffers[5*q+1]);gl.vertexAttribPointer(sp.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);gl.enableVertexAttribArray(sp.position);}
if(sp.color!==undefined&&shape._webgl.buffers[5*q+4])
{gl.bindBuffer(gl.ARRAY_BUFFER,shape._webgl.buffers[5*q+4]);gl.vertexAttribPointer(sp.color,shape._cf.geometry.node._mesh._numColComponents,shape._webgl.colorType,false,shape._colorStrideOffset[0],shape._colorStrideOffset[1]);gl.enableVertexAttribArray(sp.color);}
if(sp.texcoord!==undefined&&shape._webgl.buffers[5*q+3])
{gl.bindBuffer(gl.ARRAY_BUFFER,shape._webgl.buffers[5*q+3]);gl.vertexAttribPointer(sp.texcoord,shape._cf.geometry.node._mesh._numTexComponents,shape._webgl.texCoordType,false,shape._texCoordStrideOffset[0],shape._texCoordStrideOffset[1]);gl.enableVertexAttribArray(sp.texcoord);}}
if(shape.isSolid()){gl.enable(gl.CULL_FACE);if(shape.isCCW()){gl.frontFace(gl.CCW);}
else{gl.frontFace(gl.CW);}}
else{gl.disable(gl.CULL_FACE);}
try{if(shape._webgl.indexes&&shape._webgl.indexes[q]){if(shape._webgl.imageGeometry||shape._webgl.binaryGeometry<0||shape._webgl.bitLODGeometry<0){for(var v=0,offset=0;v<shape._cf.geometry.node._vf.vertexCount.length;v++){gl.drawArrays(shape._webgl.primType[v],offset,shape._cf.geometry.node._vf.vertexCount[v]);offset+=shape._cf.geometry.node._vf.vertexCount[v];}}
else if(shape._webgl.binaryGeometry>0||shape._webgl.bitLODGeometry>0){for(var v=0,offset=0;v<shape._cf.geometry.node._vf.vertexCount.length;v++){gl.drawElements(shape._webgl.primType[v],shape._cf.geometry.node._vf.vertexCount[v],gl.UNSIGNED_SHORT,2*offset);offset+=shape._cf.geometry.node._vf.vertexCount[v];}}
else if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.IndexedTriangleStripSet)&&shape._webgl.primType==gl.TRIANGLE_STRIP){var indOff=shape._cf.geometry.node._indexOffset;for(var io=1;io<indOff.length;io++){gl.drawElements(gl.TRIANGLE_STRIP,indOff[io]-indOff[io-1],gl.UNSIGNED_SHORT,2*indOff[io-1]);}}
else{gl.drawElements(shape._webgl.primType,shape._webgl.indexes[q].length,gl.UNSIGNED_SHORT,0);}}}
catch(e){x3dom.debug.logException(shape._DEF+" renderPickingPass(): "+e);}
if(!next_shape||(next_shape&&next_shape._cf.geometry.node._mesh!==shape._cf.geometry.node._mesh))
{if(sp.position!==undefined){gl.disableVertexAttribArray(sp.position);}
if(sp.color!==undefined){gl.disableVertexAttribArray(sp.color);}
if(sp.texcoord!==undefined){gl.disableVertexAttribArray(sp.texcoord);}}}}
gl.flush();try{var x=lastX*scene._webgl.pickScale,y=scene._webgl.fboPick.height-1-lastY*scene._webgl.pickScale;var data=new Uint8Array(4);gl.readPixels(x,y,1,1,gl.RGBA,gl.UNSIGNED_BYTE,data);scene._webgl.fboPick.pixelData=data;}
catch(se){scene._webgl.fboPick.pixelData=[];x3dom.debug.logException(se+" (cannot pick)");}
gl.bindFramebuffer(gl.FRAMEBUFFER,null);};Context.prototype.renderShape=function(transform,shape,prev_shape,next_shape,viewarea,slights,numLights,mat_view,mat_scene,mat_light,mat_proj,gl,oneShadowExistsAlready)
{if(shape._webgl===undefined){return;}
var tex=null;var scene=viewarea._scene;var sp=shape._webgl.shader;if(!sp){shape._webgl.shader=getDefaultShaderProgram(gl,'default');sp=shape._webgl.shader;}
sp.bind();if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.Text)){sp.useText=1.0;}else{sp.useText=0.0;}
if(shape._webgl.coordType!=gl.FLOAT)
{sp.bgCenter=shape._cf.geometry.node._vf.position.toGL();sp.bgSize=shape._cf.geometry.node._vf.size.toGL();sp.bgPrecisionMax=shape._cf.geometry.node.getPrecisionMax('coordType');}
if(shape._webgl.colorType!=gl.FLOAT){sp.bgPrecisionColMax=shape._cf.geometry.node.getPrecisionMax('colorType');}
if(shape._webgl.texCoordType!=gl.FLOAT){sp.bgPrecisionTexMax=shape._cf.geometry.node.getPrecisionMax('texCoordType');}
if(shape._webgl.normalType!=gl.FLOAT){sp.bgPrecisionNorMax=shape._cf.geometry.node.getPrecisionMax('normalType');}
if(shape._webgl.imageGeometry){sp.IG_bboxMin=shape._cf.geometry.node.getMin().toGL();sp.IG_bboxMax=shape._cf.geometry.node.getMax().toGL();sp.IG_coordTextureWidth=shape._webgl.coordTextureWidth;sp.IG_coordTextureHeight=shape._webgl.coordTextureHeight;sp.IG_implicitMeshSize=shape._cf.geometry.node._vf.implicitMeshSize.x;if(shape._webgl.indexedImageGeometry){sp.IG_indexTextureWidth=shape._webgl.indexTextureWidth;sp.IG_indexTextureHeight=shape._webgl.indexTextureHeight;}
var IG_texUnit=1;if(shape._cf.geometry.node.getIndexTexture()){sp.IG_indexTexture=IG_texUnit++;}
for(var i=0;i<shape._webgl.imageGeometry;i++){if(shape._cf.geometry.node.getCoordinateTexture(i)){sp['IG_coordinateTexture'+i]=IG_texUnit++;}}
if(shape._cf.geometry.node.getNormalTexture(0)){sp.IG_normalTexture=IG_texUnit++;}
if(shape._cf.geometry.node.getTexCoordTexture()){sp.IG_texCoordTexture=IG_texUnit++;}
if(shape._cf.geometry.node.getColorTexture()){sp.IG_colorTexture=IG_texUnit++;}}
if(shape._webgl.bitLODGeometry!=0)
{sp.BLG_bboxMin=shape._cf.geometry.node.getMin().toGL();sp.BLG_bboxMax=shape._cf.geometry.node.getMax().toGL();}
var fog=scene.getFog();if(fog){if(x3dom.caps.MOBILE){sp.fogColor=fog._vf.color.toGL();sp.fogRange=fog._vf.visibilityRange;sp.fogType=(fog._vf.fogType=="LINEAR")?0.0:1.0;}else{sp['fog.color']=fog._vf.color.toGL();sp['fog.visibilityRange']=fog._vf.visibilityRange;sp['fog.fogType']=(fog._vf.fogType=="LINEAR")?0.0:1.0;}}
var mat=shape._cf.appearance.node._cf.material.node;var shaderCSS=shape._cf.appearance.node._shader;if(shaderCSS!==null&&x3dom.isa(shaderCSS,x3dom.nodeTypes.CommonSurfaceShader)){sp['material.diffuseColor']=shaderCSS._vf.diffuseFactor.toGL();sp['material.specularColor']=shaderCSS._vf.specularFactor.toGL();sp['material.emissiveColor']=shaderCSS._vf.emissiveFactor.toGL();sp['material.shininess']=shaderCSS._vf.shininessFactor;sp['material.ambientIntensity']=(shaderCSS._vf.ambientFactor.x+
shaderCSS._vf.ambientFactor.y+
shaderCSS._vf.ambientFactor.z)/3;sp['material.transparency']=1.0-shaderCSS._vf.alphaFactor;}
else{shaderCSS=null;if(x3dom.caps.MOBILE){sp.diffuseColor=mat._vf.diffuseColor.toGL();sp.specularColor=mat._vf.specularColor.toGL();sp.emissiveColor=mat._vf.emissiveColor.toGL();sp.shininess=mat._vf.shininess;sp.ambientIntensity=mat._vf.ambientIntensity;sp.transparency=mat._vf.transparency;}else{sp['material.diffuseColor']=mat._vf.diffuseColor.toGL();sp['material.specularColor']=mat._vf.specularColor.toGL();sp['material.emissiveColor']=mat._vf.emissiveColor.toGL();sp['material.shininess']=mat._vf.shininess;sp['material.ambientIntensity']=mat._vf.ambientIntensity;sp['material.transparency']=mat._vf.transparency;}}
sp.alpha=1.0-mat._vf.transparency;if(numLights>0)
{if(numLights>8){x3dom.debug.logWarning("Too many lights! Only 8 lights supported!");numLights=8;}
for(var p=0;p<numLights;p++){var light_transform=mat_view.mult(slights[p].getCurrentTransform());if(x3dom.isa(slights[p],x3dom.nodeTypes.DirectionalLight))
{if(x3dom.caps.MOBILE){sp['Light'+p+'_Type']=0.0;sp['Light'+p+'_On']=(slights[p]._vf.on)?1.0:0.0;sp['Light'+p+'_Color']=slights[p]._vf.color.toGL();sp['Light'+p+'_Intensity']=slights[p]._vf.intensity;sp['Light'+p+'_AmbientIntensity']=slights[p]._vf.ambientIntensity;sp['Light'+p+'_Direction']=light_transform.multMatrixVec(slights[p]._vf.direction).toGL();sp['Light'+p+'_Attenuation']=[1.0,1.0,1.0];sp['Light'+p+'_Location']=[1.0,1.0,1.0];sp['Light'+p+'_Radius']=0.0;sp['Light'+p+'_BeamWidth']=0.0;sp['Light'+p+'_CutOffAngle']=0.0;sp['Light'+p+'_shadowIntensity']=slights[p]._vf.shadowIntensity;}else{sp['light['+p+'].type']=0.0;sp['light['+p+'].on']=(slights[p]._vf.on)?1.0:0.0;sp['light['+p+'].color']=slights[p]._vf.color.toGL();sp['light['+p+'].intensity']=slights[p]._vf.intensity;sp['light['+p+'].ambientIntensity']=slights[p]._vf.ambientIntensity;sp['light['+p+'].direction']=light_transform.multMatrixVec(slights[p]._vf.direction).toGL();sp['light['+p+'].attenuation']=[1.0,1.0,1.0];sp['light['+p+'].location']=[1.0,1.0,1.0];sp['light['+p+'].radius']=0.0;sp['light['+p+'].beamWidth']=0.0;sp['light['+p+'].cutOffAngle']=0.0;sp['light['+p+'].shadowIntensity']=slights[p]._vf.shadowIntensity;}}
else if(x3dom.isa(slights[p],x3dom.nodeTypes.PointLight))
{if(x3dom.caps.MOBILE){sp['Light'+p+'_Type']=1.0;sp['Light'+p+'_On']=(slights[p]._vf.on)?1.0:0.0;sp['Light'+p+'_Color']=slights[p]._vf.color.toGL();sp['Light'+p+'_Intensity']=slights[p]._vf.intensity;sp['Light'+p+'_AmbientIntensity']=slights[p]._vf.ambientIntensity;sp['Light'+p+'_Direction']=[1.0,1.0,1.0];sp['Light'+p+'_Attenuation']=slights[p]._vf.attenuation.toGL();sp['Light'+p+'_Location']=light_transform.multMatrixPnt(slights[p]._vf.location).toGL();sp['Light'+p+'_Radius']=slights[p]._vf.radius;sp['Light'+p+'_BeamWidth']=0.0;sp['Light'+p+'_CutOffAngle']=0.0;sp['Light'+p+'_shadowIntensity']=slights[p]._vf.shadowIntensity;}else{sp['light['+p+'].type']=1.0;sp['light['+p+'].on']=(slights[p]._vf.on)?1.0:0.0;sp['light['+p+'].color']=slights[p]._vf.color.toGL();sp['light['+p+'].intensity']=slights[p]._vf.intensity;sp['light['+p+'].ambientIntensity']=slights[p]._vf.ambientIntensity;sp['light['+p+'].direction']=[1.0,1.0,1.0];sp['light['+p+'].attenuation']=slights[p]._vf.attenuation.toGL();sp['light['+p+'].location']=light_transform.multMatrixPnt(slights[p]._vf.location).toGL();sp['light['+p+'].radius']=slights[p]._vf.radius;sp['light['+p+'].beamWidth']=0.0;sp['light['+p+'].cutOffAngle']=0.0;sp['light['+p+'].shadowIntensity']=slights[p]._vf.shadowIntensity;}}
else if(x3dom.isa(slights[p],x3dom.nodeTypes.SpotLight))
{if(x3dom.caps.MOBILE){sp['Light'+p+'_Type']=2.0;sp['Light'+p+'_On']=(slights[p]._vf.on)?1.0:0.0;sp['Light'+p+'_Color']=slights[p]._vf.color.toGL();sp['Light'+p+'_Intensity']=slights[p]._vf.intensity;sp['Light'+p+'_AmbientIntensity']=slights[p]._vf.ambientIntensity;sp['Light'+p+'_Direction']=light_transform.multMatrixVec(slights[p]._vf.direction).toGL();sp['Light'+p+'_Attenuation']=slights[p]._vf.attenuation.toGL();sp['Light'+p+'_Location']=light_transform.multMatrixPnt(slights[p]._vf.location).toGL();sp['Light'+p+'_Radius']=slights[p]._vf.radius;sp['Light'+p+'_BeamWidth']=slights[p]._vf.beamWidth;sp['Light'+p+'_CutOffAngle']=slights[p]._vf.cutOffAngle;sp['Light'+p+'_shadowIntensity']=slights[p]._vf.shadowIntensity;}else{sp['light['+p+'].type']=2.0;sp['light['+p+'].on']=(slights[p]._vf.on)?1.0:0.0;sp['light['+p+'].color']=slights[p]._vf.color.toGL();sp['light['+p+'].intensity']=slights[p]._vf.intensity;sp['light['+p+'].ambientIntensity']=slights[p]._vf.ambientIntensity;sp['light['+p+'].direction']=light_transform.multMatrixVec(slights[p]._vf.direction).toGL();sp['light['+p+'].attenuation']=slights[p]._vf.attenuation.toGL();sp['light['+p+'].location']=light_transform.multMatrixPnt(slights[p]._vf.location).toGL();sp['light['+p+'].radius']=slights[p]._vf.radius;sp['light['+p+'].beamWidth']=slights[p]._vf.beamWidth;sp['light['+p+'].cutOffAngle']=slights[p]._vf.cutOffAngle;sp['light['+p+'].shadowIntensity']=slights[p]._vf.shadowIntensity;}}}}
var nav=scene.getNavigationInfo();if(nav._vf.headlight){numLights=(numLights)?numLights:0;if(x3dom.caps.MOBILE){sp['Light'+numLights+'_Type']=0.0;sp['Light'+numLights+'_On']=1.0;sp['Light'+numLights+'_Color']=[1.0,1.0,1.0];sp['Light'+numLights+'_Intensity']=1.0;sp['Light'+numLights+'_AmbientIntensity']=0.0;sp['Light'+numLights+'_Direction']=[0.0,0.0,-1.0];sp['Light'+numLights+'_Attenuation']=[1.0,1.0,1.0];sp['Light'+numLights+'_Location']=[1.0,1.0,1.0];sp['Light'+numLights+'_Radius']=0.0;sp['Light'+numLights+'_BeamWidth']=0.0;sp['Light'+numLights+'_CutOffAngle']=0.0;}else{sp['light['+numLights+'].type']=0.0;sp['light['+numLights+'].on']=1.0;sp['light['+numLights+'].color']=[1.0,1.0,1.0];sp['light['+numLights+'].intensity']=1.0;sp['light['+numLights+'].ambientIntensity']=0.0;sp['light['+numLights+'].direction']=[0.0,0.0,-1.0];sp['light['+numLights+'].attenuation']=[1.0,1.0,1.0];sp['light['+numLights+'].location']=[1.0,1.0,1.0];sp['light['+numLights+'].radius']=0.0;sp['light['+numLights+'].beamWidth']=0.0;sp['light['+numLights+'].cutOffAngle']=0.0;}}
var userShader=shape._cf.appearance.node._shader;if(userShader){for(var fName in userShader._vf){if(userShader._vf.hasOwnProperty(fName)&&fName!=='language'){var field=userShader._vf[fName];try{sp[fName]=field.toGL();}
catch(noToGl){sp[fName]=field;}}}}
var model_view=mat_view.mult(transform);sp.modelViewMatrix=model_view.toGL();sp.normalMatrix=model_view.inverse().transpose().toGL();sp.projectionMatrix=mat_proj.toGL();sp.viewMatrix=mat_view.toGL();sp.modelViewMatrixInverse=model_view.inverse().toGL();sp.modelViewProjectionMatrix=mat_scene.mult(transform).toGL();for(var cnt=0;shape._webgl.texture!==undefined&&cnt<shape._webgl.texture.length;cnt++)
{if(shape._webgl.texture[cnt])
{if(shape._cf.appearance.node._cf.texture.node){tex=shape._cf.appearance.node._cf.texture.node.getTexture(cnt);}
if(tex){sp.origChannelCount=tex._vf.origChannelCount;}
var wrapS=gl.REPEAT,wrapT=gl.REPEAT;var minFilter=gl.LINEAR,magFilter=gl.LINEAR;var genMipMaps=false;if(shape._webgl.textureFilter){minFilter=shape._webgl.textureFilter[cnt];magFilter=shape._webgl.textureFilter[cnt];}
if(tex&&tex._cf.textureProperties.node!==null)
{var texProp=tex._cf.textureProperties.node;wrapS=shape._webgl._boundaryModesDic[texProp._vf.boundaryModeS.toUpperCase()];wrapT=shape._webgl._boundaryModesDic[texProp._vf.boundaryModeT.toUpperCase()];minFilter=shape._webgl._minFilterDic[texProp._vf.minificationFilter.toUpperCase()];magFilter=shape._webgl._magFilterDic[texProp._vf.magnificationFilter.toUpperCase()];if(texProp._vf.generateMipMaps===true)
{if(minFilter==gl.NEAREST)
minFilter=gl.NEAREST_MIPMAP_NEAREST;if(minFilter==gl.LINEAR)
minFilter=gl.LINEAR_MIPMAP_LINEAR;genMipMaps=true;}
else
{if((minFilter==gl.LINEAR_MIPMAP_LINEAR)||(minFilter==gl.LINEAR_MIPMAP_NEAREST))
minFilter=gl.LINEAR;if((minFilter==gl.NEAREST_MIPMAP_LINEAR)||(minFilter==gl.NEAREST_MIPMAP_NEAREST))
minFilter=gl.NEAREST;}}
else
{if(!tex||tex._vf.repeatS==false){wrapS=gl.CLAMP_TO_EDGE;}
if(!tex||tex._vf.repeatT==false){wrapT=gl.CLAMP_TO_EDGE;}}
if(shape._webgl.texture[cnt].textureCubeReady&&tex&&x3dom.isa(tex,x3dom.nodeTypes.X3DEnvironmentTextureNode))
{gl.activeTexture(gl.TEXTURE0+cnt);gl.bindTexture(gl.TEXTURE_CUBE_MAP,shape._webgl.texture[cnt]);gl.texParameteri(gl.TEXTURE_CUBE_MAP,gl.TEXTURE_WRAP_S,wrapS);gl.texParameteri(gl.TEXTURE_CUBE_MAP,gl.TEXTURE_WRAP_T,wrapT);gl.texParameteri(gl.TEXTURE_CUBE_MAP,gl.TEXTURE_MAG_FILTER,magFilter);gl.texParameteri(gl.TEXTURE_CUBE_MAP,gl.TEXTURE_MIN_FILTER,minFilter);if(genMipMaps){gl.generateMipmap(gl.TEXTURE_CUBE_MAP);}}
else
{gl.activeTexture(gl.TEXTURE0+cnt);gl.bindTexture(gl.TEXTURE_2D,shape._webgl.texture[cnt]);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,wrapS);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,wrapT);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,magFilter);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,minFilter);if(genMipMaps){gl.generateMipmap(gl.TEXTURE_2D);}}
if(shape._cf.appearance.node._cf.textureTransform.node!==null)
{var texTrafo=shape._cf.appearance.node.texTransformMatrix();sp.texTrafoMatrix=texTrafo.toGL();}
if(shaderCSS){var texUnit=0;if(shaderCSS.getDiffuseMap()){if(!sp.tex){sp.tex=texUnit++;}}
if(shaderCSS.getNormalMap()){if(!sp.bump){sp.bump=texUnit++;}}
if(shaderCSS.getSpecularMap()){if(!sp.spec){sp.spec=texUnit++;}}}else{if(!sp.tex){sp.tex=0;}}}}
if(oneShadowExistsAlready)
{if(!sp.sh_tex){sp.sh_tex=cnt;}
gl.activeTexture(gl.TEXTURE0+cnt);gl.bindTexture(gl.TEXTURE_2D,scene._webgl.fboShadow.tex);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);sp.matPV=mat_light.mult(transform).toGL();}
var attrib;for(var df=0;df<shape._webgl.dynamicFields.length;df++)
{attrib=shape._webgl.dynamicFields[df];if(sp[attrib.name]!==undefined)
{gl.bindBuffer(gl.ARRAY_BUFFER,attrib.buf);gl.vertexAttribPointer(sp[attrib.name],attrib.numComponents,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(sp[attrib.name]);}}
if(shape.isSolid()){gl.enable(gl.CULL_FACE);if(shape.isCCW()){gl.frontFace(gl.CCW);}
else{gl.frontFace(gl.CW);}}
else{gl.disable(gl.CULL_FACE);}
sp.solid=(shape.isSolid()?1.0:0.0);for(var q=0;q<shape._webgl.positions.length;q++)
{if(!prev_shape||(prev_shape&&prev_shape._cf.geometry.node._mesh!==shape._cf.geometry.node._mesh))
{if(shape._webgl.buffers[5*q+0])
{gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,shape._webgl.buffers[5*q+0]);}
if(sp.position!==undefined&&shape._webgl.buffers[5*q+1])
{gl.bindBuffer(gl.ARRAY_BUFFER,shape._webgl.buffers[5*q+1]);gl.vertexAttribPointer(sp.position,3,shape._webgl.coordType,false,shape._coordStrideOffset[0],shape._coordStrideOffset[1]);gl.enableVertexAttribArray(sp.position);}
if(sp.normal!==undefined&&shape._webgl.buffers[5*q+2])
{gl.bindBuffer(gl.ARRAY_BUFFER,shape._webgl.buffers[5*q+2]);if(shape._webgl.bitLODGeometry!=0){gl.vertexAttribPointer(sp.normal,2,shape._webgl.normalType,true,shape._normalStrideOffset[0],shape._normalStrideOffset[1]);gl.enableVertexAttribArray(sp.normal);}else{gl.vertexAttribPointer(sp.normal,3,shape._webgl.normalType,false,shape._normalStrideOffset[0],shape._normalStrideOffset[1]);gl.enableVertexAttribArray(sp.normal);}}
if(sp.texcoord!==undefined&&shape._webgl.buffers[5*q+3])
{gl.bindBuffer(gl.ARRAY_BUFFER,shape._webgl.buffers[5*q+3]);gl.vertexAttribPointer(sp.texcoord,shape._cf.geometry.node._mesh._numTexComponents,shape._webgl.texCoordType,false,shape._texCoordStrideOffset[0],shape._texCoordStrideOffset[1]);gl.enableVertexAttribArray(sp.texcoord);}
if(sp.color!==undefined&&shape._webgl.buffers[5*q+4])
{gl.bindBuffer(gl.ARRAY_BUFFER,shape._webgl.buffers[5*q+4]);gl.vertexAttribPointer(sp.color,shape._cf.geometry.node._mesh._numColComponents,shape._webgl.colorType,false,shape._colorStrideOffset[0],shape._colorStrideOffset[1]);gl.enableVertexAttribArray(sp.color);}}
try{if(viewarea._points!==undefined&&viewarea._points>0){var polyMode=(viewarea._points==1)?gl.POINTS:gl.LINES;if(shape._webgl.imageGeometry||shape._webgl.binaryGeometry<0||shape._webgl.bitLODGeometry<0){for(var i=0,offset=0;i<shape._cf.geometry.node._vf.vertexCount.length;i++){gl.drawArrays(polyMode,offset,shape._cf.geometry.node._vf.vertexCount[i]);offset+=shape._cf.geometry.node._vf.vertexCount[i];}}
else if(shape._webgl.binaryGeometry>0||shape._webgl.bitLODGeometry>0){for(var i=0,offset=0;i<shape._cf.geometry.node._vf.vertexCount.length;i++){gl.drawElements(polyMode,shape._cf.geometry.node._vf.vertexCount[i],gl.UNSIGNED_SHORT,2*offset);offset+=shape._cf.geometry.node._vf.vertexCount[i];}}
else{gl.drawElements(polyMode,shape._webgl.indexes[q].length,gl.UNSIGNED_SHORT,0);}}
else{if(shape._webgl.primType==gl.POINTS){gl.drawArrays(gl.POINTS,0,shape._webgl.positions[q].length/3);}
else{if(shape._webgl.indexes&&shape._webgl.indexes[q]){if(shape._webgl.imageGeometry||shape._webgl.binaryGeometry<0||shape._webgl.bitLODGeometry<0){for(var i=0,offset=0;i<shape._cf.geometry.node._vf.vertexCount.length;i++){gl.drawArrays(shape._webgl.primType[i],offset,shape._cf.geometry.node._vf.vertexCount[i]);offset+=shape._cf.geometry.node._vf.vertexCount[i];}}
else if(shape._webgl.binaryGeometry>0||shape._webgl.bitLODGeometry>0){for(var i=0,offset=0;i<shape._cf.geometry.node._vf.vertexCount.length;i++){gl.drawElements(shape._webgl.primType[i],shape._cf.geometry.node._vf.vertexCount[i],gl.UNSIGNED_SHORT,2*offset);offset+=shape._cf.geometry.node._vf.vertexCount[i];}}
else if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.IndexedTriangleStripSet)&&shape._webgl.primType==gl.TRIANGLE_STRIP){var indOff=shape._cf.geometry.node._indexOffset;for(var io=1;io<indOff.length;io++){gl.drawElements(gl.TRIANGLE_STRIP,indOff[io]-indOff[io-1],gl.UNSIGNED_SHORT,2*indOff[io-1]);}}
else{gl.drawElements(shape._webgl.primType,shape._webgl.indexes[q].length,gl.UNSIGNED_SHORT,0);}}}}}
catch(e){x3dom.debug.logException(shape._DEF+" renderScene(): "+e);}
if(!next_shape||(next_shape&&next_shape._cf.geometry.node._mesh!==shape._cf.geometry.node._mesh))
{if(sp.position!==undefined){gl.disableVertexAttribArray(sp.position);}
if(sp.normal!==undefined){gl.disableVertexAttribArray(sp.normal);}
if(sp.texcoord!==undefined){gl.disableVertexAttribArray(sp.texcoord);}
if(sp.color!==undefined){gl.disableVertexAttribArray(sp.color);}}}
if(shape._webgl.indexes&&shape._webgl.indexes[0]){if(shape._webgl.imageGeometry){for(var i=0;i<shape._cf.geometry.node._vf.vertexCount.length;i++){if(shape._webgl.primType[i]==gl.TRIANGLE_STRIP)
this.numFaces+=(shape._cf.geometry.node._vf.vertexCount[i]-2);else
this.numFaces+=(shape._cf.geometry.node._vf.vertexCount[i]/3);}}
else{this.numFaces+=shape._cf.geometry.node._mesh._numFaces;}}
if(shape._webgl.imageGeometry){for(var i=0;i<shape._cf.geometry.node._vf.vertexCount.length;i++)
this.numCoords+=shape._cf.geometry.node._vf.vertexCount[i];this.numDrawCalls+=shape._cf.geometry.node._vf.vertexCount.length;}
else if(shape._webgl.binaryGeometry!=0||shape._webgl.bitLODGeometry!=0){this.numCoords+=shape._cf.geometry.node._mesh._numCoords;this.numDrawCalls+=shape._cf.geometry.node._vf.vertexCount.length;}
else{this.numCoords+=shape._cf.geometry.node._mesh._numCoords;if(x3dom.isa(shape._cf.geometry.node,x3dom.nodeTypes.IndexedTriangleStripSet)&&shape._webgl.primType==gl.TRIANGLE_STRIP){this.numDrawCalls+=shape._cf.geometry.node._indexOffset.length;}
else{this.numDrawCalls+=1;}}
for(cnt=0;shape._webgl.texture!==undefined&&cnt<shape._webgl.texture.length;cnt++)
{if(shape._webgl.texture[cnt])
{tex=null;if(shape._cf.appearance.node._cf.texture.node){tex=shape._cf.appearance.node._cf.texture.node.getTexture(cnt);}
if(shape._webgl.texture[cnt].textureCubeReady&&tex&&x3dom.isa(tex,x3dom.nodeTypes.X3DEnvironmentTextureNode))
{gl.activeTexture(gl.TEXTURE0+cnt);gl.bindTexture(gl.TEXTURE_CUBE_MAP,null);}else{gl.activeTexture(gl.TEXTURE0+cnt);gl.bindTexture(gl.TEXTURE_2D,null);}}}
if(oneShadowExistsAlready){gl.activeTexture(gl.TEXTURE0+cnt);gl.bindTexture(gl.TEXTURE_2D,null);}
for(df=0;df<shape._webgl.dynamicFields.length;df++){attrib=shape._webgl.dynamicFields[df];if(sp[attrib.name]!==undefined){gl.disableVertexAttribArray(sp[attrib.name]);}}};Context.prototype.pickValue=function(viewarea,x,y,viewMat,sceneMat)
{var gl=this.ctx3d;var scene=viewarea._scene;if(gl===null||scene===null||!scene._webgl||scene.drawableObjects===undefined||!scene.drawableObjects||scene._vf.pickMode.toLowerCase()==="box")
{return false;}
var mat_view,mat_scene;if(arguments.length>4){mat_view=viewMat;mat_scene=sceneMat;}
else{mat_view=viewarea._last_mat_view;mat_scene=viewarea._last_mat_scene;}
var pickMode=(scene._vf.pickMode.toLowerCase()==="color")?1:((scene._vf.pickMode.toLowerCase()==="texcoord")?2:0);var min=scene._lastMin;var max=scene._lastMax;this.renderPickingPass(gl,scene,mat_view,mat_scene,min,max,pickMode,x,y);var index=0;if(index>=0&&index<scene._webgl.fboPick.pixelData.length){var pickPos=new x3dom.fields.SFVec3f(0,0,0);var charMax=(pickMode>0)?1:255;pickPos.x=scene._webgl.fboPick.pixelData[index+0]/charMax;pickPos.y=scene._webgl.fboPick.pixelData[index+1]/charMax;pickPos.z=scene._webgl.fboPick.pixelData[index+2]/charMax;if(pickMode===0){pickPos=pickPos.multComponents(max.subtract(min)).add(min);}
var objId=255-scene._webgl.fboPick.pixelData[index+3];if(objId>0){viewarea._pickingInfo.pickPos=pickPos;viewarea._pickingInfo.pickObj=x3dom.nodeTypes.Shape.idMap.nodeID[objId];}
else{viewarea._pickingInfo.pickObj=null;viewarea._pickingInfo.lastClickObj=null;}}
return true;};Context.prototype.renderScene=function(viewarea)
{var gl=this.ctx3d;var scene=viewarea._scene;if(gl===null||scene===null)
{return;}
var rentex=viewarea._doc._nodeBag.renderTextures;var rt_tex,rtl_i,rtl_n=rentex.length;if(!scene._webgl)
{var type=gl.UNSIGNED_BYTE;this._fpTexSupport=gl.getExtension("OES_texture_float");if(this._fpTexSupport){type=gl.FLOAT;}
scene._webgl={};this.setupFgnds(gl,scene);scene._webgl.pickScale=0.5;scene._webgl._currFboWidth=Math.round(this.canvas.width*scene._webgl.pickScale);scene._webgl._currFboHeight=Math.round(this.canvas.height*scene._webgl.pickScale);scene._webgl.fboPick=this.initFbo(gl,scene._webgl._currFboWidth,scene._webgl._currFboHeight,true,gl.UNSIGNED_BYTE);scene._webgl.fboPick.pixelData=null;scene._webgl.pickShader=getDefaultShaderProgram(gl,'pick');if(!x3dom.caps.MOBILE)
scene._webgl.pickShaderIG=this.getShaderProgram(gl,['vs-x3d-pickIG','fs-x3d-pick']);scene._webgl.pickShaderBLG=this.getShaderProgram(gl,['vs-x3d-pickBLG','fs-x3d-pick']);scene._webgl.pickColorShader=getDefaultShaderProgram(gl,'vertexcolorUnlit');scene._webgl.pickTexCoordShader=getDefaultShaderProgram(gl,'texcoordUnlit');scene._webgl.fboShadow=this.initFbo(gl,1024,1024,false,gl.UNSIGNED_BYTE);scene._webgl.shadowShader=getDefaultShaderProgram(gl,'shadow');for(rtl_i=0;rtl_i<rtl_n;rtl_i++){rt_tex=rentex[rtl_i];rt_tex._webgl={};rt_tex._webgl.fbo=this.initFbo(gl,rt_tex._vf.dimensions[0],rt_tex._vf.dimensions[1],false,type);}
var min=x3dom.fields.SFVec3f.MAX();var max=x3dom.fields.SFVec3f.MIN();scene.getVolume(min,max,true);scene._lastMin=min;scene._lastMax=max;viewarea._last_mat_view=x3dom.fields.SFMatrix4f.identity();viewarea._last_mat_proj=x3dom.fields.SFMatrix4f.identity();viewarea._last_mat_scene=x3dom.fields.SFMatrix4f.identity();this._calledViewpointChangedHandler=false;}
else
{var fboWidth=Math.round(this.canvas.width*scene._webgl.pickScale);var fboHeight=Math.round(this.canvas.height*scene._webgl.pickScale);if(scene._webgl._currFboWidth!==fboWidth||scene._webgl._currFboHeight!==fboHeight)
{scene._webgl._currFboWidth=fboWidth;scene._webgl._currFboHeight=fboHeight;scene._webgl.fboPick=this.initFbo(gl,fboWidth,fboHeight,true,scene._webgl.fboPick.typ);scene._webgl.fboPick.pixelData=null;x3dom.debug.logInfo("Refreshed picking FBO to size ("+
(fboWidth)+", "+(fboHeight)+")");}}
var bgnd=scene.getBackground();this.setupScene(gl,bgnd);var t0,t1;this.numFaces=0;this.numCoords=0;this.numDrawCalls=0;scene.drawableObjects=null;scene.drawableObjects=[];scene.drawableObjects.LODs=[];scene.drawableObjects.Billboards=[];scene.drawableObjects.useIdList=false;scene.drawableObjects.collect=false;scene.drawableObjects.idList=[];t0=new Date().getTime();scene.collectDrawableObjects(x3dom.fields.SFMatrix4f.identity(),scene.drawableObjects);t1=new Date().getTime()-t0;if(this.canvas.parent.statDiv){this.canvas.parent.statDiv.appendChild(document.createElement("br"));this.canvas.parent.statDiv.appendChild(document.createTextNode("traverse: "+t1));}
var mat_proj=viewarea.getProjectionMatrix();var mat_view=viewarea.getViewMatrix();if(!this._calledViewpointChangedHandler||!viewarea._last_mat_view.equals(mat_view))
{var e_viewpoint=viewarea._scene.getViewpoint();var e_eventType="viewpointChanged";try{if(e_viewpoint._xmlNode&&(e_viewpoint._xmlNode["on"+e_eventType]||e_viewpoint._xmlNode.hasAttribute("on"+e_eventType)||e_viewpoint._listeners[e_eventType]))
{var e_viewtrafo=e_viewpoint.getCurrentTransform();e_viewtrafo=e_viewtrafo.inverse().mult(mat_view);var e_mat=e_viewtrafo.inverse();var e_rotation=new x3dom.fields.Quaternion(0,0,1,0);e_rotation.setValue(e_mat);var e_translation=e_mat.e3();var e_event={target:e_viewpoint._xmlNode,type:e_eventType,matrix:e_viewtrafo,position:e_translation,orientation:e_rotation.toAxisAngle(),cancelBubble:false,stopPropagation:function(){this.cancelBubble=true;}};e_viewpoint.callEvtHandler(e_eventType,e_event);this._calledViewpointChangedHandler=true;}}
catch(e_e){x3dom.debug.logException(e_e);}}
viewarea._last_mat_view=mat_view;viewarea._last_mat_proj=mat_proj;var mat_scene=mat_proj.mult(mat_view);viewarea._last_mat_scene=mat_scene;t0=new Date().getTime();var zPos=[],sortKeyArr=[],zPosTransp={};var sortKeyProp="";var i,m,n=scene.drawableObjects.length;var center,trafo,obj3d;for(i=0;i<n;i++)
{trafo=scene.drawableObjects[i][0];obj3d=scene.drawableObjects[i][1];this.setupShape(gl,obj3d,viewarea);center=obj3d.getCenter();center=trafo.multMatrixPnt(center);center=mat_view.multMatrixPnt(center);var sortType=(obj3d._cf.appearance.node!==undefined)?obj3d._cf.appearance.node._vf.sortType:"opaque";var sortKey=(obj3d._cf.appearance.node!==undefined)?obj3d._cf.appearance.node._vf.sortKey:0;if(sortType.toLowerCase()==="opaque"){zPos.push([i,center.z,sortKey]);}
else{sortKeyProp=sortKey.toString();if(zPosTransp[sortKeyProp]===undefined)
zPosTransp[sortKeyProp]=[];zPosTransp[sortKeyProp].push([i,center.z,sortKey]);sortKeyArr.push(sortKey);}}
zPos.sort(function(a,b){return a[2]-b[2];});sortKeyArr.sort(function(a,b){return a-b;});sortKeyArr=(function(arr){var a=[],l=arr.length;for(var i=0;i<l;i++){for(var j=i+1;j<l;j++){if(arr[i]===arr[j])
j=++i;}
a.push(arr[i]);}
return a;})(sortKeyArr);for(var sortKeyArrIt=0,sortKeyArrN=sortKeyArr.length;sortKeyArrIt<sortKeyArrN;++sortKeyArrIt){sortKeyProp=sortKeyArr[sortKeyArrIt];var zPosTranspArr=zPosTransp[sortKeyProp];zPosTranspArr.sort(function(a,b){return a[1]-b[1];});zPos.push.apply(zPos,zPosTranspArr);}
m=scene.drawableObjects.Billboards.length;n=scene.drawableObjects.LODs.length;if(m||n){center=new x3dom.fields.SFVec3f(0,0,0);center=mat_view.inverse().multMatrixPnt(center);}
for(i=0;i<n;i++)
{trafo=scene.drawableObjects.LODs[i][0];obj3d=scene.drawableObjects.LODs[i][1];if(obj3d){obj3d._eye=trafo.inverse().multMatrixPnt(center);}}
for(i=0;i<m;i++)
{trafo=scene.drawableObjects.Billboards[i][0];obj3d=scene.drawableObjects.Billboards[i][1];if(obj3d){var mat_view_model=mat_view.mult(trafo);obj3d._eye=trafo.inverse().multMatrixPnt(center);obj3d._eyeViewUp=new x3dom.fields.SFVec3f(mat_view_model._10,mat_view_model._11,mat_view_model._12);obj3d._eyeLook=new x3dom.fields.SFVec3f(mat_view_model._20,mat_view_model._21,mat_view_model._22);}}
t1=new Date().getTime()-t0;if(this.canvas.parent.statDiv){this.canvas.parent.statDiv.appendChild(document.createElement("br"));this.canvas.parent.statDiv.appendChild(document.createTextNode("sort: "+t1));}
var slights=viewarea.getLights();var numLights=slights.length;var oneShadowExistsAlready=false;var mat_light;for(var p=0;p<numLights;p++){if(slights[p]._vf.shadowIntensity>0.0&&!oneShadowExistsAlready){oneShadowExistsAlready=true;t0=new Date().getTime();var lightMatrix=viewarea.getLightMatrix()[0];mat_light=viewarea.getWCtoLCMatrix(lightMatrix);this.renderShadowPass(gl,scene,lightMatrix,mat_light);t1=new Date().getTime()-t0;if(this.canvas.parent.statDiv){this.canvas.parent.statDiv.appendChild(document.createElement("br"));this.canvas.parent.statDiv.appendChild(document.createTextNode("shadow: "+t1));}}}
for(rtl_i=0;rtl_i<rtl_n;rtl_i++){this.renderRTPass(gl,viewarea,rentex[rtl_i]);}
t0=new Date().getTime();gl.viewport(0,0,this.canvas.width,this.canvas.height);bgnd._webgl.render(gl,mat_view,mat_proj);gl.depthMask(true);gl.depthFunc(gl.LEQUAL);gl.enable(gl.DEPTH_TEST);gl.enable(gl.CULL_FACE);gl.blendFuncSeparate(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA,gl.ONE,gl.ONE);gl.enable(gl.BLEND);for(i=0,n=zPos.length;i<n;i++)
{var obj=scene.drawableObjects[zPos[i][0]];if(i>0){var prev_obj=scene.drawableObjects[zPos[i-1][0]][1];}
if(i<zPos.length-1){var next_obj=scene.drawableObjects[zPos[i+1][0]][1];}
var needEnableBlending=false;var needEnableDepthMask=false;var shapeApp=obj[1]._cf.appearance.node;if(shapeApp._cf.blendMode.node&&shapeApp._cf.blendMode.node._vf.srcFactor.toLowerCase()==="none"&&shapeApp._cf.blendMode.node._vf.destFactor.toLowerCase()==="none")
{needEnableBlending=true;gl.disable(gl.BLEND);}
if(shapeApp._cf.depthMode.node&&shapeApp._cf.depthMode.node._vf.readOnly===true)
{needEnableDepthMask=true;gl.depthMask(false);}
this.renderShape(obj[0],obj[1],prev_obj,next_obj,viewarea,slights,numLights,mat_view,mat_scene,mat_light,mat_proj,gl,oneShadowExistsAlready);if(needEnableBlending){gl.enable(gl.BLEND);}
if(needEnableDepthMask){gl.depthMask(true);}}
gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);if(viewarea._visDbgBuf!==undefined&&viewarea._visDbgBuf)
{if(scene._vf.pickMode.toLowerCase()==="idbuf"||scene._vf.pickMode.toLowerCase()==="color"||scene._vf.pickMode.toLowerCase()==="texcoord"){gl.viewport(0,3*this.canvas.height/4,this.canvas.width/4,this.canvas.height/4);scene._fgnd._webgl.render(gl,scene._webgl.fboPick.tex);}
if(oneShadowExistsAlready){gl.viewport(this.canvas.width/4,3*this.canvas.height/4,this.canvas.width/4,this.canvas.height/4);scene._fgnd._webgl.render(gl,scene._webgl.fboShadow.tex);}}
gl.flush();t1=new Date().getTime()-t0;if(this.canvas.parent.statDiv){this.canvas.parent.statDiv.appendChild(document.createElement("br"));this.canvas.parent.statDiv.appendChild(document.createTextNode("render: "+t1));this.canvas.parent.statDiv.appendChild(document.createElement("br"));this.canvas.parent.statDiv.appendChild(document.createTextNode("#Tris: "+this.numFaces));this.canvas.parent.statDiv.appendChild(document.createElement("br"));this.canvas.parent.statDiv.appendChild(document.createTextNode("#Pnts: "+this.numCoords));this.canvas.parent.statDiv.appendChild(document.createElement("br"));this.canvas.parent.statDiv.appendChild(document.createTextNode("#Draws: "+this.numDrawCalls));}};Context.prototype.renderRTPass=function(gl,viewarea,rt)
{switch(rt._vf.update.toUpperCase())
{case"NONE":return;case"NEXT_FRAME_ONLY":if(!rt._needRenderUpdate){return;}
rt._needRenderUpdate=false;break;case"ALWAYS":default:break;}
var scene=viewarea._scene;var bgnd=null;var mat_view=rt.getViewMatrix();var mat_proj=rt.getProjectionMatrix();var mat_scene=mat_proj.mult(mat_view);var lightMatrix=viewarea.getLightMatrix()[0];var mat_light=viewarea.getWCtoLCMatrix(lightMatrix);var i,n,m=rt._cf.excludeNodes.nodes.length;var arr=new Array(m);for(i=0;i<m;i++){var render=rt._cf.excludeNodes.nodes[i]._vf.render;if(render===undefined){arr[i]=-1;}
else{if(render===true){arr[i]=1;}else{arr[i]=0;}}
rt._cf.excludeNodes.nodes[i]._vf.render=false;}
gl.bindFramebuffer(gl.FRAMEBUFFER,rt._webgl.fbo.fbo);gl.viewport(0,0,rt._webgl.fbo.width,rt._webgl.fbo.height);if(rt._cf.background.node===null)
{gl.clearColor(0,0,0,1);gl.clearDepth(1.0);gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT|gl.STENCIL_BUFFER_BIT);}
else if(rt._cf.background.node===scene.getBackground())
{bgnd=scene.getBackground();bgnd._webgl.render(gl,mat_view,mat_proj);}
else
{bgnd=rt._cf.background.node;this.setupScene(gl,bgnd);bgnd._webgl.render(gl,mat_view,mat_proj);}
gl.depthFunc(gl.LEQUAL);gl.enable(gl.DEPTH_TEST);gl.enable(gl.CULL_FACE);gl.blendFuncSeparate(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA,gl.ONE,gl.ONE);gl.enable(gl.BLEND);var slights=viewarea.getLights();var numLights=slights.length;var oneShadowExistsAlready=false;var transform,shape;var locScene=rt._cf.scene.node;var needEnableBlending,needEnableDepthMask;if(!locScene||locScene===scene)
{n=scene.drawableObjects.length;for(i=0;i<n;i++)
{transform=scene.drawableObjects[i][0];shape=scene.drawableObjects[i][1];if(shape._vf.render!==undefined&&shape._vf.render===false){continue;}
if(i>0){var prev_shape=scene.drawableObjects[i-1][1];}
if(i<scene.drawableObjects.length-1){var next_shape=scene.drawableObjects[i+1][1];}
needEnableBlending=false;needEnableDepthMask=false;appearance=shape._cf.appearance.node;if(appearance._cf.blendMode.node&&appearance._cf.blendMode.node._vf.srcFactor.toLowerCase()==="none"&&appearance._cf.blendMode.node._vf.destFactor.toLowerCase()==="none")
{needEnableBlending=true;gl.disable(gl.BLEND);}
if(appearance._cf.depthMode.node&&appearance._cf.depthMode.node._vf.readOnly===true)
{needEnableDepthMask=true;gl.depthMask(false);}
this.renderShape(transform,shape,prev_shape,next_shape,viewarea,slights,numLights,mat_view,mat_scene,mat_light,mat_proj,gl,oneShadowExistsAlready);if(needEnableBlending){gl.enable(gl.BLEND);}
if(needEnableDepthMask){gl.depthMask(true);}}}
else
{locScene.drawableObjects=[];locScene.drawableObjects.useIdList=false;locScene.drawableObjects.collect=false;locScene.drawableObjects.idList=[];locScene.collectDrawableObjects(locScene.transformMatrix(x3dom.fields.SFMatrix4f.identity()),locScene.drawableObjects);n=locScene.drawableObjects.length;for(i=0;i<n;i++)
{transform=locScene.drawableObjects[i][0];shape=locScene.drawableObjects[i][1];if(shape._vf.render!==undefined&&shape._vf.render===false){continue;}
this.setupShape(gl,shape,viewarea);if(i>0){var prev_shape=locScene.drawableObjects[i-1][1];}
if(i<locScene.drawableObjects.length-1){var next_shape=locScene.drawableObjects[i+1][1];}
needEnableBlending=false;needEnableDepthMask=false;appearance=shape._cf.appearance.node;if(appearance._cf.blendMode.node&&appearance._cf.blendMode.node._vf.srcFactor.toLowerCase()==="none"&&appearance._cf.blendMode.node._vf.destFactor.toLowerCase()==="none")
{needEnableBlending=true;gl.disable(gl.BLEND);}
if(appearance._cf.depthMode.node&&appearance._cf.depthMode.node._vf.readOnly===true)