text: var mjsr=function(){"use strict";var version="v1.0.0",EPSILON=1e-6,ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array;function create(){var t=new ARRAY_TYPE(16);return ARRAY_TYPE!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0),t[0]=1,t[5]=1,t[10]=1,t[15]=1,t}function transpose(t,e){if(t===e){var r=e[1],i=e[2],s=e[3],o=e[6],n=e[7],a=e[11];t[1]=e[4],t[2]=e[8],t[3]=e[12],t[4]=r,t[6]=e[9],t[7]=e[13],t[8]=i,t[9]=o,t[11]=e[14],t[12]=s,t[13]=n,t[14]=a}else t[0]=e[0],t[1]=e[4],t[2]=e[8],t[3]=e[12],t[4]=e[1],t[5]=e[5],t[6]=e[9],t[7]=e[13],t[8]=e[2],t[9]=e[6],t[10]=e[10],t[11]=e[14],t[12]=e[3],t[13]=e[7],t[14]=e[11],t[15]=e[15];return t}function invert(t,e){var r=e[0],i=e[1],s=e[2],o=e[3],n=e[4],a=e[5],l=e[6],h=e[7],c=e[8],u=e[9],m=e[10],p=e[11],d=e[12],f=e[13],v=e[14],g=e[15],_=r*a-i*n,w=r*l-s*n,b=r*h-o*n,E=i*l-s*a,L=i*h-o*a,y=s*h-o*l,P=c*f-u*d,I=c*v-m*d,N=c*g-p*d,O=u*v-m*f,C=u*g-p*f,S=m*g-p*v,M=_*S-w*C+b*O+E*N-L*I+y*P;return M?(M=1/M,t[0]=(a*S-l*C+h*O)*M,t[1]=(s*C-i*S-o*O)*M,t[2]=(f*y-v*L+g*E)*M,t[3]=(m*L-u*y-p*E)*M,t[4]=(l*N-n*S-h*I)*M,t[5]=(r*S-s*N+o*I)*M,t[6]=(v*b-d*y-g*w)*M,t[7]=(c*y-m*b+p*w)*M,t[8]=(n*C-a*N+h*P)*M,t[9]=(i*N-r*C-o*P)*M,t[10]=(d*L-f*b+g*_)*M,t[11]=(u*b-c*L-p*_)*M,t[12]=(a*I-n*O-l*P)*M,t[13]=(r*O-i*I+s*P)*M,t[14]=(f*w-d*E-v*_)*M,t[15]=(c*E-u*w+m*_)*M,t):null}function multiply(t,e,r){var i=e[0],s=e[1],o=e[2],n=e[3],a=e[4],l=e[5],h=e[6],c=e[7],u=e[8],m=e[9],p=e[10],d=e[11],f=e[12],v=e[13],g=e[14],_=e[15],w=r[0],b=r[1],E=r[2],L=r[3];return t[0]=w*i+b*a+E*u+L*f,t[1]=w*s+b*l+E*m+L*v,t[2]=w*o+b*h+E*p+L*g,t[3]=w*n+b*c+E*d+L*_,w=r[4],b=r[5],E=r[6],L=r[7],t[4]=w*i+b*a+E*u+L*f,t[5]=w*s+b*l+E*m+L*v,t[6]=w*o+b*h+E*p+L*g,t[7]=w*n+b*c+E*d+L*_,w=r[8],b=r[9],E=r[10],L=r[11],t[8]=w*i+b*a+E*u+L*f,t[9]=w*s+b*l+E*m+L*v,t[10]=w*o+b*h+E*p+L*g,t[11]=w*n+b*c+E*d+L*_,w=r[12],b=r[13],E=r[14],L=r[15],t[12]=w*i+b*a+E*u+L*f,t[13]=w*s+b*l+E*m+L*v,t[14]=w*o+b*h+E*p+L*g,t[15]=w*n+b*c+E*d+L*_,t}function translate(t,e,r){var i,s,o,n,a,l,h,c,u,m,p,d,f=r[0],v=r[1],g=r[2];return e===t?(t[12]=e[0]*f+e[4]*v+e[8]*g+e[12],t[13]=e[1]*f+e[5]*v+e[9]*g+e[13],t[14]=e[2]*f+e[6]*v+e[10]*g+e[14],t[15]=e[3]*f+e[7]*v+e[11]*g+e[15]):(i=e[0],s=e[1],o=e[2],n=e[3],a=e[4],l=e[5],h=e[6],c=e[7],u=e[8],m=e[9],p=e[10],d=e[11],t[0]=i,t[1]=s,t[2]=o,t[3]=n,t[4]=a,t[5]=l,t[6]=h,t[7]=c,t[8]=u,t[9]=m,t[10]=p,t[11]=d,t[12]=i*f+a*v+u*g+e[12],t[13]=s*f+l*v+m*g+e[13],t[14]=o*f+h*v+p*g+e[14],t[15]=n*f+c*v+d*g+e[15]),t}function scale(t,e,r){var i=r[0],s=r[1],o=r[2];return t[0]=e[0]*i,t[1]=e[1]*i,t[2]=e[2]*i,t[3]=e[3]*i,t[4]=e[4]*s,t[5]=e[5]*s,t[6]=e[6]*s,t[7]=e[7]*s,t[8]=e[8]*o,t[9]=e[9]*o,t[10]=e[10]*o,t[11]=e[11]*o,t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15],t}function rotate(t,e,r,i){var s,o,n,a,l,h,c,u,m,p,d,f,v,g,_,w,b,E,L,y,P,I,N,O,C=i[0],S=i[1],M=i[2],R=Math.hypot(C,S,M);return R<EPSILON?null:(C*=R=1/R,S*=R,M*=R,s=Math.sin(r),n=1-(o=Math.cos(r)),a=e[0],l=e[1],h=e[2],c=e[3],u=e[4],m=e[5],p=e[6],d=e[7],f=e[8],v=e[9],g=e[10],_=e[11],w=C*C*n+o,b=S*C*n+M*s,E=M*C*n-S*s,L=C*S*n-M*s,y=S*S*n+o,P=M*S*n+C*s,I=C*M*n+S*s,N=S*M*n-C*s,O=M*M*n+o,t[0]=a*w+u*b+f*E,t[1]=l*w+m*b+v*E,t[2]=h*w+p*b+g*E,t[3]=c*w+d*b+_*E,t[4]=a*L+u*y+f*P,t[5]=l*L+m*y+v*P,t[6]=h*L+p*y+g*P,t[7]=c*L+d*y+_*P,t[8]=a*I+u*N+f*O,t[9]=l*I+m*N+v*O,t[10]=h*I+p*N+g*O,t[11]=c*I+d*N+_*O,e!==t&&(t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15]),t)}function rotateX(t,e,r){var i=Math.sin(r),s=Math.cos(r),o=e[4],n=e[5],a=e[6],l=e[7],h=e[8],c=e[9],u=e[10],m=e[11];return e!==t&&(t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15]),t[4]=o*s+h*i,t[5]=n*s+c*i,t[6]=a*s+u*i,t[7]=l*s+m*i,t[8]=h*s-o*i,t[9]=c*s-n*i,t[10]=u*s-a*i,t[11]=m*s-l*i,t}function rotateY(t,e,r){var i=Math.sin(r),s=Math.cos(r),o=e[0],n=e[1],a=e[2],l=e[3],h=e[8],c=e[9],u=e[10],m=e[11];return e!==t&&(t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15]),t[0]=o*s-h*i,t[1]=n*s-c*i,t[2]=a*s-u*i,t[3]=l*s-m*i,t[8]=o*i+h*s,t[9]=n*i+c*s,t[10]=a*i+u*s,t[11]=l*i+m*s,t}function perspective(t,e,r,i,s){var o,n=1/Math.tan(e/2);return t[0]=n/r,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=n,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=s&&s!==1/0?(o=1/(i-s),t[10]=(s+i)*o,t[14]=2*s*i*o):(t[10]=-1,t[14]=-2*i),t}Math.hypot||(Math.hypot=function(){for(var t=0,e=arguments.length;e--;)t+=arguments[e]*arguments[e];return Math.sqrt(t)});class Camera{constructor(t=[0,0,0],e=[0,0,0],r=45){return this.pos=t,this.rot=e,this.fov=r,this.model=create(),this.view=create(),this.projection=create(),this}vp(t){let e=perspective(create(),this.fov*(Math.PI/180),t.width/t.height,.1,100),r=create();return rotateX(r,r,this.rot[0]),rotateY(r,r,this.rot[1]),translate(r,r,this.pos),multiply(create(),e,r)}modelit(){let t=this.model;return invert(t,t),transpose(t,t),t}}class Screen{constructor(t={width:640,height:480},e=document.body,r=document.createElement("canvas")){return this.canvas=r,this.canvas.width=t.width,this.canvas.height=t.height,this.gl=this.canvas.getContext("webgl"),this.parent=e,e instanceof HTMLElement&&e.appendChild(this.canvas),this}fullscreen(){this.canvas.width=innerWidth,this.canvas.height=innerHeight,window.addEventListener("resize",(()=>{this.canvas.width=innerWidth,this.canvas.height=innerHeight}));let t=document.createElement("style");return t.innerText="html,body{margin:0;overflow:hidden}",document.head.appendChild(t),this}fillParent(){return this.canvas.width=this.parent.clientWidth,this.canvas.height=this.parent.clientHeight,window.addEventListener("resize",(()=>{this.canvas.width=this.parent.clientWidth,this.canvas.height=this.parent.clientHeight})),this}square(t){return this.canvas.width=t,this.canvas.height=t,this}rect(t,e){return this.canvas.width=t,this.canvas.height=e,this}}class None{update(){}attributes(){}setup(){}}class FirstPerson{constructor(){this.keys=[]}attributes(t,e){this.screen=t,this.camera=e}setup(){let{canvas:t}=this.screen;window.addEventListener("keydown",(t=>this.keys[t.key.toLowerCase()]=!0)),window.addEventListener("keyup",(t=>this.keys[t.key.toLowerCase()]=!1));let e=t=>Math.abs(t.movementX)>50||Math.abs(t.movementY)>50?void 0:this.mouseRotation([t.movementX,t.movementY]);t.requestPointerLock=t.requestPointerLock||t.mozRequestPointerLock,document.exitPointerLock=document.exitPointerLock||document.mozExitPointerLock,t.onclick=()=>t.requestPointerLock();let r=()=>{document.pointerLockElement===t||document.mozPointerLockElement===t?t.onmousemove=e:t.onmousemove=null};document.addEventListener("pointerlockchange",r),document.addEventListener("mozpointerlockchange",r)}mouseRotation(t,e=3){let[r,i]=t;r/=e*=100,i/=e,this.camera.rot[0]+i<Math.PI/2&&this.camera.rot[0]+i>-Math.PI/2&&(this.camera.rot[0]+=i),this.camera.rot[1]+=r}update(t){let{canvas:e}=this.screen;if(document.pointerLockElement==e||document.mozPointerLockElement==e){let e=t/160;this.keys.q&&(this.camera.pos[1]-=e),this.keys.e&&(this.camera.pos[1]+=e);let r=e*Math.sin(this.camera.rot[1]),i=e*Math.cos(this.camera.rot[1]);this.keys.w&&(this.camera.pos[0]-=r,this.camera.pos[2]+=i),this.keys.s&&(this.camera.pos[0]+=r,this.camera.pos[2]-=i),this.keys.a&&(this.camera.pos[0]+=i,this.camera.pos[2]+=r),this.keys.d&&(this.camera.pos[0]-=i,this.camera.pos[2]-=r)}}}class ModelRotate{constructor(){this.keys=[]}attributes(t,e){this.screen=t,this.camera=e}setup(){let{canvas:t}=this.screen,e=[0,0];const r=t=>this.mouseRotation([t.movementX,t.movementY]);t.onmousedown=()=>t.onmousemove=r,window.onmouseup=()=>t.onmousemove=null,t.addEventListener("touchstart",(t=>e=[t.touches[0].screenX,t.touches[0].screenY]),{passive:!0}),t.addEventListener("touchmove",(t=>(this.mouseRotation([-(e[0]-t.touches[0].screenX),e[1]-t.touches[0].screenY]),e=[t.touches[0].screenX,t.touches[0].screenY])),{passive:!0}),t.addEventListener("touchend",(()=>(t.ontouchmove=null,e=[0,0])))}mouseRotation(t){rotateY(this.camera.model,this.camera.model,.01*t[0])}update(){}}const Input={None:None,FirstPerson:FirstPerson,ModelRotate:ModelRotate};class Webglu{constructor(t){return this.gl=t,this.shaders=[],this.glprogram=null,this.locations={},this}frag(t){this.shader(t,this.gl.FRAGMENT_SHADER)}vert(t){this.shader(t,this.gl.VERTEX_SHADER)}shader(t,e){if(t=t.raw?t.raw.join(""):t,!e){let r=new RegExp("// ?vert(ex)?( |_|-)shader","i"),i=new RegExp("// ?frag(ment)?( |_|-)shader","i");if(r.test(t))e=this.gl.VERTEX_SHADER;else{if(!i.test(t))throw new Error("No shader type found.");e=this.gl.FRAGMENT_SHADER}}let r=this.gl.createShader(e);if(this.gl.shaderSource(r,t),this.gl.compileShader(r),this.gl.getShaderParameter(r,this.gl.COMPILE_STATUS))return this.shaders.push(r),r;console.error(`Error in shader:\n${t.split(/\n/).map(((t,e)=>`${e+1}: ${t}`)).join("\n")}`);let i=new Error(this.gl.getShaderInfoLog(r));throw this.gl.deleteShader(r),i}program(...t){if(0==t.length&&(t=this.shaders),0==t.length)throw new Error("No shaders were supplied.");let e=this.gl.createProgram();for(let r of t)this.gl.attachShader(e,r);if(this.gl.linkProgram(e),this.gl.getProgramParameter(e,this.gl.LINK_STATUS))return this.glprogram=e,e;let r=new Error(this.gl.getProgramInfoLog(e));throw this.gl.deleteProgram(e),r}buffers(t,e={}){if(0==t.length)throw new Error("No buffers were supplied.");for(let r in t){let i=t[r];this.buffer32f(i,this.gl.ARRAY_BUFFER);let s=this.gl.getAttribLocation(this.glprogram,r);this.gl.enableVertexAttribArray(s),e[r]?this.gl.vertexAttribPointer(s,e[r],this.gl.FLOAT,!1,0,0):this.gl.vertexAttribPointer(s,3,this.gl.FLOAT,!1,0,0)}}uniform3fv(t,e){return this.gl.uniform3fv(this._location(t),e)}uniformMatrix4fv(t,e,r){return this.gl.uniformMatrix4fv(this._location(t),e,r)}uniform1f(t,e){return this.gl.uniform1f(this._location(t),e)}_location(t){return this.locations[t]||(this.locations[t]=this.gl.getUniformLocation(this.glprogram,t)),this.locations[t]}buffer32f(t,e){let r=bufferInit(this.gl,e);return this.gl.bufferData(e,new Float32Array(t),this.gl.STATIC_DRAW),r}buffer16u(t,e){let r=bufferInit(this.gl,e);return this.gl.bufferData(e,new Uint16Array(t),this.gl.STATIC_DRAW),r}buffer32u(t,e){let r=bufferInit(this.gl,e);return this.gl.bufferData(e,new Uint32Array(t),this.gl.STATIC_DRAW),r}}function bufferInit(t,e){const r=t.createBuffer();return t.bindBuffer(e,r),r}var mono="float lum=(gl_FragColor.r+gl_FragColor.g+gl_FragColor.b)/3.0;vec2 monoColour=vec2(lum,1.0);gl_FragColor=monoColour.xxxy;",posterization="vec3 c=gl_FragColor.rgb;c=pow(c,vec3(p_gamma,p_gamma,p_gamma));c=c*p_colours;c=floor(c);c=c/p_colours;c=pow(c,vec3(1.0/p_gamma));gl_FragColor=vec4(c,1.0);",lighting="vec3 normal=normalize(v_normal);vec3 lightd=normalize(light.position-v_fragPos);float strength=0.3;vec3 viewd=normalize(v_viewPos-v_fragPos);vec3 reflectd=reflect(-lightd,normal);\n#if (options.mode == 2)\nvec3 halfwayd=normalize(lightd+viewd);float sp=pow(max(dot(normal,halfwayd),0.0),u_shinyness);vec3 specular=light.colour*sp;\n#else\nfloat sp=pow(max(dot(viewd,reflectd),0.0),u_shinyness);vec3 specular=strength*sp*light.colour;\n#endif\nfloat df=max(dot(normal,lightd),0.0);vec3 diffuse=df*light.colour;vec3 ambient=0.1*light.colour;gl_FragColor=vec4((ambient+diffuse+specular)*gl_FragColor.rgb,1.0);",fragments=Object.freeze({__proto__:null,mono:mono,posteriz:posterization,lighting:lighting});function preprocess(source,options){let lines=source.split(/\n/),lineCount=lines.length;var options=options;let opText=`let options = ${JSON.stringify(options)};`,depths={},output="";return traverse(),output.trim();function traverse(currentLine=0,condition=!0,depth=0){for(;currentLine<lineCount;){let line=lines[currentLine];if(line.trim().startsWith("#"))switch(line.trim().substr(1).split(/\s/)[0]){case"if":depths[depth]=condition,currentLine=traverse(currentLine+1,eval(opText+line.trim().substr(3))&&depths[depth],depth+1);break;case"else":currentLine=traverse(currentLine+1,!condition&&depths[depth-1],depth);break;case"endif":currentLine=traverse(currentLine+1,depths[depth-1],depth-1);break;case"import":condition&&(output+=preprocess(fragments[line.trim().substr(8)],options))}else condition&&(output+=`${line}\n`);currentLine++}return currentLine}}var vert="precision mediump float;attribute vec4 position;attribute vec3 normal;varying vec3 v_colour;varying vec3 v_normal;varying float v_shinyness;varying vec3 v_fragPos,v_viewPos;uniform mat4 u_vp,u_model,u_modelit;uniform vec3 u_pos;uniform mat4 u_modelobj;void main(){\n#if (options.primitive == 2 && options.mode !== 0)\nv_fragPos=vec3(u_model*u_modelobj*position);v_viewPos=u_pos;v_normal=mat3(u_modelit)*mat3(u_modelobj)*normal;\n#endif\n#if (options.primitive == 0)\ngl_PointSize=5.0;\n#endif\ngl_Position=(u_vp*u_model)*(u_modelobj*position);}";function vertex(t){return preprocess(vert,t)}var frag="precision mediump float;varying vec3 v_normal;uniform vec3 u_colour;uniform float u_shinyness;\n#if (options.mode !== 0)\nvarying vec3 v_fragPos,v_viewPos;struct Light{vec3 position;vec3 colour;};uniform Light light;\n#endif\n#if options.posterization\nuniform float p_gamma;uniform float p_colours;\n#endif\nvoid main(){gl_FragColor=vec4(u_colour,1.0);\n#if (options.mode !== 0)\n#import lighting\n#endif\n#if options.mono\n#import mono\n#endif\n#if options.posterization\n#import posteriz\n#endif\n}";function fragment(t){return preprocess(frag,t)}const POINTS=0,LINES=1,TRIANGLES=2,NONE=0,PHONG=1,BLINN_PHONG=2,COUNTER_CLOCKWISE=0,CLOCKWISE=1;var constants=Object.freeze({__proto__:null,POINTS:POINTS,LINES:LINES,TRIANGLES:TRIANGLES,NONE:NONE,PHONG:PHONG,BLINN_PHONG:BLINN_PHONG,COUNTER_CLOCKWISE:COUNTER_CLOCKWISE,CLOCKWISE:CLOCKWISE});class Object3d{constructor(t=TRIANGLES,e=!1){switch(this.primitive=t,this.verts=[],this.edges=[],this.faces=[],this.model=create(),this.transformations={scale:[1,1,1],rotateX:0,rotateY:0,rotateZ:0,translate:[0,0,0]},t){case TRIANGLES:e?this.materials=[]:this.colours=[];break;case LINES:case POINTS:this.colours=[];break;default:throw new Error(`The primitive ${t} is not a valid primitive`)}}scale(t){return this.transformations.scale=t,this._updateModel(),this}rotateX(t){return this.transformations.rotateX=t,this._updateModel(),this}rotateY(t){return this.transformations.rotateY=t,this._updateModel(),this}rotateZ(t){return this.transformations.rotateZ=t,this._updateModel(),this}translate(t){return this.transformations.translate=t,this._updateModel(),this}_updateModel(){scale(this.model,create(),this.transformations.scale),rotate(this.model,this.model,this.transformations.rotateX,[1,0,0]),rotate(this.model,this.model,this.transformations.rotateY,[0,1,0]),rotate(this.model,this.model,this.transformations.rotateZ,[0,0,1]),translate(this.model,this.model,this.transformations.translate)}static from(t){const e=new Object3d,r={0:["verts","colours","primitive"],1:["verts","edges","colours","primitive"],2:["verts","faces","colours","primitive"]},i=["points","lines","triangles"];let s=-1;if("string"==typeof t.primitive&&void 0!==i.includes(t.primitive))s=i.indexOf(t.primitive);else{if("number"!=typeof t.primitive)throw new Error("No primitive type supplied.");s=t.primitive}for(let i of r[s]){if(void 0===t[i]){if("colours"==i&&t.materials)continue;throw new Error(`Object doesn't have required property ${i}.`)}e[i]=t[i]}return e.primitive=s,e}}function crossProduct(t){try{let e=[t[1][0]-t[0][0],t[1][1]-t[0][1],t[1][2]-t[0][2]],r=[t[2][0]-t[0][0],t[2][1]-t[0][1],t[2][2]-t[0][2]];return normalize([e[1]*r[2]-e[2]*r[1],e[2]*r[0]-e[0]*r[2],e[0]*r[1]-e[1]*r[0]])}catch(t){throw t}}function normalize(t){let e=Math.sqrt(t[0]**2+t[1]**2+t[2]**2);return[t[0]/=e,t[1]/=e,t[2]/=e]}function clamp(t,e,r){return Math.max(Math.min(t,r),e)}function parseColour(t,e){if(t=t.trim(),!e)if(/rgb\([^\)]*\)/.test(t))e="rgb";else{if(!/(?:#|0x)(?:[a-f0-9]{3}|[a-f0-9]{6})\b/i.test(t))throw new Error(`${t} is not a valid colour.`);e="hex"}switch(e){case"hex":return[...(t=3==(t=t.substr(1)).length?t.split("").reduce(((t,e)=>t.push(e+e)&&t),[]):t.match(/.{1,2}/g)).map((t=>clamp(parseInt(t,16)/255,0,1)))];case"rgb":return[...(t=(t=t.substr(4).slice(0,-1)).split(",")).map((t=>clamp(parseInt(t)/255,0,1)))];default:throw new Error(`${e} is not a valid colour type.`)}}class Material{constructor(t,e=32){if("string"==typeof t)this.colour=parseColour(t);else{if(!Array.isArray(t))throw new Error(`${t} is not a valid colour.`);this.colour=t}this.shinyness=e}}function generateMesh(t){const e=["points","lines","triangles"];let r=-1;const i={0:["verts","colours","primitive"],1:["verts","edges","colours","primitive"],2:["verts","faces","colours","primitive"]};if("string"==typeof t.primitive&&void 0!==e.includes(t.primitive))r=e.indexOf(t.primitive);else{if("number"!=typeof t.primitive)throw new Error("No primitive type supplied.");r=t.primitive}for(let e of i[r])if(void 0===t[e]){if("colours"==e&&t.materials)continue;throw new Error(`Object doesn't have required property ${e}.`)}let s=[];if(t.materials)for(let e in t.materials)s[e]={material:t.materials[e],data:{position:[],normal:[],primitive:r}};else for(let e in t.colours)s[e]={material:new Material(t.colours[e]),data:{position:[],normal:[],primitive:r}};try{switch(r){case 0:for(let e of t.verts)s[e[3]].data.position.push(e[0],e[1],e[2]);break;case 1:for(let e of t.edges)s[e[2]].data.position.push(...t.verts[e[1]],...t.verts[e[0]]);break;case 2:for(let e of t.faces){let r=crossProduct([t.verts[e[0]],t.verts[e[1]],t.verts[e[2]]]);s[e[3]].data.position.push(...t.verts[e[2]],...t.verts[e[1]],...t.verts[e[0]]),s[e[3]].data.normal.push(...r,...r,...r)}break;default:throw new Error("Invalid primitive")}}catch(t){throw t instanceof TypeError?new Error("There was an unexpected error while parsing the mesh."):t}return s}class Renderer{constructor(t=new Screen,e=new Camera,r=new Input.None,i={mono:!1,lighting:BLINN_PHONG,culling:!0,posterization:!1}){return this.options={},this.options.mono=i.mono??!1,this.options.lighting=i.lighting??BLINN_PHONG,this.options.culling=i.culling??!0,this.options.posterization=i.posterization??!1,this.lighting={colour:[1,1,1],position:[0,-2,-5]},this.posterization={colours:5,gamma:1},this.screen=t,this.camera=e,assert(r.attributes,"Input handler doesn't have a .attributes() method.")&&r.attributes(t,e),assert(r.setup,"Input handler doesn't have a .setup() method."),assert(r.update,"Input handler doesn't have a .update() method."),this.input=r,this.dt=0,this.last=0,this}setup(...t){const{gl:e}=this.screen;this.scenes=[],this.__scene=0,this.primitives={0:!1,1:!1,2:!1},this.shaders={};for(let e in t){let r=t[e],i=[];assert(r.length,`Scene ${e} has no objects.`);for(let t in r){let e=r[t];assert("object"==typeof e,"Invalid object in scene."),e instanceof Object3d||(e=Object3d.from(e));let s=generateMesh(e);this.primitives[s[0].data.primitive]=!0,i.push(...s.map((e=>(e.object=t,e))))}this.scenes.push({meshes:i,objects:r})}for(let t in this.primitives)if(this.primitives[t]){let r=new Webglu(e),i=2==t?this.options.lighting:0;r.vert(vertex({mode:i,primitive:t})),r.frag(fragment({mode:i,primitive:t,mono:this.options.mono,posterization:this.options.posterization})),r.program(),this.shaders[t]=r}e.clearColor(1,1,1,1),e.enable(e.DEPTH_TEST),this.options.culling&&e.enable(e.CULL_FACE),this.input.setup()}draw(){const{gl:t}=this.screen;let e=[t.POINTS,t.LINES,t.TRIANGLES];t.viewport(0,0,t.drawingBufferWidth,t.drawingBufferHeight),t.clear(t.COLOR_BUFFER_BIT|t.DEPTH_BUFFER_BIT);for(let e in this.shaders){let r=this.shaders[e];t.useProgram(r.glprogram),r.uniform3fv("u_pos",this.camera.pos),r.uniformMatrix4fv("u_modelit",!1,this.camera.modelit()),r.uniformMatrix4fv("u_model",!1,this.camera.model),r.uniformMatrix4fv("u_vp",!1,this.camera.vp(this.screen.canvas)),this.options.lighting!==NONE&&(r.uniform3fv("light.position",this.lighting.position),r.uniform3fv("light.colour",this.lighting.colour)),this.options.posterization&&(r.uniform1f("p_gamma",this.posterization.gamma),r.uniform1f("p_colours",this.posterization.colours)),t.useProgram(null)}for(let r of this.scenes[this.__scene].meshes){const i=r.data.primitive,s=this.shaders[i];t.useProgram(s.glprogram),s.uniform1f("u_shinyness",r.material.shinyness),s.uniform3fv("u_colour",r.material.colour);let o=this.scenes[this.__scene].objects[r.object].model;o?s.uniformMatrix4fv("u_modelobj",!1,o):s.uniformMatrix4fv("u_modelobj",!1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);let n={position:r.data.position};2==i&&(n.normal=r.data.normal),s.buffers(n),t.drawArrays(e[i],0,r.data.position.length/(i+1)),t.useProgram(null)}}update(t){assert("number"==typeof t,"Invalid timestamp."),this.dt=t-this.last,this.last=t,this.input.update(this.dt)}get scene(){return this.__scene}set scene(t){assert("number"==typeof t&&this.scenes[t],"Invalid scene index.")&&(this.__scene=t)}}function assert(t,e){if(t)return!0;throw new Error("Assertion failed: "+e)}class Cube{constructor(t=[0,0,0]){let[e,r,i]=t;this.coords=t,this.primitive="triangles",this.verts=[[e-1,r-1,i-1],[e+1,r-1,i-1],[e+1,r+1,i-1],[e-1,r+1,i-1],[e-1,r-1,i+1],[e+1,r-1,i+1],[e+1,r+1,i+1],[e-1,r+1,i+1]],this.edges=[[0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7]],this.faces=[[0,1,2,0],[2,3,0,0],[1,5,6,1],[6,2,1,1],[4,5,1,2],[1,0,4,2],[6,5,4,3],[4,7,6,3],[7,4,0,4],[0,3,7,4],[2,6,7,5],[7,3,2,5]],this.colours=["#0ff","#0f0","#f0f","#00f","#ff0","#f00"]}}class Plane{constructor(t=[0,0,0]){this.coords=t;let[e,r,i]=t;this.primitive="triangles",this.verts=[[e-1,r,i-1],[e-1,r,i+1],[e+1,r,i+1],[e+1,r,i-1]],this.faces=[[0,1,2,0],[2,3,0,0],[2,1,0,1],[0,3,2,1]],this.colours=["#faf","#aff"]}}const Geometry={Cube:Cube,Plane:Plane};class OBJLoader{constructor(t,e=CLOCKWISE,r=new Material("#fff",128)){if(this.url=t,this.object=new Object3d(TRIANGLES,!0),this.normals=e,!(r instanceof Material))throw new Error(`${r} is not a valid material`);this.object.materials[0]=r}async load(){const t=(await loadFile(this.url)).split(/\n/);for(let e of t){switch(e=e.trim().split(/\s/),e.shift()){case"#":break;case"v":this.object.verts.push(e.map(((t,e)=>parseFloat(t))));break;case"f":e=e.map((t=>parseInt(t.split(/\//)[0])-1)),this.normals==COUNTER_CLOCKWISE?this.object.faces.push([e[0],e[1],e[2],0]):this.object.faces.push([e[2],e[1],e[0],0])}}if(!this.object.verts.length)throw new Error("Object doesn't have any vertices.");if(!this.object.faces.length)throw new Error("Object doesn't have any faces.");return this.object}}async function loadFile(t){try{return(await fetch(t)).text()}catch(t){throw t}}var index={VERSION:version,...constants,Renderer:Renderer,Screen:Screen,Camera:Camera,Input:Input,Geometry:Geometry,Material:Material,Object3d:Object3d,OBJLoader:OBJLoader};return console.log(`Loaded mjsr version: %c${version}`,"text-decoration:underline"),index}();
  