rglwidgetClass=function(){this.canvas=null,this.userMatrix=new CanvasMatrix4,this.types=[],this.prMatrix=new CanvasMatrix4,this.mvMatrix=new CanvasMatrix4,this.vp=null,this.prmvMatrix=null,this.origs=null,this.gl=null,this.scene=null,this.select={state:"inactive",subscene:null,region:{p1:{x:0,y:0},p2:{x:0,y:0}}},this.drawing=!1},rglwidgetClass.prototype.f_is_lit=1,rglwidgetClass.prototype.f_is_smooth=2,rglwidgetClass.prototype.f_has_texture=4,rglwidgetClass.prototype.f_depth_sort=8,rglwidgetClass.prototype.f_fixed_quads=16,rglwidgetClass.prototype.f_is_transparent=32,rglwidgetClass.prototype.f_is_lines=64,rglwidgetClass.prototype.f_sprites_3d=128,rglwidgetClass.prototype.f_is_subscene=256,rglwidgetClass.prototype.f_is_clipplanes=512,rglwidgetClass.prototype.f_fixed_size=1024,rglwidgetClass.prototype.f_is_points=2048,rglwidgetClass.prototype.f_is_twosided=4096,rglwidgetClass.prototype.f_fat_lines=8192,rglwidgetClass.prototype.f_is_brush=16384,rglwidgetClass.prototype.f_has_fog=32768,rglwidgetClass.prototype.fogNone=0,rglwidgetClass.prototype.fogLinear=1,rglwidgetClass.prototype.fogExp=2,rglwidgetClass.prototype.fogExp2=3,rglwidgetClass.prototype.start=function(){"undefined"!=typeof this.prefix&&(this.debugelement=document.getElementById(this.prefix+"debug"),this.debug("")),this.drag=0,this.drawScene()},rglwidgetClass.prototype.multMV=function(M,v){return[M.m11*v[0]+M.m12*v[1]+M.m13*v[2]+M.m14*v[3],M.m21*v[0]+M.m22*v[1]+M.m23*v[2]+M.m24*v[3],M.m31*v[0]+M.m32*v[1]+M.m33*v[2]+M.m34*v[3],M.m41*v[0]+M.m42*v[1]+M.m43*v[2]+M.m44*v[3]]},rglwidgetClass.prototype.multVM=function(v,M){return[M.m11*v[0]+M.m21*v[1]+M.m31*v[2]+M.m41*v[3],M.m12*v[0]+M.m22*v[1]+M.m32*v[2]+M.m42*v[3],M.m13*v[0]+M.m23*v[1]+M.m33*v[2]+M.m43*v[3],M.m14*v[0]+M.m24*v[1]+M.m34*v[2]+M.m44*v[3]]},rglwidgetClass.prototype.vlen=function(v){return Math.sqrt(this.dotprod(v,v))},rglwidgetClass.prototype.dotprod=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]},rglwidgetClass.prototype.xprod=function(a,b){return[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]]},rglwidgetClass.prototype.cbind=function(a,b){return b.lengthi;i++)value=arr[i],Array.isArray(value)?this.flatten(value,result):result.push(value);return result},rglwidgetClass.prototype.setElement=function(a,i,value){if(Array.isArray(a[0])){var dim=a.length,col=Math.floor(i/dim),row=i%dim;a[row][col]=value}else a[i]=value},rglwidgetClass.prototype.transpose=function(a){var i,newArray=[],n=a.length,m=a[0].length;for(i=0;m>i;i++)newArray.push([]);for(i=0;n>i;i++)for(var j=0;m>j;j++)newArray[j].push(a[i][j]);return newArray},rglwidgetClass.prototype.sumsq=function(x){var i,result=0;for(i=0;i>16&255)/255,(bigint>>8&255)/255,(255&bigint)/255]},rglwidgetClass.prototype.whichList=function(id){var obj=this.getObj(id),flags=obj.flags;return"light"===obj.type?"lights":this.isSet(flags,this.f_is_subscene)?"subscenes":this.isSet(flags,this.f_is_clipplanes)?"clipplanes":this.isSet(flags,this.f_is_transparent)?"transparent":"opaque"},rglwidgetClass.prototype.componentProduct=function(x,y){"undefined"==typeof y&&this.alertOnce("Bad arg to componentProduct");var i,result=new Float32Array(3);for(i=0;3>i;i++)result[i]=x[i]*y[i];return result},rglwidgetClass.prototype.getPowerOfTwo=function(value){for(var pow=1;value>pow;)pow*=2;return pow},rglwidgetClass.prototype.unique=function(arr){return arr=[].concat(arr),arr.filter(function(value,index,self){return self.indexOf(value)===index})},rglwidgetClass.prototype.equalArrays=function(a,b){return a===b||a&&b&&a.length===b.length&&a.every(function(v,i){return v===b[i]})},rglwidgetClass.prototype.repeatToLen=function(arr,len){for(arr=[].concat(arr);arr.length=-windHeight&&rect.left>=-windWidth&&rect.bottom<=2*windHeight&&rect.right<=2*windWidth},rglwidgetClass.prototype.keydiff=function(obj1,obj2){var i,keys=Object.keys(obj1),result=[];for(i=0;i-1},rglwidgetClass.prototype.translateCoords=function(subsceneid,coords){var viewport=this.getObj(subsceneid).par3d.viewport;return{x:coords.x-viewport.x*this.canvas.width,y:coords.y-viewport.y*this.canvas.height}},rglwidgetClass.prototype.inViewport=function(coords,subsceneid){var viewport=this.getObj(subsceneid).par3d.viewport,x0=coords.x-viewport.x*this.canvas.width,y0=coords.y-viewport.y*this.canvas.height;return x0>=0&&x0<=viewport.width*this.canvas.width&&y0>=0&&y0<=viewport.height*this.canvas.height},rglwidgetClass.prototype.whichSubscene=function(coords){var self=this,recurse=function(subsceneid){var i,id,subscenes=self.getChildSubscenes(subsceneid);for(i=0;i-1&&(thesub.objects.splice(i,1),thelist=this.whichList(id),i=thesub[thelist].indexOf(id),thesub[thelist].splice(i,1))},rglwidgetClass.prototype.setSubsceneEntries=function(ids,subsceneid){var sub=this.getObj(subsceneid);sub.objects=ids,this.initSubscene(subsceneid)},rglwidgetClass.prototype.getSubsceneEntries=function(subscene){return this.getObj(subscene).objects},rglwidgetClass.prototype.getChildSubscenes=function(subscene){return this.getObj(subscene).subscenes},rglwidgetClass.prototype.useid=function(subsceneid,type){var sub=this.getObj(subsceneid);return"inherit"===sub.embeddings[type]?this.useid(sub.parent,type):subsceneid},rglwidgetClass.prototype.getVertexShader=function(id){var result,obj=this.getObj(id),userShader=obj.userVertexShader,flags=obj.flags,type=obj.type,is_lit=this.isSet(flags,this.f_is_lit),has_texture=this.isSet(flags,this.f_has_texture),fixed_quads=this.isSet(flags,this.f_fixed_quads),sprites_3d=this.isSet(flags,this.f_sprites_3d),nclipplanes=this.countClipplanes(),fixed_size=this.isSet(flags,this.f_fixed_size),is_points=this.isSet(flags,this.f_is_points),is_twosided=this.isSet(flags,this.f_is_twosided),fat_lines=this.isSet(flags,this.f_fat_lines),is_brush=this.isSet(flags,this.f_is_brush),has_fog=this.isSet(flags,this.f_has_fog),has_normals="undefined"!=typeof obj.normals,needs_vnormal=is_lit&&!fixed_quads&&!is_brush||is_twosided&&(has_normals||"spheres"===obj.type);if("clipplanes"!==type&&!sprites_3d){if("undefined"!=typeof userShader)return userShader;if(result=" /* ****** "+type+" object "+id+" vertex shader ****** */\n#ifdef GL_ES\n#ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n#else\n precision mediump float;\n#endif\n#endif\n attribute vec3 aPos;\n attribute vec4 aCol;\n uniform mat4 mvMatrix;\n uniform mat4 prMatrix;\n varying vec4 vCol;\n varying vec4 vPosition;\n",needs_vnormal&&(result+=" attribute vec3 aNorm;\n uniform mat4 normMatrix;\n varying vec3 vNormal;\n"),(has_texture||"text"===type)&&(result+=" attribute vec2 aTexcoord;\n varying vec2 vTexcoord;\n"),fixed_size&&(result+=" uniform vec2 textScale;\n"),fixed_quads&&(result+=" attribute vec2 aOfs;\n"),is_twosided&&(result+=has_normals||"spheres"===obj.type?" varying float normz;\n":" attribute vec3 aPos1;\n attribute vec3 aPos2;\n varying float normz;\n"),fat_lines&&(result+=" attribute vec3 aNext;\n attribute vec2 aPoint;\n varying vec2 vPoint;\n varying float vLength;\n uniform float uAspect;\n uniform float uLwd;\n"),result+=" void main(void) {\n",!nclipplanes&&fixed_quads&&!has_fog||is_brush||(result+=" vPosition = mvMatrix * vec4(aPos, 1.);\n"),fixed_quads||is_brush||(result+=" gl_Position = prMatrix * vPosition;\n"),is_points){var size=this.getMaterial(id,"size");result=result+" gl_PointSize = "+size.toFixed(1)+";\n"}return result+=" vCol = aCol;\n",needs_vnormal&&(result+=" vNormal = normalize((normMatrix * vec4(aNorm, 1.)).xyz);\n"),(has_texture||"text"===type)&&(result+=" vTexcoord = aTexcoord;\n"),fixed_size&&(result+=" vec4 pos = prMatrix * mvMatrix * vec4(aPos, 1.);\n pos = pos/pos.w;\n gl_Position = pos + vec4(aOfs*textScale, 0.,0.);\n"),"sprites"!==type||fixed_size||(result+=" vec4 pos = mvMatrix * vec4(aPos, 1.);\n pos = pos/pos.w + vec4(aOfs, 0., 0.);\n gl_Position = prMatrix*pos;\n"),is_twosided&&(result+=has_normals||"spheres"===obj.type?" normz = vNormal.z;":" vec4 pos1 = prMatrix*(mvMatrix*vec4(aPos1, 1.));\n pos1 = pos1/pos1.w - gl_Position/gl_Position.w;\n vec4 pos2 = prMatrix*(mvMatrix*vec4(aPos2, 1.));\n pos2 = pos2/pos2.w - gl_Position/gl_Position.w;\n normz = pos1.x*pos2.y - pos1.y*pos2.x;\n"),fat_lines&&(result+=" vec2 aspectVec = vec2(uAspect, 1.0);\n mat4 projViewModel = prMatrix * mvMatrix;\n vec4 currentProjected = projViewModel * vec4(aPos, 1.0);\n currentProjected = currentProjected/currentProjected.w;\n vec4 nextProjected = projViewModel * vec4(aNext, 1.0);\n vec2 currentScreen = currentProjected.xy * aspectVec;\n vec2 nextScreen = (nextProjected.xy / nextProjected.w) * aspectVec;\n float len = uLwd;\n vec2 dir = vec2(1.0, 0.0);\n vPoint = aPoint;\n vLength = length(nextScreen - currentScreen)/2.0;\n vLength = vLength/(vLength + len);\n if (vLength > 0.0) {\n dir = normalize(nextScreen - currentScreen);\n }\n vec2 normal = vec2(-dir.y, dir.x);\n dir.x /= uAspect;\n normal.x /= uAspect;\n vec4 offset = vec4(len*(normal*aPoint.x*aPoint.y - dir), 0.0, 0.0);\n gl_Position = currentProjected + offset;\n"),is_brush&&(result+=" gl_Position = vec4(aPos, 1.);\n"),result+=" }\n"}},rglwidgetClass.prototype.getFragmentShader=function(id){var i,texture_format,nlights,result,obj=this.getObj(id),userShader=obj.userFragmentShader,flags=obj.flags,type=obj.type,is_lit=this.isSet(flags,this.f_is_lit),has_texture=this.isSet(flags,this.f_has_texture),fixed_quads=this.isSet(flags,this.f_fixed_quads),sprites_3d=this.isSet(flags,this.f_sprites_3d),is_twosided=this.isSet(flags,this.f_is_twosided),fat_lines=this.isSet(flags,this.f_fat_lines),is_transparent=this.isSet(flags,this.f_is_transparent),is_points=this.isSet(flags,this.f_is_points),has_fog=this.isSet(flags,this.f_has_fog),nclipplanes=this.countClipplanes();if("clipplanes"!==type&&!sprites_3d){if("undefined"!=typeof userShader)return userShader;for(has_texture&&(texture_format=this.getMaterial(id,"textype")),result="/* ****** "+type+" object "+id+" fragment shader ****** */\n#ifdef GL_ES\n#ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n#else\n precision mediump float;\n#endif\n#endif\n varying vec4 vCol; // carries alpha\n varying vec4 vPosition;\n",(has_texture||"text"===type)&&(result+=" varying vec2 vTexcoord;\n uniform sampler2D uSampler;\n"),has_fog&&(result+=" uniform int uFogMode;\n uniform vec3 uFogColor;\n uniform vec4 uFogParms;\n"),is_lit&&!fixed_quads&&(result+=" varying vec3 vNormal;\n"),i=0;nclipplanes>i;i++)result=result+" uniform vec4 vClipplane"+i+";\n";if(is_lit&&(nlights=this.countLights(),nlights?result+=" uniform mat4 mvMatrix;\n":is_lit=!1),is_lit)for(result+=" uniform vec3 emission;\n uniform float shininess;\n",i=0;nlights>i;i++)result=result+" uniform vec3 ambient"+i+";\n uniform vec3 specular"+i+"; // light*material\n uniform vec3 diffuse"+i+";\n uniform vec3 lightDir"+i+";\n uniform bool viewpoint"+i+";\n uniform bool finite"+i+";\n";if(is_twosided&&(result+=" uniform bool front;\n varying float normz;\n"),fat_lines&&(result+=" varying vec2 vPoint;\n varying float vLength;\n"),result+=" void main(void) {\n vec4 fragColor;\n",fat_lines&&(result+=" vec2 point = vPoint;\n bool neg = point.y < 0.0;\n point.y = neg ? (point.y + vLength)/(1.0 - vLength) :\n -(point.y - vLength)/(1.0 - vLength);\n",is_transparent&&"linestrip"===type&&(result+=" if (neg && length(point) <= 1.0) discard;\n"),result+=" point.y = min(point.y, 0.0);\n if (length(point) > 1.0) discard;\n"),is_points){var round=this.getMaterial(id,"point_antialias");round&&(result+=" vec2 coord = gl_PointCoord - vec2(0.5);\n if (length(coord) > 0.5) discard;\n")}for(i=0;nclipplanes>i;i++)result=result+" if (dot(vPosition, vClipplane"+i+") < 0.0) discard;\n";if(fixed_quads?result+=" vec3 n = vec3(0., 0., 1.);\n":is_lit&&(result+=" vec3 n = normalize(vNormal);\n"),is_twosided&&(result+=" if ((normz <= 0.) != front) discard;\n"),is_lit)for(result+=" vec3 eye = normalize(-vPosition.xyz);\n vec3 lightdir;\n vec4 colDiff;\n vec3 halfVec;\n vec4 lighteffect = vec4(emission, 0.);\n vec3 col;\n float nDotL;\n",fixed_quads||(result+=" n = -faceforward(n, n, eye);\n"),i=0;nlights>i;i++)result=result+" colDiff = vec4(vCol.rgb * diffuse"+i+", vCol.a);\n lightdir = lightDir"+i+";\n if (!viewpoint"+i+")\n lightdir = (mvMatrix * vec4(lightdir, 1.)).xyz;\n if (!finite"+i+") {\n halfVec = normalize(lightdir + eye);\n } else {\n lightdir = normalize(lightdir - vPosition.xyz);\n halfVec = normalize(lightdir + eye);\n }\n col = ambient"+i+";\n nDotL = dot(n, lightdir);\n col = col + max(nDotL, 0.) * colDiff.rgb;\n col = col + pow(max(dot(halfVec, n), 0.), shininess) * specular"+i+";\n lighteffect = lighteffect + vec4(col, colDiff.a);\n";else result+=" vec4 colDiff = vCol;\n vec4 lighteffect = colDiff;\n";return"text"===type&&(result+=" vec4 textureColor = lighteffect*texture2D(uSampler, vTexcoord);\n"),has_texture?result=result+{rgb:" vec4 textureColor = lighteffect*vec4(texture2D(uSampler, vTexcoord).rgb, 1.);\n",rgba:" vec4 textureColor = lighteffect*texture2D(uSampler, vTexcoord);\n",alpha:" vec4 textureColor = texture2D(uSampler, vTexcoord);\n float luminance = dot(vec3(1.,1.,1.), textureColor.rgb)/3.;\n textureColor = vec4(lighteffect.rgb, lighteffect.a*luminance);\n",luminance:" vec4 textureColor = vec4(lighteffect.rgb*dot(texture2D(uSampler, vTexcoord).rgb, vec3(1.,1.,1.))/3., lighteffect.a);\n","luminance.alpha":" vec4 textureColor = texture2D(uSampler, vTexcoord);\n float luminance = dot(vec3(1.,1.,1.),textureColor.rgb)/3.;\n textureColor = vec4(lighteffect.rgb*luminance, lighteffect.a*textureColor.a);\n"}[texture_format]+" fragColor = textureColor;\n":result+="text"===type?" if (textureColor.a < 0.1)\n discard;\n else\n fragColor = textureColor;\n":" fragColor = lighteffect;\n",result+=has_fog?" float fogF;\n if (uFogMode > 0) {\n fogF = (uFogParms.y - vPosition.z/vPosition.w)/(uFogParms.y - uFogParms.x);\n if (uFogMode > 1)\n fogF = mix(uFogParms.w, 1.0, fogF);\n fogF = fogF*uFogParms.z;\n if (uFogMode == 2)\n fogF = 1.0 - exp(-fogF);\n else if (uFogMode == 3)\n fogF = 1.0 - exp(-fogF*fogF);\n fogF = clamp(fogF, 0.0, 1.0);\n gl_FragColor = vec4(mix(fragColor.rgb, uFogColor, fogF), fragColor.a);\n } else gl_FragColor = fragColor;\n":" gl_FragColor = fragColor;\n",result+=" }\n"}},rglwidgetClass.prototype.getShader=function(shaderType,code){var shader,gl=this.gl;return shader=gl.createShader(shaderType),gl.shaderSource(shader,code),gl.compileShader(shader),gl.getShaderParameter(shader,gl.COMPILE_STATUS)||gl.isContextLost()||alert(gl.getShaderInfoLog(shader)),shader},rglwidgetClass.prototype.handleLoadedTexture=function(texture,textureCanvas){var gl=this.gl||this.initGL();gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,!0),gl.bindTexture(gl.TEXTURE_2D,texture),gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,textureCanvas),gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR),gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_NEAREST),gl.generateMipmap(gl.TEXTURE_2D),gl.bindTexture(gl.TEXTURE_2D,null)},rglwidgetClass.prototype.getMaxTexSize=function(){var gl=this.gl||this.initGL();return Math.min(4096,gl.getParameter(gl.MAX_TEXTURE_SIZE))},rglwidgetClass.prototype.loadImageToTexture=function(uri,texture){var canvas=this.textureCanvas,ctx=canvas.getContext("2d"),image=new Image,self=this;image.onload=function(){for(var w=image.width,h=image.height,canvasX=self.getPowerOfTwo(w),canvasY=self.getPowerOfTwo(h),maxTexSize=self.getMaxTexSize();canvasX>1&&canvasY>1&&(canvasX>maxTexSize||canvasY>maxTexSize);)canvasX/=2,canvasY/=2;canvas.width=canvasX,canvas.height=canvasY,ctx.imageSmoothingEnabled=!0,ctx.drawImage(image,0,0,canvasX,canvasY),self.handleLoadedTexture(texture,canvas),self.drawScene()},image.src=uri},rglwidgetClass.prototype.drawTextToCanvas=function(text,cex,family,font){var canvasX,canvasY,i,width,offsetx,line,scaling=20,textColour="white",backgroundColour="rgba(0,0,0,0)",canvas=this.textureCanvas,ctx=canvas.getContext("2d"),textHeight=0,textHeights=[],widths=[],offsety=0,lines=[],offsetsx=[],offsetsy=[],lineoffsetsy=[],fontStrings=[],maxTexSize=this.getMaxTexSize(),getFontString=function(i){textHeights[i]=scaling*cex[i];var fontString=textHeights[i]+"px",family0=family[i],font0=font[i];return"sans"===family0?family0="sans-serif":"mono"===family0&&(family0="monospace"),fontString=fontString+" "+family0,(2===font0||4===font0)&&(fontString="bold "+fontString),(3===font0||4===font0)&&(fontString="italic "+fontString),fontString};for(cex=this.repeatToLen(cex,text.length),family=this.repeatToLen(family,text.length),font=this.repeatToLen(font,text.length),canvasX=1,line=-1,offsetx=maxTexSize,i=0;imaxTexSize&&(offsety+=2*textHeight,line>=0&&(lineoffsetsy[line]=offsety),line+=1,offsety>maxTexSize&&console.error("Too many strings for texture."),textHeight=0,offsetx=0),textHeight=Math.max(textHeight,textHeights[i]),offsetsx[i]=offsetx,offsetx+=width,canvasX=Math.max(canvasX,offsetx),lines[i]=line;for(offsety=lineoffsetsy[line]=offsety+2*textHeight,i=0;i=radius&&(radius=1);var hlen,observer=subscene.par3d.observer,distance=observer[2],FOV=subscene.par3d.FOV,ortho=0===FOV,t=ortho?1:Math.tan(FOV*Math.PI/360),near=distance-radius,far=distance+radius,aspect=this.vp.width/this.vp.height,z=subscene.par3d.zoom,userProjection=subscene.par3d.userProjection;0>far&&(far=1),far/100>near&&(near=far/100),this.frustum={near:near,far:far},hlen=t*near,ortho?aspect>1?this.prMatrix.ortho(-hlen*aspect*z,hlen*aspect*z,-hlen*z,hlen*z,near,far):this.prMatrix.ortho(-hlen*z,hlen*z,-hlen*z/aspect,hlen*z/aspect,near,far):aspect>1?this.prMatrix.frustum(-hlen*aspect*z,hlen*aspect*z,-hlen*z,hlen*z,near,far):this.prMatrix.frustum(-hlen*z,hlen*z,-hlen*z/aspect,hlen*z/aspect,near,far),this.prMatrix.multRight(userProjection)}},rglwidgetClass.prototype.setmvMatrix=function(id){var observer=this.getObj(id).par3d.observer;this.mvMatrix.makeIdentity(),this.setmodelMatrix(id),this.mvMatrix.translate(-observer[0],-observer[1],-observer[2])},rglwidgetClass.prototype.setmodelMatrix=function(id){var subscene=this.getObj(id),embedding=subscene.embeddings.model;if("inherit"!==embedding){var scale=subscene.par3d.scale,bbox=subscene.par3d.bbox,center=[(bbox[0]+bbox[1])/2,(bbox[2]+bbox[3])/2,(bbox[4]+bbox[5])/2];this.mvMatrix.translate(-center[0],-center[1],-center[2]),this.mvMatrix.scale(scale[0],scale[1],scale[2]),this.mvMatrix.multRight(subscene.par3d.userMatrix)}"replace"!==embedding&&this.setmodelMatrix(subscene.parent)},rglwidgetClass.prototype.setnormMatrix=function(subsceneid){var self=this,recurse=function(id){var sub=self.getObj(id),embedding=sub.embeddings.model;if("inherit"!==embedding){var scale=sub.par3d.scale;self.normMatrix.scale(1/scale[0],1/scale[1],1/scale[2]),self.normMatrix.multRight(sub.par3d.userMatrix)}"replace"!==embedding&&recurse(sub.parent)};self.normMatrix.makeIdentity(),recurse(subsceneid)},rglwidgetClass.prototype.setprmvMatrix=function(){this.prmvMatrix=new CanvasMatrix4(this.mvMatrix),this.prmvMatrix.multRight(this.prMatrix)},rglwidgetClass.prototype.getCursor=function(mode){switch(mode){case"none":return"none";case"trackball":case"xAxis":case"yAxis":case"zAxis":case"polar":return"grab";case"selecting":return"crosshair";case"fov":case"zoom":return"zoom-in"}return"dragging"},rglwidgetClass.prototype.setMouseMode=function(mode,button,subscene,stayActive){var sub=this.getObj(subscene),which=["left","right","middle"][button-1];stayActive||"selecting"!==sub.par3d.mouseMode[which]||this.clearBrush(null),sub.par3d.mouseMode[which]=mode,1===button&&(this.canvas.style.cursor=this.getCursor(mode))},rglwidgetClass.prototype.relMouseCoords=function(event){var rect=this.canvas.getBoundingClientRect();return{x:event.clientX-rect.left,y:event.clientY-rect.top}},rglwidgetClass.prototype.recordSelection=function(subid){var result={};"undefined"!=typeof this.select&&"undefined"!=typeof this.select.state&&"inactive"!==this.select.state?(result={subscene:subid,state:this.select.state,region:this.select.region},this.setmvMatrix(subid),result.model=this.mvMatrix,this.setprMatrix(subid),result.proj=this.prMatrix,this.getViewport(subid),result.view=this.vp):result.state="inactive",Shiny.setInputValue(this.scene.selectionInput+":shinyMouse3d",result)},rglwidgetClass.prototype.setMouseHandlers=function(){var activeSubscene,handler,self=this,handlers={},drag=0;handlers.rotBase=0,this.screenToVector=function(x,y){var viewport=this.getObj(activeSubscene).par3d.viewport,width=viewport.width*this.canvas.width,height=viewport.height*this.canvas.height,radius=Math.max(width,height)/2,cx=width/2,cy=height/2,px=(x-cx)/radius,py=(y-cy)/radius,plen=Math.sqrt(px*px+py*py);plen>1e-6&&(px/=plen,py/=plen);var angle=(Math.SQRT2-plen)/Math.SQRT2*Math.PI/2,z=Math.sin(angle),zlen=Math.sqrt(1-z*z);return px*=zlen,py*=zlen,[px,py,z]},handlers.trackballdown=function(x,y){var i,activeSub=this.getObj(activeSubscene),activeModel=this.getObj(this.useid(activeSub.id,"model")),l=activeModel.par3d.listeners;for(handlers.rotBase=this.screenToVector(x,y),this.saveMat=[],i=0;ij;j++)changepos[j]=-(dragCurrent[j]-handlers.dragBase[j]);activeSub.par3d.userMatrix.makeIdentity(),activeSub.par3d.userMatrix.rotate(180*changepos[0]/Math.PI,0,-1,0),activeSub.par3d.userMatrix.multRight(objects[l[i]].saveMat),activeSub.par3d.userMatrix.rotate(180*changepos[1]/Math.PI,-1,0,0)}this.drawScene()},handlers.polarend=0,handlers.axisdown=function(x){handlers.rotBase=this.screenToVector(x,this.canvas.height/2);var i,activeSub=this.getObj(activeSubscene),activeModel=this.getObj(this.useid(activeSub.id,"model")),l=activeModel.par3d.listeners;for(i=0;i0?del:1/del;handlers.setZoom(ds),ev.preventDefault()},handlers.get_finger_dist=function(ev){var diffX=ev.touches[0].clientX-ev.touches[1].clientX,diffY=ev.touches[0].clientY-ev.touches[1].clientY;return Math.sqrt(diffX*diffX+diffY*diffY)},handlers.touchstart=function(ev){var touch=ev.touches[0],mouseEvent=new MouseEvent("mousedown",{clientX:touch.clientX,clientY:touch.clientY});if(ev.preventDefault(),2===ev.touches.length){var coords=self.relMouseCoords(touch);coords.y=self.canvas.height-coords.y,activeSubscene=self.whichSubscene(coords),handlers.finger_dist0=handlers.get_finger_dist(ev),handlers.zoomdown(coords.x,coords.y)}this.dispatchEvent(mouseEvent)},handlers.touchend=function(ev){var mouseEvent;ev.preventDefault(),1===ev.touches.length&&(mouseEvent=new MouseEvent("mouseup",{}),this.dispatchEvent(mouseEvent))},handlers.touchmove=function(ev){var mouseEvent,touch=ev.touches[0];if(ev.preventDefault(),ev.touches.length>1){var coords=self.relMouseCoords(touch),new_dist=handlers.get_finger_dist(ev);coords.y=self.canvas.height*Math.log(handlers.finger_dist0/new_dist)+handlers.y0zoom,handlers.zoommove(coords.x,coords.y)}else mouseEvent=new MouseEvent("mousemove",{clientX:touch.clientX,clientY:touch.clientY}),this.dispatchEvent(mouseEvent)},this.canvas.addEventListener("DOMMouseScroll",handlers.wheelHandler,!1),this.canvas.addEventListener("mousewheel",handlers.wheelHandler,!1),this.canvas.addEventListener("touchstart",handlers.touchstart,{passive:!1}),this.canvas.addEventListener("touchend",handlers.touchend,{passive:!1}),this.canvas.addEventListener("touchmove",handlers.touchmove,{passive:!1})},rglwidgetClass.prototype.initGL0=function(){return window.WebGLRenderingContext?void 0:void this.alertOnce("Your browser does not support WebGL. See http://get.webgl.org")},rglwidgetClass.prototype.initGL=function(){var self=this,success=!1;if(this.gl){if(this.drawing||!this.gl.isContextLost())return this.gl;this.restartCanvas()}this.canvas.addEventListener("webglcontextrestored",this.onContextRestored,!1),this.canvas.addEventListener("webglcontextlost",this.onContextLost,!1),this.gl=this.canvas.getContext("webgl",this.webGLoptions)||this.canvas.getContext("experimental-webgl",this.webGLoptions),success=!!(this.gl&&this.gl instanceof WebGLRenderingContext),success||this.alertOnce("Your browser does not support WebGL. See http://get.webgl.org"),this.index_uint=this.gl.getExtension("OES_element_index_uint");var save=this.startDrawing();return Object.keys(this.scene.objects).forEach(function(key){self.initObj(parseInt(key,10))}),this.stopDrawing(save),this.gl},rglwidgetClass.prototype.resize=function(el){this.canvas.width=el.width,this.canvas.height=el.height},rglwidgetClass.prototype.initSphere=function(sections,segments){var i,j,k,ind,mod1,pole,v=[],phi=[],theta=[],it=[],centers=[],result={};for(i=0;sections-1>i;i++)phi.push((i+1)/sections-.5);for(j=0;segments>j;j++)for(theta.push(2*j/segments),i=0;sections-1>i;i++)v.push([Math.sin(Math.PI*theta[j])*Math.cos(Math.PI*phi[i]),Math.sin(Math.PI*phi[i]),Math.cos(Math.PI*theta[j])*Math.cos(Math.PI*phi[i]),theta[j]/2,phi[i]+.5]);for(pole=v.length,v.push([0,-1,0,0,0]),v.push([0,1,0,0,1]),result.values=new Float32Array(this.flatten(v)),result.vertexCount=v.length,mod1=segments*(sections-1),j=0;segments>j;j++){for(i=0;sections-2>i;i++)ind=i+(sections-1)*j,it.push([ind%mod1,(ind+sections-1)%mod1,(ind+sections)%mod1]),it.push([ind%mod1,(ind+sections)%mod1,(ind+1)%mod1]);it.push([pole,(j+1)*(sections-1)%mod1,((j+1)*(sections-1)-sections+1)%mod1]),it.push([pole+1,((j+1)*(sections-1)-1)%mod1,((j+1)*(sections-1)+sections-2)%mod1])}for(result.it=new Uint16Array(this.flatten(it)),i=0;ij;j++)for(k=0;3>k;k++)centers[i][j]+=v[it[i][k]][j]/3;result.centers=centers,result.vOffsets={vofs:0,cofs:-1,nofs:0,radofs:-1,oofs:-1,tofs:3,nextofs:-1,pointofs:-1,stride:5},result.f=[],result.indices={},result.colorCount=1,result.type="sphere",this.sphere=result,this.initSphereGL()},rglwidgetClass.prototype.initSphereGL=function(){var gl=this.gl||this.initGL(),sphere=this.sphere;gl.isContextLost()||(sphere.buf=gl.createBuffer(),gl.bindBuffer(gl.ARRAY_BUFFER,sphere.buf),gl.bufferData(gl.ARRAY_BUFFER,sphere.values,gl.STATIC_DRAW),sphere.ibuf=[gl.createBuffer(),gl.createBuffer()])},rglwidgetClass.prototype.initSphereFromObj=function(obj){var i,pass,f,mode,sphere=this.sphere;if(sphere.ofsLoc=obj.ofsLoc,sphere.texLoc=obj.texLoc,sphere.sampler=obj.sampler,sphere.uFogMode=obj.uFogMode,sphere.uFogColor=obj.uFogColor,sphere.uFogParms=obj.uFogParms,sphere.userAttribLocations=obj.userAttribLocations,sphere.userUniformLocations=obj.userUniformLocations,sphere.normLoc=obj.normLoc,sphere.clipLoc=obj.clipLoc,sphere.nextLoc=obj.nextLoc,sphere.pointLoc=obj.pointLoc,sphere.aspectLoc=obj.aspectLoc,sphere.lwdLoc=obj.lwdLoc,sphere.prog=obj.prog,sphere.material=obj.material,sphere.flags=obj.flags,sphere.someHidden=obj.someHidden,sphere.fastTransparency=obj.fastTransparency,sphere.nlights=obj.nlights,sphere.emission=obj.emission,sphere.emissionLoc=obj.emissionLoc,sphere.shininess=obj.shininess,sphere.shininessLoc=obj.shininessLoc,sphere.ambient=obj.ambient,sphere.ambientLoc=obj.ambientLoc,sphere.specular=obj.specular,sphere.specularLoc=obj.specularLoc,sphere.diffuse=obj.diffuse,sphere.diffuseLoc=obj.diffuseLoc,sphere.lightDir=obj.lightDir,sphere.lightDirLoc=obj.lightDirLoc,sphere.viewpoint=obj.viewpoint,sphere.viewpointLoc=obj.viewpointLoc,sphere.finite=obj.finite,sphere.finiteLoc=obj.finiteLoc,sphere.prMatLoc=obj.prMatLoc,sphere.mvMatLoc=obj.mvMatLoc,sphere.normMatLoc=obj.normMatLoc,sphere.frontLoc=obj.frontLoc,sphere.index_uint=!1,sphere.is_transparent=obj.is_transparent,sphere.ignoreExtent=obj.ignoreExtent,sphere.passes!==obj.passes||JSON.stringify(sphere.pmode)!==JSON.stringify(obj.pmode))for(sphere.passes=obj.passes,sphere.pmode=obj.pmode,pass=0;pass=0),is_brush&&this.initSelection(id),"undefined"==typeof obj.vertices&&(obj.vertices=[]),v=obj.vertices,obj.vertexCount=v.length,obj.vertexCount){if(is_twosided&&!has_normals){if("undefined"==typeof obj.userAttributes&&(obj.userAttributes={}),v1=Array(v.length),v2=Array(v.length),"triangles"===obj.type||"quads"===obj.type)for(nrow="triangles"===obj.type?3:4,i=0;ij;j++)v1[nrow*i+j]=v[nrow*i+(j+1)%nrow],v2[nrow*i+j]=v[nrow*i+(j+2)%nrow];else if("surface"===obj.type)for(dim=obj.dim[0],nx=dim[0],nz=dim[1],j=0;nx>j;j++)for(i=0;nz>i;i++)nz>i+1&&nx>j+1?(v2[j+nx*i]=v[j+nx*(i+1)],v1[j+nx*i]=v[j+1+nx*(i+1)]):nz>i+1?(v2[j+nx*i]=v[j-1+nx*i],v1[j+nx*i]=v[j+nx*(i+1)]):(v2[j+nx*i]=v[j+nx*(i-1)],v1[j+nx*i]=v[j-1+nx*(i-1)]);obj.userAttributes.aPos1=v1,obj.userAttributes.aPos2=v2}if(!sprites_3d){if(gl.isContextLost())return;obj.prog=gl.createProgram(),gl.attachShader(obj.prog,this.getShader(gl.VERTEX_SHADER,this.getVertexShader(id))),gl.attachShader(obj.prog,this.getShader(gl.FRAGMENT_SHADER,this.getFragmentShader(id))),gl.bindAttribLocation(obj.prog,0,"aPos"),gl.bindAttribLocation(obj.prog,1,"aCol"),gl.linkProgram(obj.prog);var linked=gl.getProgramParameter(obj.prog,gl.LINK_STATUS);if(!linked){var lastError=gl.getProgramInfoLog(obj.prog);return console.warn("Error in program linking:"+lastError),void gl.deleteProgram(obj.prog)}}"text"===type&&(texinfo=this.drawTextToCanvas(obj.texts,this.flatten(obj.cex),this.flatten(obj.family),this.flatten(obj.family))),fixed_quads&&!sprites_3d&&(obj.ofsLoc=gl.getAttribLocation(obj.prog,"aOfs")),(has_texture||"text"===type)&&(obj.texture||(obj.texture=gl.createTexture()),obj.texLoc=gl.getAttribLocation(obj.prog,"aTexcoord"),obj.sampler=gl.getUniformLocation(obj.prog,"uSampler")),has_fog&&!sprites_3d&&(obj.uFogMode=gl.getUniformLocation(obj.prog,"uFogMode"),obj.uFogColor=gl.getUniformLocation(obj.prog,"uFogColor"),obj.uFogParms=gl.getUniformLocation(obj.prog,"uFogParms")),has_texture&&(mat=obj.material,"undefined"!=typeof mat.uri?uri=mat.uri:"undefined"==typeof mat.uriElementId?(matobj=this.getObj(mat.uriId),uri="undefined"!=typeof matobj?matobj.material.uri:""):uri=document.getElementById(mat.uriElementId).rglinstance.getObj(mat.uriId).material.uri,this.loadImageToTexture(uri,obj.texture)),"text"===type&&this.handleLoadedTexture(obj.texture,this.textureCanvas);var nc,cofs,nofs,radofs,oofs,tofs,vnew,fnew,alias,colors,key,selection,filter,adj,pos,offset,attr,last,options,stride=3,nextofs=-1,pointofs=-1;if(obj.alias=void 0,colors=obj.colors,j=this.scene.crosstalk.id.indexOf(id),j>=0){for(key=this.scene.crosstalk.key[j],options=this.scene.crosstalk.options[j],colors=colors.slice(0),i=0;i1?(cofs=stride,stride+=4,v=this.cbind(v,colors)):(cofs=-1,obj.onecolor=this.flatten(colors)),has_normals?(nofs=stride,stride+=3,v=this.cbind(v,"undefined"!=typeof obj.pnormals?obj.pnormals:obj.normals)):nofs=-1,"undefined"!=typeof obj.radii?(radofs=stride,stride+=1,obj.radii.length===v.length?v=this.cbind(v,obj.radii):1===obj.radii.length&&(v=v.map(function(row){return row.concat(obj.radii[0])}))):radofs=-1,f=Array(v.length),i=0;ij;j++)v1=vnew[fnew[4*i+j]],v1[tofs+2]=2*(v1[tofs]-v1[tofs+2])*texinfo.widths[i],v1[tofs+3]=2*(v1[tofs+1]-v1[tofs+3])*texinfo.textHeights[i],v1[tofs]=(texinfo.offsetsx[i]+v1[tofs]*texinfo.widths[i])/texinfo.canvasX,v1[tofs+1]=1-(texinfo.offsetsy[i]-v1[tofs+1]*texinfo.textHeights[i])/texinfo.canvasY,vnew[fnew[4*i+j]]=v1;v=vnew,obj.vertexCount=v.length,obj.f=[fnew,fnew]}else"undefined"!=typeof obj.texcoords?(tofs=stride,stride+=2,oofs=-1,v=this.cbind(v,obj.texcoords)):(tofs=-1,oofs=-1);else{tofs=stride,stride+=2,oofs=stride,stride+=2,vnew=new Array(4*v.length),fnew=new Array(4*v.length),alias=new Array(v.length);var rescale=fixed_size?72:1,size=obj.radii,s=rescale*size[0]/2;for(last=v.length,f=obj.f[0],i=0;i1&&(s=rescale*size[i]/2),vnew[i]=v[i].concat([0,0,-s,-s]),fnew[4*i]=f[i],vnew[last]=v[i].concat([1,0,s,-s]),fnew[4*i+1]=last++,vnew[last]=v[i].concat([1,1,s,s]),fnew[4*i+2]=last++,vnew[last]=v[i].concat([0,1,-s,s]),fnew[4*i+3]=last++,alias[i]=[last-3,last-2,last-1];v=vnew,obj.vertexCount=v.length,obj.f=[fnew,fnew]}if(obj.alias=alias,"undefined"!=typeof obj.userAttributes){obj.userAttribOffsets={},obj.userAttribLocations={},obj.userAttribSizes={};for(attr in obj.userAttributes)obj.userAttribLocations[attr]=gl.getAttribLocation(obj.prog,attr),obj.userAttribLocations[attr]>=0&&(obj.userAttribOffsets[attr]=stride,v=this.cbind(v,obj.userAttributes[attr]),stride=v[0].length,obj.userAttribSizes[attr]=stride-obj.userAttribOffsets[attr])}if("undefined"!=typeof obj.userUniforms){obj.userUniformLocations={};for(attr in obj.userUniforms)obj.userUniformLocations[attr]=gl.getUniformLocation(obj.prog,attr)}if(sprites_3d)for(obj.userMatrix=new CanvasMatrix4(obj.usermatrix),obj.objects=this.flatten([].concat(obj.ids)),is_lit=!1,i=0;ii;i++)obj.clipLoc[i]=gl.getUniformLocation(obj.prog,"vClipplane"+i);if(is_lit)for(obj.emissionLoc=gl.getUniformLocation(obj.prog,"emission"),obj.emission=new Float32Array(this.stringToRgb(this.getMaterial(id,"emission"))),obj.shininessLoc=gl.getUniformLocation(obj.prog,"shininess"),obj.shininess=this.getMaterial(id,"shininess"),obj.nlights=this.countLights(),obj.ambientLoc=[],obj.ambient=new Float32Array(this.stringToRgb(this.getMaterial(id,"ambient"))),obj.specularLoc=[],obj.specular=new Float32Array(this.stringToRgb(this.getMaterial(id,"specular"))),obj.diffuseLoc=[],obj.lightDirLoc=[],obj.viewpointLoc=[],obj.finiteLoc=[],i=0;ii;i++)fnew[6*i]=f[3*i],fnew[6*i+1]=f[3*i+1],fnew[6*i+2]=f[3*i+1],fnew[6*i+3]=f[3*i+2],fnew[6*i+4]=f[3*i+2],fnew[6*i+5]=f[3*i]}else if("spheres"===type);else if("surface"===type)if(dim=obj.dim[0],nx=dim[0],nz=dim[1],"filled"===pmode)for(fnew=[],j=0;nx-1>j;j++)for(i=0;nz-1>i;i++)fnew.push(f[j+nx*i],f[j+nx*(i+1)],f[j+1+nx*(i+1)],f[j+nx*i],f[j+1+nx*(i+1)],f[j+1+nx*i]);else if("lines"===pmode)for(fnew=[],j=0;nx>j;j++)for(i=0;nz>i;i++)nz>i+1&&fnew.push(f[j+nx*i],f[j+nx*(i+1)]),nx>j+1&&fnew.push(f[j+nx*i],f[j+1+nx*i])}else if(nrows=Math.floor(obj.vertexCount/4),"filled"===pmode)for(fnew=Array(6*nrows),i=0;nrows>i;i++)fnew[6*i]=f[4*i],fnew[6*i+1]=f[4*i+1],fnew[6*i+2]=f[4*i+2],fnew[6*i+3]=f[4*i],fnew[6*i+4]=f[4*i+2],fnew[6*i+5]=f[4*i+3];else for(fnew=Array(8*nrows),i=0;nrows>i;i++)fnew[8*i]=f[4*i],fnew[8*i+1]=f[4*i+1],fnew[8*i+2]=f[4*i+1],fnew[8*i+3]=f[4*i+2],fnew[8*i+4]=f[4*i+2],fnew[8*i+5]=f[4*i+3],fnew[8*i+6]=f[4*i+3],fnew[8*i+7]=f[4*i];obj.f[pass]=fnew,drawtype=depth_sort?"DYNAMIC_DRAW":"STATIC_DRAW"}if(fat_lines){for(alias=void 0,obj.nextLoc=gl.getAttribLocation(obj.prog,"aNext"),obj.pointLoc=gl.getAttribLocation(obj.prog,"aPoint"),obj.aspectLoc=gl.getUniformLocation(obj.prog,"uAspect"),obj.lwdLoc=gl.getUniformLocation(obj.prog,"uLwd"),pass=0;passj;j++)vnew[k][nextofs+j]=vnew[f[i+1]][j];for(vnew[k][pointofs]=-1,vnew[k][pointofs+1]=-1,fnew[ind]=k,last++,vnew[last]=vnew[k].slice(),vnew[last][pointofs]=1,fnew[ind+1]=last,alias[f[i]].push(last-1,last),last++,k=last,vnew[k]=vnew[f[i+1]].slice(),j=0;3>j;j++)vnew[k][nextofs+j]=vnew[f[i]][j];vnew[k][pointofs]=-1,vnew[k][pointofs+1]=1,fnew[ind+2]=k,fnew[ind+3]=fnew[ind+1],last++,vnew[last]=vnew[k].slice(),vnew[last][pointofs]=1,fnew[ind+4]=last,fnew[ind+5]=fnew[ind+2],ind+=6,alias[f[i+1]].push(last-1,last)}if(vnew.length=last+1,v=vnew,obj.vertexCount=v.length,"undefined"!=typeof alias&&"undefined"!=typeof obj.alias){var oldalias=obj.alias,newalias=Array(obj.alias.length);for(i=0;i65535?this.index_uint?(obj.f[pass]=new Uint32Array(obj.f[pass]),obj.index_uint=!0):this.alertOnce("Object has "+obj.vertexCount+" vertices, not supported in this browser."):(obj.f[pass]=new Uint16Array(obj.f[pass]),obj.index_uint=!1);stride!==v[0].length&&this.alertOnce("problem in stride calculation"),obj.vOffsets={vofs:0,cofs:cofs,nofs:nofs,radofs:radofs,oofs:oofs,tofs:tofs,nextofs:nextofs,pointofs:pointofs,stride:stride},obj.values=new Float32Array(this.flatten(v)),"spheres"===type||sprites_3d||(obj.buf=gl.createBuffer(),gl.bindBuffer(gl.ARRAY_BUFFER,obj.buf),gl.bufferData(gl.ARRAY_BUFFER,obj.values,gl.STATIC_DRAW),obj.ibuf=Array(obj.passes),obj.ibuf[0]=gl.createBuffer(),gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,obj.ibuf[0]),gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,obj.f[0],gl[drawtype]),is_twosided&&(obj.ibuf[1]=gl.createBuffer(),gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,obj.ibuf[1]),gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,obj.f[1],gl[drawtype]))),sprites_3d||(obj.mvMatLoc=gl.getUniformLocation(obj.prog,"mvMatrix"),obj.prMatLoc=gl.getUniformLocation(obj.prog,"prMatrix")),fixed_size&&(obj.textScaleLoc=gl.getUniformLocation(obj.prog,"textScale")),is_lit&&!sprites_3d&&(obj.normMatLoc=gl.getUniformLocation(obj.prog,"normMatrix")),is_twosided&&(obj.frontLoc=gl.getUniformLocation(obj.prog,"front"))}}},rglwidgetClass.prototype.initialize=function(el,x){if(this.textureCanvas=document.createElement("canvas"),this.textureCanvas.style.display="block",this.scene=x,this.normMatrix=new CanvasMatrix4,this.saveMat={},this.distance=null,this.posLoc=0,this.colLoc=1,el&&(el.rglinstance=this,this.el=el,this.webGLoptions=el.rglinstance.scene.webGLoptions,this.initCanvas()),"undefined"!=typeof Shiny){var self=this;Shiny.addCustomMessageHandler("shinyGetPar3d",function(message){var i,param,subscene=self.getObj(message.subscene),parameters=[].concat(message.parameters),result={tag:message.tag,subscene:message.subscene};if("undefined"!=typeof subscene)for(i=0;ii;i++)z=this.prmvMatrix.m13*obj.centers[i][0]+this.prmvMatrix.m23*obj.centers[i][1]+this.prmvMatrix.m33*obj.centers[i][2]+this.prmvMatrix.m43,w=this.prmvMatrix.m14*obj.centers[i][0]+this.prmvMatrix.m24*obj.centers[i][1]+this.prmvMatrix.m34*obj.centers[i][2]+this.prmvMatrix.m44,depth=z/w,result[i]={context:context,objid:objid,subid:subid,index:i,depth:depth};return result},rglwidgetClass.prototype.getSpherePieces=function(context,subid,obj){return obj.fastTransparency?0===subid?this.getPieces(context,obj.id,-1,obj):[]:this.getPieces(context,obj.id,subid,this.sphere)},rglwidgetClass.prototype.mergePieces=function(pieces){var result=[];if(pieces.length>0){var i,thiscontext=pieces[0].context,thisobjid=pieces[0].objid,thissubid=pieces[0].subid,indices=[];for(i=0;i0;)diff=c1.pop()-c2.pop();0===diff&&(diff=j.objid-i.objid),0===diff&&(diff=j.subid-i.subid)}return diff},result=[];return pieces.length&&(result=pieces.sort(compare)),result},rglwidgetClass.prototype.startDrawing=function(){var value=this.drawing;return this.drawing=!0,value},rglwidgetClass.prototype.stopDrawing=function(saved){this.drawing=saved,!saved&&this.gl&&this.gl.isContextLost()&&this.restartCanvas()},rglwidgetClass.prototype.planeUpdateTriangles=function(obj,bbox){var x,xrow,elem,A,d,nhits,i,j,k,u,v,w,intersect,which,v0,v2,vx,reverse,perms=[[0,0,1],[1,2,2],[2,1,0]],face1=[],face2=[],normals=[],nPlanes=obj.normals.length;for(obj.bbox=bbox,obj.vertices=[],obj.initialized=!1,elem=0;nPlanes>elem;elem++){for(x=[],A=obj.normals[elem],d=obj.offsets[elem][0],nhits=0,i=0;3>i;i++)for(j=0;2>j;j++)for(k=0;2>k;k++)u=perms[0][i],v=perms[1][i],w=perms[2][i],0!==A[w]&&(intersect=-(d+A[u]*bbox[j+2*u]+A[v]*bbox[k+2*v])/A[w],bbox[2*w]3)for(i=0;nhits-2>i;i++){for(which=0,j=i+1;nhits>j;j++)if(face1[i]===face1[j]||face1[i]===face2[j]||face2[i]===face1[j]||face2[i]===face2[j]){which=j;break}which>i+1&&(this.swap(x,i+1,which),this.swap(face1,i+1,which),this.swap(face2,i+1,which))}if(nhits>=3)for(v0=[x[0][0]-x[1][0],x[0][1]-x[1][1],x[0][2]-x[1][2]],v2=[x[2][0]-x[1][0],x[2][1]-x[1][1],x[2][2]-x[1][2]],vx=this.xprod(v0,v2),reverse=this.dotprod(vx,A)>0,i=0;nhits-2>i;i++)for(obj.vertices.push(x[0]),normals.push(A),j=1;3>j;j++)obj.vertices.push(x[i+(reverse?3-j:j)]),normals.push(A)}obj.pnormals=normals},rglwidgetClass.prototype.mode4type={points:"POINTS",linestrip:"LINE_STRIP",abclines:"LINES",lines:"LINES",sprites:"TRIANGLES",planes:"TRIANGLES",text:"TRIANGLES",quads:"TRIANGLES",surface:"TRIANGLES",triangles:"TRIANGLES",sphere:"TRIANGLES"},rglwidgetClass.prototype.disableArrays=function(obj,enabled){var i,attr,gl=this.gl||this.initGL(),objLocs=["normLoc","texLoc","ofsLoc","pointLoc","nextLoc"],thisLocs=["posLoc","colLoc"];for(i=0;i=0?(gl.enableVertexAttribArray(obj.normLoc),gl.vertexAttribPointer(obj.normLoc,3,gl.FLOAT,!1,4*obj.vOffsets.stride,4*obj.vOffsets.nofs),!0):!1},rglwidgetClass.prototype.doTexture=function(obj){var gl=this.gl,is_spheres="spheres"===obj.type;return gl.enableVertexAttribArray(obj.texLoc),is_spheres?gl.vertexAttribPointer(obj.texLoc,2,gl.FLOAT,!1,4*this.sphere.vOffsets.stride,4*this.sphere.vOffsets.tofs):gl.vertexAttribPointer(obj.texLoc,2,gl.FLOAT,!1,4*obj.vOffsets.stride,4*obj.vOffsets.tofs),gl.activeTexture(gl.TEXTURE0),gl.bindTexture(gl.TEXTURE_2D,obj.texture),gl.uniform1i(obj.sampler,0),!0},rglwidgetClass.prototype.doUserAttributes=function(obj){if("undefined"!=typeof obj.userAttributes){var gl=this.gl;for(var attr in obj.userAttribSizes)gl.enableVertexAttribArray(obj.userAttribLocations[attr]),gl.vertexAttribPointer(obj.userAttribLocations[attr],obj.userAttribSizes[attr],gl.FLOAT,!1,4*obj.vOffsets.stride,4*obj.userAttribOffsets[attr])}},rglwidgetClass.prototype.doUserUniforms=function(obj){if("undefined"!=typeof obj.userUniforms){var gl=this.gl;for(var attr in obj.userUniformLocations){var loc=obj.userUniformLocations[attr];if(null!==loc){var uniform=obj.userUniforms[attr];if("undefined"==typeof uniform.length)gl.uniform1f(loc,uniform);else if("undefined"==typeof uniform[0].length)switch(uniform=new Float32Array(uniform),uniform.length){case 2:gl.uniform2fv(loc,uniform);break;case 3:gl.uniform3fv(loc,uniform);break;case 4:gl.uniform4fv(loc,uniform);break;default:console.warn("bad uniform length")}else 4===uniform.length&&4===uniform[0].length?gl.uniformMatrix4fv(loc,!1,new Float32Array(uniform.getAsArray())):console.warn("unsupported uniform matrix")}}}},rglwidgetClass.prototype.doLoadIndices=function(obj,pass,indices){var fnew,step,gl=this.gl,f=obj.f[pass],type=obj.type,fat_lines=this.isSet(obj.flags,this.f_fat_lines);switch(type){case"points":step=1;break;case"abclines":case"lines":step=fat_lines?6:2;break;case"linestrip":step=fat_lines?6:1;break;case"sphere":case"planes":case"triangles":step=3;break;case"text":case"sprites":case"quads":case"surface":step=6;break;default:return console.error("loadIndices for "+type),0}fnew=obj.index_uint?new Uint32Array(step*indices.length):new Uint16Array(step*indices.length);for(var i=0;ij;j++)fnew[step*i+j]=f[step*indices[i]+j];return gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,fnew,gl.DYNAMIC_DRAW),fnew.length},rglwidgetClass.prototype.doMasking=function(mask){var gl=this.gl;gl.depthMask(mask)},rglwidgetClass.prototype.doBlending=function(blend){var gl=this.gl;blend?(gl.blendFuncSeparate(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA,gl.ONE,gl.ONE),gl.enable(gl.BLEND)):gl.disable(gl.BLEND)},rglwidgetClass.prototype.doFog=function(obj,subscene){var fogmode,color,gl=this.gl,observer=subscene.par3d.observer[2],sintheta=Math.sin(subscene.par3d.FOV*Math.PI/180/2),parms=[this.frustum.near-2*observer,this.frustum.far-2*observer,this.fogScale,(1-sintheta)/(1+sintheta)];switch("undefined"==typeof this.fogType&&(this.fogType="none"),"undefined"==typeof this.fogScale&&(parms[2]=1),0===sintheta&&(parms[3]=1/3),this.fogType){case"none":fogmode=0;break;case"linear":fogmode=1;break;case"exp":fogmode=2;break;case"exp2":fogmode=3;break;default:console.error("Unknown fogtype "+this.fogType)}gl.uniform1i(obj.uFogMode,fogmode),color=this.fogColor,gl.uniform3f(obj.uFogColor,color[0],color[1],color[2]),gl.uniform4f(obj.uFogParms,parms[0],parms[1],parms[2],parms[3])},rglwidgetClass.prototype.drawSimple=function(obj,subscene,context){var count,pass,mode,pmode,flags=obj.flags,type=obj.type,is_lit=this.isSet(flags,this.f_is_lit),has_texture=this.isSet(flags,this.f_has_texture),is_transparent=this.isSet(flags,this.f_is_transparent),fixed_size=this.isSet(flags,this.f_fixed_size),fixed_quads=this.isSet(flags,this.f_fixed_quads),is_lines=this.isSet(flags,this.f_is_lines),fat_lines=this.isSet(flags,this.f_fat_lines),is_twosided=this.isSet(flags,this.f_is_twosided),has_fog=this.isSet(flags,this.f_has_fog),gl=this.gl||this.initGL(),enabled={};if(obj.initialized||this.initObj(obj.id),count=obj.vertexCount,!count)return[];if(is_transparent=is_transparent||obj.someHidden,is_transparent&&this.opaquePass)return this.getPieces(context,obj.id,0,obj);for(this.doDepthTest(obj),this.doMasking(this.getObjMaterial(obj,"depth_mask")),gl.useProgram(obj.prog),this.doPolygonOffset(obj),gl.bindBuffer(gl.ARRAY_BUFFER,obj.buf),gl.uniformMatrix4fv(obj.prMatLoc,!1,new Float32Array(this.prMatrix.getAsArray())),gl.uniformMatrix4fv(obj.mvMatLoc,!1,new Float32Array(this.mvMatrix.getAsArray())),this.doClipping(obj,subscene),is_lit&&this.doLighting(obj,subscene),has_fog&&this.doFog(obj,subscene),this.doUserAttributes(obj),this.doUserUniforms(obj),gl.enableVertexAttribArray(this.posLoc),enabled.posLoc=!0,(has_texture||"text"===obj.type)&&(enabled.texLoc=this.doTexture(obj)),enabled.colLoc=this.doColors(obj),is_lit&&(enabled.normLoc=this.doNormals(obj)),fixed_size&&gl.uniform2f(obj.textScaleLoc,.75/this.vp.width,.75/this.vp.height),fixed_quads&&(gl.enableVertexAttribArray(obj.ofsLoc),enabled.ofsLoc=!0,gl.vertexAttribPointer(obj.ofsLoc,2,gl.FLOAT,!1,4*obj.vOffsets.stride,4*obj.vOffsets.oofs)),pass=0;passi;i++)sphereMV=new CanvasMatrix4,idx=this.opaquePass?i:obj.fastTransparency?indices[i]:context.subid,"undefined"==typeof idx&&console.error("idx is undefined"),baseofs=idx*obj.vOffsets.stride,ofs=baseofs+obj.vOffsets.radofs,sscale=obj.values[ofs],sphereMV.scale(sscale/scale[0],sscale/scale[1],sscale/scale[2]),sphereMV.translate(obj.values[baseofs],obj.values[baseofs+1],obj.values[baseofs+2]),sphereMV.multRight(saveMV),this.mvMatrix=sphereMV,this.setprmvMatrix(),drawing?(nc>1&&(this.sphere.onecolor=this.flatten(obj.sphereColors[idx%obj.sphereColors.length])),this.drawSimple(this.sphere,subscene,context)):result=result.concat(this.getSpherePieces(context,i,obj));return drawing&&this.disableArrays(obj,enabled),this.normMatrix=saveNorm,this.mvMatrix=saveMV,this.prmvMatrix=savePRMV,result},rglwidgetClass.prototype.drawClipplanes=function(obj){for(var count=obj.offsets.length,IMVClip=[],i=0;count>i;i++)IMVClip[i]=this.multMV(this.invMatrix,obj.vClipplane.slice(4*i,4*(i+1)));return obj.IMVClip=IMVClip,[]},rglwidgetClass.prototype.drawLinestrip=function(obj,subscene,context){var origIndices,i,j;if(this.opaquePass)return this.drawSimple(obj,subscene,context);for(origIndices=context.indices.slice(),i=0;iiOrig;iOrig++)for(j=this.opaquePass?iOrig:context.subid,pos=this.multVM([].concat(obj.vertices[j]).concat(1),origMV),radius=obj.radii.length>1?obj.radii[j][0]:obj.radii[0][0],this.mvMatrix=new CanvasMatrix4(userMatrix),this.mvMatrix.scale(radius),this.mvMatrix.translate(pos[0]/pos[3],pos[1]/pos[3],pos[2]/pos[3]),this.setprmvMatrix(),i=0;i0)for(this.invMatrix=new CanvasMatrix4(this.mvMatrix),this.invMatrix.invert(),i=0;i0;)switch(objid=context.pop(),obj=this.getObj(objid),type=obj.type){case"subscene":this.drawSubscene(objid,!1);break;case"sprites":result=result.concat(context.pop());break;case"spheres":break;default:console.error("bad type '",type,"' in setContext")}return result},rglwidgetClass.prototype.drawPieces=function(pieces){var i,context,prevcontext=[];for(this.doBlending(!0),i=0;i=i;i++)adds=adds.concat(control.subsets[i]);else adds=adds.concat(control.subsets[value]);for(deletes=fullset.filter(function(x){return adds.indexOf(x)<0}),i=0;ivalue-svals[j-1]&&(j-=1);break}if(obj=this.getObj(control.objid),"undefined"!=typeof obj.vOffsets){for(varies=!0,k=0;ncol>k;k++)if(attrib=attributes[k],"undefined"!=typeof attrib&&(ofs=obj.vOffsets[ofss[attrib]],0>ofs)){switch(attrib){case"alpha":case"red":case"green":case"blue":obj.colors=[obj.colors[0],obj.colors[0]]}varies=!1}varies||this.initObj(control.objid)}for(propvals=obj.values,aliases=obj.alias,"undefined"==typeof aliases&&(aliases=[]),k=0;ncol>k;k++)if(newval=direct?value:interp?p*values[j-1][k]+(1-p)*values[j][k]:values[j][k],attrib=attributes[k],vertex=vertices[k],alias=aliases[vertex],("planes"===obj.type||"clipplanes"===obj.type)&&(ofs=["nx","ny","nz","offset"].indexOf(attrib),ofs>=0))3>ofs?obj.normals[vertex][ofs]!==newval&&(obj.normals[vertex][ofs]=newval,obj.initialized=!1):obj.offsets[vertex][0]!==newval&&(obj.offsets[vertex][0]=newval,obj.initialized=!1);else if(ofs=obj.vOffsets[ofss[attrib]],0>ofs)this.alertOnce("Attribute '"+attrib+"' not found in object "+control.objid);else if(stride=obj.vOffsets.stride,ofs+=pos[attrib],entry=vertex*stride+ofs,propvals[entry]=newval,"undefined"!=typeof alias)for(a=0;ai;i++)if(null!==births[i]){for(age=time-births[i],j0=1;age>ages[j0];j0++);p[i]=1/0===ages[j0]?1:ages[j0]>ages[j0-1]?(ages[j0]-age)/(ages[j0]-ages[j0-1]):0,j[i]=j0}for(l=0;nobjs>l;l++)if(objid=objids[l],obj=this.getObj(objid),varies=!0,"undefined"!=typeof obj.vOffsets){for(k=0;kofs)){switch(attribs[k]){case"colors":case"alpha":case"red":case"green":case"blue":obj.colors=[obj.colors[0],obj.colors[0]]}varies=!1}varies||this.initObj(objid)}for(l=0;nobjs>l;l++)if(objid=objids[l],obj=this.getObj(objid),"undefined"!=typeof obj.vOffsets){for(aliases=obj.alias,"undefined"==typeof aliases&&(aliases=[]),propvals=obj.values,stride=obj.vOffsets.stride,k=0;k=0){for(dim=dims[k],ofs+=pos[k],i=0;steps>i;i++)if(alias=aliases[i],null!==births[i])for(d=0;dim>d;d++)if(propvals[i*stride+ofs+d]=p[i]*attrib[dim*(j[i]-1)+d]+(1-p[i])*attrib[dim*j[i]+d],"undefined"!=typeof alias)for(a=0;a=0){for(keys=this.scene.crosstalk.key[j],obj=this.getObj(id),someHidden=!1,k=0;k=xmin&&xmax>=x&&y>=ymin&&ymax>=y&&z>=-1&&1>=z?selection.push(keys[k]):someHidden=!0);obj.someHidden=someHidden&&(filter||selection.length),obj.initialized=!1,this.equalArrays(selection,this.scene.crosstalk.selection)||(handle=this.scene.crosstalk.sel_handle[j],handle.set(selection,{rglSubsceneId:this.select.subscene}))}},rglwidgetClass.prototype.selection=function(event,filter){var i,j,ids,obj,keys,selection,someHidden,crosstalk=this.scene.crosstalk;for(crosstalk=this.scene.crosstalk,filter?(filter=crosstalk.filter=event.value,selection=crosstalk.selection):(selection=crosstalk.selection=event.value,filter=crosstalk.filter),ids=crosstalk.id,i=0;ithis.stopTime+this.stepSize/2||this.value