summaryrefslogtreecommitdiff
path: root/graphics/asymptote/base/webgl/asygl.js
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/asymptote/base/webgl/asygl.js')
-rw-r--r--graphics/asymptote/base/webgl/asygl.js39
1 files changed, 39 insertions, 0 deletions
diff --git a/graphics/asymptote/base/webgl/asygl.js b/graphics/asymptote/base/webgl/asygl.js
new file mode 100644
index 0000000000..d6417c416e
--- /dev/null
+++ b/graphics/asymptote/base/webgl/asygl.js
@@ -0,0 +1,39 @@
+/*@license
+ gl.js: Render Bezier patches via subdivision with WebGL.
+ Copyright 2019: John C. Bowman and Supakorn "Jamie" Rassameemasmuang
+ University of Alberta
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+let gl,canvas,canvasWidth,canvasHeight,halfCanvasWidth,halfCanvasHeight;!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var i=e();for(var r in i)("object"==typeof exports?exports:t)[r]=i[r]}}("undefined"!=typeof self?self:this,function(){return function(t){var e={};function i(r){if(e[r])return e[r].exports;var a=e[r]={i:r,l:!1,exports:{}};return t[r].call(a.exports,a,a.exports,i),a.l=!0,a.exports}return i.m=t,i.c=e,i.d=function(t,e,r){i.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=1)}([function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setMatrixArrayType=function(t){e.ARRAY_TYPE=t},e.toRadian=function(t){return t*a},e.equals=function(t,e){return Math.abs(t-e)<=r*Math.max(1,Math.abs(t),Math.abs(e))};var r=e.EPSILON=1e-6;e.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,e.RANDOM=Math.random;var a=Math.PI/180},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.mat4=e.mat3=void 0;var r=s(i(2)),a=s(i(3));function s(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e.default=t,e}e.mat3=r,e.mat4=a},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.create=function(){var t=new r.ARRAY_TYPE(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromMat4=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[4],t[4]=e[5],t[5]=e[6],t[6]=e[8],t[7]=e[9],t[8]=e[10],t},e.invert=function(t,e){var i=e[0],r=e[1],a=e[2],s=e[3],n=e[4],o=e[5],h=e[6],l=e[7],c=e[8],d=c*n-o*l,m=-c*s+o*h,u=l*s-n*h,f=i*d+r*m+a*u;if(!f)return null;return f=1/f,t[0]=d*f,t[1]=(-c*r+a*l)*f,t[2]=(o*r-a*n)*f,t[3]=m*f,t[4]=(c*i-a*h)*f,t[5]=(-o*i+a*s)*f,t[6]=u*f,t[7]=(-l*i+r*h)*f,t[8]=(n*i-r*s)*f,t};var r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e.default=t,e}(i(0))},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.create=function(){var t=new r.ARRAY_TYPE(16);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.invert=function(t,e){var i=e[0],r=e[1],a=e[2],s=e[3],n=e[4],o=e[5],h=e[6],l=e[7],c=e[8],d=e[9],m=e[10],u=e[11],f=e[12],v=e[13],p=e[14],g=e[15],x=i*o-r*n,M=i*h-a*n,w=i*l-s*n,A=r*h-a*o,S=r*l-s*o,b=a*l-s*h,P=c*v-d*f,z=c*p-m*f,R=c*g-u*f,y=d*p-m*v,D=d*g-u*v,T=m*g-u*p,E=x*T-M*D+w*y+A*R-S*z+b*P;if(!E)return null;return E=1/E,t[0]=(o*T-h*D+l*y)*E,t[1]=(a*D-r*T-s*y)*E,t[2]=(v*b-p*S+g*A)*E,t[3]=(m*S-d*b-u*A)*E,t[4]=(h*R-n*T-l*z)*E,t[5]=(i*T-a*R+s*z)*E,t[6]=(p*w-f*b-g*M)*E,t[7]=(c*b-m*w+u*M)*E,t[8]=(n*D-o*R+l*P)*E,t[9]=(r*R-i*D-s*P)*E,t[10]=(f*S-v*w+g*x)*E,t[11]=(d*w-c*S-u*x)*E,t[12]=(o*z-n*y-h*P)*E,t[13]=(i*y-r*z+a*P)*E,t[14]=(v*M-f*A-p*x)*E,t[15]=(c*A-d*M+m*x)*E,t},e.multiply=a,e.translate=function(t,e,i){var r=i[0],a=i[1],s=i[2],n=void 0,o=void 0,h=void 0,l=void 0,c=void 0,d=void 0,m=void 0,u=void 0,f=void 0,v=void 0,p=void 0,g=void 0;e===t?(t[12]=e[0]*r+e[4]*a+e[8]*s+e[12],t[13]=e[1]*r+e[5]*a+e[9]*s+e[13],t[14]=e[2]*r+e[6]*a+e[10]*s+e[14],t[15]=e[3]*r+e[7]*a+e[11]*s+e[15]):(n=e[0],o=e[1],h=e[2],l=e[3],c=e[4],d=e[5],m=e[6],u=e[7],f=e[8],v=e[9],p=e[10],g=e[11],t[0]=n,t[1]=o,t[2]=h,t[3]=l,t[4]=c,t[5]=d,t[6]=m,t[7]=u,t[8]=f,t[9]=v,t[10]=p,t[11]=g,t[12]=n*r+c*a+f*s+e[12],t[13]=o*r+d*a+v*s+e[13],t[14]=h*r+m*a+p*s+e[14],t[15]=l*r+u*a+g*s+e[15]);return t},e.rotate=function(t,e,i,a){var s=a[0],n=a[1],o=a[2],h=Math.sqrt(s*s+n*n+o*o),l=void 0,c=void 0,d=void 0,m=void 0,u=void 0,f=void 0,v=void 0,p=void 0,g=void 0,x=void 0,M=void 0,w=void 0,A=void 0,S=void 0,b=void 0,P=void 0,z=void 0,R=void 0,y=void 0,D=void 0,T=void 0,E=void 0,I=void 0,O=void 0;if(Math.abs(h)<r.EPSILON)return null;s*=h=1/h,n*=h,o*=h,l=Math.sin(i),c=Math.cos(i),d=1-c,m=e[0],u=e[1],f=e[2],v=e[3],p=e[4],g=e[5],x=e[6],M=e[7],w=e[8],A=e[9],S=e[10],b=e[11],P=s*s*d+c,z=n*s*d+o*l,R=o*s*d-n*l,y=s*n*d-o*l,D=n*n*d+c,T=o*n*d+s*l,E=s*o*d+n*l,I=n*o*d-s*l,O=o*o*d+c,t[0]=m*P+p*z+w*R,t[1]=u*P+g*z+A*R,t[2]=f*P+x*z+S*R,t[3]=v*P+M*z+b*R,t[4]=m*y+p*D+w*T,t[5]=u*y+g*D+A*T,t[6]=f*y+x*D+S*T,t[7]=v*y+M*D+b*T,t[8]=m*E+p*I+w*O,t[9]=u*E+g*I+A*O,t[10]=f*E+x*I+S*O,t[11]=v*E+M*I+b*O,e!==t&&(t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15]);return t},e.fromTranslation=function(t,e){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=e[0],t[13]=e[1],t[14]=e[2],t[15]=1,t},e.fromRotation=function(t,e,i){var a=i[0],s=i[1],n=i[2],o=Math.sqrt(a*a+s*s+n*n),h=void 0,l=void 0,c=void 0;if(Math.abs(o)<r.EPSILON)return null;return a*=o=1/o,s*=o,n*=o,h=Math.sin(e),l=Math.cos(e),c=1-l,t[0]=a*a*c+l,t[1]=s*a*c+n*h,t[2]=n*a*c-s*h,t[3]=0,t[4]=a*s*c-n*h,t[5]=s*s*c+l,t[6]=n*s*c+a*h,t[7]=0,t[8]=a*n*c+s*h,t[9]=s*n*c-a*h,t[10]=n*n*c+l,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.frustum=function(t,e,i,r,a,s,n){var o=1/(i-e),h=1/(a-r),l=1/(s-n);return t[0]=2*s*o,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*s*h,t[6]=0,t[7]=0,t[8]=(i+e)*o,t[9]=(a+r)*h,t[10]=(n+s)*l,t[11]=-1,t[12]=0,t[13]=0,t[14]=n*s*2*l,t[15]=0,t},e.ortho=function(t,e,i,r,a,s,n){var o=1/(e-i),h=1/(r-a),l=1/(s-n);return t[0]=-2*o,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*h,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*l,t[11]=0,t[12]=(e+i)*o,t[13]=(a+r)*h,t[14]=(n+s)*l,t[15]=1,t};var r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e.default=t,e}(i(0));function a(t,e,i){var r=e[0],a=e[1],s=e[2],n=e[3],o=e[4],h=e[5],l=e[6],c=e[7],d=e[8],m=e[9],u=e[10],f=e[11],v=e[12],p=e[13],g=e[14],x=e[15],M=i[0],w=i[1],A=i[2],S=i[3];return t[0]=M*r+w*o+A*d+S*v,t[1]=M*a+w*h+A*m+S*p,t[2]=M*s+w*l+A*u+S*g,t[3]=M*n+w*c+A*f+S*x,M=i[4],w=i[5],A=i[6],S=i[7],t[4]=M*r+w*o+A*d+S*v,t[5]=M*a+w*h+A*m+S*p,t[6]=M*s+w*l+A*u+S*g,t[7]=M*n+w*c+A*f+S*x,M=i[8],w=i[9],A=i[10],S=i[11],t[8]=M*r+w*o+A*d+S*v,t[9]=M*a+w*h+A*m+S*p,t[10]=M*s+w*l+A*u+S*g,t[11]=M*n+w*c+A*f+S*x,M=i[12],w=i[13],A=i[14],S=i[15],t[12]=M*r+w*o+A*d+S*v,t[13]=M*a+w*h+A*m+S*p,t[14]=M*s+w*l+A*u+S*g,t[15]=M*n+w*c+A*f+S*x,t}}])});let Zoom,Zoom0,pixel=.75,BezierFactor=.4,FillFactor=.1,maxViewportWidth=window.innerWidth,maxViewportHeight=window.innerHeight,viewportmargin=0,viewportshift=[0,0];const windowTrim=10;let zoomFactor,zoomPinchFactor,zoomPinchCap,zoomStep,shiftHoldDistance,shiftWaitTime,vibrateTime,lastzoom,H,zmin,zmax,size2,ArcballFactor,b,B,positionBuffer,materialBuffer,colorBuffer,indexBuffer,resizeStep=1.2,Fuzz2=1e3*Number.EPSILON,Fuzz4=Fuzz2*Fuzz2,third=1/3,P=[],Materials=[],Lights=[],Centers=[],Background=[1,1,1,1],absolute=!1,rotMat=mat4.create(),projMat=mat4.create(),viewMat=mat4.create(),projViewMat=mat4.create(),normMat=mat3.create(),viewMat3=mat3.create(),rotMats=mat4.create(),cjMatInv=mat4.create(),translMat=mat4.create(),center={x:0,y:0,z:0},shift={x:0,y:0},viewParam={xmin:0,xmax:0,ymin:0,ymax:0,zmin:0,zmax:0},redraw=!0,remesh=!0,mouseDownOrTouchActive=!1,lastMouseX=null,lastMouseY=null,touchID=null,Positions=[],Normals=[],Colors=[],Indices=[];class Material{constructor(t,e,i,r,a,s){this.diffuse=t,this.emissive=e,this.specular=i,this.shininess=r,this.metallic=a,this.fresnel0=s}setUniform(t,e,i=null){let r;r=null===i?i=>gl.getUniformLocation(t,e+"."+i):r=>gl.getUniformLocation(t,e+"["+i+"]."+r),gl.uniform4fv(r("diffuse"),new Float32Array(this.diffuse)),gl.uniform4fv(r("emissive"),new Float32Array(this.emissive)),gl.uniform4fv(r("specular"),new Float32Array(this.specular)),gl.uniform1f(r("shininess"),this.shininess),gl.uniform1f(r("metallic"),this.metallic),gl.uniform1f(r("fresnel0"),this.fresnel0)}}let enumPointLight=1,enumDirectionalLight=2;class Light{constructor(t,e){this.direction=t,this.color=e}setUniform(t,e,i){let r=r=>gl.getUniformLocation(t,e+"["+i+"]."+r);gl.uniform3fv(r("direction"),new Float32Array(this.direction)),gl.uniform3fv(r("color"),new Float32Array(this.color))}}function initGL(){try{gl=canvas.getContext("webgl",{alpha:Background[3]<1})}catch(t){}gl||alert("Could not initialize WebGL")}function getShader(t,e,i=[]){let r=document.getElementById(e);if(!r)return null;let a=`#version 100\n#ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n#else\n precision mediump float;\n#endif\n #define nlights ${Lights.length}\n\n const int nLights=${Math.max(Lights.length,1)};\n\n const int nMaterials=${Math.max(Materials.length,1)};\n`;orthographic&&(a+="#define ORTHOGRAPHIC\n"),i.forEach(t=>a+="#define "+t+"\n");let s,n=r.firstChild;for(;n;)3==n.nodeType&&(a+=n.textContent),n=n.nextSibling;if("x-shader/x-fragment"==r.type)s=t.createShader(t.FRAGMENT_SHADER);else{if("x-shader/x-vertex"!=r.type)return null;s=t.createShader(t.VERTEX_SHADER)}return t.shaderSource(s,a),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?s:(alert(t.getShaderInfoLog(s)),null)}function drawBuffer(t,e,i=t.indices){if(0==t.indices.length)return;let r=e==pixelShader,a=!r&&e!=noNormalShader;setUniforms(e),gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer),gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(t.vertices),gl.STATIC_DRAW),gl.vertexAttribPointer(e.vertexPositionAttribute,3,gl.FLOAT,!1,a?24:r?16:12,0),a?gl.vertexAttribPointer(e.vertexNormalAttribute,3,gl.FLOAT,!1,24,12):r&&gl.vertexAttribPointer(e.vertexWidthAttribute,1,gl.FLOAT,!1,16,12),gl.bindBuffer(gl.ARRAY_BUFFER,materialBuffer),gl.bufferData(gl.ARRAY_BUFFER,new Int16Array(t.materials),gl.STATIC_DRAW),gl.vertexAttribPointer(e.vertexMaterialAttribute,1,gl.SHORT,!1,2,0),e!=colorShader&&e!=transparentShader||(gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer),gl.bufferData(gl.ARRAY_BUFFER,new Uint8Array(t.colors),gl.STATIC_DRAW),gl.vertexAttribPointer(e.vertexColorAttribute,4,gl.UNSIGNED_BYTE,!0,0,0)),gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer),gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexExt?new Uint32Array(i):new Uint16Array(i),gl.STATIC_DRAW),gl.drawElements(a?gl.TRIANGLES:r?gl.POINTS:gl.LINES,i.length,indexExt?gl.UNSIGNED_INT:gl.UNSIGNED_SHORT,0)}class vertexBuffer{constructor(){this.clear()}clear(){this.vertices=[],this.materials=[],this.colors=[],this.indices=[],this.nvertices=0}vertex(t,e){return this.vertices.push(t[0]),this.vertices.push(t[1]),this.vertices.push(t[2]),this.vertices.push(e[0]),this.vertices.push(e[1]),this.vertices.push(e[2]),this.materials.push(materialIndex),this.nvertices++}Vertex(t,e,i=[0,0,0,0]){return this.vertices.push(t[0]),this.vertices.push(t[1]),this.vertices.push(t[2]),this.vertices.push(e[0]),this.vertices.push(e[1]),this.vertices.push(e[2]),this.materials.push(materialIndex),this.colors.push(i[0]),this.colors.push(i[1]),this.colors.push(i[2]),this.colors.push(i[3]),this.nvertices++}vertex1(t){return this.vertices.push(t[0]),this.vertices.push(t[1]),this.vertices.push(t[2]),this.materials.push(materialIndex),this.nvertices++}vertex0(t,e){return this.vertices.push(t[0]),this.vertices.push(t[1]),this.vertices.push(t[2]),this.vertices.push(e),this.materials.push(materialIndex),this.nvertices++}iVertex(t,e,i,r=[0,0,0,0]){let a=6*t;this.vertices[a]=e[0],this.vertices[a+1]=e[1],this.vertices[a+2]=e[2],this.vertices[a+3]=i[0],this.vertices[a+4]=i[1],this.vertices[a+5]=i[2],this.materials[t]=materialIndex;let s=4*t;this.colors[s]=r[0],this.colors[s+1]=r[1],this.colors[s+2]=r[2],this.colors[s+3]=r[3],this.indices.push(t)}append(t){append(this.vertices,t.vertices),append(this.materials,t.materials),append(this.colors,t.colors),appendOffset(this.indices,t.indices,this.nvertices),this.nvertices+=t.nvertices}}let materialIndex,material0Data=new vertexBuffer,material1Data=new vertexBuffer,materialData=new vertexBuffer,colorData=new vertexBuffer,transparentData=new vertexBuffer,triangleData=new vertexBuffer;function append(t,e){let i=t.length,r=e.length;t.length+=r;for(let a=0;a<r;++a)t[i+a]=e[a]}function appendOffset(t,e,i){let r=t.length,a=e.length;t.length+=e.length;for(let s=0;s<a;++s)t[r+s]=e[s]+i}class Geometry{constructor(){this.data=new vertexBuffer,this.Onscreen=!1,this.m=[]}offscreen(t){let e=projViewMat,i=t[0],r=i[0],a=i[1],s=i[2],n=1/(e[3]*r+e[7]*a+e[11]*s+e[15]);this.x=this.X=(e[0]*r+e[4]*a+e[8]*s+e[12])*n,this.y=this.Y=(e[1]*r+e[5]*a+e[9]*s+e[13])*n;for(let i=1,r=t.length;i<r;++i){let r=t[i],a=r[0],s=r[1],n=r[2],o=1/(e[3]*a+e[7]*s+e[11]*n+e[15]),h=(e[0]*a+e[4]*s+e[8]*n+e[12])*o,l=(e[1]*a+e[5]*s+e[9]*n+e[13])*o;h<this.x?this.x=h:h>this.X&&(this.X=h),l<this.y?this.y=l:l>this.Y&&(this.Y=l)}return(this.X<-1.01||this.x>1.01||this.Y<-1.01||this.y>1.01)&&(this.Onscreen=!1,!0)}T(t){let e=this.c[0],i=this.c[1],r=this.c[2],a=t[0]-e,s=t[1]-i,n=t[2]-r;return[a*normMat[0]+s*normMat[3]+n*normMat[6]+e,a*normMat[1]+s*normMat[4]+n*normMat[7]+i,a*normMat[2]+s*normMat[5]+n*normMat[8]+r]}Tcorners(t,e){return[this.T(t),this.T([t[0],t[1],e[2]]),this.T([t[0],e[1],t[2]]),this.T([t[0],e[1],e[2]]),this.T([e[0],t[1],t[2]]),this.T([e[0],t[1],e[2]]),this.T([e[0],e[1],t[2]]),this.T(e)]}render(){let t;if(0==this.CenterIndex?t=corners(this.Min,this.Max):(this.c=Centers[this.CenterIndex-1],t=this.Tcorners(this.Min,this.Max)),this.offscreen(t))return void this.data.clear();let e,i=this.controlpoints;if(0==this.CenterIndex){if(!remesh&&this.Onscreen)return void this.append();e=i}else{let t=i.length;e=Array(t);for(let r=0;r<t;++r)e[r]=this.T(i[r])}materialIndex=this.MaterialIndex;let r=orthographic?1:this.Min[2]/B[2],a=pixel*Math.hypot(r*(viewParam.xmax-viewParam.xmin),r*(viewParam.ymax-viewParam.ymin))/size2;this.res2=a*a,this.Epsilon=FillFactor*a,this.data.clear(),this.Onscreen=!0,this.process(e)}}class BezierPatch extends Geometry{constructor(t,e,i,r,a,s){super(),this.controlpoints=t,this.Min=r,this.Max=a,this.color=s,this.CenterIndex=e;let n=t.length;if(s){let t=s[0][3]+s[1][3]+s[2][3];this.transparent=16==n||4==n?t+s[3][3]<1020:t<765}else this.transparent=Materials[i].diffuse[3]<1;this.transparent?(this.MaterialIndex=s?-1-i:1+i,this.vertex=this.data.Vertex.bind(this.data)):(this.MaterialIndex=i,this.vertex=this.data.vertex.bind(this.data)),this.L2norm(this.controlpoints)}L2norm(t){let e=t[0];this.epsilon=0;let i=t.length;for(let r=1;r<i;++r)this.epsilon=Math.max(this.epsilon,abs2([t[r][0]-e[0],t[r][1]-e[1],t[r][2]-e[2]]));this.epsilon*=Fuzz4}processTriangle(t){let e=t[0],i=t[1],r=t[2],a=unit(cross([i[0]-e[0],i[1]-e[1],i[2]-e[2]],[r[0]-e[0],r[1]-e[1],r[2]-e[2]]));this.offscreen([e,i,r])||(this.color?(this.data.indices.push(this.data.Vertex(e,a,this.color[0])),this.data.indices.push(this.data.Vertex(i,a,this.color[1])),this.data.indices.push(this.data.Vertex(r,a,this.color[2]))):(this.data.indices.push(this.vertex(e,a)),this.data.indices.push(this.vertex(i,a)),this.data.indices.push(this.vertex(r,a))),this.append())}processQuad(t){let e=t[0],i=t[1],r=t[2],a=t[3],s=cross([i[0]-e[0],i[1]-e[1],i[2]-e[2]],[r[0]-i[0],r[1]-i[1],r[2]-i[2]]),n=cross([r[0]-a[0],r[1]-a[1],r[2]-a[2]],[a[0]-e[0],a[1]-e[1],a[2]-e[2]]),o=unit([s[0]+n[0],s[1]+n[1],s[2]+n[2]]);if(!this.offscreen([e,i,r,a])){let t,s,n,h;this.color?(t=this.data.Vertex(e,o,this.color[0]),s=this.data.Vertex(i,o,this.color[1]),n=this.data.Vertex(r,o,this.color[2]),h=this.data.Vertex(a,o,this.color[3])):(t=this.vertex(e,o),s=this.vertex(i,o),n=this.vertex(r,o),h=this.vertex(a,o)),this.data.indices.push(t),this.data.indices.push(s),this.data.indices.push(n),this.data.indices.push(t),this.data.indices.push(n),this.data.indices.push(h),this.append()}}process(t){if(10==t.length)return this.process3(t);if(3==t.length)return this.processTriangle(t);if(4==t.length)return this.processQuad(t);let e=t[0],i=t[3],r=t[12],a=t[15],s=this.normal(i,t[2],t[1],e,t[4],t[8],r);iszero(s)&&iszero(s=this.normal(i,t[2],t[1],e,t[13],t[14],a))&&(s=this.normal(a,t[11],t[7],i,t[4],t[8],r));let n=this.normal(e,t[4],t[8],r,t[13],t[14],a);iszero(n)&&iszero(n=this.normal(e,t[4],t[8],r,t[11],t[7],i))&&(n=this.normal(i,t[2],t[1],e,t[13],t[14],a));let o=this.normal(r,t[13],t[14],a,t[11],t[7],i);iszero(o)&&iszero(o=this.normal(r,t[13],t[14],a,t[2],t[1],e))&&(o=this.normal(e,t[4],t[8],r,t[11],t[7],i));let h=this.normal(a,t[11],t[7],i,t[2],t[1],e);if(iszero(h)&&iszero(h=this.normal(a,t[11],t[7],i,t[4],t[8],r))&&(h=this.normal(r,t[13],t[14],a,t[2],t[1],e)),this.color){let l=this.color[0],c=this.color[1],d=this.color[2],m=this.color[3],u=this.data.Vertex(e,s,l),f=this.data.Vertex(r,n,c),v=this.data.Vertex(a,o,d),p=this.data.Vertex(i,h,m);this.Render(t,u,f,v,p,e,r,a,i,!1,!1,!1,!1,l,c,d,m)}else{let l=this.vertex(e,s),c=this.vertex(r,n),d=this.vertex(a,o),m=this.vertex(i,h);this.Render(t,l,c,d,m,e,r,a,i,!1,!1,!1,!1)}this.data.indices.length>0&&this.append()}append(){this.transparent?transparentData.append(this.data):this.color?colorData.append(this.data):materialData.append(this.data)}Render(t,e,i,r,a,s,n,o,h,l,c,d,m,u,f,v,p){if(this.Distance(t)<this.res2)this.offscreen([s,n,o])||(this.data.indices.push(e),this.data.indices.push(i),this.data.indices.push(r)),this.offscreen([s,o,h])||(this.data.indices.push(e),this.data.indices.push(r),this.data.indices.push(a));else{if(this.offscreen(t))return;let g=t[0],x=t[3],M=t[12],w=t[15],A=new Split3(g,t[1],t[2],x),S=new Split3(t[4],t[5],t[6],t[7]),b=new Split3(t[8],t[9],t[10],t[11]),P=new Split3(M,t[13],t[14],w),z=new Split3(g,t[4],t[8],M),R=new Split3(A.m0,S.m0,b.m0,P.m0),y=new Split3(A.m3,S.m3,b.m3,P.m3),D=new Split3(A.m5,S.m5,b.m5,P.m5),T=new Split3(A.m4,S.m4,b.m4,P.m4),E=new Split3(A.m2,S.m2,b.m2,P.m2),I=new Split3(x,t[7],t[11],w),O=[g,A.m0,A.m3,A.m5,z.m0,R.m0,y.m0,D.m0,z.m3,R.m3,y.m3,D.m3,z.m5,R.m5,y.m5,D.m5],B=[z.m5,R.m5,y.m5,D.m5,z.m4,R.m4,y.m4,D.m4,z.m2,R.m2,y.m2,D.m2,M,P.m0,P.m3,P.m5],_=[D.m5,T.m5,E.m5,I.m5,D.m4,T.m4,E.m4,I.m4,D.m2,T.m2,E.m2,I.m2,P.m5,P.m4,P.m2,w],C=[A.m5,A.m4,A.m2,x,D.m0,T.m0,E.m0,I.m0,D.m3,T.m3,E.m3,I.m3,D.m5,T.m5,E.m5,I.m5],L=O[15],F=this.normal(O[0],O[4],O[8],O[12],O[13],O[14],O[15]);iszero(F)&&iszero(F=this.normal(O[0],O[4],O[8],O[12],O[11],O[7],O[3]))&&(F=this.normal(O[3],O[2],O[1],O[0],O[13],O[14],O[15]));let V=this.normal(B[12],B[13],B[14],B[15],B[11],B[7],B[3]);iszero(V)&&iszero(V=this.normal(B[12],B[13],B[14],B[15],B[2],B[1],B[0]))&&(V=this.normal(B[0],B[4],B[8],B[12],B[11],B[7],B[3]));let N=this.normal(_[15],_[11],_[7],_[3],_[2],_[1],_[0]);iszero(N)&&iszero(N=this.normal(_[15],_[11],_[7],_[3],_[4],_[8],_[12]))&&(N=this.normal(_[12],_[13],_[14],_[15],_[2],_[1],_[0]));let H=this.normal(C[3],C[2],C[1],C[0],C[4],C[8],C[12]);iszero(H)&&iszero(H=this.normal(C[3],C[2],C[1],C[0],C[13],C[14],C[15]))&&(H=this.normal(C[15],C[11],C[7],C[3],C[4],C[8],C[12]));let U=this.normal(_[3],_[2],_[1],L,_[4],_[8],_[12]),W=this.Epsilon,Y=[.5*(s[0]+n[0]),.5*(s[1]+n[1]),.5*(s[2]+n[2])];if(!l)if(l=Straightness(g,t[4],t[8],M)<this.res2){let t=unit(this.derivative(B[0],B[1],B[2],B[3]));Y=[Y[0]-W*t[0],Y[1]-W*t[1],Y[2]-W*t[2]]}else Y=O[12];let j=[.5*(n[0]+o[0]),.5*(n[1]+o[1]),.5*(n[2]+o[2])];if(!c)if(c=Straightness(M,t[13],t[14],w)<this.res2){let t=unit(this.derivative(_[12],_[8],_[4],_[0]));j=[j[0]-W*t[0],j[1]-W*t[1],j[2]-W*t[2]]}else j=B[15];let G=[.5*(o[0]+h[0]),.5*(o[1]+h[1]),.5*(o[2]+h[2])];if(!d)if(d=Straightness(w,t[11],t[7],x)<this.res2){let t=unit(this.derivative(C[15],_[14],_[13],B[12]));G=[G[0]-W*t[0],G[1]-W*t[1],G[2]-W*t[2]]}else G=_[3];let k=[.5*(h[0]+s[0]),.5*(h[1]+s[1]),.5*(h[2]+s[2])];if(!m)if(m=Straightness(g,t[1],t[2],x)<this.res2){let t=unit(this.derivative(O[3],O[7],O[11],O[15]));k=[k[0]-W*t[0],k[1]-W*t[1],k[2]-W*t[2]]}else k=C[0];if(u){let t=Array(4),g=Array(4),x=Array(4),M=Array(4),w=Array(4);for(let e=0;e<4;++e)t[e]=.5*(u[e]+f[e]),g[e]=.5*(f[e]+v[e]),x[e]=.5*(v[e]+p[e]),M[e]=.5*(p[e]+u[e]),w[e]=.5*(t[e]+x[e]);let A=this.data.Vertex(Y,F,t),S=this.data.Vertex(j,V,g),b=this.data.Vertex(G,N,x),P=this.data.Vertex(k,H,M),z=this.data.Vertex(L,U,w);this.Render(O,e,A,z,P,s,Y,L,k,l,!1,!1,m,u,t,w,M),this.Render(B,A,i,S,z,Y,n,j,L,l,c,!1,!1,t,f,g,w),this.Render(_,z,S,r,b,L,j,o,G,!1,c,d,!1,w,g,v,x),this.Render(C,P,z,b,a,k,L,G,h,!1,!1,d,m,M,w,x,p)}else{let t=this.vertex(Y,F),u=this.vertex(j,V),f=this.vertex(G,N),v=this.vertex(k,H),p=this.vertex(L,U);this.Render(O,e,t,p,v,s,Y,L,k,l,!1,!1,m),this.Render(B,t,i,u,p,Y,n,j,L,l,c,!1,!1),this.Render(_,p,u,r,f,L,j,o,G,!1,c,d,!1),this.Render(C,v,p,f,a,k,L,G,h,!1,!1,d,m)}}}process3(t){this.Res2=BezierFactor*BezierFactor*this.res2;let e=t[0],i=t[6],r=t[9],a=this.normal(r,t[5],t[2],e,t[1],t[3],i),s=this.normal(e,t[1],t[3],i,t[7],t[8],r),n=this.normal(i,t[7],t[8],r,t[5],t[2],e);if(this.color){let o=this.color[0],h=this.color[1],l=this.color[2],c=this.data.Vertex(e,a,o),d=this.data.Vertex(i,s,h),m=this.data.Vertex(r,n,l);this.Render3(t,c,d,m,e,i,r,!1,!1,!1,o,h,l)}else{let o=this.vertex(e,a),h=this.vertex(i,s),l=this.vertex(r,n);this.Render3(t,o,h,l,e,i,r,!1,!1,!1)}this.data.indices.length>0&&this.append()}Render3(t,e,i,r,a,s,n,o,h,l,c,d,m){if(this.Distance3(t)<this.Res2)this.offscreen([a,s,n])||(this.data.indices.push(e),this.data.indices.push(i),this.data.indices.push(r));else{if(this.offscreen(t))return;let u=t[0],f=t[1],v=t[2],p=t[3],g=t[4],x=t[5],M=t[6],w=t[7],A=t[8],S=t[9],b=[.5*(S[0]+x[0]),.5*(S[1]+x[1]),.5*(S[2]+x[2])],P=[.5*(S[0]+A[0]),.5*(S[1]+A[1]),.5*(S[2]+A[2])],z=[.5*(x[0]+v[0]),.5*(x[1]+v[1]),.5*(x[2]+v[2])],R=[.5*(A[0]+g[0]),.5*(A[1]+g[1]),.5*(A[2]+g[2])],y=[.5*(A[0]+w[0]),.5*(A[1]+w[1]),.5*(A[2]+w[2])],D=[.5*(v[0]+g[0]),.5*(v[1]+g[1]),.5*(v[2]+g[2])],T=[.5*(v[0]+u[0]),.5*(v[1]+u[1]),.5*(v[2]+u[2])],E=[.5*(g[0]+p[0]),.5*(g[1]+p[1]),.5*(g[2]+p[2])],I=[.5*(w[0]+M[0]),.5*(w[1]+M[1]),.5*(w[2]+M[2])],O=[.5*(u[0]+f[0]),.5*(u[1]+f[1]),.5*(u[2]+f[2])],B=[.5*(f[0]+p[0]),.5*(f[1]+p[1]),.5*(f[2]+p[2])],_=[.5*(p[0]+M[0]),.5*(p[1]+M[1]),.5*(p[2]+M[2])],C=[.5*(b[0]+z[0]),.5*(b[1]+z[1]),.5*(b[2]+z[2])],L=[.5*(P[0]+y[0]),.5*(P[1]+y[1]),.5*(P[2]+y[2])],F=[.5*(z[0]+T[0]),.5*(z[1]+T[1]),.5*(z[2]+T[2])],V=[.5*R[0]+.25*(g[0]+f[0]),.5*R[1]+.25*(g[1]+f[1]),.5*R[2]+.25*(g[2]+f[2])],N=[.5*(y[0]+I[0]),.5*(y[1]+I[1]),.5*(y[2]+I[2])],H=[.5*D[0]+.25*(g[0]+w[0]),.5*D[1]+.25*(g[1]+w[1]),.5*D[2]+.25*(g[2]+w[2])],U=[.25*(x[0]+g[0])+.5*E[0],.25*(x[1]+g[1])+.5*E[1],.25*(x[2]+g[2])+.5*E[2]],W=[.5*(O[0]+B[0]),.5*(O[1]+B[1]),.5*(O[2]+B[2])],Y=[.5*(B[0]+_[0]),.5*(B[1]+_[1]),.5*(B[2]+_[2])],j=[.5*(H[0]+W[0]),.5*(H[1]+W[1]),.5*(H[2]+W[2])],G=[.5*(H[0]+Y[0]),.5*(H[1]+Y[1]),.5*(H[2]+Y[2])],k=[.5*(W[0]+Y[0]),.5*(W[1]+Y[1]),.5*(W[2]+Y[2])],X=[.5*(U[0]+N[0]),.5*(U[1]+N[1]),.5*(U[2]+N[2])],Z=[.5*(L[0]+U[0]),.5*(L[1]+U[1]),.5*(L[2]+U[2])],q=[.5*(L[0]+N[0]),.5*(L[1]+N[1]),.5*(L[2]+N[2])],K=[.5*(C[0]+V[0]),.5*(C[1]+V[1]),.5*(C[2]+V[2])],$=[.5*(F[0]+V[0]),.5*(F[1]+V[1]),.5*(F[2]+V[2])],Q=[.5*(C[0]+F[0]),.5*(C[1]+F[1]),.5*(C[2]+F[2])],J=[u,O,T,W,[.5*(D[0]+O[0]),.5*(D[1]+O[1]),.5*(D[2]+O[2])],F,k,j,$,Q],tt=[k,Y,G,_,[.5*(E[0]+I[0]),.5*(E[1]+I[1]),.5*(E[2]+I[2])],X,M,I,N,q],et=[Q,K,C,Z,[.5*(b[0]+R[0]),.5*(b[1]+R[1]),.5*(b[2]+R[2])],b,q,L,P,S],it=[q,Z,X,K,[.25*(z[0]+y[0]+B[0]+g[0]),.25*(z[1]+y[1]+B[1]+g[1]),.25*(z[2]+y[2]+B[2]+g[2])],G,Q,$,j,k],rt=this.normal(k,G,X,q,Z,K,Q),at=this.normal(q,Z,K,Q,$,j,k),st=this.normal(Q,$,j,k,G,X,q),nt=this.Epsilon,ot=[.5*(s[0]+n[0]),.5*(s[1]+n[1]),.5*(s[2]+n[2])];if(!o)if(o=Straightness(M,w,A,S)<this.res2){let t=unit(this.sumderivative(it[0],it[2],it[5],it[9],it[1],it[3],it[6]));ot=[ot[0]-nt*t[0],ot[1]-nt*t[1],ot[2]-nt*t[2]]}else ot=q;let ht=[.5*(n[0]+a[0]),.5*(n[1]+a[1]),.5*(n[2]+a[2])];if(!h)if(h=Straightness(u,v,x,S)<this.res2){let t=unit(this.sumderivative(it[6],it[3],it[1],it[0],it[7],it[8],it[9]));ht=[ht[0]-nt*t[0],ht[1]-nt*t[1],ht[2]-nt*t[2]]}else ht=Q;let lt=[.5*(a[0]+s[0]),.5*(a[1]+s[1]),.5*(a[2]+s[2])];if(!l)if(l=Straightness(u,f,p,M)<this.res2){let t=unit(this.sumderivative(it[9],it[8],it[7],it[6],it[5],it[2],it[0]));lt=[lt[0]-nt*t[0],lt[1]-nt*t[1],lt[2]-nt*t[2]]}else lt=k;if(c){let t=Array(4),u=Array(4),f=Array(4);for(let e=0;e<4;++e)t[e]=.5*(d[e]+m[e]),u[e]=.5*(m[e]+c[e]),f[e]=.5*(c[e]+d[e]);let v=this.data.Vertex(ot,rt,t),p=this.data.Vertex(ht,at,u),g=this.data.Vertex(lt,st,f);this.Render3(J,e,g,p,a,lt,ht,!1,h,l,c,f,u),this.Render3(tt,g,i,v,lt,s,ot,o,!1,l,f,d,t),this.Render3(et,p,v,r,ht,ot,n,o,h,!1,u,t,m),this.Render3(it,v,p,g,ot,ht,lt,!1,!1,!1,t,u,f)}else{let t=this.vertex(ot,rt),c=this.vertex(ht,at),d=this.vertex(lt,st);this.Render3(J,e,d,c,a,lt,ht,!1,h,l),this.Render3(tt,d,i,t,lt,s,ot,o,!1,l),this.Render3(et,c,t,r,ht,ot,n,o,h,!1),this.Render3(it,t,c,d,ot,ht,lt,!1,!1,!1)}}}Distance(t){let e=t[0],i=t[3],r=t[12],a=t[15],s=Distance2(a,e,this.normal(i,t[2],t[1],e,t[4],t[8],r));return s=Math.max(s,Straightness(e,t[1],t[2],i)),s=Math.max(s,Straightness(e,t[4],t[8],r)),s=Math.max(s,Straightness(i,t[7],t[11],a)),s=Math.max(s,Straightness(r,t[13],t[14],a)),s=Math.max(s,Straightness(t[4],t[5],t[6],t[7])),s=Math.max(s,Straightness(t[8],t[9],t[10],t[11])),s=Math.max(s,Straightness(t[1],t[5],t[9],t[13])),Math.max(s,Straightness(t[2],t[6],t[10],t[14]))}Distance3(t){let e=t[0],i=t[4],r=t[6],a=t[9],s=abs2([(e[0]+r[0]+a[0])*third-i[0],(e[1]+r[1]+a[1])*third-i[1],(e[2]+r[2]+a[2])*third-i[2]]);return s=Math.max(s,Straightness(e,t[1],t[3],r)),s=Math.max(s,Straightness(e,t[2],t[5],a)),Math.max(s,Straightness(r,t[7],t[8],a))}derivative(t,e,i,r){let a=[e[0]-t[0],e[1]-t[1],e[2]-t[2]];if(abs2(a)>this.epsilon)return a;let s=bezierPP(t,e,i);return abs2(s)>this.epsilon?s:bezierPPP(t,e,i,r)}sumderivative(t,e,i,r,a,s,n){let o=this.derivative(t,e,i,r),h=this.derivative(t,a,s,n);return[o[0]+h[0],o[1]+h[1],o[2]+h[2]]}normal(t,e,i,r,a,s,n){let o=a[0]-r[0],h=a[1]-r[1],l=a[2]-r[2],c=i[0]-r[0],d=i[1]-r[1],m=i[2]-r[2],u=[h*m-l*d,l*c-o*m,o*d-h*c];if(abs2(u)>this.epsilon)return unit(u);let f=[c,d,m],v=[o,h,l],p=bezierPP(r,i,e),g=bezierPP(r,a,s),x=cross(g,f),M=cross(v,p);if(abs2(u=[x[0]+M[0],x[1]+M[1],x[2]+M[2]])>this.epsilon)return unit(u);let w=bezierPPP(r,i,e,t),A=bezierPPP(r,a,s,n);x=cross(g,p),M=cross(v,w);let S=cross(A,f),b=cross(A,p),P=cross(g,w),z=cross(A,w);return unit([9*x[0]+3*(M[0]+S[0]+b[0]+P[0])+z[0],9*x[1]+3*(M[1]+S[1]+b[1]+P[1])+z[1],9*x[2]+3*(M[2]+S[2]+b[2]+P[2])+z[2]])}}class BezierCurve extends Geometry{constructor(t,e,i,r,a){super(),this.controlpoints=t,this.Min=r,this.Max=a,this.CenterIndex=e,this.MaterialIndex=i}processLine(t){let e=t[0],i=t[1];this.offscreen([e,i])||(this.data.indices.push(this.data.vertex1(e)),this.data.indices.push(this.data.vertex1(i)),this.append())}process(t){if(2==t.length)return this.processLine(t);let e=this.data.vertex1(t[0]),i=this.data.vertex1(t[3]);this.Render(t,e,i),this.data.indices.length>0&&this.append()}append(){material1Data.append(this.data)}Render(t,e,i){let r=t[0],a=t[1],s=t[2],n=t[3];if(Straightness(r,a,s,n)<this.res2)this.offscreen([r,n])||(this.data.indices.push(e),this.data.indices.push(i));else{if(this.offscreen(t))return;let o=[.5*(r[0]+a[0]),.5*(r[1]+a[1]),.5*(r[2]+a[2])],h=[.5*(a[0]+s[0]),.5*(a[1]+s[1]),.5*(a[2]+s[2])],l=[.5*(s[0]+n[0]),.5*(s[1]+n[1]),.5*(s[2]+n[2])],c=[.5*(o[0]+h[0]),.5*(o[1]+h[1]),.5*(o[2]+h[2])],d=[.5*(h[0]+l[0]),.5*(h[1]+l[1]),.5*(h[2]+l[2])],m=[.5*(c[0]+d[0]),.5*(c[1]+d[1]),.5*(c[2]+d[2])],u=[r,o,c,m],f=[m,d,l,n],v=this.data.vertex1(m);this.Render(u,e,v),this.Render(f,v,i)}}}class Pixel extends Geometry{constructor(t,e,i,r,a){super(),this.controlpoint=t,this.width=e,this.CenterIndex=0,this.MaterialIndex=i,this.Min=r,this.Max=a}process(t){this.data.indices.push(this.data.vertex0(this.controlpoint,this.width)),this.append()}append(){material0Data.append(this.data)}}class Triangles extends Geometry{constructor(t,e,i){super(),this.CenterIndex=0,this.MaterialIndex=t,this.Min=e,this.Max=i,this.Positions=Positions,this.Normals=Normals,this.Colors=Colors,this.Indices=Indices,Positions=[],Normals=[],Colors=[],Indices=[],this.transparent=Materials[t].diffuse[3]<1}process(t){for(let t=0,e=this.Indices.length;t<e;++t){let e=this.Indices[t],i=e[0],r=this.Positions[i[0]],a=this.Positions[i[1]],s=this.Positions[i[2]];if(!this.offscreen([r,a,s])){let t=e.length>1?e[1]:i;if(t&&0!=t.length||(t=i),this.Colors.length>0){let n=e.length>2?e[2]:i;n&&0!=n.length||(n=i);let o=this.Colors[n[0]],h=this.Colors[n[1]],l=this.Colors[n[2]];this.transparent|=o[3]+h[3]+l[3]<765,materialIndex=-1-this.MaterialIndex,this.data.iVertex(i[0],r,this.Normals[t[0]],o),this.data.iVertex(i[1],a,this.Normals[t[1]],h),this.data.iVertex(i[2],s,this.Normals[t[2]],l)}else materialIndex=1+this.MaterialIndex,this.data.iVertex(i[0],r,this.Normals[t[0]]),this.data.iVertex(i[1],a,this.Normals[t[1]]),this.data.iVertex(i[2],s,this.Normals[t[2]])}}this.data.nvertices=this.Positions.length,this.data.indices.length>0&&this.append()}append(){this.transparent?transparentData.append(this.data):triangleData.append(this.data)}}function home(){mat4.identity(rotMat),initProjection(),setProjection(),remesh=!0,redraw=!0}function initShader(t=[]){let e=getShader(gl,"fragment",t),i=getShader(gl,"vertex",t),r=gl.createProgram();return gl.attachShader(r,i),gl.attachShader(r,e),gl.linkProgram(r),gl.getProgramParameter(r,gl.LINK_STATUS)||alert("Could not initialize shaders"),r}class Split3{constructor(t,e,i,r){this.m0=[.5*(t[0]+e[0]),.5*(t[1]+e[1]),.5*(t[2]+e[2])];let a=.5*(e[0]+i[0]),s=.5*(e[1]+i[1]),n=.5*(e[2]+i[2]);this.m2=[.5*(i[0]+r[0]),.5*(i[1]+r[1]),.5*(i[2]+r[2])],this.m3=[.5*(this.m0[0]+a),.5*(this.m0[1]+s),.5*(this.m0[2]+n)],this.m4=[.5*(a+this.m2[0]),.5*(s+this.m2[1]),.5*(n+this.m2[2])],this.m5=[.5*(this.m3[0]+this.m4[0]),.5*(this.m3[1]+this.m4[1]),.5*(this.m3[2]+this.m4[2])]}}function iszero(t){return 0==t[0]&&0==t[1]&&0==t[2]}function unit(t){let e=1/(Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2])||1);return[t[0]*e,t[1]*e,t[2]*e]}function abs2(t){return t[0]*t[0]+t[1]*t[1]+t[2]*t[2]}function dot(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function cross(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function bezierPP(t,e,i){return[t[0]+i[0]-2*e[0],t[1]+i[1]-2*e[1],t[2]+i[2]-2*e[2]]}function bezierPPP(t,e,i,r){return[r[0]-t[0]+3*(e[0]-i[0]),r[1]-t[1]+3*(e[1]-i[1]),r[2]-t[2]+3*(e[2]-i[2])]}function Straightness(t,e,i,r){let a=[third*(r[0]-t[0]),third*(r[1]-t[1]),third*(r[2]-t[2])];return Math.max(abs2([e[0]-a[0]-t[0],e[1]-a[1]-t[1],e[2]-a[2]-t[2]]),abs2([r[0]-a[0]-i[0],r[1]-a[1]-i[1],r[2]-a[2]-i[2]]))}function Distance2(t,e,i){let r=dot([t[0]-e[0],t[1]-e[1],t[2]-e[2]],i);return r*r}function corners(t,e){return[t,[t[0],t[1],e[2]],[t[0],e[1],t[2]],[t[0],e[1],e[2]],[e[0],t[1],t[2]],[e[0],t[1],e[2]],[e[0],e[1],t[2]],e]}function COBTarget(t,e){mat4.fromTranslation(translMat,[center.x,center.y,center.z]),mat4.invert(cjMatInv,translMat),mat4.multiply(t,e,cjMatInv),mat4.multiply(t,translMat,t)}function setUniforms(t){let e=t==pixelShader;gl.useProgram(t),t.vertexPositionAttribute=gl.getAttribLocation(t,"position"),gl.enableVertexAttribArray(t.vertexPositionAttribute),e&&(t.vertexWidthAttribute=gl.getAttribLocation(t,"width"),gl.enableVertexAttribArray(t.vertexWidthAttribute)),t==noNormalShader||e||(t.vertexNormalAttribute=gl.getAttribLocation(t,"normal"),gl.enableVertexAttribArray(t.vertexNormalAttribute)),t.vertexMaterialAttribute=gl.getAttribLocation(t,"materialIndex"),gl.enableVertexAttribArray(t.vertexMaterialAttribute),t.projViewMatUniform=gl.getUniformLocation(t,"projViewMat"),t.viewMatUniform=gl.getUniformLocation(t,"viewMat"),t.normMatUniform=gl.getUniformLocation(t,"normMat"),t!=colorShader&&t!=transparentShader||(t.vertexColorAttribute=gl.getAttribLocation(t,"color"),gl.enableVertexAttribArray(t.vertexColorAttribute));for(let e=0;e<Materials.length;++e)Materials[e].setUniform(t,"Materials",e);for(let e=0;e<Lights.length;++e)Lights[e].setUniform(t,"Lights",e);gl.uniformMatrix4fv(t.projViewMatUniform,!1,projViewMat),gl.uniformMatrix4fv(t.viewMatUniform,!1,viewMat),gl.uniformMatrix3fv(t.normMatUniform,!1,normMat)}function handleMouseDown(t){mouseDownOrTouchActive=!0,lastMouseX=t.clientX,lastMouseY=t.clientY}let pinchStart,touchStartTime,pinch=!1;function pinchDistance(t){return Math.hypot(t[0].pageX-t[1].pageX,t[0].pageY-t[1].pageY)}function handleTouchStart(t){t.preventDefault();let e=t.targetTouches;swipe=rotate=pinch=!1,zooming||(1!=e.length||mouseDownOrTouchActive||(touchStartTime=(new Date).getTime(),touchId=e[0].identifier,lastMouseX=e[0].pageX,lastMouseY=e[0].pageY),2!=e.length||mouseDownOrTouchActive||(touchId=e[0].identifier,pinchStart=pinchDistance(e),pinch=!0))}function handleMouseUpOrTouchEnd(t){mouseDownOrTouchActive=!1}function rotateScene(t,e,i,r,a){if(t==i&&e==r)return;let[s,n]=arcball([t,-e],[i,-r]);mat4.fromRotation(rotMats,2*a*ArcballFactor*s/lastzoom,n),mat4.multiply(rotMat,rotMats,rotMat)}function shiftScene(t,e,i,r){let a=1/lastzoom;shift.x+=(i-t)*a*halfCanvasWidth,shift.y-=(r-e)*a*halfCanvasHeight}function panScene(t,e,i,r){orthographic?shiftScene(t,e,i,r):(center.x+=(i-t)*(viewParam.xmax-viewParam.xmin),center.y-=(r-e)*(viewParam.ymax-viewParam.ymin))}function updateViewMatrix(){COBTarget(viewMat,rotMat),mat4.translate(viewMat,viewMat,[center.x,center.y,0]),mat3.fromMat4(viewMat3,viewMat),mat3.invert(normMat,viewMat3),mat4.multiply(projViewMat,projMat,viewMat)}function capzoom(){let t=Math.sqrt(Number.MAX_VALUE),e=1/t;Zoom<=e&&(Zoom=e),Zoom>=t&&(Zoom=t),Zoom!=lastzoom&&(remesh=!0),lastzoom=Zoom}function zoomImage(t){let e=zoomStep*halfCanvasHeight*t;const i=Math.log(.1*Number.MAX_VALUE)/Math.log(zoomFactor);Math.abs(e)<i&&(Zoom*=zoomFactor**e,capzoom())}function normMouse(t){let e=t[0],i=t[1],r=Math.hypot(e,i);return r>1&&(denom=1/r,e*=denom,i*=denom),[e,i,Math.sqrt(Math.max(1-i*i-e*e,0))]}function arcball(t,e){let i=normMouse(t),r=normMouse(e),a=dot(i,r);return a>1?a=1:a<-1&&(a=-1),[Math.acos(a),unit(cross(i,r))]}function zoomScene(t,e,i,r){zoomImage(e-r)}const DRAGMODE_ROTATE=1,DRAGMODE_SHIFT=2,DRAGMODE_ZOOM=3,DRAGMODE_PAN=4;function processDrag(t,e,i,r=1){let a;switch(i){case DRAGMODE_ROTATE:a=rotateScene;break;case DRAGMODE_SHIFT:a=shiftScene;break;case DRAGMODE_ZOOM:a=zoomScene;break;case DRAGMODE_PAN:a=panScene;break;default:a=((t,e,i,r)=>{})}a((lastMouseX-halfCanvasWidth)/halfCanvasWidth,(lastMouseY-halfCanvasHeight)/halfCanvasHeight,(t-halfCanvasWidth)/halfCanvasWidth,(e-halfCanvasHeight)/halfCanvasHeight,r),lastMouseX=t,lastMouseY=e,setProjection(),redraw=!0}function handleKey(t){let e=[];switch(t.key){case"x":e=[1,0,0];break;case"y":e=[0,1,0];break;case"z":e=[0,0,1];break;case"h":home();break;case"+":case"=":case">":expand();break;case"-":case"_":case"<":shrink()}e.length>0&&(mat4.rotate(rotMat,rotMat,.1,e),updateViewMatrix(),redraw=!0)}function handleMouseWheel(t){t.preventDefault(),t.deltaY<0?Zoom*=zoomFactor:Zoom/=zoomFactor,capzoom(),setProjection(),redraw=!0}function handleMouseMove(t){if(!mouseDownOrTouchActive)return;let e;processDrag(t.clientX,t.clientY,e=t.getModifierState("Control")?DRAGMODE_SHIFT:t.getModifierState("Shift")?DRAGMODE_ZOOM:t.getModifierState("Alt")?DRAGMODE_PAN:DRAGMODE_ROTATE)}let indexExt,zooming=!1,swipe=!1,rotate=!1;function handleTouchMove(t){if(t.preventDefault(),zooming)return;let e=t.targetTouches;if(!pinch&&1==e.length&&touchId==e[0].identifier){let t=e[0].pageX,i=e[0].pageY,r=t-lastMouseX,a=i-lastMouseY,s=r*r+a*a<=shiftHoldDistance*shiftHoldDistance;if(s&&!swipe&&!rotate&&(new Date).getTime()-touchStartTime>shiftWaitTime&&(navigator.vibrate&&window.navigator.vibrate(vibrateTime),swipe=!0),swipe)processDrag(t,i,DRAGMODE_SHIFT);else if(!s){rotate=!0,processDrag(e[0].pageX,e[0].pageY,DRAGMODE_ROTATE,.5)}}if(pinch&&!swipe&&2==e.length&&touchId==e[0].identifier){let t=pinchDistance(e),i=t-pinchStart;zooming=!0,(i*=zoomPinchFactor)>zoomPinchCap&&(i=zoomPinchCap),i<-zoomPinchCap&&(i=-zoomPinchCap),zoomImage(i/size2),pinchStart=t,swipe=rotate=zooming=!1,setProjection(),redraw=!0}}function setBuffer(){positionBuffer=gl.createBuffer(),materialBuffer=gl.createBuffer(),colorBuffer=gl.createBuffer(),indexBuffer=gl.createBuffer(),indexExt=gl.getExtension("OES_element_index_uint")}let pixelShader,noNormalShader,materialShader,colorShader,transparentShader,zbuffer=[];function transformVertices(t){let e=viewMat[2],i=viewMat[6],r=viewMat[10];zbuffer.length=t.length;for(let a=0;a<t.length;++a){let s=6*a;zbuffer[a]=e*t[s]+i*t[s+1]+r*t[s+2]}}function draw(){gl.clearColor(Background[0],Background[1],Background[2],Background[3]),gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT),material0Data.clear(),material1Data.clear(),materialData.clear(),colorData.clear(),triangleData.clear(),transparentData.clear(),P.forEach(function(t){t.render()}),drawBuffer(material0Data,pixelShader),drawBuffer(material1Data,noNormalShader),drawBuffer(materialData,materialShader),drawBuffer(colorData,colorShader),drawBuffer(triangleData,transparentShader);let t=transparentData.indices;if(t.length>0){transformVertices(transparentData.vertices);let e=t.length/3,i=Array(e).fill().map((t,e)=>e);i.sort(function(e,i){let r=3*e;Ia=t[r],Ib=t[r+1],Ic=t[r+2];let a=3*i;return IA=t[a],IB=t[a+1],IC=t[a+2],zbuffer[Ia]+zbuffer[Ib]+zbuffer[Ic]<zbuffer[IA]+zbuffer[IB]+zbuffer[IC]?-1:1});let r=Array(t.length);for(let a=0;a<e;++a){let e=3*i[a];r[3*a]=t[e],r[3*a+1]=t[e+1],r[3*a+2]=t[e+2]}gl.depthMask(!1),drawBuffer(transparentData,transparentShader,r),gl.depthMask(!0)}remesh=!1}function tick(){requestAnimationFrame(tick),redraw&&(draw(),redraw=!1)}function setDimensions(t,e,i,r){let a=t/e,s=1/lastzoom,n=(i/t+viewportshift[0])*lastzoom,o=(r/e+viewportshift[1])*lastzoom;if(orthographic){let t=B[0]-b[0],e=B[1]-b[1];if(t<e*a){let t=.5*e*a*s,i=2*t*n,r=e*s*o;viewParam.xmin=-t-i,viewParam.xmax=t-i,viewParam.ymin=b[1]*s-r,viewParam.ymax=B[1]*s-r}else{let e=.5*t/(a*Zoom),i=t*s*n,r=2*e*o;viewParam.xmin=b[0]*s-i,viewParam.xmax=B[0]*s-i,viewParam.ymin=-e-r,viewParam.ymax=e-r}}else{let t=H*s,e=t*a,i=2*e*n,r=2*t*o;viewParam.xmin=-e-i,viewParam.xmax=e-i,viewParam.ymin=-t-r,viewParam.ymax=t-r}}function setProjection(){setDimensions(canvasWidth,canvasHeight,shift.x,shift.y),(orthographic?mat4.ortho:mat4.frustum)(projMat,viewParam.xmin,viewParam.xmax,viewParam.ymin,viewParam.ymax,-viewParam.zmax,-viewParam.zmin),updateViewMatrix()}function initProjection(){H=-Math.tan(.5*angle)*B[2],center.x=center.y=0,center.z=.5*(b[2]+B[2]),lastzoom=Zoom=Zoom0,viewParam.zmin=b[2],viewParam.zmax=B[2],shift.x=shift.y=0}function setViewport(){gl.viewportWidth=canvasWidth,gl.viewportHeight=canvasHeight,gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight),home()}function setCanvas(){canvas.width=canvasWidth,canvas.height=canvasHeight,size2=Math.hypot(canvasWidth,canvasHeight),halfCanvasWidth=.5*canvasWidth,halfCanvasHeight=.5*canvasHeight}function setsize(t,e){t>maxViewportWidth&&(t=maxViewportWidth),e>maxViewportHeight&&(e=maxViewportHeight),shift.x*=t/canvasWidth,shift.y*=e/canvasHeight,canvasWidth=t,canvasHeight=e,setCanvas(),setViewport()}function expand(){setsize(canvasWidth*resizeStep+.5,canvasHeight*resizeStep+.5)}function shrink(){setsize(Math.max(canvasWidth/resizeStep+.5,1),Math.max(canvasHeight/resizeStep+.5,1))}function webGLStart(){if(canvas=document.getElementById("Asymptote"),absolute)canvasWidth*=window.devicePixelRatio,canvasHeight*=window.devicePixelRatio;else{0==canvas.width&&(canvas.width=Math.max(window.innerWidth-windowTrim,windowTrim)),0==canvas.height&&(canvas.height=Math.max(window.innerHeight-windowTrim,windowTrim));let t=canvasWidth/canvasHeight;canvas.width>canvas.height*t?canvas.width=Math.min(canvas.height*t,canvas.width):canvas.height=Math.min(canvas.width/t,canvas.height),canvas.width>0&&(canvasWidth=canvas.width),canvas.height>0&&(canvasHeight=canvas.height)}setCanvas(),ArcballFactor=1+8*Math.hypot(viewportmargin[0],viewportmargin[1])/size2,viewportshift[0]/=Zoom0,viewportshift[1]/=Zoom0,initGL(),gl.enable(gl.BLEND),gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA),gl.enable(gl.DEPTH_TEST),setViewport(),noNormalShader=initShader(),pixelShader=initShader(["WIDTH"]),materialShader=initShader(["NORMAL"]),colorShader=initShader(["NORMAL","COLOR"]),transparentShader=initShader(["NORMAL","COLOR","TRANSPARENT"]),setBuffer(),canvas.onmousedown=handleMouseDown,document.onmouseup=handleMouseUpOrTouchEnd,document.onmousemove=handleMouseMove,canvas.onkeydown=handleKey,canvas.addEventListener("wheel",handleMouseWheel,!1),canvas.addEventListener("touchstart",handleTouchStart,!1),canvas.addEventListener("touchend",handleMouseUpOrTouchEnd,!1),canvas.addEventListener("touchcancel",handleMouseUpOrTouchEnd,!1),canvas.addEventListener("touchleave",handleMouseUpOrTouchEnd,!1),canvas.addEventListener("touchmove",handleTouchMove,!1),document.addEventListener("keydown",handleKey,!1),tick()}
+/*@license for gl-matrix mat3 and mat4 functions:
+Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.*/ \ No newline at end of file