diff --git a/README.md b/README.md
index d7e7b6b..c448ace 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@ https://art.mekanoe.com
- [./001-platform-provenance](https://art.mekanoe.com/001-platform-provenance)
- [./002-webgl-engine](https://art.mekanoe.com/002-webgl-engine)
- [./003-scene](https://art.mekanoe.com/003-scene)
+- [./004-a-new-leaf](https://art.mekanoe.com/004-a-new-leaf)
## Development
diff --git a/hack/templates/work.html.txt b/hack/templates/work.html.txt
index 0f879b4..cb45028 100644
--- a/hack/templates/work.html.txt
+++ b/hack/templates/work.html.txt
@@ -23,6 +23,7 @@
XX.X FPS (XX.X ms)
[noeidelon] [stage 1]
bootstrapping...
this is taking a while...
[panic] heck wtf
+
diff --git a/html/003-scene/index.html b/html/003-scene/index.html
index ecb4e54..739489b 100644
--- a/html/003-scene/index.html
+++ b/html/003-scene/index.html
@@ -23,6 +23,7 @@
XX.X FPS (XX.X ms)
[noeidelon] [stage 1]
bootstrapping...
this is taking a while...
[panic] heck wtf
-
+
+
diff --git a/html/003-scene/main.js b/html/003-scene/main.js
index f3fc351..3c50944 100644
--- a/html/003-scene/main.js
+++ b/html/003-scene/main.js
@@ -1,6 +1 @@
-var UJ=Object.defineProperty;var VB=(B,J)=>{for(var V in J)UJ(B,V,{get:J[V],enumerable:!0,configurable:!0,set:(I)=>J[V]=()=>I})};var P=0.000001,j=typeof Float32Array!=="undefined"?Float32Array:Array,n=Math.random,GV=Math.PI/180;if(!Math.hypot)Math.hypot=function(){var B=0,J=arguments.length;while(J--)B+=arguments[J]*arguments[J];return Math.sqrt(B)};function QB(){var B=new j(9);if(j!=Float32Array)B[1]=0,B[2]=0,B[3]=0,B[5]=0,B[6]=0,B[7]=0;return B[0]=1,B[4]=1,B[8]=1,B}var g={};VB(g,{transpose:()=>{{return SJ}},translate:()=>{{return GJ}},targetTo:()=>{{return rJ}},subtract:()=>{{return DB}},sub:()=>{{return tJ}},str:()=>{{return zJ}},set:()=>{{return FJ}},scale:()=>{{return _J}},rotateZ:()=>{{return TJ}},rotateY:()=>{{return DJ}},rotateX:()=>{{return PJ}},rotate:()=>{{return HJ}},perspectiveZO:()=>{{return dJ}},perspectiveNO:()=>{{return HB}},perspectiveFromFieldOfView:()=>{{return lJ}},perspective:()=>{{return nJ}},orthoZO:()=>{{return iJ}},orthoNO:()=>{{return PB}},ortho:()=>{{return sJ}},multiplyScalarAndAdd:()=>{{return bJ}},multiplyScalar:()=>{{return eJ}},multiply:()=>{{return $B}},mul:()=>{{return aJ}},lookAt:()=>{{return yJ}},invert:()=>{{return QJ}},identity:()=>{{return KB}},getTranslation:()=>{{return hJ}},getScaling:()=>{{return _B}},getRotation:()=>{{return gJ}},frustum:()=>{{return cJ}},fromZRotation:()=>{{return AJ}},fromYRotation:()=>{{return CJ}},fromXRotation:()=>{{return pJ}},fromValues:()=>{{return EJ}},fromTranslation:()=>{{return jJ}},fromScaling:()=>{{return qJ}},fromRotationTranslationScaleOrigin:()=>{{return fJ}},fromRotationTranslationScale:()=>{{return wJ}},fromRotationTranslation:()=>{{return GB}},fromRotation:()=>{{return ZJ}},fromQuat2:()=>{{return OJ}},fromQuat:()=>{{return vJ}},frob:()=>{{return xJ}},exactEquals:()=>{{return uJ}},equals:()=>{{return oJ}},determinant:()=>{{return $J}},create:()=>{{return YJ}},copy:()=>{{return MJ}},clone:()=>{{return XJ}},adjoint:()=>{{return KJ}},add:()=>{{return mJ}}});function YJ(){var B=new j(16);if(j!=Float32Array)B[1]=0,B[2]=0,B[3]=0,B[4]=0,B[6]=0,B[7]=0,B[8]=0,B[9]=0,B[11]=0,B[12]=0,B[13]=0,B[14]=0;return B[0]=1,B[5]=1,B[10]=1,B[15]=1,B}function XJ(B){var J=new j(16);return J[0]=B[0],J[1]=B[1],J[2]=B[2],J[3]=B[3],J[4]=B[4],J[5]=B[5],J[6]=B[6],J[7]=B[7],J[8]=B[8],J[9]=B[9],J[10]=B[10],J[11]=B[11],J[12]=B[12],J[13]=B[13],J[14]=B[14],J[15]=B[15],J}function MJ(B,J){return B[0]=J[0],B[1]=J[1],B[2]=J[2],B[3]=J[3],B[4]=J[4],B[5]=J[5],B[6]=J[6],B[7]=J[7],B[8]=J[8],B[9]=J[9],B[10]=J[10],B[11]=J[11],B[12]=J[12],B[13]=J[13],B[14]=J[14],B[15]=J[15],B}function EJ(B,J,V,I,L,N,R,W,U,k,Y,M,F,E,Q,S){var X=new j(16);return X[0]=B,X[1]=J,X[2]=V,X[3]=I,X[4]=L,X[5]=N,X[6]=R,X[7]=W,X[8]=U,X[9]=k,X[10]=Y,X[11]=M,X[12]=F,X[13]=E,X[14]=Q,X[15]=S,X}function FJ(B,J,V,I,L,N,R,W,U,k,Y,M,F,E,Q,S,X){return B[0]=J,B[1]=V,B[2]=I,B[3]=L,B[4]=N,B[5]=R,B[6]=W,B[7]=U,B[8]=k,B[9]=Y,B[10]=M,B[11]=F,B[12]=E,B[13]=Q,B[14]=S,B[15]=X,B}function KB(B){return B[0]=1,B[1]=0,B[2]=0,B[3]=0,B[4]=0,B[5]=1,B[6]=0,B[7]=0,B[8]=0,B[9]=0,B[10]=1,B[11]=0,B[12]=0,B[13]=0,B[14]=0,B[15]=1,B}function SJ(B,J){if(B===J){var V=J[1],I=J[2],L=J[3],N=J[6],R=J[7],W=J[11];B[1]=J[4],B[2]=J[8],B[3]=J[12],B[4]=V,B[6]=J[9],B[7]=J[13],B[8]=I,B[9]=N,B[11]=J[14],B[12]=L,B[13]=R,B[14]=W}else B[0]=J[0],B[1]=J[4],B[2]=J[8],B[3]=J[12],B[4]=J[1],B[5]=J[5],B[6]=J[9],B[7]=J[13],B[8]=J[2],B[9]=J[6],B[10]=J[10],B[11]=J[14],B[12]=J[3],B[13]=J[7],B[14]=J[11],B[15]=J[15];return B}function QJ(B,J){var V=J[0],I=J[1],L=J[2],N=J[3],R=J[4],W=J[5],U=J[6],k=J[7],Y=J[8],M=J[9],F=J[10],E=J[11],Q=J[12],S=J[13],X=J[14],K=J[15],D=V*W-I*R,H=V*U-L*R,_=V*k-N*R,$=I*U-L*W,G=I*k-N*W,C=L*k-N*U,q=Y*S-M*Q,Z=Y*X-F*Q,p=Y*K-E*Q,A=M*X-F*S,O=M*K-E*S,h=F*K-E*X,T=D*h-H*O+_*A+$*p-G*Z+C*q;if(!T)return null;return T=1/T,B[0]=(W*h-U*O+k*A)*T,B[1]=(L*O-I*h-N*A)*T,B[2]=(S*C-X*G+K*$)*T,B[3]=(F*G-M*C-E*$)*T,B[4]=(U*p-R*h-k*Z)*T,B[5]=(V*h-L*p+N*Z)*T,B[6]=(X*_-Q*C-K*H)*T,B[7]=(Y*C-F*_+E*H)*T,B[8]=(R*O-W*p+k*q)*T,B[9]=(I*p-V*O-N*q)*T,B[10]=(Q*G-S*_+K*D)*T,B[11]=(M*_-Y*G-E*D)*T,B[12]=(W*Z-R*A-U*q)*T,B[13]=(V*A-I*Z+L*q)*T,B[14]=(S*H-Q*$-X*D)*T,B[15]=(Y*$-M*H+F*D)*T,B}function KJ(B,J){var V=J[0],I=J[1],L=J[2],N=J[3],R=J[4],W=J[5],U=J[6],k=J[7],Y=J[8],M=J[9],F=J[10],E=J[11],Q=J[12],S=J[13],X=J[14],K=J[15];return B[0]=W*(F*K-E*X)-M*(U*K-k*X)+S*(U*E-k*F),B[1]=-(I*(F*K-E*X)-M*(L*K-N*X)+S*(L*E-N*F)),B[2]=I*(U*K-k*X)-W*(L*K-N*X)+S*(L*k-N*U),B[3]=-(I*(U*E-k*F)-W*(L*E-N*F)+M*(L*k-N*U)),B[4]=-(R*(F*K-E*X)-Y*(U*K-k*X)+Q*(U*E-k*F)),B[5]=V*(F*K-E*X)-Y*(L*K-N*X)+Q*(L*E-N*F),B[6]=-(V*(U*K-k*X)-R*(L*K-N*X)+Q*(L*k-N*U)),B[7]=V*(U*E-k*F)-R*(L*E-N*F)+Y*(L*k-N*U),B[8]=R*(M*K-E*S)-Y*(W*K-k*S)+Q*(W*E-k*M),B[9]=-(V*(M*K-E*S)-Y*(I*K-N*S)+Q*(I*E-N*M)),B[10]=V*(W*K-k*S)-R*(I*K-N*S)+Q*(I*k-N*W),B[11]=-(V*(W*E-k*M)-R*(I*E-N*M)+Y*(I*k-N*W)),B[12]=-(R*(M*X-F*S)-Y*(W*X-U*S)+Q*(W*F-U*M)),B[13]=V*(M*X-F*S)-Y*(I*X-L*S)+Q*(I*F-L*M),B[14]=-(V*(W*X-U*S)-R*(I*X-L*S)+Q*(I*U-L*W)),B[15]=V*(W*F-U*M)-R*(I*F-L*M)+Y*(I*U-L*W),B}function $J(B){var J=B[0],V=B[1],I=B[2],L=B[3],N=B[4],R=B[5],W=B[6],U=B[7],k=B[8],Y=B[9],M=B[10],F=B[11],E=B[12],Q=B[13],S=B[14],X=B[15],K=J*R-V*N,D=J*W-I*N,H=J*U-L*N,_=V*W-I*R,$=V*U-L*R,G=I*U-L*W,C=k*Q-Y*E,q=k*S-M*E,Z=k*X-F*E,p=Y*S-M*Q,A=Y*X-F*Q,O=M*X-F*S;return K*O-D*A+H*p+_*Z-$*q+G*C}function $B(B,J,V){var I=J[0],L=J[1],N=J[2],R=J[3],W=J[4],U=J[5],k=J[6],Y=J[7],M=J[8],F=J[9],E=J[10],Q=J[11],S=J[12],X=J[13],K=J[14],D=J[15],H=V[0],_=V[1],$=V[2],G=V[3];return B[0]=H*I+_*W+$*M+G*S,B[1]=H*L+_*U+$*F+G*X,B[2]=H*N+_*k+$*E+G*K,B[3]=H*R+_*Y+$*Q+G*D,H=V[4],_=V[5],$=V[6],G=V[7],B[4]=H*I+_*W+$*M+G*S,B[5]=H*L+_*U+$*F+G*X,B[6]=H*N+_*k+$*E+G*K,B[7]=H*R+_*Y+$*Q+G*D,H=V[8],_=V[9],$=V[10],G=V[11],B[8]=H*I+_*W+$*M+G*S,B[9]=H*L+_*U+$*F+G*X,B[10]=H*N+_*k+$*E+G*K,B[11]=H*R+_*Y+$*Q+G*D,H=V[12],_=V[13],$=V[14],G=V[15],B[12]=H*I+_*W+$*M+G*S,B[13]=H*L+_*U+$*F+G*X,B[14]=H*N+_*k+$*E+G*K,B[15]=H*R+_*Y+$*Q+G*D,B}function GJ(B,J,V){var I=V[0],L=V[1],N=V[2],R,W,U,k,Y,M,F,E,Q,S,X,K;if(J===B)B[12]=J[0]*I+J[4]*L+J[8]*N+J[12],B[13]=J[1]*I+J[5]*L+J[9]*N+J[13],B[14]=J[2]*I+J[6]*L+J[10]*N+J[14],B[15]=J[3]*I+J[7]*L+J[11]*N+J[15];else R=J[0],W=J[1],U=J[2],k=J[3],Y=J[4],M=J[5],F=J[6],E=J[7],Q=J[8],S=J[9],X=J[10],K=J[11],B[0]=R,B[1]=W,B[2]=U,B[3]=k,B[4]=Y,B[5]=M,B[6]=F,B[7]=E,B[8]=Q,B[9]=S,B[10]=X,B[11]=K,B[12]=R*I+Y*L+Q*N+J[12],B[13]=W*I+M*L+S*N+J[13],B[14]=U*I+F*L+X*N+J[14],B[15]=k*I+E*L+K*N+J[15];return B}function _J(B,J,V){var I=V[0],L=V[1],N=V[2];return B[0]=J[0]*I,B[1]=J[1]*I,B[2]=J[2]*I,B[3]=J[3]*I,B[4]=J[4]*L,B[5]=J[5]*L,B[6]=J[6]*L,B[7]=J[7]*L,B[8]=J[8]*N,B[9]=J[9]*N,B[10]=J[10]*N,B[11]=J[11]*N,B[12]=J[12],B[13]=J[13],B[14]=J[14],B[15]=J[15],B}function HJ(B,J,V,I){var L=I[0],N=I[1],R=I[2],W=Math.hypot(L,N,R),U,k,Y,M,F,E,Q,S,X,K,D,H,_,$,G,C,q,Z,p,A,O,h,T,w;if(W0)V[0]=(W*R+Y*I+U*N-k*L)*2/M,V[1]=(U*R+Y*L+k*I-W*N)*2/M,V[2]=(k*R+Y*N+W*L-U*I)*2/M;else V[0]=(W*R+Y*I+U*N-k*L)*2,V[1]=(U*R+Y*L+k*I-W*N)*2,V[2]=(k*R+Y*N+W*L-U*I)*2;return GB(B,J,V),B}function hJ(B,J){return B[0]=J[12],B[1]=J[13],B[2]=J[14],B}function _B(B,J){var V=J[0],I=J[1],L=J[2],N=J[4],R=J[5],W=J[6],U=J[8],k=J[9],Y=J[10];return B[0]=Math.hypot(V,I,L),B[1]=Math.hypot(N,R,W),B[2]=Math.hypot(U,k,Y),B}function gJ(B,J){var V=new j(3);_B(V,J);var I=1/V[0],L=1/V[1],N=1/V[2],R=J[0]*I,W=J[1]*L,U=J[2]*N,k=J[4]*I,Y=J[5]*L,M=J[6]*N,F=J[8]*I,E=J[9]*L,Q=J[10]*N,S=R+Y+Q,X=0;if(S>0)X=Math.sqrt(S+1)*2,B[3]=0.25*X,B[0]=(M-E)/X,B[1]=(F-U)/X,B[2]=(W-k)/X;else if(R>Y&&R>Q)X=Math.sqrt(1+R-Y-Q)*2,B[3]=(M-E)/X,B[0]=0.25*X,B[1]=(W+k)/X,B[2]=(F+U)/X;else if(Y>Q)X=Math.sqrt(1+Y-R-Q)*2,B[3]=(F-U)/X,B[0]=(W+k)/X,B[1]=0.25*X,B[2]=(M+E)/X;else X=Math.sqrt(1+Q-R-Y)*2,B[3]=(W-k)/X,B[0]=(F+U)/X,B[1]=(M+E)/X,B[2]=0.25*X;return B}function wJ(B,J,V,I){var L=J[0],N=J[1],R=J[2],W=J[3],U=L+L,k=N+N,Y=R+R,M=L*U,F=L*k,E=L*Y,Q=N*k,S=N*Y,X=R*Y,K=W*U,D=W*k,H=W*Y,_=I[0],$=I[1],G=I[2];return B[0]=(1-(Q+X))*_,B[1]=(F+H)*_,B[2]=(E-D)*_,B[3]=0,B[4]=(F-H)*$,B[5]=(1-(M+X))*$,B[6]=(S+K)*$,B[7]=0,B[8]=(E+D)*G,B[9]=(S-K)*G,B[10]=(1-(M+Q))*G,B[11]=0,B[12]=V[0],B[13]=V[1],B[14]=V[2],B[15]=1,B}function fJ(B,J,V,I,L){var N=J[0],R=J[1],W=J[2],U=J[3],k=N+N,Y=R+R,M=W+W,F=N*k,E=N*Y,Q=N*M,S=R*Y,X=R*M,K=W*M,D=U*k,H=U*Y,_=U*M,$=I[0],G=I[1],C=I[2],q=L[0],Z=L[1],p=L[2],A=(1-(S+K))*$,O=(E+_)*$,h=(Q-H)*$,T=(E-_)*G,w=(1-(F+K))*G,i=(X+D)*G,y=(Q+H)*C,FB=(X-D)*C,SB=(1-(F+S))*C;return B[0]=A,B[1]=O,B[2]=h,B[3]=0,B[4]=T,B[5]=w,B[6]=i,B[7]=0,B[8]=y,B[9]=FB,B[10]=SB,B[11]=0,B[12]=V[0]+q-(A*q+T*Z+y*p),B[13]=V[1]+Z-(O*q+w*Z+FB*p),B[14]=V[2]+p-(h*q+i*Z+SB*p),B[15]=1,B}function vJ(B,J){var V=J[0],I=J[1],L=J[2],N=J[3],R=V+V,W=I+I,U=L+L,k=V*R,Y=I*R,M=I*W,F=L*R,E=L*W,Q=L*U,S=N*R,X=N*W,K=N*U;return B[0]=1-M-Q,B[1]=Y+K,B[2]=F-X,B[3]=0,B[4]=Y-K,B[5]=1-k-Q,B[6]=E+S,B[7]=0,B[8]=F+X,B[9]=E-S,B[10]=1-k-M,B[11]=0,B[12]=0,B[13]=0,B[14]=0,B[15]=1,B}function cJ(B,J,V,I,L,N,R){var W=1/(V-J),U=1/(L-I),k=1/(N-R);return B[0]=N*2*W,B[1]=0,B[2]=0,B[3]=0,B[4]=0,B[5]=N*2*U,B[6]=0,B[7]=0,B[8]=(V+J)*W,B[9]=(L+I)*U,B[10]=(R+N)*k,B[11]=-1,B[12]=0,B[13]=0,B[14]=R*N*2*k,B[15]=0,B}function HB(B,J,V,I,L){var N=1/Math.tan(J/2),R;if(B[0]=N/V,B[1]=0,B[2]=0,B[3]=0,B[4]=0,B[5]=N,B[6]=0,B[7]=0,B[8]=0,B[9]=0,B[11]=-1,B[12]=0,B[13]=0,B[15]=0,L!=null&&L!==Infinity)R=1/(I-L),B[10]=(L+I)*R,B[14]=2*L*I*R;else B[10]=-1,B[14]=-2*I;return B}function dJ(B,J,V,I,L){var N=1/Math.tan(J/2),R;if(B[0]=N/V,B[1]=0,B[2]=0,B[3]=0,B[4]=0,B[5]=N,B[6]=0,B[7]=0,B[8]=0,B[9]=0,B[11]=-1,B[12]=0,B[13]=0,B[15]=0,L!=null&&L!==Infinity)R=1/(I-L),B[10]=L*R,B[14]=L*I*R;else B[10]=-1,B[14]=-I;return B}function lJ(B,J,V,I){var L=Math.tan(J.upDegrees*Math.PI/180),N=Math.tan(J.downDegrees*Math.PI/180),R=Math.tan(J.leftDegrees*Math.PI/180),W=Math.tan(J.rightDegrees*Math.PI/180),U=2/(R+W),k=2/(L+N);return B[0]=U,B[1]=0,B[2]=0,B[3]=0,B[4]=0,B[5]=k,B[6]=0,B[7]=0,B[8]=-((R-W)*U*0.5),B[9]=(L-N)*k*0.5,B[10]=I/(V-I),B[11]=-1,B[12]=0,B[13]=0,B[14]=I*V/(V-I),B[15]=0,B}function PB(B,J,V,I,L,N,R){var W=1/(J-V),U=1/(I-L),k=1/(N-R);return B[0]=-2*W,B[1]=0,B[2]=0,B[3]=0,B[4]=0,B[5]=-2*U,B[6]=0,B[7]=0,B[8]=0,B[9]=0,B[10]=2*k,B[11]=0,B[12]=(J+V)*W,B[13]=(L+I)*U,B[14]=(R+N)*k,B[15]=1,B}function iJ(B,J,V,I,L,N,R){var W=1/(J-V),U=1/(I-L),k=1/(N-R);return B[0]=-2*W,B[1]=0,B[2]=0,B[3]=0,B[4]=0,B[5]=-2*U,B[6]=0,B[7]=0,B[8]=0,B[9]=0,B[10]=k,B[11]=0,B[12]=(J+V)*W,B[13]=(L+I)*U,B[14]=N*k,B[15]=1,B}function yJ(B,J,V,I){var L,N,R,W,U,k,Y,M,F,E,Q=J[0],S=J[1],X=J[2],K=I[0],D=I[1],H=I[2],_=V[0],$=V[1],G=V[2];if(Math.abs(Q-_)
0)E=1/Math.sqrt(E),Y*=E,M*=E,F*=E;var Q=U*F-k*M,S=k*Y-W*F,X=W*M-U*Y;if(E=Q*Q+S*S+X*X,E>0)E=1/Math.sqrt(E),Q*=E,S*=E,X*=E;return B[0]=Q,B[1]=S,B[2]=X,B[3]=0,B[4]=M*X-F*S,B[5]=F*Q-Y*X,B[6]=Y*S-M*Q,B[7]=0,B[8]=Y,B[9]=M,B[10]=F,B[11]=0,B[12]=L,B[13]=N,B[14]=R,B[15]=1,B}function zJ(B){return"mat4("+B[0]+", "+B[1]+", "+B[2]+", "+B[3]+", "+B[4]+", "+B[5]+", "+B[6]+", "+B[7]+", "+B[8]+", "+B[9]+", "+B[10]+", "+B[11]+", "+B[12]+", "+B[13]+", "+B[14]+", "+B[15]+")"}function xJ(B){return Math.hypot(B[0],B[1],B[2],B[3],B[4],B[5],B[6],B[7],B[8],B[9],B[10],B[11],B[12],B[13],B[14],B[15])}function mJ(B,J,V){return B[0]=J[0]+V[0],B[1]=J[1]+V[1],B[2]=J[2]+V[2],B[3]=J[3]+V[3],B[4]=J[4]+V[4],B[5]=J[5]+V[5],B[6]=J[6]+V[6],B[7]=J[7]+V[7],B[8]=J[8]+V[8],B[9]=J[9]+V[9],B[10]=J[10]+V[10],B[11]=J[11]+V[11],B[12]=J[12]+V[12],B[13]=J[13]+V[13],B[14]=J[14]+V[14],B[15]=J[15]+V[15],B}function DB(B,J,V){return B[0]=J[0]-V[0],B[1]=J[1]-V[1],B[2]=J[2]-V[2],B[3]=J[3]-V[3],B[4]=J[4]-V[4],B[5]=J[5]-V[5],B[6]=J[6]-V[6],B[7]=J[7]-V[7],B[8]=J[8]-V[8],B[9]=J[9]-V[9],B[10]=J[10]-V[10],B[11]=J[11]-V[11],B[12]=J[12]-V[12],B[13]=J[13]-V[13],B[14]=J[14]-V[14],B[15]=J[15]-V[15],B}function eJ(B,J,V){return B[0]=J[0]*V,B[1]=J[1]*V,B[2]=J[2]*V,B[3]=J[3]*V,B[4]=J[4]*V,B[5]=J[5]*V,B[6]=J[6]*V,B[7]=J[7]*V,B[8]=J[8]*V,B[9]=J[9]*V,B[10]=J[10]*V,B[11]=J[11]*V,B[12]=J[12]*V,B[13]=J[13]*V,B[14]=J[14]*V,B[15]=J[15]*V,B}function bJ(B,J,V,I){return B[0]=J[0]+V[0]*I,B[1]=J[1]+V[1]*I,B[2]=J[2]+V[2]*I,B[3]=J[3]+V[3]*I,B[4]=J[4]+V[4]*I,B[5]=J[5]+V[5]*I,B[6]=J[6]+V[6]*I,B[7]=J[7]+V[7]*I,B[8]=J[8]+V[8]*I,B[9]=J[9]+V[9]*I,B[10]=J[10]+V[10]*I,B[11]=J[11]+V[11]*I,B[12]=J[12]+V[12]*I,B[13]=J[13]+V[13]*I,B[14]=J[14]+V[14]*I,B[15]=J[15]+V[15]*I,B}function uJ(B,J){return B[0]===J[0]&&B[1]===J[1]&&B[2]===J[2]&&B[3]===J[3]&&B[4]===J[4]&&B[5]===J[5]&&B[6]===J[6]&&B[7]===J[7]&&B[8]===J[8]&&B[9]===J[9]&&B[10]===J[10]&&B[11]===J[11]&&B[12]===J[12]&&B[13]===J[13]&&B[14]===J[14]&&B[15]===J[15]}function oJ(B,J){var V=B[0],I=B[1],L=B[2],N=B[3],R=B[4],W=B[5],U=B[6],k=B[7],Y=B[8],M=B[9],F=B[10],E=B[11],Q=B[12],S=B[13],X=B[14],K=B[15],D=J[0],H=J[1],_=J[2],$=J[3],G=J[4],C=J[5],q=J[6],Z=J[7],p=J[8],A=J[9],O=J[10],h=J[11],T=J[12],w=J[13],i=J[14],y=J[15];return Math.abs(V-D)<=P*Math.max(1,Math.abs(V),Math.abs(D))&&Math.abs(I-H)<=P*Math.max(1,Math.abs(I),Math.abs(H))&&Math.abs(L-_)<=P*Math.max(1,Math.abs(L),Math.abs(_))&&Math.abs(N-$)<=P*Math.max(1,Math.abs(N),Math.abs($))&&Math.abs(R-G)<=P*Math.max(1,Math.abs(R),Math.abs(G))&&Math.abs(W-C)<=P*Math.max(1,Math.abs(W),Math.abs(C))&&Math.abs(U-q)<=P*Math.max(1,Math.abs(U),Math.abs(q))&&Math.abs(k-Z)<=P*Math.max(1,Math.abs(k),Math.abs(Z))&&Math.abs(Y-p)<=P*Math.max(1,Math.abs(Y),Math.abs(p))&&Math.abs(M-A)<=P*Math.max(1,Math.abs(M),Math.abs(A))&&Math.abs(F-O)<=P*Math.max(1,Math.abs(F),Math.abs(O))&&Math.abs(E-h)<=P*Math.max(1,Math.abs(E),Math.abs(h))&&Math.abs(Q-T)<=P*Math.max(1,Math.abs(Q),Math.abs(T))&&Math.abs(S-w)<=P*Math.max(1,Math.abs(S),Math.abs(w))&&Math.abs(X-i)<=P*Math.max(1,Math.abs(X),Math.abs(i))&&Math.abs(K-y)<=P*Math.max(1,Math.abs(K),Math.abs(y))}var nJ=HB,sJ=PB,aJ=$B,tJ=DB;var f={};VB(f,{str:()=>{{return b0}},squaredLength:()=>{{return aB}},sqrLen:()=>{{return LV}},sqlerp:()=>{{return UV}},slerp:()=>{{return b}},setAxisAngle:()=>{{return rB}},setAxes:()=>{{return kV}},set:()=>{{return t0}},scale:()=>{{return bB}},rotationTo:()=>{{return WV}},rotateZ:()=>{{return i0}},rotateY:()=>{{return s0}},rotateX:()=>{{return l0}},random:()=>{{return z0}},pow:()=>{{return r0}},normalize:()=>{{return RB}},multiply:()=>{{return zB}},mul:()=>{{return JV}},ln:()=>{{return mB}},lerp:()=>{{return VV}},length:()=>{{return oB}},len:()=>{{return IV}},invert:()=>{{return x0}},identity:()=>{{return c0}},getAxisAngle:()=>{{return n0}},getAngle:()=>{{return d0}},fromValues:()=>{{return o0}},fromMat3:()=>{{return eB}},fromEuler:()=>{{return e0}},exp:()=>{{return xB}},exactEquals:()=>{{return NV}},equals:()=>{{return RV}},dot:()=>{{return uB}},create:()=>{{return NB}},copy:()=>{{return a0}},conjugate:()=>{{return m0}},clone:()=>{{return u0}},calculateW:()=>{{return y0}},add:()=>{{return BV}}});var s={};VB(s,{zero:()=>{{return T0}},transformQuat:()=>{{return G0}},transformMat4:()=>{{return K0}},transformMat3:()=>{{return $0}},subtract:()=>{{return jB}},sub:()=>{{return p0}},str:()=>{{return j0}},squaredLength:()=>{{return AB}},squaredDistance:()=>{{return CB}},sqrLen:()=>{{return g0}},sqrDist:()=>{{return h0}},set:()=>{{return V0}},scaleAndAdd:()=>{{return Y0}},scale:()=>{{return k0}},round:()=>{{return U0}},rotateZ:()=>{{return P0}},rotateY:()=>{{return H0}},rotateX:()=>{{return _0}},random:()=>{{return Q0}},normalize:()=>{{return IB}},negate:()=>{{return X0}},multiply:()=>{{return qB}},mul:()=>{{return C0}},min:()=>{{return R0}},max:()=>{{return W0}},lerp:()=>{{return E0}},length:()=>{{return TB}},len:()=>{{return LB}},inverse:()=>{{return M0}},hermite:()=>{{return F0}},fromValues:()=>{{return m}},forEach:()=>{{return w0}},floor:()=>{{return N0}},exactEquals:()=>{{return q0}},equals:()=>{{return Z0}},dot:()=>{{return e}},divide:()=>{{return ZB}},div:()=>{{return A0}},distance:()=>{{return pB}},dist:()=>{{return O0}},cross:()=>{{return z}},create:()=>{{return x}},copy:()=>{{return J0}},clone:()=>{{return B0}},ceil:()=>{{return L0}},bezier:()=>{{return S0}},angle:()=>{{return D0}},add:()=>{{return I0}}});function x(){var B=new j(3);if(j!=Float32Array)B[0]=0,B[1]=0,B[2]=0;return B}function B0(B){var J=new j(3);return J[0]=B[0],J[1]=B[1],J[2]=B[2],J}function TB(B){var J=B[0],V=B[1],I=B[2];return Math.hypot(J,V,I)}function m(B,J,V){var I=new j(3);return I[0]=B,I[1]=J,I[2]=V,I}function J0(B,J){return B[0]=J[0],B[1]=J[1],B[2]=J[2],B}function V0(B,J,V,I){return B[0]=J,B[1]=V,B[2]=I,B}function I0(B,J,V){return B[0]=J[0]+V[0],B[1]=J[1]+V[1],B[2]=J[2]+V[2],B}function jB(B,J,V){return B[0]=J[0]-V[0],B[1]=J[1]-V[1],B[2]=J[2]-V[2],B}function qB(B,J,V){return B[0]=J[0]*V[0],B[1]=J[1]*V[1],B[2]=J[2]*V[2],B}function ZB(B,J,V){return B[0]=J[0]/V[0],B[1]=J[1]/V[1],B[2]=J[2]/V[2],B}function L0(B,J){return B[0]=Math.ceil(J[0]),B[1]=Math.ceil(J[1]),B[2]=Math.ceil(J[2]),B}function N0(B,J){return B[0]=Math.floor(J[0]),B[1]=Math.floor(J[1]),B[2]=Math.floor(J[2]),B}function R0(B,J,V){return B[0]=Math.min(J[0],V[0]),B[1]=Math.min(J[1],V[1]),B[2]=Math.min(J[2],V[2]),B}function W0(B,J,V){return B[0]=Math.max(J[0],V[0]),B[1]=Math.max(J[1],V[1]),B[2]=Math.max(J[2],V[2]),B}function U0(B,J){return B[0]=Math.round(J[0]),B[1]=Math.round(J[1]),B[2]=Math.round(J[2]),B}function k0(B,J,V){return B[0]=J[0]*V,B[1]=J[1]*V,B[2]=J[2]*V,B}function Y0(B,J,V,I){return B[0]=J[0]+V[0]*I,B[1]=J[1]+V[1]*I,B[2]=J[2]+V[2]*I,B}function pB(B,J){var V=J[0]-B[0],I=J[1]-B[1],L=J[2]-B[2];return Math.hypot(V,I,L)}function CB(B,J){var V=J[0]-B[0],I=J[1]-B[1],L=J[2]-B[2];return V*V+I*I+L*L}function AB(B){var J=B[0],V=B[1],I=B[2];return J*J+V*V+I*I}function X0(B,J){return B[0]=-J[0],B[1]=-J[1],B[2]=-J[2],B}function M0(B,J){return B[0]=1/J[0],B[1]=1/J[1],B[2]=1/J[2],B}function IB(B,J){var V=J[0],I=J[1],L=J[2],N=V*V+I*I+L*L;if(N>0)N=1/Math.sqrt(N);return B[0]=J[0]*N,B[1]=J[1]*N,B[2]=J[2]*N,B}function e(B,J){return B[0]*J[0]+B[1]*J[1]+B[2]*J[2]}function z(B,J,V){var I=J[0],L=J[1],N=J[2],R=V[0],W=V[1],U=V[2];return B[0]=L*U-N*W,B[1]=N*R-I*U,B[2]=I*W-L*R,B}function E0(B,J,V,I){var L=J[0],N=J[1],R=J[2];return B[0]=L+I*(V[0]-L),B[1]=N+I*(V[1]-N),B[2]=R+I*(V[2]-R),B}function F0(B,J,V,I,L,N){var R=N*N,W=R*(2*N-3)+1,U=R*(N-2)+N,k=R*(N-1),Y=R*(3-2*N);return B[0]=J[0]*W+V[0]*U+I[0]*k+L[0]*Y,B[1]=J[1]*W+V[1]*U+I[1]*k+L[1]*Y,B[2]=J[2]*W+V[2]*U+I[2]*k+L[2]*Y,B}function S0(B,J,V,I,L,N){var R=1-N,W=R*R,U=N*N,k=W*R,Y=3*N*W,M=3*U*R,F=U*N;return B[0]=J[0]*k+V[0]*Y+I[0]*M+L[0]*F,B[1]=J[1]*k+V[1]*Y+I[1]*M+L[1]*F,B[2]=J[2]*k+V[2]*Y+I[2]*M+L[2]*F,B}function Q0(B,J){J=J||1;var V=n()*2*Math.PI,I=n()*2-1,L=Math.sqrt(1-I*I)*J;return B[0]=Math.cos(V)*L,B[1]=Math.sin(V)*L,B[2]=I*J,B}function K0(B,J,V){var I=J[0],L=J[1],N=J[2],R=V[3]*I+V[7]*L+V[11]*N+V[15];return R=R||1,B[0]=(V[0]*I+V[4]*L+V[8]*N+V[12])/R,B[1]=(V[1]*I+V[5]*L+V[9]*N+V[13])/R,B[2]=(V[2]*I+V[6]*L+V[10]*N+V[14])/R,B}function $0(B,J,V){var I=J[0],L=J[1],N=J[2];return B[0]=I*V[0]+L*V[3]+N*V[6],B[1]=I*V[1]+L*V[4]+N*V[7],B[2]=I*V[2]+L*V[5]+N*V[8],B}function G0(B,J,V){var I=V[0],L=V[1],N=V[2],R=V[3],W=J[0],U=J[1],k=J[2],Y=L*k-N*U,M=N*W-I*k,F=I*U-L*W,E=L*F-N*M,Q=N*Y-I*F,S=I*M-L*Y,X=R*2;return Y*=X,M*=X,F*=X,E*=2,Q*=2,S*=2,B[0]=W+Y+E,B[1]=U+M+Q,B[2]=k+F+S,B}function _0(B,J,V,I){var L=[],N=[];return L[0]=J[0]-V[0],L[1]=J[1]-V[1],L[2]=J[2]-V[2],N[0]=L[0],N[1]=L[1]*Math.cos(I)-L[2]*Math.sin(I),N[2]=L[1]*Math.sin(I)+L[2]*Math.cos(I),B[0]=N[0]+V[0],B[1]=N[1]+V[1],B[2]=N[2]+V[2],B}function H0(B,J,V,I){var L=[],N=[];return L[0]=J[0]-V[0],L[1]=J[1]-V[1],L[2]=J[2]-V[2],N[0]=L[2]*Math.sin(I)+L[0]*Math.cos(I),N[1]=L[1],N[2]=L[2]*Math.cos(I)-L[0]*Math.sin(I),B[0]=N[0]+V[0],B[1]=N[1]+V[1],B[2]=N[2]+V[2],B}function P0(B,J,V,I){var L=[],N=[];return L[0]=J[0]-V[0],L[1]=J[1]-V[1],L[2]=J[2]-V[2],N[0]=L[0]*Math.cos(I)-L[1]*Math.sin(I),N[1]=L[0]*Math.sin(I)+L[1]*Math.cos(I),N[2]=L[2],B[0]=N[0]+V[0],B[1]=N[1]+V[1],B[2]=N[2]+V[2],B}function D0(B,J){var V=B[0],I=B[1],L=B[2],N=J[0],R=J[1],W=J[2],U=Math.sqrt(V*V+I*I+L*L),k=Math.sqrt(N*N+R*R+W*W),Y=U*k,M=Y&&e(B,J)/Y;return Math.acos(Math.min(Math.max(M,-1),1))}function T0(B){return B[0]=0,B[1]=0,B[2]=0,B}function j0(B){return"vec3("+B[0]+", "+B[1]+", "+B[2]+")"}function q0(B,J){return B[0]===J[0]&&B[1]===J[1]&&B[2]===J[2]}function Z0(B,J){var V=B[0],I=B[1],L=B[2],N=J[0],R=J[1],W=J[2];return Math.abs(V-N)<=P*Math.max(1,Math.abs(V),Math.abs(N))&&Math.abs(I-R)<=P*Math.max(1,Math.abs(I),Math.abs(R))&&Math.abs(L-W)<=P*Math.max(1,Math.abs(L),Math.abs(W))}var p0=jB,C0=qB,A0=ZB,O0=pB,h0=CB,LB=TB,g0=AB,w0=function(){var B=x();return function(J,V,I,L,N,R){var W,U;if(!V)V=3;if(!I)I=0;if(L)U=Math.min(L*V+I,J.length);else U=J.length;for(W=I;W0)R=1/Math.sqrt(R);return B[0]=V*R,B[1]=I*R,B[2]=L*R,B[3]=N*R,B}function lB(B,J){return B[0]*J[0]+B[1]*J[1]+B[2]*J[2]+B[3]*J[3]}function sB(B,J,V,I){var L=J[0],N=J[1],R=J[2],W=J[3];return B[0]=L+I*(V[0]-L),B[1]=N+I*(V[1]-N),B[2]=R+I*(V[2]-R),B[3]=W+I*(V[3]-W),B}function iB(B,J){return B[0]===J[0]&&B[1]===J[1]&&B[2]===J[2]&&B[3]===J[3]}function yB(B,J){var V=B[0],I=B[1],L=B[2],N=B[3],R=J[0],W=J[1],U=J[2],k=J[3];return Math.abs(V-R)<=P*Math.max(1,Math.abs(V),Math.abs(R))&&Math.abs(I-W)<=P*Math.max(1,Math.abs(I),Math.abs(W))&&Math.abs(L-U)<=P*Math.max(1,Math.abs(L),Math.abs(U))&&Math.abs(N-k)<=P*Math.max(1,Math.abs(N),Math.abs(k))}var _V=function(){var B=f0();return function(J,V,I,L,N,R){var W,U;if(!V)V=4;if(!I)I=0;if(L)U=Math.min(L*V+I,J.length);else U=J.length;for(W=I;WP)B[0]=J[0]/I,B[1]=J[1]/I,B[2]=J[2]/I;else B[0]=1,B[1]=0,B[2]=0;return V}function d0(B,J){var V=uB(B,J);return Math.acos(2*V*V-1)}function zB(B,J,V){var I=J[0],L=J[1],N=J[2],R=J[3],W=V[0],U=V[1],k=V[2],Y=V[3];return B[0]=I*Y+R*W+L*k-N*U,B[1]=L*Y+R*U+N*W-I*k,B[2]=N*Y+R*k+I*U-L*W,B[3]=R*Y-I*W-L*U-N*k,B}function l0(B,J,V){V*=0.5;var I=J[0],L=J[1],N=J[2],R=J[3],W=Math.sin(V),U=Math.cos(V);return B[0]=I*U+R*W,B[1]=L*U+N*W,B[2]=N*U-L*W,B[3]=R*U-I*W,B}function s0(B,J,V){V*=0.5;var I=J[0],L=J[1],N=J[2],R=J[3],W=Math.sin(V),U=Math.cos(V);return B[0]=I*U-N*W,B[1]=L*U+R*W,B[2]=N*U+I*W,B[3]=R*U-L*W,B}function i0(B,J,V){V*=0.5;var I=J[0],L=J[1],N=J[2],R=J[3],W=Math.sin(V),U=Math.cos(V);return B[0]=I*U+L*W,B[1]=L*U-I*W,B[2]=N*U+R*W,B[3]=R*U-N*W,B}function y0(B,J){var V=J[0],I=J[1],L=J[2];return B[0]=V,B[1]=I,B[2]=L,B[3]=Math.sqrt(Math.abs(1-V*V-I*I-L*L)),B}function xB(B,J){var V=J[0],I=J[1],L=J[2],N=J[3],R=Math.sqrt(V*V+I*I+L*L),W=Math.exp(N),U=R>0?W*Math.sin(R)/R:0;return B[0]=V*U,B[1]=I*U,B[2]=L*U,B[3]=W*Math.cos(R),B}function mB(B,J){var V=J[0],I=J[1],L=J[2],N=J[3],R=Math.sqrt(V*V+I*I+L*L),W=R>0?Math.atan2(R,N)/R:0;return B[0]=V*W,B[1]=I*W,B[2]=L*W,B[3]=0.5*Math.log(V*V+I*I+L*L+N*N),B}function r0(B,J,V){return mB(B,J),bB(B,B,V),xB(B,B),B}function b(B,J,V,I){var L=J[0],N=J[1],R=J[2],W=J[3],U=V[0],k=V[1],Y=V[2],M=V[3],F,E,Q,S,X;if(E=L*U+N*k+R*Y+W*M,E<0)E=-E,U=-U,k=-k,Y=-Y,M=-M;if(1-E>P)F=Math.acos(E),Q=Math.sin(F),S=Math.sin((1-I)*F)/Q,X=Math.sin(I*F)/Q;else S=1-I,X=I;return B[0]=S*L+X*U,B[1]=S*N+X*k,B[2]=S*R+X*Y,B[3]=S*W+X*M,B}function z0(B){var J=n(),V=n(),I=n(),L=Math.sqrt(1-J),N=Math.sqrt(J);return B[0]=L*Math.sin(2*Math.PI*V),B[1]=L*Math.cos(2*Math.PI*V),B[2]=N*Math.sin(2*Math.PI*I),B[3]=N*Math.cos(2*Math.PI*I),B}function x0(B,J){var V=J[0],I=J[1],L=J[2],N=J[3],R=V*V+I*I+L*L+N*N,W=R?1/R:0;return B[0]=-V*W,B[1]=-I*W,B[2]=-L*W,B[3]=N*W,B}function m0(B,J){return B[0]=-J[0],B[1]=-J[1],B[2]=-J[2],B[3]=J[3],B}function eB(B,J){var V=J[0]+J[4]+J[8],I;if(V>0)I=Math.sqrt(V+1),B[3]=0.5*I,I=0.5/I,B[0]=(J[5]-J[7])*I,B[1]=(J[6]-J[2])*I,B[2]=(J[1]-J[3])*I;else{var L=0;if(J[4]>J[0])L=1;if(J[8]>J[L*3+L])L=2;var N=(L+1)%3,R=(L+2)%3;I=Math.sqrt(J[L*3+L]-J[N*3+N]-J[R*3+R]+1),B[L]=0.5*I,I=0.5/I,B[3]=(J[N*3+R]-J[R*3+N])*I,B[N]=(J[N*3+L]+J[L*3+N])*I,B[R]=(J[R*3+L]+J[L*3+R])*I}return B}function e0(B,J,V,I){var L=0.5*Math.PI/180;J*=L,V*=L,I*=L;var N=Math.sin(J),R=Math.cos(J),W=Math.sin(V),U=Math.cos(V),k=Math.sin(I),Y=Math.cos(I);return B[0]=N*U*Y-R*W*k,B[1]=R*W*Y+N*U*k,B[2]=R*U*k-N*W*Y,B[3]=R*U*Y+N*W*k,B}function b0(B){return"quat("+B[0]+", "+B[1]+", "+B[2]+", "+B[3]+")"}var u0=OB,o0=hB,a0=gB,t0=wB,BV=fB,JV=zB,bB=vB,uB=lB,VV=sB,oB=cB,IV=oB,aB=nB,LV=aB,RB=dB,NV=iB,RV=yB,WV=function(){var B=x(),J=m(1,0,0),V=m(0,1,0);return function(I,L,N){var R=e(L,N);if(R<-0.999999){if(z(B,J,L),LB(B)<0.000001)z(B,V,L);return IB(B,B),rB(I,B,Math.PI),I}else if(R>0.999999)return I[0]=0,I[1]=0,I[2]=0,I[3]=1,I;else return z(B,L,N),I[0]=B[0],I[1]=B[1],I[2]=B[2],I[3]=1+R,RB(I,I)}}(),UV=function(){var B=NB(),J=NB();return function(V,I,L,N,R,W){return b(B,I,R,W),b(J,L,N,W),b(V,B,J,2*W*(1-W)),V}}(),kV=function(){var B=QB();return function(J,V,I,L){return B[0]=I[0],B[3]=I[1],B[6]=I[2],B[1]=L[0],B[4]=L[1],B[7]=L[2],B[2]=-V[0],B[5]=-V[1],B[8]=-V[2],RB(J,eB(J,B))}}();class d{B;constructor(B){this.app=B;this.onStart&&B.onStart(this.onStart.bind(this)),this.onUpdate&&B.onUpdate(this.onUpdate.bind(this)),this.onAfterUpdate&&B.onAfterUpdate(this.onAfterUpdate.bind(this)),this.onBeforeUpdate&&B.onBeforeUpdate(this.onBeforeUpdate.bind(this)),this.onDraw&&B.onDraw(this.onDraw.bind(this))}}class c{B;J;V;constructor(B=s.create(),J=f.create(),V=s.fromValues(1,1,1)){this.position=B;this.rotation=J;this.scale=V}rotateEuler(B,J,V){return f.fromEuler(this.rotation,B,J,V),this}toMat4(){const B=g.create();return g.fromRotationTranslationScale(B,this.rotation,this.position,this.scale),B}}var u=(B)=>f.fromEuler(f.create(),B[0],B[1],B[2]),tB=(B)=>[B,B,B];class o extends d{B;J;V;I;L;N;projectionMatrix=g.create();buffers={textures:{}};faceDataType;colorDataType;constructor(B,J,V,I=new c([0,0,-6]),L=new c([100,100,0]),N={}){super(B);this.app=B;this.mesh=J;this.shader=V;this.camera=I;this.light=L;this.config=N;this.faceDataType=this.getDataType(J.config.faces),this.colorDataType=J.config.colors?this.getDataType(J.config.colors):null}getDataType(B){switch(B.BYTES_PER_ELEMENT){case 1:return 5121;case 2:return 5123;case 4:return 5125;default:return 5126}}configure(B){return this.config=B,this}makeBuffer(B,J=34962){const V=this.app.gl,I=V.createBuffer();if(!I)throw new Error("failed to create a buffer");return V.bindBuffer(J,I),V.bufferData(J,B,V.STATIC_DRAW),V.bindBuffer(J,null),I}initializeBuffers(){const B=this.app.gl.createVertexArray();if(!B)throw new Error("VAO creation failed");this.buffers.vao=B,this.app.gl.bindVertexArray(B),this.buffers.faces=this.makeBuffer(this.mesh.config.faces,this.app.gl.ELEMENT_ARRAY_BUFFER);const J=this.shader.mappings;if(this.buffers.position=this.makeBuffer(this.mesh.config.positions),this.bindAttrib(this.buffers.position,J.attributes.vertex,3,this.app.gl.FLOAT),this.mesh.config.normals)this.buffers.normal=this.makeBuffer(this.mesh.config.normals),this.bindAttrib(this.buffers.normal,J.attributes.normal,3,this.app.gl.FLOAT,!0);if(this.mesh.config.colors)this.buffers.color=this.makeBuffer(this.mesh.config.colors),this.bindAttrib(this.buffers.color,J.attributes.vertexColor,4,this.colorDataType||this.app.gl.UNSIGNED_BYTE);if(this.mesh.config.uvs)this.buffers.uv=this.makeBuffer(this.mesh.config.uvs),this.bindAttrib(this.buffers.uv,J.attributes.uv0,2,this.app.gl.FLOAT);this.app.gl.bindVertexArray(null)}async initializeTextures(){const{gl:B}=this.app;for(let[J,V]of Object.entries(this.shader.textures)){await V.loadImage();const I=B.createTexture();if(!I)throw new Error("failed to allocate texture");const L=V.texture;B.bindTexture(B.TEXTURE_2D,I),B.texImage2D(B.TEXTURE_2D,0,B.RGBA,V.width,V.height,0,B.RGBA,B.UNSIGNED_BYTE,L),B.texParameteri(B.TEXTURE_2D,B.TEXTURE_WRAP_S,B.REPEAT),B.texParameteri(B.TEXTURE_2D,B.TEXTURE_WRAP_T,B.REPEAT),B.texParameteri(B.TEXTURE_2D,B.TEXTURE_MAG_FILTER,B.NEAREST),B.texParameteri(B.TEXTURE_2D,B.TEXTURE_MIN_FILTER,B.NEAREST),this.buffers.textures[J]=I}}bindTextures(){const{gl:B}=this.app,J=this.app.gl.TEXTURE0,V=Object.entries(this.buffers.textures),I=[];return V.forEach(([L,N],R)=>{const W=this.shader.mappings.uniforms[L];if(!W)return console.warn("had no uniform to set for",{textures:V,key:L,tex:N,uniform:W,index:R}),!1;B.activeTexture(J+R),B.bindTexture(B.TEXTURE_2D,N),B.uniform1i(W,R),I.push(()=>{B.activeTexture(J+R),B.bindTexture(B.TEXTURE_2D,null)})}),I}bindAttrib(B,J,V,I,L=!1){const N=this.app.gl;N.bindBuffer(N.ARRAY_BUFFER,B);const R=Number.isSafeInteger(J)?J:this.shader.attrib(J);if(R!==-1)N.vertexAttribPointer(R,V,I,L,0,0),N.enableVertexAttribArray(R);N.bindBuffer(N.ARRAY_BUFFER,null)}initializeShader(B,J){const V=g.invert(g.create(),this.camera.toMat4()),I=this.app.gl,{uniforms:L}=this.shader.mappings;this.shader.use(),I.uniform1f(L.time,B),I.uniform4fv(L.light0Color,[1,1,1,1]),I.uniformMatrix4fv(L.view,!1,V),I.uniformMatrix4fv(L.projection,!1,this.projectionMatrix),I.uniform3fv(L.light0,this.light.position),I.uniformMatrix4fv(L.objectToWorld,!1,J.toMat4()),I.uniformMatrix4fv(L.objectToWorldInv,!1,g.invert(g.create(),J.toMat4()))}async onStart(B,J){J.loading("baking vectors"),J.telemetry?.addRenderers(1),J.telemetry?.addTriangles(this.mesh.config.faces.length),J.telemetry?.addVertexes(this.mesh.config.vertexCount),g.perspective(this.projectionMatrix,this.app.config.fov||45,this.app.aspect,this.app.config.zNear||0.1,this.app.config.zFar||100),this.shader.compile(),this.shader.link(),this.initializeBuffers(),this.shader.link(),await this.initializeTextures()}onRenderableUpdate(B,J){const V=this.app.gl;V.bindVertexArray(this.buffers.vao||null),V.bindBuffer(V.ELEMENT_ARRAY_BUFFER,this.buffers.faces||null),V.bindBuffer(V.ARRAY_BUFFER,this.buffers.position||null),this.initializeShader(B,J);const I=this.bindTextures();V.drawElements(this.config.drawMode??V.TRIANGLES,this.mesh.config.faces.length,this.faceDataType,0);const L=V.getError();if(L!==0)throw console.log({err:L}),new Error(`(MeshRenderer) webgl failure: ${L}`);V.bindVertexArray(null),V.bindBuffer(V.ELEMENT_ARRAY_BUFFER,null),V.bindBuffer(V.ARRAY_BUFFER,null),I.forEach((N)=>N())}}class WB extends d{B;el;frameTimes=[];maxFrameTimes=100;lastFrameTime=0;activeTriangles=0;activeVertexes=0;activeRenderers=0;activeTextures=0;constructor(B,J="#telemetry"){super(B);this.app=B;if(this.el=document.querySelector(J),this.el&&location.search.includes("telemetry"))this.el.style.display="block"}insertTime(B){if(this.frameTimes.push(B),this.frameTimes.length>this.maxFrameTimes)this.frameTimes.shift()}async onStart(){this.lastFrameTime=0,this.frameTimes=[],setTimeout(()=>this.setText(),0),setInterval(()=>{this.setText()},1001)}setText(){const B=this.frameTimes.reduce((V,I)=>V+I,0)/this.frameTimes.length,J=1000/B;this.el.innerHTML=`${J.toFixed(1)} FPS (${B.toFixed(3)} ms)
update :: b: ${this.app.registry.onBeforeUpdate.length} | u: ${this.app.registry.onUpdate.length} | a: ${this.app.registry.onAfterUpdate.length} | d: ${this.app.registry.onDraw.length}
render :: mr: ${this.activeRenderers} | v: ${this.activeVertexes} | t: ${this.activeTriangles}
others :: tex: ${this.activeTextures}`}onAfterUpdate(B){const J=B-this.lastFrameTime;this.insertTime(J),this.lastFrameTime=B}addTriangles(B){this.activeTriangles+=B}addVertexes(B){this.activeVertexes+=B}addRenderers(B){this.activeRenderers+=B}addTextures(B){this.activeTextures+=B}}class UB{B;canvas;telemetry;gl;loadingMessages=new Set(["[noeidelon] [stage 2]"]);registry={onBeforeUpdate:[],onAfterUpdate:[],onUpdate:[],onStart:[],onDraw:[]};constructor(B={}){this.config=B;try{this.canvas=document.querySelector("canvas"),this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight;const J=this.canvas.getContext("webgl2");if(!J)throw new Error("Canvas was unable to get a webgl2 context");const V=this.gl=J;if(V.viewport(0,0,V.drawingBufferWidth,V.drawingBufferHeight),this.gl.getExtension("EXT_texture_filter_anisotropic"),location.search.includes("telemetry"))this.telemetry=new WB(this)}catch(J){const V=document.querySelector("main");if(V)V.innerHTML="your browser didn't let me set up webgl.
";throw new Error(`Unable to initialize WebGL. Your browser or machine may not support it.\n -> ${J}`)}}get aspect(){return this.canvas.clientWidth/this.canvas.clientHeight}clear(){const B=this.gl;B.clearColor(0,0,0,1),B.clearDepth(1),B.enable(B.DEPTH_TEST),B.depthFunc(B.LEQUAL),B.clear(B.COLOR_BUFFER_BIT|B.DEPTH_BUFFER_BIT)}loading(B){this.loadingMessages.add(B.toLowerCase()),document.querySelector("#loading-text").innerHTML=[...this.loadingMessages].join("
")}ready(){document.querySelector("#loading")?.classList.remove("loading-active")}onBeforeUpdate(B){this.registry.onBeforeUpdate.push(B)}onAfterUpdate(B){this.registry.onAfterUpdate.push(B)}onUpdate(B){this.registry.onUpdate.push(B)}onStart(B){this.registry.onStart.push(B)}onDraw(B){this.registry.onDraw.push(B)}doUpdate(B){this.registry.onBeforeUpdate.forEach((J)=>J(B,this)),this.registry.onUpdate.forEach((J)=>J(B,this)),this.registry.onAfterUpdate.forEach((J)=>J(B,this)),this.registry.onDraw.forEach((J)=>J(B,this))}async doStart(B=0){this.loading("setting launch parameters"),this.clear();try{for(let J of this.registry.onStart)await J(B,this)}catch(J){if(this.loading('[panic] failed to start noeidelon'),this.telemetry)this.loading(`${J}`);return}this.ready()}async oneShot(B=0){await this.doStart(B),this.doUpdate(B)}async start(){await this.doStart();const B=(J)=>{this.doUpdate(J),requestAnimationFrame(B)};requestAnimationFrame(B)}}class a extends d{B;J;V;constructor(B,J,V){super(B);this.app=B;this.transform=J;this.renderer=V}onDraw(B){this.renderer.onRenderableUpdate(B,this.transform)}}class kB{B;constructor(B){this.config=B}get name(){return this.config.name}}var t=new kB({colors:null,faces:new Uint8Array([0,1,2,1,0,3,0,2,4,0,4,5,0,5,3,1,3,6,2,1,7,4,2,8,9,10,11,12,9,13,1,6,7,2,7,8,10,8,11,9,11,13,12,13,6,7,6,14,8,7,14,11,8,14,13,11,14,6,13,14,15,16,17,17,16,18,19,20,21,18,16,22,22,16,15,23,24,25]),name:"src/meshes/trianglething/trianglething.ply",normals:new Float32Array([0,-1,0.00000083803394,-0.5257306,-0.44721383,0.723607,-0.8506533,-0.44721213,-0.2763879,0.5257306,-0.4472139,0.723607,0,-0.44721153,-0.89442825,0.8506533,-0.4472122,-0.27638793,0,0.44721153,0.89442825,-0.8506533,0.44721216,0.27638793,-0.5257306,0.4472139,-0.72360694,0.8506533,-0.4472122,-0.27638793,0,-0.44721153,-0.89442825,0.5257306,0.4472139,-0.72360694,0.5257306,-0.4472139,0.723607,0.85065323,0.4472122,0.2763879,0,1,-0.0000008165459,0.8999471,-0.43599886,0.00000024163015,-0.00000005150958,1,0,-0.000000030203772,-0.4359989,0.8999472,-0.8999471,-0.4359989,-0.00000024291313,-0.000000030203772,-0.4359989,0.8999472,0,-0.43599886,-0.8999471,0.8999471,-0.43599886,0.00000024163015,0,-0.43599886,-0.8999471,-0.000000030203772,-0.4359989,0.8999472,-0.8999471,-0.4359989,-0.00000024291313,0,-0.43599886,-0.8999471]),positions:new Float32Array([0,2.6090002,0,-0.36800402,2.9959497,0.50652003,-0.5954481,2.9959497,-0.19346952,0.36800402,2.9959497,0.50652003,0,2.9959497,-0.62609756,0.5954481,2.9959497,-0.19346952,0,3.6220508,0.62609756,-0.5954481,3.6220508,0.19346952,-0.36800402,3.6220508,-0.50652003,0.5954481,2.9959497,-0.19346952,0,2.9959497,-0.62609756,0.36800402,3.6220508,-0.50652003,0.36800402,2.9959497,0.50652003,0.5954481,3.6220508,0.19346952,0,4.0090003,0,1.0000001,0,0,0,2.5000002,0,-0.000000043711395,0,1.0000001,-1.0000001,0,-0.00000008742279,-0.000000043711395,0,1.0000001,0.000000011924882,0,-1.0000001,1.0000001,0,0,0.000000011924882,0,-1.0000001,-0.000000043711395,0,1.0000001,-1.0000001,0,-0.00000008742279,0.000000011924882,0,-1.0000001]),uvs:new Float32Array([0.7660872,0.5526656,0.6449925,0.52286637,0.8418907,0.33128682,0.60803074,0.79587877,0.96344936,0.40123126,0.8416727,0.64077806,0.50600564,0.49428308,0.704352,0.31297976,0.79145527,0.046412975,0.35179207,0.26814616,0.47356877,0.028599411,0.5382167,0.15491244,0.118150145,0.42324704,0.40614995,0.39580685,0.5992601,0.26365823,0.4984935,0.5027367,0.24900003,0.7522302,-0.00049349666,0.50273675,-0.00049346685,1.0017238,0.7633698,0.99398905,0.99752307,0.7598357,0.9975231,0.99398893,0.49849355,1.0017238,0.99646366,0.7612665,0.99646366,0.9954198,0.7623104,0.9954198]),vertexCount:26});var YB="../texture0-577d5216cdab32bc.png";var XB="../texture1-e472a46c91711e86.png";class l{B;static VERTEX=35633;static FRAGMENT=35632;constructor(B){this.config=B}vertexCode="";fragmentCode="";_app;program=null;mappings={};textures={};get gl(){const B=this._app?.gl;if(!B)throw new Error("GL context not defined at shader compile time.");return B}app(B){return this._app=B,this.program=B.gl.createProgram(),this}vertex(B){return this.vertexCode=B,this}fragment(B){return this.fragmentCode=B,this}attrib(B){return this.gl.getAttribLocation(this.program,B)}uniform(B){return this.gl.getUniformLocation(this.program,B)}generateMappings(B){return{attributes:{normal:this.attrib(B.attributes.normal),uv0:this.attrib(B.attributes.uv0),vertex:this.attrib(B.attributes.vertex),vertexColor:this.attrib(B.attributes.vertexColor)},uniforms:{albedo:this.uniform(B.uniforms.albedo),light0:this.uniform(B.uniforms.light0),light0Color:this.uniform(B.uniforms.light0Color),objectToWorld:this.uniform(B.uniforms.objectToWorld),objectToWorldInv:this.uniform(B.uniforms.objectToWorldInv),projection:this.uniform(B.uniforms.projection),texture0:this.uniform(B.uniforms.texture0),texture1:this.uniform(B.uniforms.texture1),time:this.uniform(B.uniforms.time),view:this.uniform(B.uniforms.view)}}}attach(B,J){const V=this.gl,I=V.createShader(B);if(!I)throw new Error(`failed to init ${MV(B)} shader`);V.shaderSource(I,J),V.compileShader(I),V.attachShader(this.program,I)}addTexture(B,J){return this.textures[B]=J,this}compile(){const B=this.gl;this.attach(B.FRAGMENT_SHADER,this.fragmentCode),this.attach(B.VERTEX_SHADER,this.vertexCode)}link(){if(this.gl.linkProgram(this.program),!this.gl.getProgramParameter(this.program,this.gl.LINK_STATUS))throw new Error("Unable to initialize the shader program: "+this.gl.getProgramInfoLog(this.program));this.mappings=this.generateMappings(this.config)}bindAttrib(B,J){this.gl.bindAttribLocation(this.program,B,J)}use(){this._app?.gl.useProgram(this.program)}}var MV=(B)=>{switch(B){case l.FRAGMENT:return"fragment";case l.VERTEX:return"vertex";default:return"some unknown type of"}};var BB=`#version 300 es
-precision highp float;uniform sampler2D u_texture_0;uniform sampler2D u_texture_1;in vec2 uv0;in vec3 normal;in vec3 light_pos;out vec4 fragColor;void main(){vec4 normalTex=texture(u_texture_1,uv0);vec3 normal=normalize(normal*normalTex.xyz);float light=dot(normal,light_pos);fragColor=vec4(1.0);fragColor.rgb=texture(u_texture_0,uv0).rgb;fragColor.rgb*=max(light,0.1);fragColor.a=1.0;}`;var BJ=`#version 300 es
-uniform mat4 u_view;uniform mat4 u_projection;uniform mat4 u_object_to_world;uniform mat4 u_object_to_world_inv;uniform vec3 u_light_0;in vec4 a_vertex;in vec2 a_uv0;in vec3 a_normal;in vec4 a_vertex_color;out vec2 uv0;out vec3 normal;out vec4 vertex_color;out vec3 light_pos;void main(){mat4 worldInv=inverse(u_view);mat4 MVW=u_projection*u_view*u_object_to_world;gl_Position=MVW*a_vertex;uv0=a_uv0;normal=normalize(mat3(worldInv)*a_normal);vertex_color=a_vertex_color;light_pos=normalize(mat3(u_object_to_world_inv)*u_light_0);}`;var SV={attributes:{vertex:"a_vertex",uv0:"a_uv0",normal:"a_normal",vertexColor:"a_vertex_color"},uniforms:{view:"u_view",projection:"u_projection",objectToWorld:"u_object_to_world",objectToWorldInv:"u_object_to_world_inv",light0:"u_light_0",light0Color:"u_light_0_color",time:"u_time",albedo:"u_albedo",texture0:"u_texture_0",texture1:"u_texture_1"}},JJ=(B)=>new l(SV).vertex(BJ).fragment(BB).app(B);class JB{B;J;texture=null;width=0;height=0;constructor(B,J){this.app=B;this.url=J}setImage(B,J,V){return this.texture=B,this.width=J,this.height=V,this}async loadImage(){if(this.url==="manual"){if(this.texture===null)throw new Error("manual specified, but texture was not ready...");return}if(this.texture!==null)return;this.app.telemetry?.addTextures(-1),this.app.loading("Fetching textures...");const B=new Image;return new Promise((J,V)=>{B.onload=async()=>{this.texture=await createImageBitmap(B,{imageOrientation:"flipY"}),this.width=this.texture.width,this.height=this.texture.height,this.app.telemetry?.addTextures(2),J(void 0)},B.onerror=(I)=>{this.app.telemetry?.addTextures(1),V(new Error(`texture load of ${this.url} failed: ${I.toString()}`))},B.src=this.url})}}var VJ=`#version 300 es
-uniform mat4 u_view;uniform mat4 u_projection;uniform mat4 u_object_to_world;uniform mat4 u_object_to_world_inv;uniform vec3 u_light_0;in vec4 a_vertex;in vec2 a_uv0;in vec3 a_normal;in vec4 a_vertex_color;out vec2 uv0;out vec3 normal;out vec4 vertex_color;out vec3 light_pos;
-#define ROUNDING_FACTOR 230.0f
-void main(){mat4 worldInv=inverse(u_view);mat4 MVW=u_projection*u_view*u_object_to_world;vec4 realPosition=MVW*a_vertex;realPosition.xyz=round(vec3(realPosition.xyz*ROUNDING_FACTOR))/ROUNDING_FACTOR;gl_Position=realPosition;uv0=a_uv0;normal=normalize(mat3(worldInv)*a_normal);vertex_color=a_vertex_color;light_pos=normalize(mat3(u_object_to_world_inv)*u_light_0);}`;var KV={attributes:{vertex:"a_vertex",uv0:"a_uv0",normal:"a_normal",vertexColor:"a_vertex_color"},uniforms:{view:"u_view",projection:"u_projection",objectToWorld:"u_object_to_world",objectToWorldInv:"u_object_to_world_inv",light0:"u_light_0",light0Color:"u_light_0_color",time:"u_time",albedo:"u_albedo",texture0:"u_texture_0",texture1:"u_texture_1"}},IJ=(B)=>new l(KV).vertex(VJ).fragment(BB).app(B);var v=new UB({fov:45}),LJ=new c([2,3,3],u([-15,40,0])),NJ=new c([1,1,0]),MB=new c(tB(0),u([0,0,0])),EB=new c([-3,0,1],u([0,0,0])),RJ=new JB(v,YB),WJ=new JB(v,XB);v.onUpdate(()=>{f.rotateY(MB.rotation,MB.rotation,0.001),f.rotateY(EB.rotation,EB.rotation,0.001)});new a(v,MB,new o(v,t,IJ(v).addTexture("texture0",RJ).addTexture("texture1",WJ),LJ,NJ).configure({}));new a(v,EB,new o(v,t,JJ(v).addTexture("texture0",RJ).addTexture("texture1",WJ),LJ,NJ).configure({}));v.start();
+import{a as I,b as J,c,d as S,e as R,f as Y,g as p,h as q,i as f,j as k,k as w,l as N,m as U} from"../chunk-2ef356c72587f126.js";var s=new k({colors:null,faces:new Uint8Array([0,1,2,1,0,3,0,2,4,0,4,5,0,5,3,1,3,6,2,1,7,4,2,8,9,10,11,12,9,13,1,6,7,2,7,8,10,8,11,9,11,13,12,13,6,7,6,14,8,7,14,11,8,14,13,11,14,6,13,14,15,16,17,17,16,18,19,20,21,18,16,22,22,16,15,23,24,25]),name:"src/meshes/trianglething/trianglething.ply",normals:new Float32Array([0,-1,0.00000083803394,-0.5257306,-0.44721383,0.723607,-0.8506533,-0.44721213,-0.2763879,0.5257306,-0.4472139,0.723607,0,-0.44721153,-0.89442825,0.8506533,-0.4472122,-0.27638793,0,0.44721153,0.89442825,-0.8506533,0.44721216,0.27638793,-0.5257306,0.4472139,-0.72360694,0.8506533,-0.4472122,-0.27638793,0,-0.44721153,-0.89442825,0.5257306,0.4472139,-0.72360694,0.5257306,-0.4472139,0.723607,0.85065323,0.4472122,0.2763879,0,1,-0.0000008165459,0.8999471,-0.43599886,0.00000024163015,-0.00000005150958,1,0,-0.000000030203772,-0.4359989,0.8999472,-0.8999471,-0.4359989,-0.00000024291313,-0.000000030203772,-0.4359989,0.8999472,0,-0.43599886,-0.8999471,0.8999471,-0.43599886,0.00000024163015,0,-0.43599886,-0.8999471,-0.000000030203772,-0.4359989,0.8999472,-0.8999471,-0.4359989,-0.00000024291313,0,-0.43599886,-0.8999471]),positions:new Float32Array([0,2.6090002,0,-0.36800402,2.9959497,0.50652003,-0.5954481,2.9959497,-0.19346952,0.36800402,2.9959497,0.50652003,0,2.9959497,-0.62609756,0.5954481,2.9959497,-0.19346952,0,3.6220508,0.62609756,-0.5954481,3.6220508,0.19346952,-0.36800402,3.6220508,-0.50652003,0.5954481,2.9959497,-0.19346952,0,2.9959497,-0.62609756,0.36800402,3.6220508,-0.50652003,0.36800402,2.9959497,0.50652003,0.5954481,3.6220508,0.19346952,0,4.0090003,0,1.0000001,0,0,0,2.5000002,0,-0.000000043711395,0,1.0000001,-1.0000001,0,-0.00000008742279,-0.000000043711395,0,1.0000001,0.000000011924882,0,-1.0000001,1.0000001,0,0,0.000000011924882,0,-1.0000001,-0.000000043711395,0,1.0000001,-1.0000001,0,-0.00000008742279,0.000000011924882,0,-1.0000001]),uvs:new Float32Array([0.7660872,0.5526656,0.6449925,0.52286637,0.8418907,0.33128682,0.60803074,0.79587877,0.96344936,0.40123126,0.8416727,0.64077806,0.50600564,0.49428308,0.704352,0.31297976,0.79145527,0.046412975,0.35179207,0.26814616,0.47356877,0.028599411,0.5382167,0.15491244,0.118150145,0.42324704,0.40614995,0.39580685,0.5992601,0.26365823,0.4984935,0.5027367,0.24900003,0.7522302,-0.00049349666,0.50273675,-0.00049346685,1.0017238,0.7633698,0.99398905,0.99752307,0.7598357,0.9975231,0.99398893,0.49849355,1.0017238,0.99646366,0.7612665,0.99646366,0.9954198,0.7623104,0.9954198]),vertexCount:26});var V="../texture0-577d5216cdab32bc.png";var g="../texture1-e472a46c91711e86.png";var Q={attributes:{vertex:"a_vertex",uv0:"a_uv0",normal:"a_normal",vertexColor:"a_vertex_color"},uniforms:{view:"u_view",projection:"u_projection",objectToWorld:"u_object_to_world",objectToWorldInv:"u_object_to_world_inv",light0:"u_light_0",light0Color:"u_light_0_color",time:"u_time",albedo:"u_albedo",texture0:"u_texture_0",texture1:"u_texture_1",texture2:"u_texture_2"}},W=(b)=>new p(Q).vertex(U).fragment(q).app(b);var B=new Y({fov:45}),X=new J([2,3,3],c([-15,40,0])),l=new J([2,2,0]),a=new J(S(0),c([0,0,0])),L=new J([-3,0,1],c([0,0,0])),F=new N(B,V),y=new N(B,g);B.onUpdate(()=>{I.rotateY(a.rotation,a.rotation,0.001),I.rotateY(L.rotation,L.rotation,0.001)});new w(B,a,new R(B,s,W(B).addTexture("texture0",F).addTexture("texture1",y),X,l).configure({}));new w(B,L,new R(B,s,f(B).addTexture("texture0",F).addTexture("texture1",y),X,l).configure({}));B.start();
diff --git a/html/004-a-new-leaf/index.html b/html/004-a-new-leaf/index.html
new file mode 100644
index 0000000..696255c
--- /dev/null
+++ b/html/004-a-new-leaf/index.html
@@ -0,0 +1,29 @@
+
+
+com.mekanoe.art // 004-a-new-leaf
+
+
+
+
+ XX.X FPS (XX.X ms)
+ [noeidelon] [stage 1]
bootstrapping...
this is taking a while...
[panic] heck wtf
+
+
+
+
diff --git a/html/004-a-new-leaf/main.js b/html/004-a-new-leaf/main.js
new file mode 100644
index 0000000..2cf4b20
--- /dev/null
+++ b/html/004-a-new-leaf/main.js
@@ -0,0 +1,2 @@
+import{b as c,c as Y,d as $,e as E,f as a,g,j as i,k as Q,l as q,m as C} from"../chunk-2ef356c72587f126.js";var B=`#version 300 es
+precision highp float;uniform vec4 u_light_0_color;uniform vec4 u_albedo;uniform sampler2D u_texture_0;uniform sampler2D u_texture_1;uniform sampler2D u_texture_2;in vec2 uv0;in vec3 normal;in vec3 light_pos;out vec4 fragColor;void main(){vec3 normal=normalize(normal);float light=clamp(dot(normal,light_pos),0.0,1.0);vec3 ramp=texture(u_texture_2,vec2(light,0.0)).rgb;fragColor=vec4(1.0);fragColor.rgb=texture(u_texture_0,uv0).rgb;fragColor.rgb*=ramp;fragColor.a=1.0;}`;var V={attributes:{vertex:"a_vertex",uv0:"a_uv0",normal:"a_normal",vertexColor:"a_vertex_color"},uniforms:{view:"u_view",projection:"u_projection",objectToWorld:"u_object_to_world",objectToWorldInv:"u_object_to_world_inv",light0:"u_light_0",light0Color:"u_light_0_color",time:"u_time",albedo:"u_albedo",texture0:"u_texture_0",texture1:"u_texture_1",texture2:"u_texture_2"}},s=(R,y=[0.1,0.1,0.1,1])=>new g(V).vertex(C).fragment(B).app(R).prerenderHook(({gl:A},H)=>{A.uniform4fv(H.mappings.uniforms.albedo,y)});var J=new i({colors:null,faces:new Uint8Array([0,1,2,3,4,0,0,5,3,0,4,1,3,6,4,0,7,5]),name:"src/meshes/cube-backdrop/cube-backdrop.ply",normals:new Float32Array([0.5773503,0.5773503,0.5773503,1,0,0,0.70710677,0.70710677,0,0,0.70710677,0.70710677,0.70710677,0,0.70710677,0,1,0,0,0,1,0.70710677,0.70710677,0]),positions:new Float32Array([-0.10000001,-0.0025735903,-0.10000001,-0.10000001,0.19742644,0.10000001,-0.10000001,-0.0025735903,0.10000001,0.10000001,-0.0025735903,-0.10000001,-0.10000001,0.19742644,-0.10000001,0.10000001,-0.0025735903,0.10000001,0.10000001,0.19742644,-0.10000001,-0.10000001,-0.0025735903,0.10000001]),uvs:new Float32Array([0.5,0.5,-0.000000059604645,1,0,0.49999997,1,0.50000006,0.49999997,1,1,0,1,1,0.50000006,0]),vertexCount:8});var D=new c($(0),Y([0,-45,0]),$(20));var x=(R,y,A,H=255)=>[R/255,y/255,A/255,H/255];var d="../ramp-aa773f5148819e95.png";var X=new i({colors:null,faces:new Uint16Array([0,1,2,0,3,4,2,3,0,5,3,2,6,7,8,8,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,1,23,24,25,26,27,28,29,30,31,27,32,18,17,33,34,35,36,37,38,39,40,13,41,42,43,44,45,46,47,15,14,48,18,32,49,26,50,33,35,51,52,53,54,54,47,14,55,48,56,11,10,57,13,58,59,40,14,13,53,47,54,60,61,62,44,63,64,6,60,65,65,7,6,66,67,54,60,68,61,38,37,69,26,49,70,67,10,12,55,71,48,72,22,23,9,68,8,68,60,6,73,17,74,75,10,67,76,26,77,1,26,76,78,47,79,0,80,81,82,50,83,84,85,86,39,13,59,87,27,29,87,20,88,29,21,87,20,89,88,90,17,16,29,72,91,40,84,86,58,92,59,21,11,19,73,87,88,27,31,2,31,5,2,52,49,53,61,68,9,93,48,94,88,93,94,51,35,95,37,96,69,33,51,41,77,52,54,67,12,77,26,1,0,76,77,12,97,49,82,46,98,99,79,53,97,23,76,72,25,50,26,0,24,26,100,37,36,52,70,49,36,101,102,64,45,44,86,66,40,11,21,91,12,72,76,82,49,50,72,11,91,75,103,89,19,89,20,32,88,94,87,21,20,79,47,53,2,1,22,22,72,29,22,29,28,27,2,28,51,95,42,50,25,83,26,70,77,0,81,24,91,21,29,23,1,76,53,49,97,77,54,67,104,105,106,52,77,70,101,36,38,4,80,0,66,54,14,62,107,60,44,46,108,41,51,42,86,109,66,57,10,75,71,16,18,55,16,71,35,110,95,32,17,73,111,3,5,40,39,84,112,75,67,72,12,11,75,89,19,75,19,57,88,89,93,74,27,73,94,48,32,19,11,57,71,18,48,40,66,14,73,88,32,113,62,61,22,28,2,35,114,110,73,27,87,115,93,89,115,89,103,116,117,118,119,120,121,122,30,74,123,124,122,125,126,127,128,129,130,131,132,133,4,132,134,135,121,136,137,112,86,138,128,139,140,141,142,143,144,145,146,147,148,122,124,30,123,136,121,56,48,93,58,13,15,121,141,140,123,121,124,30,27,74,149,150,151,152,122,74,145,153,154,120,141,121,100,36,102,155,156,153,157,151,118,152,74,17,121,135,119,144,119,145,119,144,120,158,159,160,4,159,132,100,161,162,163,98,164,138,98,45,15,165,149,166,34,33,154,153,167,153,145,155,93,115,56,154,167,164,116,168,117,150,168,116,92,157,118,136,123,169,109,112,67,3,111,160,170,171,127,132,131,34,165,150,149,148,147,172,115,85,173,158,139,159,159,4,160,149,151,157,126,125,148,45,174,129,128,133,159,156,163,167,92,58,157,175,5,142,140,31,124,144,141,120,86,85,137,8,68,6,45,98,46,34,176,35,64,176,174,176,34,177,64,174,45,64,63,176,132,34,166,162,96,100,58,149,157,125,127,171,178,179,180,181,125,171,147,182,172,126,148,172,129,128,138,130,133,128,179,178,183,177,34,131,132,166,134,159,139,128,159,133,132,160,111,175,154,143,145,137,85,115,138,45,129,35,176,114,100,102,161,100,96,37,139,98,138,164,98,158,99,98,184,98,163,184,165,47,78,160,4,3,17,90,152,167,153,156,75,112,103,142,144,143,113,107,62,151,150,116,124,31,30,142,5,140,5,31,140,125,146,148,176,63,114,139,158,98,5,175,111,164,158,160,143,164,160,15,149,58,118,151,116,112,137,103,163,164,167,175,142,143,164,143,154,175,143,160,142,141,144,121,140,124,103,137,115,80,4,134,67,66,109,109,86,112,47,165,15,181,171,170,185,186,187,188,189,190,191,192,193,191,194,192,195,196,197,198,199,200,201,199,198,202,203,204,205,201,206,207,201,205,208,185,209,210,185,208,211,185,210,212,185,211,194,189,213,194,190,189,214,215,216,192,212,217,218,219,220,221,219,218,213,192,194,198,206,201,187,209,185,217,193,192,193,222,191,193,223,222,193,224,223,193,225,224,193,226,225,193,203,226,193,204,203,218,227,221,218,199,227,218,200,199,204,215,202,204,216,215,216,219,214,216,220,219,211,217,212,228,229,85,228,85,84,230,231,84,230,84,39,232,230,39,232,39,59,233,234,90,233,90,16,235,236,55,235,55,56,237,238,173,239,240,16,239,16,55,241,232,59,241,59,92,242,241,92,231,228,84,240,233,16,243,244,122,243,122,152,245,246,119,245,119,135,247,248,136,247,136,169,246,249,119,250,251,168,234,252,152,234,152,90,244,253,122,254,255,118,253,256,123,253,123,122,257,258,145,256,259,169,256,169,123,260,261,262,248,135,136,263,237,173,263,173,85,238,264,115,238,115,173,265,254,118,265,118,117,264,235,56,264,56,115,255,242,92,255,92,118,258,266,155,258,155,145,252,243,152,259,247,169,249,257,145,249,145,119,251,265,117,251,117,168,267,268,269,270,271,272,273,274,275,276,277,278,236,239,55,229,263,85,279,280,281,282,283,284]),name:"src/meshes/fox/fox.ply",normals:new Float32Array([0.3475203,-0.1423119,-0.92681,0.5162422,0.12797521,-0.8468272,0.15832935,0.05530619,-0.98583627,-0.34248725,0.027904412,-0.9391081,-0.5169309,-0.31768712,-0.7948945,-0.48697895,-0.1626665,-0.85813236,0.979832,0.13666466,-0.14578043,0.9031805,0.21487509,-0.37160963,0.66321534,0.26724067,-0.6990907,0.6848186,0.23503296,-0.68977004,0.50283414,0.37262148,-0.779943,0.23640795,0.47815725,-0.84585875,0.3647613,0.40136182,-0.8401535,0.3046436,0.23757984,0.92236,0.31008115,0.576068,0.7563038,-0.22806334,0.32389933,0.91819185,0.17951295,-0.316014,-0.931617,-0.17395478,-0.060770363,-0.9828767,0.3371145,-0.028111659,-0.94104385,0.5286752,0.36182427,-0.76784486,0.37282482,0.34924614,-0.8596678,0.04436654,0.3120137,-0.9490411,0.1748497,-0.08175629,-0.981195,0.4760932,0.18387188,-0.8599573,0.77194935,-0.10489054,-0.6269707,0.8878576,0.018637033,-0.45974046,0.8233882,0.00536109,-0.5674533,0.50706327,0.2949509,-0.8098708,0.5776023,0.024086185,-0.8159629,0.20082258,0.4428197,-0.8738313,-0.3673268,-0.008583662,-0.9300523,-0.23037066,-0.14419852,-0.9623597,0.10130113,0.55220604,-0.82753044,-0.30028316,0.6138469,-0.7300836,-0.42857707,0.59847176,-0.67687017,0.2310956,0.77802414,-0.5841861,0.40507296,-0.59645694,-0.69293207,0.018303465,0.44150117,-0.8970739,0.77194935,-0.10489054,-0.6269707,0.6770759,-0.15234865,0.71997094,0.5551748,0.09818922,0.82591754,0.5862696,0.275684,-0.7617652,0.8878576,0.018637033,-0.45974046,0.77194935,-0.10489054,-0.6269707,0.3452935,0.52275664,0.7794215,-0.037781123,0.40868607,0.9118927,0.47639555,0.22756127,0.8492721,0.038687505,0.4890638,0.87138975,0.4779266,0.31795877,-0.8188335,0.9412043,0.3062575,0.14262189,0.985557,-0.050912835,-0.16150954,0.41709664,0.43660966,-0.79712135,0.65320575,0.7567542,-0.025403246,0.5102622,0.5121896,0.6908649,0.5327677,0.8339708,0.14370571,0.50982845,-0.2752561,-0.81505156,0.9362124,0.034893714,-0.34969804,0.49277383,0.474742,-0.729242,-0.10767815,0.15382154,0.98221403,0.53157943,-0.18795584,0.825891,0.3452935,0.52275664,0.7794215,0.73606163,0.6634644,-0.13426952,-0.17794462,0.9747583,-0.13484038,-0.38528097,0.9081675,0.1636775,0.03706524,0.8542405,0.51855505,0.90783143,0.11600388,0.40297043,0.8010637,0.5264299,0.2849009,0.6885465,0.57700217,-0.43928608,0.95855004,0.10577212,0.26456407,0.5862696,0.275684,-0.7617652,0.78829354,0.5408408,-0.2934015,0.21502984,0.04666299,-0.97549206,0.102968186,0.09595936,-0.9900452,-0.42321405,0.5065525,-0.7511954,-0.69715625,-0.08602459,-0.71173936,0.82457936,0.081235796,-0.5598835,0.4377959,0.26956058,-0.85771316,0.6155783,0.5745703,-0.5393813,0.07019434,0.24138543,0.9678872,0.3541473,0.25355586,0.9001605,-0.29064578,-0.724498,-0.62500215,0.375913,-0.73612595,-0.56285685,0.90783143,0.11600388,0.40297043,0.9031805,0.21487509,-0.37160963,0.5472127,-0.29103354,0.7847661,0.87695193,-0.2072897,0.4335738,0.8803676,0.14394727,0.45192042,0.15257555,0.7520019,-0.64125955,0.073696144,0.91218823,-0.40308988,0.48116767,0.69189876,-0.5382877,-0.38885155,-0.2292497,-0.8923223,-0.08802483,0.3184032,-0.94385976,-0.16566989,-0.31949857,0.9329921,0.4088575,0.88988423,-0.20234066,0.23401263,0.7841241,-0.5747935,0.9031805,0.21487509,-0.37160963,-0.30028316,0.6138469,-0.7300836,0.47639555,0.22756127,0.8492721,-0.13893181,0.08481444,0.98666334,0.3541473,0.25355586,0.9001605,-0.6594078,-0.34964943,-0.6655273,0.375913,-0.73612595,-0.56285685,-0.29064578,-0.724498,-0.62500215,0.7611686,0.58185023,-0.28648314,-0.04397583,0.70420456,-0.7086339,0.73606163,0.6634644,-0.13426952,0.6848186,0.23503296,-0.68977004,-0.38528097,0.9081675,0.1636775,0.90783143,0.11600388,0.40297043,0.9180944,0.3928391,0.052727237,0.6848186,0.23503296,-0.68977004,-0.75246775,0.008946161,-0.6585683,0.93610126,0.23180684,-0.26453748,-0.04397583,0.70420456,-0.7086339,-0.04397583,0.70420456,-0.7086339,0.92324126,0.38289523,0.03188642,-0.8208653,0.15153797,0.55065095,-0.6847748,0.31241915,0.6583902,-0.44955286,-0.170653,0.87680095,-0.69434595,0.69967836,-0.16832665,-0.64949834,0.59640735,-0.47164628,-0.72120667,0.6666094,-0.18839571,-0.44213012,-0.017088598,-0.8967881,-0.16689667,0.37004504,-0.9138995,-0.32365012,-0.16409263,-0.93183917,-0.81858766,0.5451293,-0.18096499,-0.992983,0.08945896,0.07734239,-0.21252948,0.5347677,0.81783545,-0.7021046,-0.14130145,0.6979133,-0.992983,0.08945896,0.07734239,-0.9546164,0.028929858,-0.2964296,-0.7311533,0.36524838,-0.5762018,-0.9617006,-0.03754102,-0.27151904,-0.9879483,0.08645398,-0.1283894,-0.78725094,-0.2752617,-0.5517852,-0.74839973,-0.49738073,-0.4387599,-0.6237263,0.711984,-0.32255915,0.9198568,0.38913035,-0.049406413,-0.44723478,0.13983466,0.883418,-0.6689012,-0.23592637,0.7049185,-0.8903412,-0.15419926,-0.42838684,-0.92482555,0.016368585,-0.3800392,-0.8165544,-0.1464694,-0.55837774,-0.87178856,-0.35990623,-0.3323434,-0.517776,0.4540006,-0.7251148,-0.8433312,0.09983585,0.52803904,-0.47634494,-0.05045076,-0.87780994,-0.7311533,0.36524838,-0.5762018,-0.6984636,-0.017294424,-0.71543664,-0.64312565,0.17802551,0.7447794,-0.66986597,-0.026210472,0.7420193,-0.90760005,0.06683492,0.41448176,-0.71550065,-0.2610496,-0.6480061,-0.48163462,-0.16273934,0.86112946,-0.9447443,-0.18422589,0.271144,-0.84864473,-0.16340141,0.5030924,-0.66986597,-0.026210472,0.7420193,-0.44133595,0.045067813,0.8962095,-0.84305483,-0.09319865,0.52969086,-0.96471584,-0.253683,0.070486,-0.90281165,-0.30579108,-0.30236223,-0.78725094,-0.2752617,-0.5517852,-0.747842,0.21194589,-0.6291353,-0.38904643,0.09032617,0.9167791,-0.8832008,-0.12243323,0.45273212,-0.38904643,0.09032617,0.9167791,-0.747842,0.21194589,-0.6291353,-0.4839415,-0.097555116,0.86964566,-0.84864473,-0.16340141,0.5030924,-0.05462312,0.1690641,-0.9840902,0.075866185,0.9794647,-0.18679745,0.02688641,0.9635681,-0.26610863,-0.9546164,0.028929858,-0.2964296,0.94705594,-0.2590572,-0.18966934,-0.21252948,0.5347677,0.81783545,-0.6675564,-0.59708816,-0.444808,0.075866185,0.9794647,-0.18679745,-0.23479536,0.67432845,-0.7001088,-0.23479536,0.67432845,-0.7001088,-0.47634494,-0.05045076,-0.87780994,-0.81858766,0.5451293,-0.18096499,-0.23479536,0.67432845,-0.7001088,-0.9879483,0.08645398,-0.1283894,-0.7311533,0.36524838,-0.5762018,0.07019434,0.24138543,0.9678872,-0.40643814,-0.8098558,-0.42301488,-0.19065972,-0.720445,-0.66678923,0.075374685,-0.7676886,-0.6363747,0.41129172,-0.60820895,-0.6789117,0.3633369,-0.6630077,-0.65452826,-0.52704555,-0.58184344,-0.6194199,-0.017521787,-0.99930537,0.032890607,-0.021521537,-0.94214505,-0.3345139,0.6121442,-0.6924734,-0.38178536,-0.70010203,-0.5537167,-0.45083794,-0.7312984,-0.6671969,-0.14160144,-0.70010203,-0.5537167,-0.45083794,-0.017521787,-0.99930537,0.032890607,0.3288468,-0.8804425,0.34158558,-0.1467376,-0.75445783,0.63973546,0.24385142,-0.7973807,0.55201495,-0.23899291,-0.84482497,0.4786994,-0.80877304,-0.50211614,0.3062115,-0.847515,-0.42922866,-0.3122198,0.5623081,-0.8260273,-0.03858204,0.04242061,-0.8742375,0.4836417,0.407,-0.7800877,0.47519907,-0.12836032,-0.80886763,0.57380897,0.16910498,-0.7943238,-0.5834837,0.12811182,-0.79456544,-0.59350926,0.40930107,-0.86440027,-0.29203552,0.48217154,-0.858188,-0.17613666,-0.57233065,-0.7097642,-0.41069746,0.22967121,-0.49633533,-0.83719915,-0.27430204,-0.8970687,0.34644783,-0.62714297,-0.48046845,0.6130593,0.5038301,-0.8556301,0.1185428,0.42636088,-0.8999785,-0.09085657,0.39348367,-0.810439,0.4340037,-0.38334632,-0.9040218,0.18918258,0.4810456,-0.8009131,0.35655776,-0.68955994,-0.7188539,0.0880689,-0.0558253,-0.9859457,0.15746342,-0.0028608302,-0.9999959,-0.000106975036,-0.011426341,-0.9991058,-0.04070532,-0.011439374,-0.9991109,-0.04057865,-0.58131546,-0.51583326,-0.6292762,-0.58025545,-0.63782334,0.5064435,0.39348367,-0.810439,0.4340037,0.4810456,-0.8009131,0.35655776,0.3288468,-0.8804425,0.34158558,0.24385142,-0.7973807,0.55201495,0.407,-0.7800877,0.47519907,0.075374685,-0.7676886,-0.6363747,-0.19065972,-0.720445,-0.66678923,0.48217154,-0.858188,-0.17613666,0.40930107,-0.86440027,-0.29203552,0.5623081,-0.8260273,-0.03858204,0.6121442,-0.6924734,-0.38178536,0.16910498,-0.7943238,-0.5834837,0.12811182,-0.79456544,-0.59350926,0.04242061,-0.8742375,0.4836417,-0.12836032,-0.80886763,0.57380897,-0.57233065,-0.7097642,-0.41069746,-0.021521537,-0.94214505,-0.3345139,-0.58131546,-0.51583326,-0.6292762,-0.847515,-0.42922866,-0.3122198,-0.52704555,-0.58184344,-0.6194199,-0.70010203,-0.5537167,-0.45083794,-0.80877304,-0.50211614,0.3062115,-0.38334632,-0.9040218,0.18918258,-0.68955994,-0.7188539,0.0880689,-0.40643814,-0.8098558,-0.42301488,0.22967121,-0.49633533,-0.83719915,-0.1467376,-0.75445783,0.63973546,-0.23899291,-0.84482497,0.4786994,0.3633369,-0.6630077,-0.65452826,-0.62714297,-0.48046845,0.6130593,-0.27430204,-0.8970687,0.34644783,0.41129172,-0.60820895,-0.6789117,-0.70010203,-0.5537167,-0.45083794,-0.7312984,-0.6671969,-0.14160144,-0.74839973,-0.49738073,-0.4387599,0.5038301,-0.8556301,0.1185428,0.42636088,-0.8999785,-0.09085657,-0.58025545,-0.63782334,0.5064435,-0.38334632,-0.9040218,0.18918258,-0.7312984,-0.6671969,-0.14160144,-0.017521787,-0.99930537,0.032890607,-0.74839973,-0.49738073,-0.4387599,-0.0028608302,-0.9999959,-0.000106975036,-0.011426341,-0.9991058,-0.04070532,-0.74839973,-0.49738073,-0.4387599,-0.017521787,-0.99930537,0.032890607,-0.0558253,-0.9859457,0.15746342,-0.74839973,-0.49738073,-0.4387599,-0.0558253,-0.9859457,0.15746342,-0.0028608302,-0.9999959,-0.000106975036,-0.74839973,-0.49738073,-0.4387599,-0.011439374,-0.9991109,-0.04057865,-0.58131546,-0.51583326,-0.6292762,-0.74839973,-0.49738073,-0.4387599,-0.011426341,-0.9991058,-0.04070532,-0.011439374,-0.9991109,-0.04057865,-0.74839973,-0.49738073,-0.4387599]),positions:new Float32Array([-0.6999253,6.443001,-0.82603,0.07097474,5.343301,-0.52663046,-0.76262593,4.472701,-1.15393,-1.7783258,5.520501,-0.86433035,-2.2427258,6.713101,-0.82603,-1.5250261,4.4763007,-0.9856301,0.29497454,9.249201,0.16336976,0.06327439,8.8725,-0.28472978,-0.035225682,9.543601,0.14946976,-0.30342564,9.674201,-0.23032992,2.4808748,3.6319008,-0.11143037,2.0297747,3.2159004,-0.4459305,1.5565743,4.603301,-0.21123049,2.1004748,3.2381003,3.2929707,1.8371744,4.748301,2.81227,0.20437472,4.420901,2.9141703,1.8253747,0.4645001,-1.7956301,0.91437465,0.9539002,-2.1209302,2.4374743,1.0497,-1.8992304,2.5767748,2.7875004,-0.6003304,1.7599748,1.8992002,-1.1086301,1.5595742,2.5219004,-1.29143,0.24357454,3.5395007,-0.67183006,0.24817431,4.333201,-0.45933002,-0.3960259,7.7391005,-1.2657304,0.05687409,8.074501,-0.67993015,-0.12432557,6.748201,-0.34603044,-0.06132584,2.9543004,-0.8707303,-0.20062563,3.4773006,-0.68853,0.43317416,2.5253003,-0.46623006,-0.4904259,2.1981003,-0.90393,-1.0552258,3.1734004,-1.06763,1.4597749,1.4790002,-2.0267305,-1.8893259,8.729101,-1.7110304,-2.2624261,9.345001,-1.37473,-0.97242594,9.702102,-0.89533013,-1.2870256,7.527001,-2.5206306,-1.5926256,8.311801,-2.8306303,-0.3960259,7.7391005,-1.2657304,2.5549746,1.4319001,2.9302707,2.773675,2.7475002,3.0280704,-0.94812554,8.5809,-1.5055304,0.05687409,8.074501,-0.67993015,-0.3960259,7.7391005,-1.2657304,-0.40532535,9.700401,0.84696966,-1.540426,8.934701,1.6871705,-0.62042546,7.995201,1.7714701,-0.15842591,5.3485007,2.2917705,3.3480747,1.1927001,-1.4741304,0.23047411,6.9421005,0.8096703,0.17777406,7.816401,-0.13533022,-0.80692565,9.159501,-1.4650301,0.73637474,6.182101,0.90636986,0.16357423,6.238301,1.5856699,2.0266747,5.562201,1.4546701,3.4768748,0.57150006,-1.4508302,4.1452746,0.9685002,-0.7070302,2.576082,3.1560004,-0.31358007,0.7198746,2.4339004,3.54267,2.288975,1.3705001,3.4610705,-0.40532535,9.700401,0.84696966,0.14267427,10.748201,0.011170197,-0.35632557,10.885501,-0.026630403,-1.0288259,10.067701,0.053869635,-1.2105256,9.758201,0.87647027,0.09657441,8.901701,0.59447026,3.0635746,4.299401,1.8075701,2.5929751,4.772801,0.5979699,0.16167451,9.942601,0.37547,-0.94812554,8.5809,-1.5055304,0.47697452,6.306901,0.39987034,3.0665743,0.73340005,-1.42483,0.6858742,3.7022007,-0.62512976,0.044074252,1.8123003,-1.5475305,-0.053825382,1.2451001,-1.5953302,3.2380748,2.4352005,-0.08572999,0.5252747,5.1989007,-0.29223025,0.8465745,5.738801,0.27866977,-0.7709256,5.724101,2.2065706,-0.619426,6.356501,1.9183702,-1.9789258,7.178801,-1.18583,-0.91182566,7.3815007,-1.4608301,0.09657441,8.901701,0.59447026,0.06327439,8.8725,-0.28472978,3.0936747,0.6671002,2.4830706,4.0453753,0.52309996,1.4920702,3.6563747,2.4587002,2.1933703,0.5219742,1.8811003,-1.0851305,1.1984742,1.6896003,-1.65813,2.625175,1.7991003,-0.6557297,0.67027444,0.5334,-1.9347303,1.2843744,3.0958004,-0.5304299,0.77727437,1.2146001,3.4750705,3.4174747,1.7396003,-0.85813,2.3443742,1.5199003,-1.5742303,0.06327439,8.8725,-0.28472978,-1.8893259,8.729101,-1.7110304,-0.62042546,7.995201,1.7714701,-1.219426,6.696401,2.0643702,-0.619426,6.356501,1.9183702,-2.161226,7.667401,-2.4847305,-0.91182566,7.3815007,-1.4608301,-1.9789258,7.178801,-1.18583,3.1734743,1.5024002,0.15137026,-0.7888257,10.067701,-0.3484299,0.14267427,10.748201,0.011170197,-0.30342564,9.674201,-0.23032992,-1.0288259,10.067701,0.053869635,0.09657441,8.901701,0.59447026,3.387675,3.7165008,1.58967,-0.30342564,9.674201,-0.23032992,-2.2445261,4.9454007,-0.66073006,3.6162753,2.8629005,0.8747697,-0.7888257,10.067701,-0.3484299,-0.7888257,10.067701,-0.3484299,4.364375,1.0550001,0.5702698,-0.61192554,1.0255002,2.04657,-1.0520257,0.52869993,2.4247699,-0.0897255,0.5721001,2.6455705,-2.517626,0.78980017,0.25796968,-1.337726,0.8835,0.28996965,-1.4268259,0.95919997,-0.43353048,-0.44272542,1.0345002,-0.70443004,-1.0315259,1.0731,-0.7273301,-1.0638257,2.0252004,-0.7415303,-3.471126,10.565201,0.1122696,-3.4521263,9.519001,0.46967015,-2.878626,9.963901,0.81987005,-2.741226,7.508901,1.3471704,-3.4521263,9.519001,0.46967015,-3.433826,9.038601,0.28866962,-2.882526,9.084501,-0.10313035,-3.3896263,8.113201,-0.3605301,-3.3058262,8.5403,0.07176972,-2.7694259,7.7350006,-1.0115304,-2.230626,0.22640002,-0.41983035,-1.868326,0.75070006,-0.9546304,3.880675,1.3958001,1.1265702,-2.327826,8.2278,1.5766702,-2.5213258,6.882601,1.3467698,-1.4618257,2.4264002,-0.6133301,-1.2621258,1.7734003,0.17966996,-1.4422258,3.0290003,0.4318703,-1.9845258,3.6388009,0.69077003,-1.890426,1.0817002,0.44496998,-2.0575259,0.9955001,0.9599702,-2.964326,9.822501,-0.10223008,-2.882526,9.084501,-0.10313035,-3.092126,9.502201,0.2502701,-0.087125406,3.1274004,2.8989704,-0.8196259,2.3198001,1.7973703,-0.8748258,2.0967002,2.7634706,0.02887421,0.7540002,-1.4195303,-1.665426,1.8197002,1.62437,-2.1923258,3.5194008,1.3925699,-1.186226,0.55610013,1.5514703,-0.8196259,2.3198001,1.7973703,-0.029425815,2.1513002,3.4381702,-2.5888262,6.208601,0.9756699,-3.112326,7.3445005,0.3178696,-2.667426,4.758001,0.018969728,-2.7694259,7.7350006,-1.0115304,-2.392026,8.487902,-1.3364304,-0.8792256,4.817401,2.3403704,-2.6100261,4.707801,1.3596704,-0.8792256,4.817401,2.3403704,-2.392026,8.487902,-1.3364304,-1.8001261,4.085301,1.9035699,-1.186226,0.55610013,1.5514703,-1.569626,0.3742001,-1.4788301,-1.9930261,9.862201,-0.003130341,-3.0411263,10.770401,0.043869786,-3.433826,9.038601,0.28866962,4.2867746,0.52519995,0.41017002,-2.878626,9.963901,0.81987005,-1.9710261,3.9114006,0.01537018,-1.9930261,9.862201,-0.003130341,-2.2901258,9.714901,-0.21963045,-2.2901258,9.714901,-0.21963045,-2.964326,9.822501,-0.10223008,-3.471126,10.565201,0.1122696,-2.2901258,9.714901,-0.21963045,-3.3058262,8.5403,0.07176972,-2.882526,9.084501,-0.10313035,-0.7709256,5.724101,2.2065706,0.58418125,0.22400019,-1.7113466,0.7487328,0.22400019,-1.869269,1.2752382,0.22400019,-1.8116388,-1.4210848,0.22400019,-1.3924581,-1.2286401,0.22400019,-1.2118917,-1.7548681,0.22400019,-1.3470285,-2.2161448,0.22400019,-0.43305972,-0.5065232,0.22400019,-0.5854172,3.6921923,0.22400019,-0.5356896,-1.9521799,0.22400019,-1.126045,-2.2274122,0.22400019,-0.4297089,-1.9521799,0.22400019,-1.126045,-2.2161448,0.22400019,-0.43305972,2.2313638,0.22400019,2.680494,-0.6810555,0.22400019,2.4642336,2.4538667,0.22400019,2.5940027,0.41850665,0.22400019,2.7519977,-2.6425998,0.22400019,0.70022744,-2.7626433,0.22400019,0.07626649,4.1131854,0.22400019,0.46040884,1.955617,0.22400019,2.7750673,2.1960154,0.22400019,2.7574801,0.7445824,0.22400019,2.9373279,2.7569857,0.22400019,-1.5163606,2.100773,0.22400019,-1.6653436,3.4797022,0.22400019,-1.0087174,3.5642383,0.22400019,-0.8515244,-0.37594378,0.22400019,-0.7854573,-1.1313287,0.22400019,-1.2045778,-1.2935071,0.22400019,1.0919343,-2.5766528,0.22400019,0.8374413,4.0127363,0.22400019,0.9127198,3.5815594,0.22400019,-0.7074967,3.4810352,0.22400019,1.8996607,-1.11559,0.22400019,1.3025575,3.8143253,0.22400019,1.5762239,-1.0991356,0.22400019,2.0397234,-2.209373,0.22400019,-0.42154086,-2.1618967,0.22400019,-0.40970844,-2.1749234,0.22400019,-0.40605244,-2.1937947,0.22400019,-0.40073627,-2.2783449,0.22400019,-0.37692034,-1.0468484,0.22400019,2.382645,3.4810352,0.22400019,1.8996607,3.8143253,0.22400019,1.5762239,2.2313638,0.22400019,2.680494,2.4538667,0.22400019,2.5940027,2.1960154,0.22400019,2.7574801,1.2752382,0.22400019,-1.8116388,0.7487328,0.22400019,-1.869269,3.5642383,0.22400019,-0.8515244,3.4797022,0.22400019,-1.0087174,4.1131854,0.22400019,0.46040884,3.6921923,0.22400019,-0.5356896,2.7569857,0.22400019,-1.5163606,2.100773,0.22400019,-1.6653436,1.955617,0.22400019,2.7750673,0.7445824,0.22400019,2.9373279,-0.37594378,0.22400019,-0.7854573,-0.5065232,0.22400019,-0.5854172,-2.2783449,0.22400019,-0.37692034,-2.7626433,0.22400019,0.07626649,-1.7548681,0.22400019,-1.3470285,-1.9521799,0.22400019,-1.126045,-2.6425998,0.22400019,0.70022744,-1.11559,0.22400019,1.3025575,-1.0991356,0.22400019,2.0397234,0.58418125,0.22400019,-1.7113466,-1.1313287,0.22400019,-1.2045778,-0.6810555,0.22400019,2.4642336,0.41850665,0.22400019,2.7519977,-1.2286401,0.22400019,-1.2118917,-2.5766528,0.22400019,0.8374413,-1.2935071,0.22400019,1.0919343,-1.4210848,0.22400019,-1.3924581,-1.9521799,0.22400019,-1.126045,-2.2274122,0.22400019,-0.4297089,-2.230626,0.22640002,-0.41983035,4.0127363,0.22400019,0.9127198,3.5815594,0.22400019,-0.7074967,-1.0468484,0.22400019,2.382645,-1.11559,0.22400019,1.3025575,-2.2274122,0.22400019,-0.4297089,-2.2161448,0.22400019,-0.43305972,-2.230626,0.22640002,-0.41983035,-2.1618967,0.22400019,-0.40970844,-2.1749234,0.22400019,-0.40605244,-2.230626,0.22640002,-0.41983035,-2.2161448,0.22400019,-0.43305972,-2.209373,0.22400019,-0.42154086,-2.230626,0.22640002,-0.41983035,-2.209373,0.22400019,-0.42154086,-2.1618967,0.22400019,-0.40970844,-2.230626,0.22640002,-0.41983035,-2.1937947,0.22400019,-0.40073627,-2.2783449,0.22400019,-0.37692034,-2.230626,0.22640002,-0.41983035,-2.1749234,0.22400019,-0.40605244,-2.1937947,0.22400019,-0.40073627,-2.230626,0.22640002,-0.41983035]),uvs:new Float32Array([0.21851481,0.38709354,0.25122124,0.29925498,0.33613995,0.31277353,0.31780326,0.41546077,0.26634175,0.49754715,0.36926088,0.35428312,0.8862014,0.7660378,0.96414614,0.65773886,0.9142767,0.82184976,0.96414614,0.8656495,0.24378048,0.15517116,0.27324826,0.1538348,0.24071635,0.21034758,0.12782207,0.13377228,0.13686845,0.17050092,0.097095504,0.18026535,0.3456612,0.015984222,0.38372317,0.05219409,0.3173124,0.03967564,0.2669188,0.12665303,0.3150151,0.10144508,0.312529,0.12937495,0.32927862,0.22344446,0.2904697,0.2528519,0.13747068,0.42125323,0.1110152,0.38961607,0.17645767,0.34971166,0.37940347,0.20685007,0.3529383,0.23464157,0.35064337,0.17517665,0.43924242,0.18647039,0.41530237,0.2674248,0.34998143,0.06725915,0.12322961,0.6801839,0.1720783,0.6964544,0.16144735,0.7933706,0.8861246,0.52512723,0.84557533,0.5134298,0.9878913,0.42880467,0.12832226,0.086800925,0.14096868,0.11748978,0.074313566,0.7435197,0.020883663,0.84153533,0.00000001081579,0.77996564,0.32931674,0.8416559,0.35599756,0.7471563,0.4352468,0.76457715,0.09890157,0.21372627,0.28071728,0.038383927,0.12732372,0.2965882,0.11473294,0.36185902,0.110673696,0.76611084,0.1568792,0.258202,0.11916661,0.24799357,0.1670033,0.20147358,0.27564877,0.017370421,0.24627076,0.033188876,0.25064924,0.13463129,0.09065693,0.12818988,0.11538713,0.09199737,0.8276462,0.8879465,0.8977165,0.9073449,0.8979689,0.9335955,0.24703515,0.8216678,0.30523577,0.7905776,0.8020745,0.7431329,0.17493051,0.15400115,0.20319703,0.1803566,0.89068747,0.8602873,0.8669603,0.42128757,0.1696568,0.2862294,0.29085746,0.022808408,0.30401754,0.21331184,0.4063384,0.124203816,0.4319168,0.09517003,0.24068871,0.10983848,0.2422915,0.26877972,0.19642983,0.2589539,0.084621415,0.22762483,0.08997824,0.2432744,0.21659407,0.49825695,0.16409814,0.4431432,0.06007273,0.3584054,0.077401064,0.3881148,0.13976377,0.06055675,0.1772671,0.045047924,0.1689892,0.10318307,0.36747235,0.13334484,0.35129,0.09048066,0.27406374,0.088201545,0.40481266,0.033736143,0.3024185,0.17043002,0.080950305,0.101946086,0.26399732,0.060749806,0.3123137,0.06264582,0.08229262,0.8732247,0.78262734,0.48695683,0.054573745,0.28939876,0.4784059,0.67288846,0.52534187,0.6902852,0.843693,0.54919225,0.967211,0.5381632,0.8863765,0.6507956,0.23814057,0.07682296,0.52430856,0.78790325,0.5076637,0.9781552,0.42495766,0.8044593,0.88358545,0.94791806,0.39027283,0.865766,0.18311635,0.13782379,0.15227878,0.86758876,0.37036988,0.41615537,0.20584682,0.11498356,0.935007,0.9301176,0.19761893,0.83779246,0.20950294,0.045586396,0.0322884,0.11481223,0.02451134,0.09802288,0.048454616,0.09665558,0.6460075,0.21836895,0.5963892,0.2274105,0.5771463,0.1884031,0.5055221,0.114784405,0.5447714,0.15467297,0.48357084,0.21026236,0.75558704,0.9432239,0.8020744,0.9034289,0.7897775,0.96688294,0.36300594,0.6462114,0.27383736,0.69182056,0.27248618,0.6792056,0.2478923,0.6867268,0.25436208,0.6271816,0.26854706,0.6570603,0.2133645,0.5806204,0.637635,0.17406993,0.60493344,0.1558058,0.19796096,0.06852602,0.35857934,0.69122976,0.3951752,0.6194137,0.48257515,0.25476277,0.5577472,0.2591085,0.5101766,0.3366432,0.50301826,0.39985734,0.6224612,0.2508355,0.65923995,0.27131322,0.7339221,0.92058545,0.667627,0.84930974,0.75460386,0.8875665,0.07549074,0.15373975,0.036297202,0.14856292,0.053295545,0.13493255,0.45089763,0.06624607,0.65852106,0.35673973,0.5478699,0.43424743,0.734133,0.3012958,0.69251174,0.422131,0.07396352,0.1281145,0.4061021,0.5678618,0.31435022,0.5997315,0.4114268,0.44731957,0.75763285,0.6744133,0.734765,0.56230044,0.5902533,0.5873184,0.48538992,0.4962032,0.07417127,0.20548928,0.16459617,0.6398786,0.5627961,0.49731115,0.010203981,0.1122183,0.61384606,0.11812159,0.7293909,0.98951745,0.753717,0.961225,0.8020744,0.78846765,0.20760685,0.029241929,0.27992412,0.7168905,0.45012152,0.3856737,0.2468168,0.7547342,0.23586477,0.728986,0.52842814,0.74081594,0.58254737,0.8386313,0.5380133,0.9808106,0.69757915,0.9635888,0.70988774,0.65773886,0.6677008,0.75300074,0.5507923,0.6433447,0.9718312,0.020504208,0.97220457,0.021100836,0.9716987,0.022655101,0.9721315,0.014245303,0.9714647,0.014712902,0.97220457,0.013208317,0.96973413,0.01123883,0.96911705,0.01649964,0.96632093,0.029152708,0.9716613,0.012472974,0.80359983,1.0238159,0.80359983,0.95338476,0.8044696,1.023133,0.95752156,0.022717984,0.96000504,0.01405433,0.95764303,0.02344461,0.95844465,0.017195703,0.9665674,0.0092362035,0.96852803,0.009265589,0.9630468,0.029798763,0.9574091,0.02182542,0.95731115,0.022562819,0.9576798,0.018064456,0.9698729,0.026945414,0.9707365,0.02505687,0.9678838,0.028808849,0.96735567,0.028965177,0.9696391,0.017020183,0.9713813,0.015002267,0.96453613,0.013066204,0.96611136,0.009349244,0.9617433,0.029211031,0.96690965,0.028926747,0.9590955,0.02698438,0.963788,0.013471412,0.95986325,0.028194623,0.96155035,0.013057904,0.9696951,0.011252033,0.9696294,0.011387991,0.96961904,0.011344941,0.9696118,0.01128404,0.969593,0.011013629,0.9604814,0.013000401,0.15420465,0.04102335,0.16792865,0.037144165,0.110636964,0.05624038,0.117879316,0.05280347,0.1069449,0.059347447,0.37604672,0.008110086,0.4070614,0.013023422,0.25538462,0.0031148791,0.2648711,0.000000008450675,0.20259783,0.019268692,0.23897217,0.0057812533,0.3031835,0.0016587148,0.3331248,0.0026185757,0.09809749,0.06282124,0.068156235,0.07761529,0.52157223,0.044851843,0.5435285,0.046751596,0.63853747,0.17621852,0.66334546,0.19258852,0.62489164,0.1247898,0.6287393,0.14086775,0.68118423,0.21481499,-0.0000000033102134,0.10996528,0.013690739,0.09781893,0.42186216,0.014245739,0.6017828,0.094806425,0.030619193,0.091465615,0.057839744,0.08235605,0.59865737,0.10087764,0.67908764,0.21657859,0.7325371,0.2680749,0.614245,0.10814548,0.43263742,0.92657316,0.43597075,0.8869815,0.43614823,0.88644433,0.18772343,0.02667462,0.24657853,0.0037103465,0.021488441,0.09233946,0.7439689,0.2791134,0.67494655,0.99038863,0.67444944,0.9913764,0.67444944,0.98951757,0.80714715,0.95338464,0.8076674,0.95454615,0.80714715,0.9599234,0.67331666,0.9900621,0.6744493,0.98951745,0.67444944,0.99153584,0.80814487,0.9553456,0.8076674,0.95992327,0.8076674,0.9533845,0.8044694,0.9616473,0.8044694,0.95338464,0.807147,0.9587995,0.67240256,0.98951757,0.6733167,0.9911193,0.67240256,0.9949199]),vertexCount:285});var F="../fox-tex-03f042508a92e722.png";var _="../fox-normal-7ce4a77b1285eb7a.png";var b="../backdrop-0e5863d39a0305cf.png";var O="../backdrop-normals-6ba4b06676f112b6.png";var I=new a({fov:45}),f=new c([0,2,4],Y([-15,0,0])),G=new c([10,10,10]),S=new c($(0),Y([0,225,0]),$(0.1)),N=new q(I,d,{uvClamp:!0}),T=new q(I,b),v=new q(I,O),w=new q(I,F),u=new q(I,_),L=x(35,76,37);I.onUpdate((R,y)=>{});new Q(I,S,new E(I,X,s(I,L).addTexture("texture0",w).addTexture("texture1",u).addTexture("texture2",N),f,G).configure({}));new Q(I,D,new E(I,J,s(I,L).addTexture("texture0",T).addTexture("texture1",v).addTexture("texture2",N),f,G).configure({}));I.start();
diff --git a/html/backdrop-0e5863d39a0305cf.png b/html/backdrop-0e5863d39a0305cf.png
new file mode 100644
index 0000000..cac2e0c
Binary files /dev/null and b/html/backdrop-0e5863d39a0305cf.png differ
diff --git a/html/backdrop-normals-6ba4b06676f112b6.png b/html/backdrop-normals-6ba4b06676f112b6.png
new file mode 100644
index 0000000..ee06369
Binary files /dev/null and b/html/backdrop-normals-6ba4b06676f112b6.png differ
diff --git a/html/chunk-2ef356c72587f126.js b/html/chunk-2ef356c72587f126.js
new file mode 100644
index 0000000..b3e583e
--- /dev/null
+++ b/html/chunk-2ef356c72587f126.js
@@ -0,0 +1,8 @@
+var u0=Object.defineProperty;var u=(C,M)=>{for(var I in M)u0(C,I,{get:M[I],enumerable:!0,configurable:!0,set:(N)=>M[I]=()=>N})};var f={};u(f,{str:()=>{{return mC}},squaredLength:()=>{{return i0}},sqrLen:()=>{{return IM}},sqlerp:()=>{{return WM}},slerp:()=>{{return e}},setAxisAngle:()=>{{return h0}},setAxes:()=>{{return AM}},set:()=>{{return oC}},scale:()=>{{return g0}},rotationTo:()=>{{return QM}},rotateZ:()=>{{return lC}},rotateY:()=>{{return dC}},rotateX:()=>{{return iC}},random:()=>{{return yC}},pow:()=>{{return zC}},normalize:()=>{{return C0}},multiply:()=>{{return q0}},mul:()=>{{return aC}},ln:()=>{{return v0}},lerp:()=>{{return CM}},length:()=>{{return f0}},len:()=>{{return MM}},invert:()=>{{return rC}},identity:()=>{{return gC}},getAxisAngle:()=>{{return nC}},getAngle:()=>{{return fC}},fromValues:()=>{{return bC}},fromMat3:()=>{{return w0}},fromEuler:()=>{{return sC}},exp:()=>{{return p0}},exactEquals:()=>{{return NM}},equals:()=>{{return VM}},dot:()=>{{return n0}},create:()=>{{return a}},copy:()=>{{return uC}},conjugate:()=>{{return xC}},clone:()=>{{return eC}},calculateW:()=>{{return cC}},add:()=>{{return tC}}});var F=0.000001,k=typeof Float32Array!=="undefined"?Float32Array:Array,n=Math.random,AI=Math.PI/180;if(!Math.hypot)Math.hypot=function(){var C=0,M=arguments.length;while(M--)C+=arguments[M]*arguments[M];return Math.sqrt(C)};function X0(){var C=new k(9);if(k!=Float32Array)C[1]=0,C[2]=0,C[3]=0,C[5]=0,C[6]=0,C[7]=0;return C[0]=1,C[4]=1,C[8]=1,C}var d={};u(d,{zero:()=>{{return FC}},transformQuat:()=>{{return HC}},transformMat4:()=>{{return PC}},transformMat3:()=>{{return LC}},subtract:()=>{{return Z0}},sub:()=>{{return _C}},str:()=>{{return OC}},squaredLength:()=>{{return L0}},squaredDistance:()=>{{return P0}},sqrLen:()=>{{return qC}},sqrDist:()=>{{return hC}},set:()=>{{return CC}},scaleAndAdd:()=>{{return EC}},scale:()=>{{return AC}},round:()=>{{return WC}},rotateZ:()=>{{return GC}},rotateY:()=>{{return DC}},rotateX:()=>{{return JC}},random:()=>{{return KC}},normalize:()=>{{return o}},negate:()=>{{return XC}},multiply:()=>{{return $0}},mul:()=>{{return TC}},min:()=>{{return VC}},max:()=>{{return QC}},lerp:()=>{{return ZC}},length:()=>{{return Y0}},len:()=>{{return t}},inverse:()=>{{return YC}},hermite:()=>{{return $C}},fromValues:()=>{{return s}},forEach:()=>{{return pC}},floor:()=>{{return NC}},exactEquals:()=>{{return RC}},equals:()=>{{return kC}},dot:()=>{{return m}},divide:()=>{{return B0}},div:()=>{{return jC}},distance:()=>{{return K0}},dist:()=>{{return SC}},cross:()=>{{return r}},create:()=>{{return x}},copy:()=>{{return a0}},clone:()=>{{return t0}},ceil:()=>{{return IC}},bezier:()=>{{return BC}},angle:()=>{{return UC}},add:()=>{{return MC}}});function x(){var C=new k(3);if(k!=Float32Array)C[0]=0,C[1]=0,C[2]=0;return C}function t0(C){var M=new k(3);return M[0]=C[0],M[1]=C[1],M[2]=C[2],M}function Y0(C){var M=C[0],I=C[1],N=C[2];return Math.hypot(M,I,N)}function s(C,M,I){var N=new k(3);return N[0]=C,N[1]=M,N[2]=I,N}function a0(C,M){return C[0]=M[0],C[1]=M[1],C[2]=M[2],C}function CC(C,M,I,N){return C[0]=M,C[1]=I,C[2]=N,C}function MC(C,M,I){return C[0]=M[0]+I[0],C[1]=M[1]+I[1],C[2]=M[2]+I[2],C}function Z0(C,M,I){return C[0]=M[0]-I[0],C[1]=M[1]-I[1],C[2]=M[2]-I[2],C}function $0(C,M,I){return C[0]=M[0]*I[0],C[1]=M[1]*I[1],C[2]=M[2]*I[2],C}function B0(C,M,I){return C[0]=M[0]/I[0],C[1]=M[1]/I[1],C[2]=M[2]/I[2],C}function IC(C,M){return C[0]=Math.ceil(M[0]),C[1]=Math.ceil(M[1]),C[2]=Math.ceil(M[2]),C}function NC(C,M){return C[0]=Math.floor(M[0]),C[1]=Math.floor(M[1]),C[2]=Math.floor(M[2]),C}function VC(C,M,I){return C[0]=Math.min(M[0],I[0]),C[1]=Math.min(M[1],I[1]),C[2]=Math.min(M[2],I[2]),C}function QC(C,M,I){return C[0]=Math.max(M[0],I[0]),C[1]=Math.max(M[1],I[1]),C[2]=Math.max(M[2],I[2]),C}function WC(C,M){return C[0]=Math.round(M[0]),C[1]=Math.round(M[1]),C[2]=Math.round(M[2]),C}function AC(C,M,I){return C[0]=M[0]*I,C[1]=M[1]*I,C[2]=M[2]*I,C}function EC(C,M,I,N){return C[0]=M[0]+I[0]*N,C[1]=M[1]+I[1]*N,C[2]=M[2]+I[2]*N,C}function K0(C,M){var I=M[0]-C[0],N=M[1]-C[1],V=M[2]-C[2];return Math.hypot(I,N,V)}function P0(C,M){var I=M[0]-C[0],N=M[1]-C[1],V=M[2]-C[2];return I*I+N*N+V*V}function L0(C){var M=C[0],I=C[1],N=C[2];return M*M+I*I+N*N}function XC(C,M){return C[0]=-M[0],C[1]=-M[1],C[2]=-M[2],C}function YC(C,M){return C[0]=1/M[0],C[1]=1/M[1],C[2]=1/M[2],C}function o(C,M){var I=M[0],N=M[1],V=M[2],Q=I*I+N*N+V*V;if(Q>0)Q=1/Math.sqrt(Q);return C[0]=M[0]*Q,C[1]=M[1]*Q,C[2]=M[2]*Q,C}function m(C,M){return C[0]*M[0]+C[1]*M[1]+C[2]*M[2]}function r(C,M,I){var N=M[0],V=M[1],Q=M[2],W=I[0],A=I[1],E=I[2];return C[0]=V*E-Q*A,C[1]=Q*W-N*E,C[2]=N*A-V*W,C}function ZC(C,M,I,N){var V=M[0],Q=M[1],W=M[2];return C[0]=V+N*(I[0]-V),C[1]=Q+N*(I[1]-Q),C[2]=W+N*(I[2]-W),C}function $C(C,M,I,N,V,Q){var W=Q*Q,A=W*(2*Q-3)+1,E=W*(Q-2)+Q,X=W*(Q-1),Y=W*(3-2*Q);return C[0]=M[0]*A+I[0]*E+N[0]*X+V[0]*Y,C[1]=M[1]*A+I[1]*E+N[1]*X+V[1]*Y,C[2]=M[2]*A+I[2]*E+N[2]*X+V[2]*Y,C}function BC(C,M,I,N,V,Q){var W=1-Q,A=W*W,E=Q*Q,X=A*W,Y=3*Q*A,$=3*E*W,K=E*Q;return C[0]=M[0]*X+I[0]*Y+N[0]*$+V[0]*K,C[1]=M[1]*X+I[1]*Y+N[1]*$+V[1]*K,C[2]=M[2]*X+I[2]*Y+N[2]*$+V[2]*K,C}function KC(C,M){M=M||1;var I=n()*2*Math.PI,N=n()*2-1,V=Math.sqrt(1-N*N)*M;return C[0]=Math.cos(I)*V,C[1]=Math.sin(I)*V,C[2]=N*M,C}function PC(C,M,I){var N=M[0],V=M[1],Q=M[2],W=I[3]*N+I[7]*V+I[11]*Q+I[15];return W=W||1,C[0]=(I[0]*N+I[4]*V+I[8]*Q+I[12])/W,C[1]=(I[1]*N+I[5]*V+I[9]*Q+I[13])/W,C[2]=(I[2]*N+I[6]*V+I[10]*Q+I[14])/W,C}function LC(C,M,I){var N=M[0],V=M[1],Q=M[2];return C[0]=N*I[0]+V*I[3]+Q*I[6],C[1]=N*I[1]+V*I[4]+Q*I[7],C[2]=N*I[2]+V*I[5]+Q*I[8],C}function HC(C,M,I){var N=I[0],V=I[1],Q=I[2],W=I[3],A=M[0],E=M[1],X=M[2],Y=V*X-Q*E,$=Q*A-N*X,K=N*E-V*A,B=V*K-Q*$,L=Q*Y-N*K,P=N*$-V*Y,Z=W*2;return Y*=Z,$*=Z,K*=Z,B*=2,L*=2,P*=2,C[0]=A+Y+B,C[1]=E+$+L,C[2]=X+K+P,C}function JC(C,M,I,N){var V=[],Q=[];return V[0]=M[0]-I[0],V[1]=M[1]-I[1],V[2]=M[2]-I[2],Q[0]=V[0],Q[1]=V[1]*Math.cos(N)-V[2]*Math.sin(N),Q[2]=V[1]*Math.sin(N)+V[2]*Math.cos(N),C[0]=Q[0]+I[0],C[1]=Q[1]+I[1],C[2]=Q[2]+I[2],C}function DC(C,M,I,N){var V=[],Q=[];return V[0]=M[0]-I[0],V[1]=M[1]-I[1],V[2]=M[2]-I[2],Q[0]=V[2]*Math.sin(N)+V[0]*Math.cos(N),Q[1]=V[1],Q[2]=V[2]*Math.cos(N)-V[0]*Math.sin(N),C[0]=Q[0]+I[0],C[1]=Q[1]+I[1],C[2]=Q[2]+I[2],C}function GC(C,M,I,N){var V=[],Q=[];return V[0]=M[0]-I[0],V[1]=M[1]-I[1],V[2]=M[2]-I[2],Q[0]=V[0]*Math.cos(N)-V[1]*Math.sin(N),Q[1]=V[0]*Math.sin(N)+V[1]*Math.cos(N),Q[2]=V[2],C[0]=Q[0]+I[0],C[1]=Q[1]+I[1],C[2]=Q[2]+I[2],C}function UC(C,M){var I=C[0],N=C[1],V=C[2],Q=M[0],W=M[1],A=M[2],E=Math.sqrt(I*I+N*N+V*V),X=Math.sqrt(Q*Q+W*W+A*A),Y=E*X,$=Y&&m(C,M)/Y;return Math.acos(Math.min(Math.max($,-1),1))}function FC(C){return C[0]=0,C[1]=0,C[2]=0,C}function OC(C){return"vec3("+C[0]+", "+C[1]+", "+C[2]+")"}function RC(C,M){return C[0]===M[0]&&C[1]===M[1]&&C[2]===M[2]}function kC(C,M){var I=C[0],N=C[1],V=C[2],Q=M[0],W=M[1],A=M[2];return Math.abs(I-Q)<=F*Math.max(1,Math.abs(I),Math.abs(Q))&&Math.abs(N-W)<=F*Math.max(1,Math.abs(N),Math.abs(W))&&Math.abs(V-A)<=F*Math.max(1,Math.abs(V),Math.abs(A))}var _C=Z0,TC=$0,jC=B0,SC=K0,hC=P0,t=Y0,qC=L0,pC=function(){var C=x();return function(M,I,N,V,Q,W){var A,E;if(!I)I=3;if(!N)N=0;if(V)E=Math.min(V*I+N,M.length);else E=M.length;for(A=N;A0)W=1/Math.sqrt(W);return C[0]=I*W,C[1]=N*W,C[2]=V*W,C[3]=Q*W,C}function _0(C,M){return C[0]*M[0]+C[1]*M[1]+C[2]*M[2]+C[3]*M[3]}function T0(C,M,I,N){var V=M[0],Q=M[1],W=M[2],A=M[3];return C[0]=V+N*(I[0]-V),C[1]=Q+N*(I[1]-Q),C[2]=W+N*(I[2]-W),C[3]=A+N*(I[3]-A),C}function j0(C,M){return C[0]===M[0]&&C[1]===M[1]&&C[2]===M[2]&&C[3]===M[3]}function S0(C,M){var I=C[0],N=C[1],V=C[2],Q=C[3],W=M[0],A=M[1],E=M[2],X=M[3];return Math.abs(I-W)<=F*Math.max(1,Math.abs(I),Math.abs(W))&&Math.abs(N-A)<=F*Math.max(1,Math.abs(N),Math.abs(A))&&Math.abs(V-E)<=F*Math.max(1,Math.abs(V),Math.abs(E))&&Math.abs(Q-X)<=F*Math.max(1,Math.abs(Q),Math.abs(X))}var EI=function(){var C=vC();return function(M,I,N,V,Q,W){var A,E;if(!I)I=4;if(!N)N=0;if(V)E=Math.min(V*I+N,M.length);else E=M.length;for(A=N;AF)C[0]=M[0]/N,C[1]=M[1]/N,C[2]=M[2]/N;else C[0]=1,C[1]=0,C[2]=0;return I}function fC(C,M){var I=n0(C,M);return Math.acos(2*I*I-1)}function q0(C,M,I){var N=M[0],V=M[1],Q=M[2],W=M[3],A=I[0],E=I[1],X=I[2],Y=I[3];return C[0]=N*Y+W*A+V*X-Q*E,C[1]=V*Y+W*E+Q*A-N*X,C[2]=Q*Y+W*X+N*E-V*A,C[3]=W*Y-N*A-V*E-Q*X,C}function iC(C,M,I){I*=0.5;var N=M[0],V=M[1],Q=M[2],W=M[3],A=Math.sin(I),E=Math.cos(I);return C[0]=N*E+W*A,C[1]=V*E+Q*A,C[2]=Q*E-V*A,C[3]=W*E-N*A,C}function dC(C,M,I){I*=0.5;var N=M[0],V=M[1],Q=M[2],W=M[3],A=Math.sin(I),E=Math.cos(I);return C[0]=N*E-Q*A,C[1]=V*E+W*A,C[2]=Q*E+N*A,C[3]=W*E-V*A,C}function lC(C,M,I){I*=0.5;var N=M[0],V=M[1],Q=M[2],W=M[3],A=Math.sin(I),E=Math.cos(I);return C[0]=N*E+V*A,C[1]=V*E-N*A,C[2]=Q*E+W*A,C[3]=W*E-Q*A,C}function cC(C,M){var I=M[0],N=M[1],V=M[2];return C[0]=I,C[1]=N,C[2]=V,C[3]=Math.sqrt(Math.abs(1-I*I-N*N-V*V)),C}function p0(C,M){var I=M[0],N=M[1],V=M[2],Q=M[3],W=Math.sqrt(I*I+N*N+V*V),A=Math.exp(Q),E=W>0?A*Math.sin(W)/W:0;return C[0]=I*E,C[1]=N*E,C[2]=V*E,C[3]=A*Math.cos(W),C}function v0(C,M){var I=M[0],N=M[1],V=M[2],Q=M[3],W=Math.sqrt(I*I+N*N+V*V),A=W>0?Math.atan2(W,Q)/W:0;return C[0]=I*A,C[1]=N*A,C[2]=V*A,C[3]=0.5*Math.log(I*I+N*N+V*V+Q*Q),C}function zC(C,M,I){return v0(C,M),g0(C,C,I),p0(C,C),C}function e(C,M,I,N){var V=M[0],Q=M[1],W=M[2],A=M[3],E=I[0],X=I[1],Y=I[2],$=I[3],K,B,L,P,Z;if(B=V*E+Q*X+W*Y+A*$,B<0)B=-B,E=-E,X=-X,Y=-Y,$=-$;if(1-B>F)K=Math.acos(B),L=Math.sin(K),P=Math.sin((1-N)*K)/L,Z=Math.sin(N*K)/L;else P=1-N,Z=N;return C[0]=P*V+Z*E,C[1]=P*Q+Z*X,C[2]=P*W+Z*Y,C[3]=P*A+Z*$,C}function yC(C){var M=n(),I=n(),N=n(),V=Math.sqrt(1-M),Q=Math.sqrt(M);return C[0]=V*Math.sin(2*Math.PI*I),C[1]=V*Math.cos(2*Math.PI*I),C[2]=Q*Math.sin(2*Math.PI*N),C[3]=Q*Math.cos(2*Math.PI*N),C}function rC(C,M){var I=M[0],N=M[1],V=M[2],Q=M[3],W=I*I+N*N+V*V+Q*Q,A=W?1/W:0;return C[0]=-I*A,C[1]=-N*A,C[2]=-V*A,C[3]=Q*A,C}function xC(C,M){return C[0]=-M[0],C[1]=-M[1],C[2]=-M[2],C[3]=M[3],C}function w0(C,M){var I=M[0]+M[4]+M[8],N;if(I>0)N=Math.sqrt(I+1),C[3]=0.5*N,N=0.5/N,C[0]=(M[5]-M[7])*N,C[1]=(M[6]-M[2])*N,C[2]=(M[1]-M[3])*N;else{var V=0;if(M[4]>M[0])V=1;if(M[8]>M[V*3+V])V=2;var Q=(V+1)%3,W=(V+2)%3;N=Math.sqrt(M[V*3+V]-M[Q*3+Q]-M[W*3+W]+1),C[V]=0.5*N,N=0.5/N,C[3]=(M[Q*3+W]-M[W*3+Q])*N,C[Q]=(M[Q*3+V]+M[V*3+Q])*N,C[W]=(M[W*3+V]+M[V*3+W])*N}return C}function sC(C,M,I,N){var V=0.5*Math.PI/180;M*=V,I*=V,N*=V;var Q=Math.sin(M),W=Math.cos(M),A=Math.sin(I),E=Math.cos(I),X=Math.sin(N),Y=Math.cos(N);return C[0]=Q*E*Y-W*A*X,C[1]=W*A*Y+Q*E*X,C[2]=W*E*X-Q*A*Y,C[3]=W*E*Y+Q*A*X,C}function mC(C){return"quat("+C[0]+", "+C[1]+", "+C[2]+", "+C[3]+")"}var eC=H0,bC=J0,uC=D0,oC=G0,tC=U0,aC=q0,g0=F0,n0=_0,CM=T0,f0=O0,MM=f0,i0=R0,IM=i0,C0=k0,NM=j0,VM=S0,QM=function(){var C=x(),M=s(1,0,0),I=s(0,1,0);return function(N,V,Q){var W=m(V,Q);if(W<-0.999999){if(r(C,M,V),t(C)<0.000001)r(C,I,V);return o(C,C),h0(N,C,Math.PI),N}else if(W>0.999999)return N[0]=0,N[1]=0,N[2]=0,N[3]=1,N;else return r(C,V,Q),N[0]=C[0],N[1]=C[1],N[2]=C[2],N[3]=1+W,C0(N,N)}}(),WM=function(){var C=a(),M=a();return function(I,N,V,Q,W,A){return e(C,N,W,A),e(M,V,Q,A),e(I,C,M,2*A*(1-A)),I}}(),AM=function(){var C=X0();return function(M,I,N,V){return C[0]=N[0],C[3]=N[1],C[6]=N[2],C[1]=V[0],C[4]=V[1],C[7]=V[2],C[2]=-I[0],C[5]=-I[1],C[8]=-I[2],C0(M,w0(M,C))}}();var v={};u(v,{transpose:()=>{{return BM}},translate:()=>{{return HM}},targetTo:()=>{{return zM}},subtract:()=>{{return x0}},sub:()=>{{return oM}},str:()=>{{return yM}},set:()=>{{return $M}},scale:()=>{{return JM}},rotateZ:()=>{{return FM}},rotateY:()=>{{return UM}},rotateX:()=>{{return GM}},rotate:()=>{{return DM}},perspectiveZO:()=>{{return fM}},perspectiveNO:()=>{{return y0}},perspectiveFromFieldOfView:()=>{{return iM}},perspective:()=>{{return nM}},orthoZO:()=>{{return lM}},orthoNO:()=>{{return r0}},ortho:()=>{{return dM}},multiplyScalarAndAdd:()=>{{return mM}},multiplyScalar:()=>{{return sM}},multiply:()=>{{return l0}},mul:()=>{{return uM}},lookAt:()=>{{return cM}},invert:()=>{{return KM}},identity:()=>{{return d0}},getTranslation:()=>{{return hM}},getScaling:()=>{{return z0}},getRotation:()=>{{return qM}},frustum:()=>{{return gM}},fromZRotation:()=>{{return jM}},fromYRotation:()=>{{return TM}},fromXRotation:()=>{{return _M}},fromValues:()=>{{return ZM}},fromTranslation:()=>{{return OM}},fromScaling:()=>{{return RM}},fromRotationTranslationScaleOrigin:()=>{{return vM}},fromRotationTranslationScale:()=>{{return pM}},fromRotationTranslation:()=>{{return c0}},fromRotation:()=>{{return kM}},fromQuat2:()=>{{return SM}},fromQuat:()=>{{return wM}},frob:()=>{{return rM}},exactEquals:()=>{{return eM}},equals:()=>{{return bM}},determinant:()=>{{return LM}},create:()=>{{return EM}},copy:()=>{{return YM}},clone:()=>{{return XM}},adjoint:()=>{{return PM}},add:()=>{{return xM}}});function EM(){var C=new k(16);if(k!=Float32Array)C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[6]=0,C[7]=0,C[8]=0,C[9]=0,C[11]=0,C[12]=0,C[13]=0,C[14]=0;return C[0]=1,C[5]=1,C[10]=1,C[15]=1,C}function XM(C){var M=new k(16);return M[0]=C[0],M[1]=C[1],M[2]=C[2],M[3]=C[3],M[4]=C[4],M[5]=C[5],M[6]=C[6],M[7]=C[7],M[8]=C[8],M[9]=C[9],M[10]=C[10],M[11]=C[11],M[12]=C[12],M[13]=C[13],M[14]=C[14],M[15]=C[15],M}function YM(C,M){return C[0]=M[0],C[1]=M[1],C[2]=M[2],C[3]=M[3],C[4]=M[4],C[5]=M[5],C[6]=M[6],C[7]=M[7],C[8]=M[8],C[9]=M[9],C[10]=M[10],C[11]=M[11],C[12]=M[12],C[13]=M[13],C[14]=M[14],C[15]=M[15],C}function ZM(C,M,I,N,V,Q,W,A,E,X,Y,$,K,B,L,P){var Z=new k(16);return Z[0]=C,Z[1]=M,Z[2]=I,Z[3]=N,Z[4]=V,Z[5]=Q,Z[6]=W,Z[7]=A,Z[8]=E,Z[9]=X,Z[10]=Y,Z[11]=$,Z[12]=K,Z[13]=B,Z[14]=L,Z[15]=P,Z}function $M(C,M,I,N,V,Q,W,A,E,X,Y,$,K,B,L,P,Z){return C[0]=M,C[1]=I,C[2]=N,C[3]=V,C[4]=Q,C[5]=W,C[6]=A,C[7]=E,C[8]=X,C[9]=Y,C[10]=$,C[11]=K,C[12]=B,C[13]=L,C[14]=P,C[15]=Z,C}function d0(C){return C[0]=1,C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[5]=1,C[6]=0,C[7]=0,C[8]=0,C[9]=0,C[10]=1,C[11]=0,C[12]=0,C[13]=0,C[14]=0,C[15]=1,C}function BM(C,M){if(C===M){var I=M[1],N=M[2],V=M[3],Q=M[6],W=M[7],A=M[11];C[1]=M[4],C[2]=M[8],C[3]=M[12],C[4]=I,C[6]=M[9],C[7]=M[13],C[8]=N,C[9]=Q,C[11]=M[14],C[12]=V,C[13]=W,C[14]=A}else C[0]=M[0],C[1]=M[4],C[2]=M[8],C[3]=M[12],C[4]=M[1],C[5]=M[5],C[6]=M[9],C[7]=M[13],C[8]=M[2],C[9]=M[6],C[10]=M[10],C[11]=M[14],C[12]=M[3],C[13]=M[7],C[14]=M[11],C[15]=M[15];return C}function KM(C,M){var I=M[0],N=M[1],V=M[2],Q=M[3],W=M[4],A=M[5],E=M[6],X=M[7],Y=M[8],$=M[9],K=M[10],B=M[11],L=M[12],P=M[13],Z=M[14],H=M[15],O=I*A-N*W,U=I*E-V*W,G=I*X-Q*W,J=N*E-V*A,D=N*X-Q*A,S=V*X-Q*E,_=Y*P-$*L,T=Y*Z-K*L,j=Y*H-B*L,h=$*Z-K*P,q=$*H-B*P,p=K*H-B*Z,R=O*p-U*q+G*h+J*j-D*T+S*_;if(!R)return null;return R=1/R,C[0]=(A*p-E*q+X*h)*R,C[1]=(V*q-N*p-Q*h)*R,C[2]=(P*S-Z*D+H*J)*R,C[3]=(K*D-$*S-B*J)*R,C[4]=(E*j-W*p-X*T)*R,C[5]=(I*p-V*j+Q*T)*R,C[6]=(Z*G-L*S-H*U)*R,C[7]=(Y*S-K*G+B*U)*R,C[8]=(W*q-A*j+X*_)*R,C[9]=(N*j-I*q-Q*_)*R,C[10]=(L*D-P*G+H*O)*R,C[11]=($*G-Y*D-B*O)*R,C[12]=(A*T-W*h-E*_)*R,C[13]=(I*h-N*T+V*_)*R,C[14]=(P*U-L*J-Z*O)*R,C[15]=(Y*J-$*U+K*O)*R,C}function PM(C,M){var I=M[0],N=M[1],V=M[2],Q=M[3],W=M[4],A=M[5],E=M[6],X=M[7],Y=M[8],$=M[9],K=M[10],B=M[11],L=M[12],P=M[13],Z=M[14],H=M[15];return C[0]=A*(K*H-B*Z)-$*(E*H-X*Z)+P*(E*B-X*K),C[1]=-(N*(K*H-B*Z)-$*(V*H-Q*Z)+P*(V*B-Q*K)),C[2]=N*(E*H-X*Z)-A*(V*H-Q*Z)+P*(V*X-Q*E),C[3]=-(N*(E*B-X*K)-A*(V*B-Q*K)+$*(V*X-Q*E)),C[4]=-(W*(K*H-B*Z)-Y*(E*H-X*Z)+L*(E*B-X*K)),C[5]=I*(K*H-B*Z)-Y*(V*H-Q*Z)+L*(V*B-Q*K),C[6]=-(I*(E*H-X*Z)-W*(V*H-Q*Z)+L*(V*X-Q*E)),C[7]=I*(E*B-X*K)-W*(V*B-Q*K)+Y*(V*X-Q*E),C[8]=W*($*H-B*P)-Y*(A*H-X*P)+L*(A*B-X*$),C[9]=-(I*($*H-B*P)-Y*(N*H-Q*P)+L*(N*B-Q*$)),C[10]=I*(A*H-X*P)-W*(N*H-Q*P)+L*(N*X-Q*A),C[11]=-(I*(A*B-X*$)-W*(N*B-Q*$)+Y*(N*X-Q*A)),C[12]=-(W*($*Z-K*P)-Y*(A*Z-E*P)+L*(A*K-E*$)),C[13]=I*($*Z-K*P)-Y*(N*Z-V*P)+L*(N*K-V*$),C[14]=-(I*(A*Z-E*P)-W*(N*Z-V*P)+L*(N*E-V*A)),C[15]=I*(A*K-E*$)-W*(N*K-V*$)+Y*(N*E-V*A),C}function LM(C){var M=C[0],I=C[1],N=C[2],V=C[3],Q=C[4],W=C[5],A=C[6],E=C[7],X=C[8],Y=C[9],$=C[10],K=C[11],B=C[12],L=C[13],P=C[14],Z=C[15],H=M*W-I*Q,O=M*A-N*Q,U=M*E-V*Q,G=I*A-N*W,J=I*E-V*W,D=N*E-V*A,S=X*L-Y*B,_=X*P-$*B,T=X*Z-K*B,j=Y*P-$*L,h=Y*Z-K*L,q=$*Z-K*P;return H*q-O*h+U*j+G*T-J*_+D*S}function l0(C,M,I){var N=M[0],V=M[1],Q=M[2],W=M[3],A=M[4],E=M[5],X=M[6],Y=M[7],$=M[8],K=M[9],B=M[10],L=M[11],P=M[12],Z=M[13],H=M[14],O=M[15],U=I[0],G=I[1],J=I[2],D=I[3];return C[0]=U*N+G*A+J*$+D*P,C[1]=U*V+G*E+J*K+D*Z,C[2]=U*Q+G*X+J*B+D*H,C[3]=U*W+G*Y+J*L+D*O,U=I[4],G=I[5],J=I[6],D=I[7],C[4]=U*N+G*A+J*$+D*P,C[5]=U*V+G*E+J*K+D*Z,C[6]=U*Q+G*X+J*B+D*H,C[7]=U*W+G*Y+J*L+D*O,U=I[8],G=I[9],J=I[10],D=I[11],C[8]=U*N+G*A+J*$+D*P,C[9]=U*V+G*E+J*K+D*Z,C[10]=U*Q+G*X+J*B+D*H,C[11]=U*W+G*Y+J*L+D*O,U=I[12],G=I[13],J=I[14],D=I[15],C[12]=U*N+G*A+J*$+D*P,C[13]=U*V+G*E+J*K+D*Z,C[14]=U*Q+G*X+J*B+D*H,C[15]=U*W+G*Y+J*L+D*O,C}function HM(C,M,I){var N=I[0],V=I[1],Q=I[2],W,A,E,X,Y,$,K,B,L,P,Z,H;if(M===C)C[12]=M[0]*N+M[4]*V+M[8]*Q+M[12],C[13]=M[1]*N+M[5]*V+M[9]*Q+M[13],C[14]=M[2]*N+M[6]*V+M[10]*Q+M[14],C[15]=M[3]*N+M[7]*V+M[11]*Q+M[15];else W=M[0],A=M[1],E=M[2],X=M[3],Y=M[4],$=M[5],K=M[6],B=M[7],L=M[8],P=M[9],Z=M[10],H=M[11],C[0]=W,C[1]=A,C[2]=E,C[3]=X,C[4]=Y,C[5]=$,C[6]=K,C[7]=B,C[8]=L,C[9]=P,C[10]=Z,C[11]=H,C[12]=W*N+Y*V+L*Q+M[12],C[13]=A*N+$*V+P*Q+M[13],C[14]=E*N+K*V+Z*Q+M[14],C[15]=X*N+B*V+H*Q+M[15];return C}function JM(C,M,I){var N=I[0],V=I[1],Q=I[2];return C[0]=M[0]*N,C[1]=M[1]*N,C[2]=M[2]*N,C[3]=M[3]*N,C[4]=M[4]*V,C[5]=M[5]*V,C[6]=M[6]*V,C[7]=M[7]*V,C[8]=M[8]*Q,C[9]=M[9]*Q,C[10]=M[10]*Q,C[11]=M[11]*Q,C[12]=M[12],C[13]=M[13],C[14]=M[14],C[15]=M[15],C}function DM(C,M,I,N){var V=N[0],Q=N[1],W=N[2],A=Math.hypot(V,Q,W),E,X,Y,$,K,B,L,P,Z,H,O,U,G,J,D,S,_,T,j,h,q,p,R,w;if(A0)I[0]=(A*W+Y*N+E*Q-X*V)*2/$,I[1]=(E*W+Y*V+X*N-A*Q)*2/$,I[2]=(X*W+Y*Q+A*V-E*N)*2/$;else I[0]=(A*W+Y*N+E*Q-X*V)*2,I[1]=(E*W+Y*V+X*N-A*Q)*2,I[2]=(X*W+Y*Q+A*V-E*N)*2;return c0(C,M,I),C}function hM(C,M){return C[0]=M[12],C[1]=M[13],C[2]=M[14],C}function z0(C,M){var I=M[0],N=M[1],V=M[2],Q=M[4],W=M[5],A=M[6],E=M[8],X=M[9],Y=M[10];return C[0]=Math.hypot(I,N,V),C[1]=Math.hypot(Q,W,A),C[2]=Math.hypot(E,X,Y),C}function qM(C,M){var I=new k(3);z0(I,M);var N=1/I[0],V=1/I[1],Q=1/I[2],W=M[0]*N,A=M[1]*V,E=M[2]*Q,X=M[4]*N,Y=M[5]*V,$=M[6]*Q,K=M[8]*N,B=M[9]*V,L=M[10]*Q,P=W+Y+L,Z=0;if(P>0)Z=Math.sqrt(P+1)*2,C[3]=0.25*Z,C[0]=($-B)/Z,C[1]=(K-E)/Z,C[2]=(A-X)/Z;else if(W>Y&&W>L)Z=Math.sqrt(1+W-Y-L)*2,C[3]=($-B)/Z,C[0]=0.25*Z,C[1]=(A+X)/Z,C[2]=(K+E)/Z;else if(Y>L)Z=Math.sqrt(1+Y-W-L)*2,C[3]=(K-E)/Z,C[0]=(A+X)/Z,C[1]=0.25*Z,C[2]=($+B)/Z;else Z=Math.sqrt(1+L-W-Y)*2,C[3]=(A-X)/Z,C[0]=(K+E)/Z,C[1]=($+B)/Z,C[2]=0.25*Z;return C}function pM(C,M,I,N){var V=M[0],Q=M[1],W=M[2],A=M[3],E=V+V,X=Q+Q,Y=W+W,$=V*E,K=V*X,B=V*Y,L=Q*X,P=Q*Y,Z=W*Y,H=A*E,O=A*X,U=A*Y,G=N[0],J=N[1],D=N[2];return C[0]=(1-(L+Z))*G,C[1]=(K+U)*G,C[2]=(B-O)*G,C[3]=0,C[4]=(K-U)*J,C[5]=(1-($+Z))*J,C[6]=(P+H)*J,C[7]=0,C[8]=(B+O)*D,C[9]=(P-H)*D,C[10]=(1-($+L))*D,C[11]=0,C[12]=I[0],C[13]=I[1],C[14]=I[2],C[15]=1,C}function vM(C,M,I,N,V){var Q=M[0],W=M[1],A=M[2],E=M[3],X=Q+Q,Y=W+W,$=A+A,K=Q*X,B=Q*Y,L=Q*$,P=W*Y,Z=W*$,H=A*$,O=E*X,U=E*Y,G=E*$,J=N[0],D=N[1],S=N[2],_=V[0],T=V[1],j=V[2],h=(1-(P+H))*J,q=(B+G)*J,p=(L-U)*J,R=(B-G)*D,w=(1-(K+H))*D,c=(Z+O)*D,z=(L+U)*S,A0=(Z-O)*S,E0=(1-(K+P))*S;return C[0]=h,C[1]=q,C[2]=p,C[3]=0,C[4]=R,C[5]=w,C[6]=c,C[7]=0,C[8]=z,C[9]=A0,C[10]=E0,C[11]=0,C[12]=I[0]+_-(h*_+R*T+z*j),C[13]=I[1]+T-(q*_+w*T+A0*j),C[14]=I[2]+j-(p*_+c*T+E0*j),C[15]=1,C}function wM(C,M){var I=M[0],N=M[1],V=M[2],Q=M[3],W=I+I,A=N+N,E=V+V,X=I*W,Y=N*W,$=N*A,K=V*W,B=V*A,L=V*E,P=Q*W,Z=Q*A,H=Q*E;return C[0]=1-$-L,C[1]=Y+H,C[2]=K-Z,C[3]=0,C[4]=Y-H,C[5]=1-X-L,C[6]=B+P,C[7]=0,C[8]=K+Z,C[9]=B-P,C[10]=1-X-$,C[11]=0,C[12]=0,C[13]=0,C[14]=0,C[15]=1,C}function gM(C,M,I,N,V,Q,W){var A=1/(I-M),E=1/(V-N),X=1/(Q-W);return C[0]=Q*2*A,C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[5]=Q*2*E,C[6]=0,C[7]=0,C[8]=(I+M)*A,C[9]=(V+N)*E,C[10]=(W+Q)*X,C[11]=-1,C[12]=0,C[13]=0,C[14]=W*Q*2*X,C[15]=0,C}function y0(C,M,I,N,V){var Q=1/Math.tan(M/2),W;if(C[0]=Q/I,C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[5]=Q,C[6]=0,C[7]=0,C[8]=0,C[9]=0,C[11]=-1,C[12]=0,C[13]=0,C[15]=0,V!=null&&V!==Infinity)W=1/(N-V),C[10]=(V+N)*W,C[14]=2*V*N*W;else C[10]=-1,C[14]=-2*N;return C}function fM(C,M,I,N,V){var Q=1/Math.tan(M/2),W;if(C[0]=Q/I,C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[5]=Q,C[6]=0,C[7]=0,C[8]=0,C[9]=0,C[11]=-1,C[12]=0,C[13]=0,C[15]=0,V!=null&&V!==Infinity)W=1/(N-V),C[10]=V*W,C[14]=V*N*W;else C[10]=-1,C[14]=-N;return C}function iM(C,M,I,N){var V=Math.tan(M.upDegrees*Math.PI/180),Q=Math.tan(M.downDegrees*Math.PI/180),W=Math.tan(M.leftDegrees*Math.PI/180),A=Math.tan(M.rightDegrees*Math.PI/180),E=2/(W+A),X=2/(V+Q);return C[0]=E,C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[5]=X,C[6]=0,C[7]=0,C[8]=-((W-A)*E*0.5),C[9]=(V-Q)*X*0.5,C[10]=N/(I-N),C[11]=-1,C[12]=0,C[13]=0,C[14]=N*I/(I-N),C[15]=0,C}function r0(C,M,I,N,V,Q,W){var A=1/(M-I),E=1/(N-V),X=1/(Q-W);return C[0]=-2*A,C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[5]=-2*E,C[6]=0,C[7]=0,C[8]=0,C[9]=0,C[10]=2*X,C[11]=0,C[12]=(M+I)*A,C[13]=(V+N)*E,C[14]=(W+Q)*X,C[15]=1,C}function lM(C,M,I,N,V,Q,W){var A=1/(M-I),E=1/(N-V),X=1/(Q-W);return C[0]=-2*A,C[1]=0,C[2]=0,C[3]=0,C[4]=0,C[5]=-2*E,C[6]=0,C[7]=0,C[8]=0,C[9]=0,C[10]=X,C[11]=0,C[12]=(M+I)*A,C[13]=(V+N)*E,C[14]=Q*X,C[15]=1,C}function cM(C,M,I,N){var V,Q,W,A,E,X,Y,$,K,B,L=M[0],P=M[1],Z=M[2],H=N[0],O=N[1],U=N[2],G=I[0],J=I[1],D=I[2];if(Math.abs(L-G)0)B=1/Math.sqrt(B),Y*=B,$*=B,K*=B;var L=E*K-X*$,P=X*Y-A*K,Z=A*$-E*Y;if(B=L*L+P*P+Z*Z,B>0)B=1/Math.sqrt(B),L*=B,P*=B,Z*=B;return C[0]=L,C[1]=P,C[2]=Z,C[3]=0,C[4]=$*Z-K*P,C[5]=K*L-Y*Z,C[6]=Y*P-$*L,C[7]=0,C[8]=Y,C[9]=$,C[10]=K,C[11]=0,C[12]=V,C[13]=Q,C[14]=W,C[15]=1,C}function yM(C){return"mat4("+C[0]+", "+C[1]+", "+C[2]+", "+C[3]+", "+C[4]+", "+C[5]+", "+C[6]+", "+C[7]+", "+C[8]+", "+C[9]+", "+C[10]+", "+C[11]+", "+C[12]+", "+C[13]+", "+C[14]+", "+C[15]+")"}function rM(C){return Math.hypot(C[0],C[1],C[2],C[3],C[4],C[5],C[6],C[7],C[8],C[9],C[10],C[11],C[12],C[13],C[14],C[15])}function xM(C,M,I){return C[0]=M[0]+I[0],C[1]=M[1]+I[1],C[2]=M[2]+I[2],C[3]=M[3]+I[3],C[4]=M[4]+I[4],C[5]=M[5]+I[5],C[6]=M[6]+I[6],C[7]=M[7]+I[7],C[8]=M[8]+I[8],C[9]=M[9]+I[9],C[10]=M[10]+I[10],C[11]=M[11]+I[11],C[12]=M[12]+I[12],C[13]=M[13]+I[13],C[14]=M[14]+I[14],C[15]=M[15]+I[15],C}function x0(C,M,I){return C[0]=M[0]-I[0],C[1]=M[1]-I[1],C[2]=M[2]-I[2],C[3]=M[3]-I[3],C[4]=M[4]-I[4],C[5]=M[5]-I[5],C[6]=M[6]-I[6],C[7]=M[7]-I[7],C[8]=M[8]-I[8],C[9]=M[9]-I[9],C[10]=M[10]-I[10],C[11]=M[11]-I[11],C[12]=M[12]-I[12],C[13]=M[13]-I[13],C[14]=M[14]-I[14],C[15]=M[15]-I[15],C}function sM(C,M,I){return C[0]=M[0]*I,C[1]=M[1]*I,C[2]=M[2]*I,C[3]=M[3]*I,C[4]=M[4]*I,C[5]=M[5]*I,C[6]=M[6]*I,C[7]=M[7]*I,C[8]=M[8]*I,C[9]=M[9]*I,C[10]=M[10]*I,C[11]=M[11]*I,C[12]=M[12]*I,C[13]=M[13]*I,C[14]=M[14]*I,C[15]=M[15]*I,C}function mM(C,M,I,N){return C[0]=M[0]+I[0]*N,C[1]=M[1]+I[1]*N,C[2]=M[2]+I[2]*N,C[3]=M[3]+I[3]*N,C[4]=M[4]+I[4]*N,C[5]=M[5]+I[5]*N,C[6]=M[6]+I[6]*N,C[7]=M[7]+I[7]*N,C[8]=M[8]+I[8]*N,C[9]=M[9]+I[9]*N,C[10]=M[10]+I[10]*N,C[11]=M[11]+I[11]*N,C[12]=M[12]+I[12]*N,C[13]=M[13]+I[13]*N,C[14]=M[14]+I[14]*N,C[15]=M[15]+I[15]*N,C}function eM(C,M){return C[0]===M[0]&&C[1]===M[1]&&C[2]===M[2]&&C[3]===M[3]&&C[4]===M[4]&&C[5]===M[5]&&C[6]===M[6]&&C[7]===M[7]&&C[8]===M[8]&&C[9]===M[9]&&C[10]===M[10]&&C[11]===M[11]&&C[12]===M[12]&&C[13]===M[13]&&C[14]===M[14]&&C[15]===M[15]}function bM(C,M){var I=C[0],N=C[1],V=C[2],Q=C[3],W=C[4],A=C[5],E=C[6],X=C[7],Y=C[8],$=C[9],K=C[10],B=C[11],L=C[12],P=C[13],Z=C[14],H=C[15],O=M[0],U=M[1],G=M[2],J=M[3],D=M[4],S=M[5],_=M[6],T=M[7],j=M[8],h=M[9],q=M[10],p=M[11],R=M[12],w=M[13],c=M[14],z=M[15];return Math.abs(I-O)<=F*Math.max(1,Math.abs(I),Math.abs(O))&&Math.abs(N-U)<=F*Math.max(1,Math.abs(N),Math.abs(U))&&Math.abs(V-G)<=F*Math.max(1,Math.abs(V),Math.abs(G))&&Math.abs(Q-J)<=F*Math.max(1,Math.abs(Q),Math.abs(J))&&Math.abs(W-D)<=F*Math.max(1,Math.abs(W),Math.abs(D))&&Math.abs(A-S)<=F*Math.max(1,Math.abs(A),Math.abs(S))&&Math.abs(E-_)<=F*Math.max(1,Math.abs(E),Math.abs(_))&&Math.abs(X-T)<=F*Math.max(1,Math.abs(X),Math.abs(T))&&Math.abs(Y-j)<=F*Math.max(1,Math.abs(Y),Math.abs(j))&&Math.abs($-h)<=F*Math.max(1,Math.abs($),Math.abs(h))&&Math.abs(K-q)<=F*Math.max(1,Math.abs(K),Math.abs(q))&&Math.abs(B-p)<=F*Math.max(1,Math.abs(B),Math.abs(p))&&Math.abs(L-R)<=F*Math.max(1,Math.abs(L),Math.abs(R))&&Math.abs(P-w)<=F*Math.max(1,Math.abs(P),Math.abs(w))&&Math.abs(Z-c)<=F*Math.max(1,Math.abs(Z),Math.abs(c))&&Math.abs(H-z)<=F*Math.max(1,Math.abs(H),Math.abs(z))}var nM=y0,dM=r0,uM=l0,oM=x0;class l{C;M;I;constructor(C=d.create(),M=f.create(),I=d.fromValues(1,1,1)){this.position=C;this.rotation=M;this.scale=I}rotateEuler(C,M,I){return f.fromEuler(this.rotation,C,M,I),this}toMat4(){const C=v.create();return v.fromRotationTranslationScale(C,this.rotation,this.position,this.scale),C}}var ZI=(C)=>f.fromEuler(f.create(),C[0],C[1],C[2]),$I=(C)=>[C,C,C];class g{C;constructor(C){this.app=C;this.onStart&&C.onStart(this.onStart.bind(this)),this.onUpdate&&C.onUpdate(this.onUpdate.bind(this)),this.onAfterUpdate&&C.onAfterUpdate(this.onAfterUpdate.bind(this)),this.onBeforeUpdate&&C.onBeforeUpdate(this.onBeforeUpdate.bind(this)),this.onDraw&&C.onDraw(this.onDraw.bind(this))}}class M0 extends g{C;M;I;N;V;Q;projectionMatrix=v.create();buffers={textures:{}};faceDataType;colorDataType;constructor(C,M,I,N=new l([0,0,-6]),V=new l([100,100,0]),Q={}){super(C);this.app=C;this.mesh=M;this.shader=I;this.camera=N;this.light=V;this.config=Q;this.faceDataType=this.getDataType(M.config.faces),this.colorDataType=M.config.colors?this.getDataType(M.config.colors):null}getDataType(C){switch(C.BYTES_PER_ELEMENT){case 1:return 5121;case 2:return 5123;case 4:return 5125;default:return 5126}}configure(C){return this.config=C,this}makeBuffer(C,M=34962){const I=this.app.gl,N=I.createBuffer();if(!N)throw new Error("failed to create a buffer");return I.bindBuffer(M,N),I.bufferData(M,C,I.STATIC_DRAW),I.bindBuffer(M,null),N}initializeBuffers(){const C=this.app.gl.createVertexArray();if(!C)throw new Error("VAO creation failed");this.buffers.vao=C,this.app.gl.bindVertexArray(C),this.buffers.faces=this.makeBuffer(this.mesh.config.faces,this.app.gl.ELEMENT_ARRAY_BUFFER);const M=this.shader.mappings;if(this.buffers.position=this.makeBuffer(this.mesh.config.positions),this.bindAttrib(this.buffers.position,M.attributes.vertex,3,this.app.gl.FLOAT),this.mesh.config.normals)this.buffers.normal=this.makeBuffer(this.mesh.config.normals),this.bindAttrib(this.buffers.normal,M.attributes.normal,3,this.app.gl.FLOAT,!0);if(this.mesh.config.colors)this.buffers.color=this.makeBuffer(this.mesh.config.colors),this.bindAttrib(this.buffers.color,M.attributes.vertexColor,4,this.colorDataType||this.app.gl.UNSIGNED_BYTE);if(this.mesh.config.uvs)this.buffers.uv=this.makeBuffer(this.mesh.config.uvs),this.bindAttrib(this.buffers.uv,M.attributes.uv0,2,this.app.gl.FLOAT);this.app.gl.bindVertexArray(null)}async initializeTextures(){const{gl:C}=this.app;for(let[M,I]of Object.entries(this.shader.textures)){await I.loadImage();const N=C.createTexture();if(!N)throw new Error("failed to allocate texture");const V=I.texture;C.bindTexture(C.TEXTURE_2D,N),C.texImage2D(C.TEXTURE_2D,0,C.RGBA,I.width,I.height,0,C.RGBA,C.UNSIGNED_BYTE,V);const Q=I.config.uvClamp?C.CLAMP_TO_EDGE:C.REPEAT;C.texParameteri(C.TEXTURE_2D,C.TEXTURE_WRAP_S,Q),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_WRAP_T,Q),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_MAG_FILTER,C.NEAREST),C.texParameteri(C.TEXTURE_2D,C.TEXTURE_MIN_FILTER,C.NEAREST),this.buffers.textures[M]=N}}bindTextures(){const{gl:C}=this.app,M=this.app.gl.TEXTURE0,I=Object.entries(this.buffers.textures),N=[];return I.forEach(([V,Q],W)=>{const A=this.shader.mappings.uniforms[V];if(!A)return;C.activeTexture(M+W),C.bindTexture(C.TEXTURE_2D,Q),C.uniform1i(A,W),N.push(()=>{C.activeTexture(M+W),C.bindTexture(C.TEXTURE_2D,null)})}),N}bindAttrib(C,M,I,N,V=!1){const Q=this.app.gl;Q.bindBuffer(Q.ARRAY_BUFFER,C);const W=Number.isSafeInteger(M)?M:this.shader.attrib(M);if(W!==-1)Q.vertexAttribPointer(W,I,N,V,0,0),Q.enableVertexAttribArray(W);Q.bindBuffer(Q.ARRAY_BUFFER,null)}initializeShader(C,M){const I=v.invert(v.create(),this.camera.toMat4()),N=this.app.gl,{uniforms:V}=this.shader.mappings;this.shader.use(),N.uniform1f(V.time,C),N.uniform4fv(V.light0Color,[1,1,1,1]),N.uniformMatrix4fv(V.view,!1,I),N.uniformMatrix4fv(V.projection,!1,this.projectionMatrix),N.uniform3fv(V.light0,this.light.position),N.uniformMatrix4fv(V.objectToWorld,!1,M.toMat4()),N.uniformMatrix4fv(V.objectToWorldInv,!1,v.invert(v.create(),M.toMat4())),this.shader.onPrerender(this.app,C)}async onStart(C,M){M.loading("baking vectors"),M.telemetry?.addRenderers(1),M.telemetry?.addTriangles(this.mesh.config.faces.length),M.telemetry?.addVertexes(this.mesh.config.vertexCount),v.perspective(this.projectionMatrix,this.app.config.fov||45,this.app.aspect,this.app.config.zNear||0.1,this.app.config.zFar||100),this.shader.compile(),this.shader.link(),this.initializeBuffers(),this.shader.link(),await this.initializeTextures()}onRenderableUpdate(C,M){const I=this.app.gl;I.bindVertexArray(this.buffers.vao||null),I.bindBuffer(I.ELEMENT_ARRAY_BUFFER,this.buffers.faces||null),I.bindBuffer(I.ARRAY_BUFFER,this.buffers.position||null),this.initializeShader(C,M);const N=this.bindTextures();I.drawElements(this.config.drawMode??I.TRIANGLES,this.mesh.config.faces.length,this.faceDataType,0);const V=I.getError();if(V!==0)throw console.log({err:V}),new Error(`(MeshRenderer) webgl failure: ${V}`);I.bindVertexArray(null),I.bindBuffer(I.ELEMENT_ARRAY_BUFFER,null),I.bindBuffer(I.ARRAY_BUFFER,null),N.forEach((Q)=>Q())}}class I0 extends g{constructor(){super(...arguments)}panes=[];addTransform(C,M){this.panes.push({name:C,type:"transform",onChange:M})}}class N0 extends g{C;el;frameTimes=[];maxFrameTimes=100;lastFrameTime=0;activeTriangles=0;activeVertexes=0;activeRenderers=0;activeTextures=0;constructor(C,M="#telemetry"){super(C);this.app=C;if(this.el=document.querySelector(M),this.el&&location.search.includes("telemetry"))this.el.style.display="block"}insertTime(C){if(this.frameTimes.push(C),this.frameTimes.length>this.maxFrameTimes)this.frameTimes.shift()}async onStart(){this.lastFrameTime=0,this.frameTimes=[],setTimeout(()=>this.setText(),0),setInterval(()=>{this.setText()},1001)}setText(){const C=this.frameTimes.reduce((I,N)=>I+N,0)/this.frameTimes.length,M=1000/C;this.el.innerHTML=`${M.toFixed(1)} FPS (${C.toFixed(3)} ms)
update :: b: ${this.app.registry.onBeforeUpdate.length} | u: ${this.app.registry.onUpdate.length} | a: ${this.app.registry.onAfterUpdate.length} | d: ${this.app.registry.onDraw.length}
render :: mr: ${this.activeRenderers} | v: ${this.activeVertexes} | t: ${this.activeTriangles}
others :: tex: ${this.activeTextures}`}onAfterUpdate(C){const M=C-this.lastFrameTime;this.insertTime(M),this.lastFrameTime=C}addTriangles(C){this.activeTriangles+=C}addVertexes(C){this.activeVertexes+=C}addRenderers(C){this.activeRenderers+=C}addTextures(C){this.activeTextures+=C}}class tM{C;canvas;telemetry;gl;editor;loadingMessages=new Set(["[noeidelon] [stage 2]"]);registry={onBeforeUpdate:[],onAfterUpdate:[],onUpdate:[],onStart:[],onDraw:[]};constructor(C={}){this.config=C;try{this.canvas=document.querySelector("canvas"),this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight;const M=this.canvas.getContext("webgl2");if(!M)throw new Error("Canvas was unable to get a webgl2 context");const I=this.gl=M;if(I.viewport(0,0,I.drawingBufferWidth,I.drawingBufferHeight),this.gl.getExtension("EXT_texture_filter_anisotropic"),location.search.includes("telemetry")||C.telemetry)this.telemetry=new N0(this);if(location.search.includes("editor")||C.editor)this.editor=new I0(this)}catch(M){const I=document.querySelector("main");if(I)I.innerHTML="your browser didn't let me set up webgl.
";throw new Error(`Unable to initialize WebGL. Your browser or machine may not support it.\n -> ${M}`)}}get aspect(){return this.canvas.clientWidth/this.canvas.clientHeight}clear(){const C=this.gl;C.clearColor(0,0,0,1),C.clearDepth(1),C.enable(C.DEPTH_TEST),C.depthFunc(C.LEQUAL),C.clear(C.COLOR_BUFFER_BIT|C.DEPTH_BUFFER_BIT)}loading(C){this.loadingMessages.add(C.toLowerCase()),document.querySelector("#loading-text").innerHTML=[...this.loadingMessages].join("
")}ready(){document.querySelector("#loading")?.classList.remove("loading-active")}onBeforeUpdate(C){this.registry.onBeforeUpdate.push(C)}onAfterUpdate(C){this.registry.onAfterUpdate.push(C)}onUpdate(C){this.registry.onUpdate.push(C)}onStart(C){this.registry.onStart.push(C)}onDraw(C){this.registry.onDraw.push(C)}doUpdate(C){this.registry.onBeforeUpdate.forEach((M)=>M(C,this)),this.registry.onUpdate.forEach((M)=>M(C,this)),this.registry.onAfterUpdate.forEach((M)=>M(C,this)),this.registry.onDraw.forEach((M)=>M(C,this))}async doStart(C=0){this.loading("setting launch parameters"),this.clear();try{for(let M of this.registry.onStart)await M(C,this)}catch(M){if(this.loading('[panic] failed to start noeidelon'),this.telemetry)this.loading(`${M}`);return}this.ready()}async oneShot(C=0){await this.doStart(C),this.doUpdate(C)}async start(){await this.doStart();const C=(M)=>{this.doUpdate(M),requestAnimationFrame(C)};requestAnimationFrame(C)}}class i{C;static VERTEX=35633;static FRAGMENT=35632;constructor(C){this.config=C}vertexCode="";fragmentCode="";_app;program=null;mappings={};textures={};materialValues={};prerenderHooks=[];get gl(){const C=this._app?.gl;if(!C)throw new Error("GL context not defined at shader compile time.");return C}app(C){return this._app=C,this.program=C.gl.createProgram(),this}vertex(C){return this.vertexCode=C,this}fragment(C){return this.fragmentCode=C,this}prerenderHook(C){return this.prerenderHooks.push(C),this}attrib(C){return this.gl.getAttribLocation(this.program,C)}uniform(C){return this.gl.getUniformLocation(this.program,C)}generateMappings(C){return{attributes:{normal:this.attrib(C.attributes.normal),uv0:this.attrib(C.attributes.uv0),vertex:this.attrib(C.attributes.vertex),vertexColor:this.attrib(C.attributes.vertexColor)},uniforms:{albedo:this.uniform(C.uniforms.albedo),light0:this.uniform(C.uniforms.light0),light0Color:this.uniform(C.uniforms.light0Color),objectToWorld:this.uniform(C.uniforms.objectToWorld),objectToWorldInv:this.uniform(C.uniforms.objectToWorldInv),projection:this.uniform(C.uniforms.projection),texture0:this.uniform(C.uniforms.texture0),texture1:this.uniform(C.uniforms.texture1),texture2:this.uniform(C.uniforms.texture2),time:this.uniform(C.uniforms.time),view:this.uniform(C.uniforms.view)}}}attach(C,M){const I=this.gl,N=I.createShader(C);if(!N)throw new Error(`failed to init ${aM(C)} shader`);I.shaderSource(N,M),I.compileShader(N),I.attachShader(this.program,N)}addTexture(C,M){return this.textures[C]=M,this}compile(){const C=this.gl;this.attach(C.FRAGMENT_SHADER,this.fragmentCode),this.attach(C.VERTEX_SHADER,this.vertexCode)}link(){if(this.gl.linkProgram(this.program),!this.gl.getProgramParameter(this.program,this.gl.LINK_STATUS))throw new Error("Unable to initialize the shader program: "+this.gl.getProgramInfoLog(this.program));this.mappings=this.generateMappings(this.config)}bindAttrib(C,M){this.gl.bindAttribLocation(this.program,C,M)}use(){this._app?.gl.useProgram(this.program)}onPrerender(C,M){for(let I of this.prerenderHooks)I(C,this,M)}}var aM=(C)=>{switch(C){case i.FRAGMENT:return"fragment";case i.VERTEX:return"vertex";default:return"some unknown type of"}};var s0=`#version 300 es
+precision highp float;uniform sampler2D u_texture_0;uniform sampler2D u_texture_1;in vec2 uv0;in vec3 normal;in vec3 light_pos;out vec4 fragColor;void main(){vec4 normalTex=texture(u_texture_1,uv0);vec3 normal=normalize(normal*normalTex.xyz);float light=dot(normal,light_pos);fragColor=vec4(1.0);fragColor.rgb=texture(u_texture_0,uv0).rgb;fragColor.rgb*=max(light,0.1);fragColor.a=1.0;}`;var b=`#version 300 es
+uniform mat4 u_view;uniform mat4 u_projection;uniform mat4 u_object_to_world;uniform mat4 u_object_to_world_inv;uniform vec3 u_light_0;in vec4 a_vertex;in vec2 a_uv0;in vec3 a_normal;in vec4 a_vertex_color;out vec2 uv0;out vec3 normal;out vec4 vertex_color;out vec3 light_pos;void main(){mat4 worldInv=inverse(u_view);mat4 MVW=u_projection*u_view*u_object_to_world;gl_Position=MVW*a_vertex;uv0=a_uv0;normal=normalize(mat3(worldInv)*a_normal);vertex_color=a_vertex_color;light_pos=normalize(mat3(u_object_to_world_inv)*u_light_0);}`;var V0={attributes:{vertex:"a_vertex",uv0:"a_uv0",normal:"a_normal",vertexColor:"a_vertex_color"},uniforms:{view:"u_view",projection:"u_projection",objectToWorld:"u_object_to_world",objectToWorldInv:"u_object_to_world_inv",light0:"u_light_0",light0Color:"u_light_0_color",time:"u_time",albedo:"u_albedo",texture0:"u_texture_0",texture1:"u_texture_1",texture2:"u_texture_2"}},nI=(C)=>new i(V0).vertex(b).fragment(s0).app(C);var m0=`#version 300 es
+precision highp float;in vec4 vertex_color;out vec4 fragColor;void main(){fragColor=vertex_color;}`;class Q0{C;constructor(C){this.config=C}get name(){return this.config.name}}var e0=new Q0({colors:new Uint8Array([0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255]),faces:new Uint8Array([0,1,2,3,4,1,5,6,4,7,8,6,4,9,10,11,7,5,0,3,1,3,5,4,5,7,6,7,12,8,4,6,9,11,13,7,14,15,16,17,18,15,19,20,18,21,22,20,18,23,24,25,21,19,14,17,15,17,19,18,19,21,20,21,26,22,18,20,23,25,27,21,28,29,30,31,32,29,33,34,32,35,36,34,32,37,38,39,35,33,28,31,29,31,33,32,33,35,34,35,40,36,32,34,37,39,41,35]),name:"src/meshes/gizmo.ply",normals:new Float32Array([-0.057735033,0.5773503,-0.5773503,0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,0.057735033,0.5773503,-0.5773503,0.057735033,-0.5773503,0.5773503,0.057735033,0.5773503,0.5773503,-0.057735033,-0.5773503,0.5773503,-0.057735033,0.5773503,0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,0.057735033,-0.5773503,-0.5773503,0.057735033,0.5773503,-0.5773503,-0.057735033,0.5773503,-0.5773503,-0.057735033,0.5773503,-0.5773503,-0.5773503,0.5773503,-0.057735033,0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,0.5773503,0.5773503,-0.057735033,0.5773503,-0.5773503,0.057735033,0.5773503,0.5773503,0.057735033,-0.5773503,-0.5773503,0.057735033,-0.5773503,0.5773503,0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,0.5773503,-0.5773503,-0.057735033,0.5773503,0.5773503,-0.057735033,-0.5773503,0.5773503,-0.057735033,-0.5773503,0.5773503,-0.057735033,-0.5773503,0.057735033,-0.5773503,0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,0.5773503,0.057735033,-0.5773503,0.5773503,-0.057735033,0.5773503,0.5773503,0.057735033,0.5773503,-0.5773503,-0.057735033,0.5773503,-0.5773503,0.057735033,0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,0.5773503,-0.057735033,-0.5773503,0.5773503,0.057735033,-0.5773503,-0.5773503,0.057735033,-0.5773503,-0.5773503,0.057735033,-0.5773503]),positions:new Float32Array([0,0.05,-0.05,1,-0.05,-0.05,0,-0.05,-0.05,1,0.05,-0.05,1,-0.05,0.05,1,0.05,0.05,0,-0.05,0.05,0,0.05,0.05,0,-0.05,-0.05,0,-0.05,-0.05,1,-0.05,-0.05,1,0.05,-0.05,0,0.05,-0.05,0,0.05,-0.05,-0.05,0.05,0,0.05,-0.05,0,-0.05,-0.05,0,0.05,0.05,0,0.05,-0.05,1,0.05,0.05,1,-0.05,-0.05,1,-0.05,0.05,1,-0.05,-0.05,0,-0.05,-0.05,0,0.05,-0.05,0,0.05,0.05,0,-0.05,0.05,0,-0.05,0.05,0,-0.05,1,-0.05,0.05,0,-0.05,-0.05,0,-0.05,0.05,1,-0.05,0.05,0,0.05,0.05,1,0.05,-0.05,0,0.05,-0.05,1,0.05,-0.05,0,-0.05,-0.05,0,-0.05,0.05,0,-0.05,0.05,1,-0.05,-0.05,1,-0.05,-0.05,1,-0.05]),uvs:new Float32Array([0.625,0,0.375,0.25,0.375,0,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.125,0.75,0.125,0.5,0.875,0.5,0.625,1,0.875,0.75,0.625,0,0.375,0.25,0.375,0,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.125,0.75,0.125,0.5,0.875,0.5,0.625,1,0.875,0.75,0.625,0,0.375,0.25,0.375,0,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.125,0.75,0.125,0.5,0.875,0.5,0.625,1,0.875,0.75]),vertexCount:42});var NI=(C)=>new i(V0).vertex(b).fragment(m0).app(C),b0=(C,M,I)=>{const N=new l(I?.position,I?.rotation),V=new M0(C,e0,NI(C),M).configure({});new W0(C,N,V)};class W0 extends g{C;M;I;constructor(C,M,I,N=!1){super(C);this.app=C;this.transform=M;this.renderer=I;if(N)b0(C,I.camera,M)}onDraw(C){this.renderer.onRenderableUpdate(C,this.transform)}}class VI{C;M;I;texture=null;width=0;height=0;constructor(C,M,I={}){this.app=C;this.url=M;this.config=I}setImage(C,M,I){return this.texture=C,this.width=M,this.height=I,this}async loadImage(){if(this.url==="manual"){if(this.texture===null)throw new Error("manual specified, but texture was not ready...");return}if(this.texture!==null)return;this.app.telemetry?.addTextures(-1),this.app.loading("Fetching textures...");const C=new Image;return new Promise((M,I)=>{C.onload=async()=>{this.texture=await createImageBitmap(C,{imageOrientation:"flipY"}),this.width=this.texture.width,this.height=this.texture.height,this.app.telemetry?.addTextures(2),M(void 0)},C.onerror=(N)=>{this.app.telemetry?.addTextures(1),I(new Error(`texture load of ${this.url} failed: ${N.toString()}`))},C.src=this.url})}}var NN=`#version 300 es
+uniform mat4 u_view;uniform mat4 u_projection;uniform mat4 u_object_to_world;uniform mat4 u_object_to_world_inv;uniform vec3 u_light_0;in vec4 a_vertex;in vec2 a_uv0;in vec3 a_normal;in vec4 a_vertex_color;out vec2 uv0;out vec3 normal;out vec4 vertex_color;out vec3 light_pos;
+#define ROUNDING_FACTOR 230.0f
+void main(){mat4 worldInv=inverse(u_view);mat4 MVW=u_projection*u_view*u_object_to_world;vec4 realPosition=MVW*a_vertex;realPosition.xyz=round(vec3(realPosition.xyz*ROUNDING_FACTOR))/ROUNDING_FACTOR;gl_Position=realPosition;uv0=a_uv0;normal=normalize(mat3(worldInv)*a_normal);vertex_color=a_vertex_color;light_pos=normalize(mat3(u_object_to_world_inv)*u_light_0);}`;
+export{f as a,l as b,ZI as c,$I as d,M0 as e,tM as f,i as g,s0 as h,nI as i,Q0 as j,W0 as k,VI as l,NN as m};
diff --git a/html/fox-normal-7ce4a77b1285eb7a.png b/html/fox-normal-7ce4a77b1285eb7a.png
new file mode 100644
index 0000000..970533b
Binary files /dev/null and b/html/fox-normal-7ce4a77b1285eb7a.png differ
diff --git a/html/fox-tex-03f042508a92e722.png b/html/fox-tex-03f042508a92e722.png
new file mode 100644
index 0000000..ffa6333
Binary files /dev/null and b/html/fox-tex-03f042508a92e722.png differ
diff --git a/html/index.html b/html/index.html
index 10a5a01..659ff5c 100644
--- a/html/index.html
+++ b/html/index.html
@@ -31,6 +31,7 @@
+ - ./004-a-new-leaf
- ./003-scene
- ./002-webgl-engine
- ./001-platform-provenance
diff --git a/html/ramp-aa773f5148819e95.png b/html/ramp-aa773f5148819e95.png
new file mode 100644
index 0000000..5ea6dab
Binary files /dev/null and b/html/ramp-aa773f5148819e95.png differ
diff --git a/package.json b/package.json
index 4e1a814..4eb2257 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"main": "./hack/build.ts",
"scripts": {
"build": "bun $BUNFLAGS .",
- "build:watch": "MINIFY=false nodemon -e ts,js,frag,vert,glsl,ply",
+ "build:watch": "MINIFY=false nodemon -e ts,js,frag,vert,glsl,ply,png",
"serve": "serve ./html",
"dev": "run-p serve build:watch"
},
diff --git a/src/003-scene/main.ts b/src/003-scene/main.ts
index 675350e..6e762ce 100644
--- a/src/003-scene/main.ts
+++ b/src/003-scene/main.ts
@@ -4,16 +4,14 @@ import { Renderable } from "../renderer/renderable";
import { Transform, etoq, v3 } from "../renderer/transform";
import { quat } from "gl-matrix";
import { trianglething, texture0, texture1 } from "../meshes/trianglething";
-import teapot from "../meshes/teapot";
import { basic } from "../common-shaders/basic";
import { Texture } from "../renderer/texture";
-import { errorShader } from "../common-shaders/error";
import { basicVertexRounding } from "../common-shaders/basic-vertex-rounding";
const app = new WebGLApp({ fov: 45 });
const camera = new Transform([2, 3, 3], etoq([-15, 40, 0]));
-const light = new Transform([1, 1, 0]);
+const light = new Transform([2, 2, 0]);
const transform = new Transform(v3(0), etoq([0, 0, 0]));
const transform2 = new Transform([-3, 0, 1], etoq([0, 0, 0]));
diff --git a/src/004-a-new-leaf/main.ts b/src/004-a-new-leaf/main.ts
new file mode 100644
index 0000000..e8c14e2
--- /dev/null
+++ b/src/004-a-new-leaf/main.ts
@@ -0,0 +1,70 @@
+import { MeshRenderer } from "../renderer/mesh-renderer";
+import { WebGLApp } from "../renderer/webgl";
+import { Renderable } from "../renderer/renderable";
+import { Transform, etoq, v3 } from "../renderer/transform";
+import { Texture } from "../renderer/texture";
+import { sonya } from "../common-shaders/sonya";
+import { cubeBackdrop, defaultTransform } from "../meshes/cube-backdrop";
+import { rgbToFloat } from "../renderer/color-utils";
+import rampTexture from "./textures/ramp.png";
+import fox from "../meshes/fox/fox";
+import foxImg from "../meshes/fox/fox-tex.png";
+import foxNormal from "../meshes/fox/fox-normal.png";
+import backdropImg from "./textures/backdrop.png";
+import backdropNormalsImg from "./textures/backdrop-normals.png";
+
+const app = new WebGLApp({ fov: 45 });
+
+const camera = new Transform([0, 2, 4], etoq([-15, 0, 0]));
+const light = new Transform([10, 10, 10]);
+
+const transform = new Transform(v3(0), etoq([0, 180 + 45, 0]), v3(0.1));
+
+const ramp = new Texture(app, rampTexture, { uvClamp: true });
+const backdropTex = new Texture(app, backdropImg);
+const backdropNormalsTex = new Texture(app, backdropNormalsImg);
+const foxTex = new Texture(app, foxImg);
+const foxNormalTex = new Texture(app, foxNormal);
+
+const ambientLight = rgbToFloat(35, 76, 37);
+
+app.onUpdate((time, app) => {
+ // const wiggle = 40 * (Math.sin(time) * 0.001);
+ // camera.position = [wiggle, 2, 4 - wiggle];
+});
+
+new Renderable(
+ app,
+ transform,
+ new MeshRenderer(
+ app,
+ fox,
+ sonya(app, ambientLight)
+ .addTexture("texture0", foxTex)
+ .addTexture("texture1", foxNormalTex)
+ .addTexture("texture2", ramp),
+ camera,
+ light
+ ).configure({})
+ // true
+);
+
+new Renderable(
+ app,
+ defaultTransform,
+ new MeshRenderer(
+ app,
+ cubeBackdrop,
+ sonya(app, ambientLight)
+ .addTexture("texture0", backdropTex)
+ .addTexture("texture1", backdropNormalsTex)
+ .addTexture("texture2", ramp),
+ camera,
+ light
+ ).configure({})
+ // true
+);
+
+// createGizmo(app, camera, light);
+
+app.start();
diff --git a/src/004-a-new-leaf/textures/backdrop-normals.png b/src/004-a-new-leaf/textures/backdrop-normals.png
new file mode 100644
index 0000000..ee06369
Binary files /dev/null and b/src/004-a-new-leaf/textures/backdrop-normals.png differ
diff --git a/src/004-a-new-leaf/textures/backdrop.png b/src/004-a-new-leaf/textures/backdrop.png
new file mode 100644
index 0000000..cac2e0c
Binary files /dev/null and b/src/004-a-new-leaf/textures/backdrop.png differ
diff --git a/src/004-a-new-leaf/textures/ramp.png b/src/004-a-new-leaf/textures/ramp.png
new file mode 100644
index 0000000..5ea6dab
Binary files /dev/null and b/src/004-a-new-leaf/textures/ramp.png differ
diff --git a/src/common-shaders/basic-vertex-rounding.ts b/src/common-shaders/basic-vertex-rounding.ts
index bfdf1fb..d232171 100644
--- a/src/common-shaders/basic-vertex-rounding.ts
+++ b/src/common-shaders/basic-vertex-rounding.ts
@@ -22,6 +22,7 @@ export const basicShaderConfig: ShaderConfig = {
albedo: "u_albedo",
texture0: "u_texture_0",
texture1: "u_texture_1",
+ texture2: "u_texture_2",
},
};
diff --git a/src/common-shaders/basic.ts b/src/common-shaders/basic.ts
index e5e6f82..0dc314c 100644
--- a/src/common-shaders/basic.ts
+++ b/src/common-shaders/basic.ts
@@ -22,6 +22,7 @@ export const basicShaderConfig: ShaderConfig = {
albedo: "u_albedo",
texture0: "u_texture_0",
texture1: "u_texture_1",
+ texture2: "u_texture_2",
},
};
diff --git a/src/common-shaders/sonya.ts b/src/common-shaders/sonya.ts
new file mode 100644
index 0000000..cd99ed0
--- /dev/null
+++ b/src/common-shaders/sonya.ts
@@ -0,0 +1,37 @@
+import { Shader, ShaderConfig } from "../renderer/shader";
+import { WebGLApp } from "../renderer/webgl";
+import frag from "./toon-shading.frag";
+import vert from "./basic-vertex-rounding.vert";
+import { vec4 } from "gl-matrix";
+
+export const basicShaderConfig: ShaderConfig = {
+ attributes: {
+ vertex: "a_vertex",
+ uv0: "a_uv0",
+ normal: "a_normal",
+ vertexColor: "a_vertex_color",
+ },
+
+ uniforms: {
+ view: "u_view",
+ projection: "u_projection",
+ objectToWorld: "u_object_to_world",
+ objectToWorldInv: "u_object_to_world_inv",
+ light0: "u_light_0",
+ light0Color: "u_light_0_color",
+ time: "u_time",
+ albedo: "u_albedo",
+ texture0: "u_texture_0",
+ texture1: "u_texture_1",
+ texture2: "u_texture_2",
+ },
+};
+
+export const sonya = (app: WebGLApp, ambientLight: vec4 = [0.1, 0.1, 0.1, 1]) =>
+ new Shader(basicShaderConfig)
+ .vertex(vert)
+ .fragment(frag)
+ .app(app)
+ .prerenderHook(({ gl }: WebGLApp, shader: Shader) => {
+ gl.uniform4fv(shader.mappings.uniforms.albedo, ambientLight);
+ });
diff --git a/src/common-shaders/toon-shading.frag b/src/common-shaders/toon-shading.frag
new file mode 100644
index 0000000..315476d
--- /dev/null
+++ b/src/common-shaders/toon-shading.frag
@@ -0,0 +1,30 @@
+#version 300 es
+precision highp float;
+
+uniform vec4 u_light_0_color;
+uniform vec4 u_albedo; // ambient color
+
+uniform sampler2D u_texture_0;
+uniform sampler2D u_texture_1;
+uniform sampler2D u_texture_2;
+
+in vec2 uv0;
+in vec3 normal;
+in vec3 light_pos;
+
+out vec4 fragColor;
+
+void main() {
+ // vec4 normalTex = texture(u_texture_1, uv0);
+ // vec3 normal = normalize(normal * normalTex.rgb);
+ vec3 normal = normalize(normal);
+
+ float light = clamp(dot(normal, light_pos), 0.0, 1.0);
+
+ vec3 ramp = texture(u_texture_2, vec2(light, 0.0)).rgb;
+
+ fragColor = vec4(1.0);
+ fragColor.rgb = texture(u_texture_0, uv0).rgb;
+ fragColor.rgb *= ramp;
+ fragColor.a = 1.0;
+}
diff --git a/src/common-shaders/vertex-colors.frag b/src/common-shaders/vertex-colors.frag
new file mode 100644
index 0000000..856a039
--- /dev/null
+++ b/src/common-shaders/vertex-colors.frag
@@ -0,0 +1,11 @@
+#version 300 es
+precision highp float;
+
+in vec4 vertex_color;
+
+out vec4 fragColor;
+
+
+void main() {
+ fragColor = vertex_color;
+}
diff --git a/src/meshes/cube-backdrop/cube-backdrop.blend b/src/meshes/cube-backdrop/cube-backdrop.blend
new file mode 100644
index 0000000..cfa2e9b
Binary files /dev/null and b/src/meshes/cube-backdrop/cube-backdrop.blend differ
diff --git a/src/meshes/cube-backdrop/cube-backdrop.ply b/src/meshes/cube-backdrop/cube-backdrop.ply
new file mode 100644
index 0000000..cb0b891
--- /dev/null
+++ b/src/meshes/cube-backdrop/cube-backdrop.ply
@@ -0,0 +1,29 @@
+ply
+format ascii 1.0
+comment Created in Blender version 3.6.4
+element vertex 8
+property float x
+property float y
+property float z
+property float nx
+property float ny
+property float nz
+property float s
+property float t
+element face 6
+property list uchar uint vertex_indices
+end_header
+-0.10000001 -0.0025735903 -0.10000001 0.5773503 0.5773503 0.5773503 0.5 0.5
+-0.10000001 0.19742644 0.10000001 1 0 0 -5.9604645e-08 1
+-0.10000001 -0.0025735903 0.10000001 0.70710677 0.70710677 0 0 0.49999997
+0.10000001 -0.0025735903 -0.10000001 0 0.70710677 0.70710677 1 0.50000006
+-0.10000001 0.19742644 -0.10000001 0.70710677 0 0.70710677 0.49999997 1
+0.10000001 -0.0025735903 0.10000001 0 1 0 1 0
+0.10000001 0.19742644 -0.10000001 0 0 1 1 1
+-0.10000001 -0.0025735903 0.10000001 0.70710677 0.70710677 0 0.50000006 0
+3 0 1 2
+3 3 4 0
+3 0 5 3
+3 0 4 1
+3 3 6 4
+3 0 7 5
diff --git a/src/meshes/cube-backdrop/cube-backdrop.ts b/src/meshes/cube-backdrop/cube-backdrop.ts
new file mode 100644
index 0000000..fdeea5e
--- /dev/null
+++ b/src/meshes/cube-backdrop/cube-backdrop.ts
@@ -0,0 +1,12 @@
+import { Mesh } from "../../renderer/mesh";
+
+// prettier-ignore
+export default new Mesh({
+ colors: null,
+ faces: new Uint8Array([0,1,2,3,4,0,0,5,3,0,4,1,3,6,4,0,7,5]),
+ name: "src/meshes/cube-backdrop/cube-backdrop.ply",
+ normals: new Float32Array([0.5773503,0.5773503,0.5773503,1,0,0,0.70710677,0.70710677,0,0,0.70710677,0.70710677,0.70710677,0,0.70710677,0,1,0,0,0,1,0.70710677,0.70710677,0]),
+ positions: new Float32Array([-0.10000001,-0.0025735903,-0.10000001,-0.10000001,0.19742644,0.10000001,-0.10000001,-0.0025735903,0.10000001,0.10000001,-0.0025735903,-0.10000001,-0.10000001,0.19742644,-0.10000001,0.10000001,-0.0025735903,0.10000001,0.10000001,0.19742644,-0.10000001,-0.10000001,-0.0025735903,0.10000001]),
+ uvs: new Float32Array([0.5,0.5,-5.9604645e-8,1,0,0.49999997,1,0.50000006,0.49999997,1,1,0,1,1,0.50000006,0]),
+ vertexCount: 8
+});
diff --git a/src/meshes/cube-backdrop/index.ts b/src/meshes/cube-backdrop/index.ts
new file mode 100644
index 0000000..aba8c2f
--- /dev/null
+++ b/src/meshes/cube-backdrop/index.ts
@@ -0,0 +1,6 @@
+import { Transform, etoq, v3 } from "../../renderer/transform";
+import cubeBackdrop from "./cube-backdrop";
+
+export const defaultTransform = new Transform(v3(0), etoq([0, -45, 0]), v3(20));
+
+export { cubeBackdrop };
diff --git a/src/meshes/cube-backdrop/uv-template.png b/src/meshes/cube-backdrop/uv-template.png
new file mode 100644
index 0000000..b5edc32
Binary files /dev/null and b/src/meshes/cube-backdrop/uv-template.png differ
diff --git a/src/meshes/fox/fox-normal.png b/src/meshes/fox/fox-normal.png
new file mode 100644
index 0000000..970533b
Binary files /dev/null and b/src/meshes/fox/fox-normal.png differ
diff --git a/src/meshes/fox/fox-tex.png b/src/meshes/fox/fox-tex.png
new file mode 100644
index 0000000..ffa6333
Binary files /dev/null and b/src/meshes/fox/fox-tex.png differ
diff --git a/src/meshes/fox/fox-tex.xcf b/src/meshes/fox/fox-tex.xcf
new file mode 100644
index 0000000..262e1a0
Binary files /dev/null and b/src/meshes/fox/fox-tex.xcf differ
diff --git a/src/meshes/fox/fox-uv.png b/src/meshes/fox/fox-uv.png
new file mode 100644
index 0000000..aa2e27b
Binary files /dev/null and b/src/meshes/fox/fox-uv.png differ
diff --git a/src/meshes/fox/fox.blend b/src/meshes/fox/fox.blend
new file mode 100644
index 0000000..3f1cfb8
Binary files /dev/null and b/src/meshes/fox/fox.blend differ
diff --git a/src/meshes/fox/fox.ply b/src/meshes/fox/fox.ply
new file mode 100644
index 0000000..406e994
--- /dev/null
+++ b/src/meshes/fox/fox.ply
@@ -0,0 +1,674 @@
+ply
+format ascii 1.0
+comment Created in Blender version 3.6.4
+element vertex 285
+property float x
+property float y
+property float z
+property float nx
+property float ny
+property float nz
+property float s
+property float t
+element face 374
+property list uchar uint vertex_indices
+end_header
+-0.6999253 6.443001 -0.82603 0.3475203 -0.1423119 -0.92681 0.21851481 0.38709354
+0.07097474 5.343301 -0.52663046 0.5162422 0.12797521 -0.8468272 0.25122124 0.29925498
+-0.76262593 4.472701 -1.15393 0.15832935 0.05530619 -0.98583627 0.33613995 0.31277353
+-1.7783258 5.520501 -0.86433035 -0.34248725 0.027904412 -0.9391081 0.31780326 0.41546077
+-2.2427258 6.713101 -0.82603 -0.5169309 -0.31768712 -0.7948945 0.26634175 0.49754715
+-1.5250261 4.4763007 -0.9856301 -0.48697895 -0.1626665 -0.85813236 0.36926088 0.35428312
+0.29497454 9.249201 0.16336976 0.979832 0.13666466 -0.14578043 0.8862014 0.7660378
+0.06327439 8.8725 -0.28472978 0.9031805 0.21487509 -0.37160963 0.96414614 0.65773886
+-0.035225682 9.543601 0.14946976 0.66321534 0.26724067 -0.6990907 0.9142767 0.82184976
+-0.30342564 9.674201 -0.23032992 0.6848186 0.23503296 -0.68977004 0.96414614 0.8656495
+2.4808748 3.6319008 -0.11143037 0.50283414 0.37262148 -0.779943 0.24378048 0.15517116
+2.0297747 3.2159004 -0.4459305 0.23640795 0.47815725 -0.84585875 0.27324826 0.1538348
+1.5565743 4.603301 -0.21123049 0.3647613 0.40136182 -0.8401535 0.24071635 0.21034758
+2.1004748 3.2381003 3.2929707 0.3046436 0.23757984 0.92236 0.12782207 0.13377228
+1.8371744 4.748301 2.81227 0.31008115 0.576068 0.7563038 0.13686845 0.17050092
+0.20437472 4.420901 2.9141703 -0.22806334 0.32389933 0.91819185 0.097095504 0.18026535
+1.8253747 0.4645001 -1.7956301 0.17951295 -0.316014 -0.931617 0.3456612 0.015984222
+0.91437465 0.9539002 -2.1209302 -0.17395478 -0.060770363 -0.9828767 0.38372317 0.05219409
+2.4374743 1.0497 -1.8992304 0.3371145 -0.028111659 -0.94104385 0.3173124 0.03967564
+2.5767748 2.7875004 -0.6003304 0.5286752 0.36182427 -0.76784486 0.2669188 0.12665303
+1.7599748 1.8992002 -1.1086301 0.37282482 0.34924614 -0.8596678 0.3150151 0.10144508
+1.5595742 2.5219004 -1.29143 0.04436654 0.3120137 -0.9490411 0.312529 0.12937495
+0.24357454 3.5395007 -0.67183006 0.1748497 -0.08175629 -0.981195 0.32927862 0.22344446
+0.24817431 4.333201 -0.45933002 0.4760932 0.18387188 -0.8599573 0.2904697 0.2528519
+-0.3960259 7.7391005 -1.2657304 0.77194935 -0.10489054 -0.6269707 0.13747068 0.42125323
+0.05687409 8.074501 -0.67993015 0.8878576 0.018637033 -0.45974046 0.1110152 0.38961607
+-0.12432557 6.748201 -0.34603044 0.8233882 0.00536109 -0.5674533 0.17645767 0.34971166
+-0.06132584 2.9543004 -0.8707303 0.50706327 0.2949509 -0.8098708 0.37940347 0.20685007
+-0.20062563 3.4773006 -0.68853 0.5776023 0.024086185 -0.8159629 0.3529383 0.23464157
+0.43317416 2.5253003 -0.46623006 0.20082258 0.4428197 -0.8738313 0.35064337 0.17517665
+-0.4904259 2.1981003 -0.90393 -0.3673268 -0.008583662 -0.9300523 0.43924242 0.18647039
+-1.0552258 3.1734004 -1.06763 -0.23037066 -0.14419852 -0.9623597 0.41530237 0.2674248
+1.4597749 1.4790002 -2.0267305 0.10130113 0.55220604 -0.82753044 0.34998143 0.06725915
+-1.8893259 8.729101 -1.7110304 -0.30028316 0.6138469 -0.7300836 0.12322961 0.6801839
+-2.2624261 9.345001 -1.37473 -0.42857707 0.59847176 -0.67687017 0.1720783 0.6964544
+-0.97242594 9.702102 -0.89533013 0.2310956 0.77802414 -0.5841861 0.16144735 0.7933706
+-1.2870256 7.527001 -2.5206306 0.40507296 -0.59645694 -0.69293207 0.8861246 0.52512723
+-1.5926256 8.311801 -2.8306303 0.018303465 0.44150117 -0.8970739 0.84557533 0.5134298
+-0.3960259 7.7391005 -1.2657304 0.77194935 -0.10489054 -0.6269707 0.9878913 0.42880467
+2.5549746 1.4319001 2.9302707 0.6770759 -0.15234865 0.71997094 0.12832226 0.086800925
+2.773675 2.7475002 3.0280704 0.5551748 0.09818922 0.82591754 0.14096868 0.11748978
+-0.94812554 8.5809 -1.5055304 0.5862696 0.275684 -0.7617652 0.074313566 0.7435197
+0.05687409 8.074501 -0.67993015 0.8878576 0.018637033 -0.45974046 0.020883663 0.84153533
+-0.3960259 7.7391005 -1.2657304 0.77194935 -0.10489054 -0.6269707 1.081579e-08 0.77996564
+-0.40532535 9.700401 0.84696966 0.3452935 0.52275664 0.7794215 0.32931674 0.8416559
+-1.540426 8.934701 1.6871705 -0.037781123 0.40868607 0.9118927 0.35599756 0.7471563
+-0.62042546 7.995201 1.7714701 0.47639555 0.22756127 0.8492721 0.4352468 0.76457715
+-0.15842591 5.3485007 2.2917705 0.038687505 0.4890638 0.87138975 0.09890157 0.21372627
+3.3480747 1.1927001 -1.4741304 0.4779266 0.31795877 -0.8188335 0.28071728 0.038383927
+0.23047411 6.9421005 0.8096703 0.9412043 0.3062575 0.14262189 0.12732372 0.2965882
+0.17777406 7.816401 -0.13533022 0.985557 -0.050912835 -0.16150954 0.11473294 0.36185902
+-0.80692565 9.159501 -1.4650301 0.41709664 0.43660966 -0.79712135 0.110673696 0.76611084
+0.73637474 6.182101 0.90636986 0.65320575 0.7567542 -0.025403246 0.1568792 0.258202
+0.16357423 6.238301 1.5856699 0.5102622 0.5121896 0.6908649 0.11916661 0.24799357
+2.0266747 5.562201 1.4546701 0.5327677 0.8339708 0.14370571 0.1670033 0.20147358
+3.4768748 0.57150006 -1.4508302 0.50982845 -0.2752561 -0.81505156 0.27564877 0.017370421
+4.1452746 0.9685002 -0.7070302 0.9362124 0.034893714 -0.34969804 0.24627076 0.033188876
+2.576082 3.1560004 -0.31358007 0.49277383 0.474742 -0.729242 0.25064924 0.13463129
+0.7198746 2.4339004 3.54267 -0.10767815 0.15382154 0.98221403 0.09065693 0.12818988
+2.288975 1.3705001 3.4610705 0.53157943 -0.18795584 0.825891 0.11538713 0.09199737
+-0.40532535 9.700401 0.84696966 0.3452935 0.52275664 0.7794215 0.8276462 0.8879465
+0.14267427 10.748201 0.011170197 0.73606163 0.6634644 -0.13426952 0.8977165 0.9073449
+-0.35632557 10.885501 -0.026630403 -0.17794462 0.9747583 -0.13484038 0.8979689 0.9335955
+-1.0288259 10.067701 0.053869635 -0.38528097 0.9081675 0.1636775 0.24703515 0.8216678
+-1.2105256 9.758201 0.87647027 0.03706524 0.8542405 0.51855505 0.30523577 0.7905776
+0.09657441 8.901701 0.59447026 0.90783143 0.11600388 0.40297043 0.8020745 0.7431329
+3.0635746 4.299401 1.8075701 0.8010637 0.5264299 0.2849009 0.17493051 0.15400115
+2.5929751 4.772801 0.5979699 0.6885465 0.57700217 -0.43928608 0.20319703 0.1803566
+0.16167451 9.942601 0.37547 0.95855004 0.10577212 0.26456407 0.89068747 0.8602873
+-0.94812554 8.5809 -1.5055304 0.5862696 0.275684 -0.7617652 0.8669603 0.42128757
+0.47697452 6.306901 0.39987034 0.78829354 0.5408408 -0.2934015 0.1696568 0.2862294
+3.0665743 0.73340005 -1.42483 0.21502984 0.04666299 -0.97549206 0.29085746 0.022808408
+0.6858742 3.7022007 -0.62512976 0.102968186 0.09595936 -0.9900452 0.30401754 0.21331184
+0.044074252 1.8123003 -1.5475305 -0.42321405 0.5065525 -0.7511954 0.4063384 0.124203816
+-0.053825382 1.2451001 -1.5953302 -0.69715625 -0.08602459 -0.71173936 0.4319168 0.09517003
+3.2380748 2.4352005 -0.08572999 0.82457936 0.081235796 -0.5598835 0.24068871 0.10983848
+0.5252747 5.1989007 -0.29223025 0.4377959 0.26956058 -0.85771316 0.2422915 0.26877972
+0.8465745 5.738801 0.27866977 0.6155783 0.5745703 -0.5393813 0.19642983 0.2589539
+-0.7709256 5.724101 2.2065706 0.07019434 0.24138543 0.9678872 0.084621415 0.22762483
+-0.619426 6.356501 1.9183702 0.3541473 0.25355586 0.9001605 0.08997824 0.2432744
+-1.9789258 7.178801 -1.18583 -0.29064578 -0.724498 -0.62500215 0.21659407 0.49825695
+-0.91182566 7.3815007 -1.4608301 0.375913 -0.73612595 -0.56285685 0.16409814 0.4431432
+0.09657441 8.901701 0.59447026 0.90783143 0.11600388 0.40297043 0.06007273 0.3584054
+0.06327439 8.8725 -0.28472978 0.9031805 0.21487509 -0.37160963 0.077401064 0.3881148
+3.0936747 0.6671002 2.4830706 0.5472127 -0.29103354 0.7847661 0.13976377 0.06055675
+4.0453753 0.52309996 1.4920702 0.87695193 -0.2072897 0.4335738 0.1772671 0.045047924
+3.6563747 2.4587002 2.1933703 0.8803676 0.14394727 0.45192042 0.1689892 0.10318307
+0.5219742 1.8811003 -1.0851305 0.15257555 0.7520019 -0.64125955 0.36747235 0.13334484
+1.1984742 1.6896003 -1.65813 0.073696144 0.91218823 -0.40308988 0.35129 0.09048066
+2.625175 1.7991003 -0.6557297 0.48116767 0.69189876 -0.5382877 0.27406374 0.088201545
+0.67027444 0.5334 -1.9347303 -0.38885155 -0.2292497 -0.8923223 0.40481266 0.033736143
+1.2843744 3.0958004 -0.5304299 -0.08802483 0.3184032 -0.94385976 0.3024185 0.17043002
+0.77727437 1.2146001 3.4750705 -0.16566989 -0.31949857 0.9329921 0.080950305 0.101946086
+3.4174747 1.7396003 -0.85813 0.4088575 0.88988423 -0.20234066 0.26399732 0.060749806
+2.3443742 1.5199003 -1.5742303 0.23401263 0.7841241 -0.5747935 0.3123137 0.06264582
+0.06327439 8.8725 -0.28472978 0.9031805 0.21487509 -0.37160963 0.08229262 0.8732247
+-1.8893259 8.729101 -1.7110304 -0.30028316 0.6138469 -0.7300836 0.78262734 0.48695683
+-0.62042546 7.995201 1.7714701 0.47639555 0.22756127 0.8492721 0.054573745 0.28939876
+-1.219426 6.696401 2.0643702 -0.13893181 0.08481444 0.98666334 0.4784059 0.67288846
+-0.619426 6.356501 1.9183702 0.3541473 0.25355586 0.9001605 0.52534187 0.6902852
+-2.161226 7.667401 -2.4847305 -0.6594078 -0.34964943 -0.6655273 0.843693 0.54919225
+-0.91182566 7.3815007 -1.4608301 0.375913 -0.73612595 -0.56285685 0.967211 0.5381632
+-1.9789258 7.178801 -1.18583 -0.29064578 -0.724498 -0.62500215 0.8863765 0.6507956
+3.1734743 1.5024002 0.15137026 0.7611686 0.58185023 -0.28648314 0.23814057 0.07682296
+-0.7888257 10.067701 -0.3484299 -0.04397583 0.70420456 -0.7086339 0.52430856 0.78790325
+0.14267427 10.748201 0.011170197 0.73606163 0.6634644 -0.13426952 0.5076637 0.9781552
+-0.30342564 9.674201 -0.23032992 0.6848186 0.23503296 -0.68977004 0.42495766 0.8044593
+-1.0288259 10.067701 0.053869635 -0.38528097 0.9081675 0.1636775 0.88358545 0.94791806
+0.09657441 8.901701 0.59447026 0.90783143 0.11600388 0.40297043 0.39027283 0.865766
+3.387675 3.7165008 1.58967 0.9180944 0.3928391 0.052727237 0.18311635 0.13782379
+-0.30342564 9.674201 -0.23032992 0.6848186 0.23503296 -0.68977004 0.15227878 0.86758876
+-2.2445261 4.9454007 -0.66073006 -0.75246775 0.008946161 -0.6585683 0.37036988 0.41615537
+3.6162753 2.8629005 0.8747697 0.93610126 0.23180684 -0.26453748 0.20584682 0.11498356
+-0.7888257 10.067701 -0.3484299 -0.04397583 0.70420456 -0.7086339 0.935007 0.9301176
+-0.7888257 10.067701 -0.3484299 -0.04397583 0.70420456 -0.7086339 0.19761893 0.83779246
+4.364375 1.0550001 0.5702698 0.92324126 0.38289523 0.03188642 0.20950294 0.045586396
+-0.61192554 1.0255002 2.04657 -0.8208653 0.15153797 0.55065095 0.0322884 0.11481223
+-1.0520257 0.52869993 2.4247699 -0.6847748 0.31241915 0.6583902 0.02451134 0.09802288
+-0.0897255 0.5721001 2.6455705 -0.44955286 -0.170653 0.87680095 0.048454616 0.09665558
+-2.517626 0.78980017 0.25796968 -0.69434595 0.69967836 -0.16832665 0.6460075 0.21836895
+-1.337726 0.8835 0.28996965 -0.64949834 0.59640735 -0.47164628 0.5963892 0.2274105
+-1.4268259 0.95919997 -0.43353048 -0.72120667 0.6666094 -0.18839571 0.5771463 0.1884031
+-0.44272542 1.0345002 -0.70443004 -0.44213012 -0.017088598 -0.8967881 0.5055221 0.114784405
+-1.0315259 1.0731 -0.7273301 -0.16689667 0.37004504 -0.9138995 0.5447714 0.15467297
+-1.0638257 2.0252004 -0.7415303 -0.32365012 -0.16409263 -0.93183917 0.48357084 0.21026236
+-3.471126 10.565201 0.1122696 -0.81858766 0.5451293 -0.18096499 0.75558704 0.9432239
+-3.4521263 9.519001 0.46967015 -0.992983 0.08945896 0.07734239 0.8020744 0.9034289
+-2.878626 9.963901 0.81987005 -0.21252948 0.5347677 0.81783545 0.7897775 0.96688294
+-2.741226 7.508901 1.3471704 -0.7021046 -0.14130145 0.6979133 0.36300594 0.6462114
+-3.4521263 9.519001 0.46967015 -0.992983 0.08945896 0.07734239 0.27383736 0.69182056
+-3.433826 9.038601 0.28866962 -0.9546164 0.028929858 -0.2964296 0.27248618 0.6792056
+-2.882526 9.084501 -0.10313035 -0.7311533 0.36524838 -0.5762018 0.2478923 0.6867268
+-3.3896263 8.113201 -0.3605301 -0.9617006 -0.03754102 -0.27151904 0.25436208 0.6271816
+-3.3058262 8.5403 0.07176972 -0.9879483 0.08645398 -0.1283894 0.26854706 0.6570603
+-2.7694259 7.7350006 -1.0115304 -0.78725094 -0.2752617 -0.5517852 0.2133645 0.5806204
+-2.230626 0.22640002 -0.41983035 -0.74839973 -0.49738073 -0.4387599 0.637635 0.17406993
+-1.868326 0.75070006 -0.9546304 -0.6237263 0.711984 -0.32255915 0.60493344 0.1558058
+3.880675 1.3958001 1.1265702 0.9198568 0.38913035 -0.049406413 0.19796096 0.06852602
+-2.327826 8.2278 1.5766702 -0.44723478 0.13983466 0.883418 0.35857934 0.69122976
+-2.5213258 6.882601 1.3467698 -0.6689012 -0.23592637 0.7049185 0.3951752 0.6194137
+-1.4618257 2.4264002 -0.6133301 -0.8903412 -0.15419926 -0.42838684 0.48257515 0.25476277
+-1.2621258 1.7734003 0.17966996 -0.92482555 0.016368585 -0.3800392 0.5577472 0.2591085
+-1.4422258 3.0290003 0.4318703 -0.8165544 -0.1464694 -0.55837774 0.5101766 0.3366432
+-1.9845258 3.6388009 0.69077003 -0.87178856 -0.35990623 -0.3323434 0.50301826 0.39985734
+-1.890426 1.0817002 0.44496998 -0.517776 0.4540006 -0.7251148 0.6224612 0.2508355
+-2.0575259 0.9955001 0.9599702 -0.8433312 0.09983585 0.52803904 0.65923995 0.27131322
+-2.964326 9.822501 -0.10223008 -0.47634494 -0.05045076 -0.87780994 0.7339221 0.92058545
+-2.882526 9.084501 -0.10313035 -0.7311533 0.36524838 -0.5762018 0.667627 0.84930974
+-3.092126 9.502201 0.2502701 -0.6984636 -0.017294424 -0.71543664 0.75460386 0.8875665
+-0.087125406 3.1274004 2.8989704 -0.64312565 0.17802551 0.7447794 0.07549074 0.15373975
+-0.8196259 2.3198001 1.7973703 -0.66986597 -0.026210472 0.7420193 0.036297202 0.14856292
+-0.8748258 2.0967002 2.7634706 -0.90760005 0.06683492 0.41448176 0.053295545 0.13493255
+0.02887421 0.7540002 -1.4195303 -0.71550065 -0.2610496 -0.6480061 0.45089763 0.06624607
+-1.665426 1.8197002 1.62437 -0.48163462 -0.16273934 0.86112946 0.65852106 0.35673973
+-2.1923258 3.5194008 1.3925699 -0.9447443 -0.18422589 0.271144 0.5478699 0.43424743
+-1.186226 0.55610013 1.5514703 -0.84864473 -0.16340141 0.5030924 0.734133 0.3012958
+-0.8196259 2.3198001 1.7973703 -0.66986597 -0.026210472 0.7420193 0.69251174 0.422131
+-0.029425815 2.1513002 3.4381702 -0.44133595 0.045067813 0.8962095 0.07396352 0.1281145
+-2.5888262 6.208601 0.9756699 -0.84305483 -0.09319865 0.52969086 0.4061021 0.5678618
+-3.112326 7.3445005 0.3178696 -0.96471584 -0.253683 0.070486 0.31435022 0.5997315
+-2.667426 4.758001 0.018969728 -0.90281165 -0.30579108 -0.30236223 0.4114268 0.44731957
+-2.7694259 7.7350006 -1.0115304 -0.78725094 -0.2752617 -0.5517852 0.75763285 0.6744133
+-2.392026 8.487902 -1.3364304 -0.747842 0.21194589 -0.6291353 0.734765 0.56230044
+-0.8792256 4.817401 2.3403704 -0.38904643 0.09032617 0.9167791 0.5902533 0.5873184
+-2.6100261 4.707801 1.3596704 -0.8832008 -0.12243323 0.45273212 0.48538992 0.4962032
+-0.8792256 4.817401 2.3403704 -0.38904643 0.09032617 0.9167791 0.07417127 0.20548928
+-2.392026 8.487902 -1.3364304 -0.747842 0.21194589 -0.6291353 0.16459617 0.6398786
+-1.8001261 4.085301 1.9035699 -0.4839415 -0.097555116 0.86964566 0.5627961 0.49731115
+-1.186226 0.55610013 1.5514703 -0.84864473 -0.16340141 0.5030924 0.010203981 0.1122183
+-1.569626 0.3742001 -1.4788301 -0.05462312 0.1690641 -0.9840902 0.61384606 0.11812159
+-1.9930261 9.862201 -0.003130341 0.075866185 0.9794647 -0.18679745 0.7293909 0.98951745
+-3.0411263 10.770401 0.043869786 0.02688641 0.9635681 -0.26610863 0.753717 0.961225
+-3.433826 9.038601 0.28866962 -0.9546164 0.028929858 -0.2964296 0.8020744 0.78846765
+4.2867746 0.52519995 0.41017002 0.94705594 -0.2590572 -0.18966934 0.20760685 0.029241929
+-2.878626 9.963901 0.81987005 -0.21252948 0.5347677 0.81783545 0.27992412 0.7168905
+-1.9710261 3.9114006 0.01537018 -0.6675564 -0.59708816 -0.444808 0.45012152 0.3856737
+-1.9930261 9.862201 -0.003130341 0.075866185 0.9794647 -0.18679745 0.2468168 0.7547342
+-2.2901258 9.714901 -0.21963045 -0.23479536 0.67432845 -0.7001088 0.23586477 0.728986
+-2.2901258 9.714901 -0.21963045 -0.23479536 0.67432845 -0.7001088 0.52842814 0.74081594
+-2.964326 9.822501 -0.10223008 -0.47634494 -0.05045076 -0.87780994 0.58254737 0.8386313
+-3.471126 10.565201 0.1122696 -0.81858766 0.5451293 -0.18096499 0.5380133 0.9808106
+-2.2901258 9.714901 -0.21963045 -0.23479536 0.67432845 -0.7001088 0.69757915 0.9635888
+-3.3058262 8.5403 0.07176972 -0.9879483 0.08645398 -0.1283894 0.70988774 0.65773886
+-2.882526 9.084501 -0.10313035 -0.7311533 0.36524838 -0.5762018 0.6677008 0.75300074
+-0.7709256 5.724101 2.2065706 0.07019434 0.24138543 0.9678872 0.5507923 0.6433447
+0.58418125 0.22400019 -1.7113466 -0.40643814 -0.8098558 -0.42301488 0.9718312 0.020504208
+0.7487328 0.22400019 -1.869269 -0.19065972 -0.720445 -0.66678923 0.97220457 0.021100836
+1.2752382 0.22400019 -1.8116388 0.075374685 -0.7676886 -0.6363747 0.9716987 0.022655101
+-1.4210848 0.22400019 -1.3924581 0.41129172 -0.60820895 -0.6789117 0.9721315 0.014245303
+-1.2286401 0.22400019 -1.2118917 0.3633369 -0.6630077 -0.65452826 0.9714647 0.014712902
+-1.7548681 0.22400019 -1.3470285 -0.52704555 -0.58184344 -0.6194199 0.97220457 0.013208317
+-2.2161448 0.22400019 -0.43305972 -0.017521787 -0.99930537 0.032890607 0.96973413 0.01123883
+-0.5065232 0.22400019 -0.5854172 -0.021521537 -0.94214505 -0.3345139 0.96911705 0.01649964
+3.6921923 0.22400019 -0.5356896 0.6121442 -0.6924734 -0.38178536 0.96632093 0.029152708
+-1.9521799 0.22400019 -1.126045 -0.70010203 -0.5537167 -0.45083794 0.9716613 0.012472974
+-2.2274122 0.22400019 -0.4297089 -0.7312984 -0.6671969 -0.14160144 0.80359983 1.0238159
+-1.9521799 0.22400019 -1.126045 -0.70010203 -0.5537167 -0.45083794 0.80359983 0.95338476
+-2.2161448 0.22400019 -0.43305972 -0.017521787 -0.99930537 0.032890607 0.8044696 1.023133
+2.2313638 0.22400019 2.680494 0.3288468 -0.8804425 0.34158558 0.95752156 0.022717984
+-0.6810555 0.22400019 2.4642336 -0.1467376 -0.75445783 0.63973546 0.96000504 0.01405433
+2.4538667 0.22400019 2.5940027 0.24385142 -0.7973807 0.55201495 0.95764303 0.02344461
+0.41850665 0.22400019 2.7519977 -0.23899291 -0.84482497 0.4786994 0.95844465 0.017195703
+-2.6425998 0.22400019 0.70022744 -0.80877304 -0.50211614 0.3062115 0.9665674 0.0092362035
+-2.7626433 0.22400019 0.07626649 -0.847515 -0.42922866 -0.3122198 0.96852803 0.009265589
+4.1131854 0.22400019 0.46040884 0.5623081 -0.8260273 -0.03858204 0.9630468 0.029798763
+1.955617 0.22400019 2.7750673 0.04242061 -0.8742375 0.4836417 0.9574091 0.02182542
+2.1960154 0.22400019 2.7574801 0.407 -0.7800877 0.47519907 0.95731115 0.022562819
+0.7445824 0.22400019 2.9373279 -0.12836032 -0.80886763 0.57380897 0.9576798 0.018064456
+2.7569857 0.22400019 -1.5163606 0.16910498 -0.7943238 -0.5834837 0.9698729 0.026945414
+2.100773 0.22400019 -1.6653436 0.12811182 -0.79456544 -0.59350926 0.9707365 0.02505687
+3.4797022 0.22400019 -1.0087174 0.40930107 -0.86440027 -0.29203552 0.9678838 0.028808849
+3.5642383 0.22400019 -0.8515244 0.48217154 -0.858188 -0.17613666 0.96735567 0.028965177
+-0.37594378 0.22400019 -0.7854573 -0.57233065 -0.7097642 -0.41069746 0.9696391 0.017020183
+-1.1313287 0.22400019 -1.2045778 0.22967121 -0.49633533 -0.83719915 0.9713813 0.015002267
+-1.2935071 0.22400019 1.0919343 -0.27430204 -0.8970687 0.34644783 0.96453613 0.013066204
+-2.5766528 0.22400019 0.8374413 -0.62714297 -0.48046845 0.6130593 0.96611136 0.009349244
+4.0127363 0.22400019 0.9127198 0.5038301 -0.8556301 0.1185428 0.9617433 0.029211031
+3.5815594 0.22400019 -0.7074967 0.42636088 -0.8999785 -0.09085657 0.96690965 0.028926747
+3.4810352 0.22400019 1.8996607 0.39348367 -0.810439 0.4340037 0.9590955 0.02698438
+-1.11559 0.22400019 1.3025575 -0.38334632 -0.9040218 0.18918258 0.963788 0.013471412
+3.8143253 0.22400019 1.5762239 0.4810456 -0.8009131 0.35655776 0.95986325 0.028194623
+-1.0991356 0.22400019 2.0397234 -0.68955994 -0.7188539 0.0880689 0.96155035 0.013057904
+-2.209373 0.22400019 -0.42154086 -0.0558253 -0.9859457 0.15746342 0.9696951 0.011252033
+-2.1618967 0.22400019 -0.40970844 -0.0028608302 -0.9999959 -0.000106975036 0.9696294 0.011387991
+-2.1749234 0.22400019 -0.40605244 -0.011426341 -0.9991058 -0.04070532 0.96961904 0.011344941
+-2.1937947 0.22400019 -0.40073627 -0.011439374 -0.9991109 -0.04057865 0.9696118 0.01128404
+-2.2783449 0.22400019 -0.37692034 -0.58131546 -0.51583326 -0.6292762 0.969593 0.011013629
+-1.0468484 0.22400019 2.382645 -0.58025545 -0.63782334 0.5064435 0.9604814 0.013000401
+3.4810352 0.22400019 1.8996607 0.39348367 -0.810439 0.4340037 0.15420465 0.04102335
+3.8143253 0.22400019 1.5762239 0.4810456 -0.8009131 0.35655776 0.16792865 0.037144165
+2.2313638 0.22400019 2.680494 0.3288468 -0.8804425 0.34158558 0.110636964 0.05624038
+2.4538667 0.22400019 2.5940027 0.24385142 -0.7973807 0.55201495 0.117879316 0.05280347
+2.1960154 0.22400019 2.7574801 0.407 -0.7800877 0.47519907 0.1069449 0.059347447
+1.2752382 0.22400019 -1.8116388 0.075374685 -0.7676886 -0.6363747 0.37604672 0.008110086
+0.7487328 0.22400019 -1.869269 -0.19065972 -0.720445 -0.66678923 0.4070614 0.013023422
+3.5642383 0.22400019 -0.8515244 0.48217154 -0.858188 -0.17613666 0.25538462 0.0031148791
+3.4797022 0.22400019 -1.0087174 0.40930107 -0.86440027 -0.29203552 0.2648711 8.450675e-09
+4.1131854 0.22400019 0.46040884 0.5623081 -0.8260273 -0.03858204 0.20259783 0.019268692
+3.6921923 0.22400019 -0.5356896 0.6121442 -0.6924734 -0.38178536 0.23897217 0.0057812533
+2.7569857 0.22400019 -1.5163606 0.16910498 -0.7943238 -0.5834837 0.3031835 0.0016587148
+2.100773 0.22400019 -1.6653436 0.12811182 -0.79456544 -0.59350926 0.3331248 0.0026185757
+1.955617 0.22400019 2.7750673 0.04242061 -0.8742375 0.4836417 0.09809749 0.06282124
+0.7445824 0.22400019 2.9373279 -0.12836032 -0.80886763 0.57380897 0.068156235 0.07761529
+-0.37594378 0.22400019 -0.7854573 -0.57233065 -0.7097642 -0.41069746 0.52157223 0.044851843
+-0.5065232 0.22400019 -0.5854172 -0.021521537 -0.94214505 -0.3345139 0.5435285 0.046751596
+-2.2783449 0.22400019 -0.37692034 -0.58131546 -0.51583326 -0.6292762 0.63853747 0.17621852
+-2.7626433 0.22400019 0.07626649 -0.847515 -0.42922866 -0.3122198 0.66334546 0.19258852
+-1.7548681 0.22400019 -1.3470285 -0.52704555 -0.58184344 -0.6194199 0.62489164 0.1247898
+-1.9521799 0.22400019 -1.126045 -0.70010203 -0.5537167 -0.45083794 0.6287393 0.14086775
+-2.6425998 0.22400019 0.70022744 -0.80877304 -0.50211614 0.3062115 0.68118423 0.21481499
+-1.11559 0.22400019 1.3025575 -0.38334632 -0.9040218 0.18918258 -3.3102134e-09 0.10996528
+-1.0991356 0.22400019 2.0397234 -0.68955994 -0.7188539 0.0880689 0.013690739 0.09781893
+0.58418125 0.22400019 -1.7113466 -0.40643814 -0.8098558 -0.42301488 0.42186216 0.014245739
+-1.1313287 0.22400019 -1.2045778 0.22967121 -0.49633533 -0.83719915 0.6017828 0.094806425
+-0.6810555 0.22400019 2.4642336 -0.1467376 -0.75445783 0.63973546 0.030619193 0.091465615
+0.41850665 0.22400019 2.7519977 -0.23899291 -0.84482497 0.4786994 0.057839744 0.08235605
+-1.2286401 0.22400019 -1.2118917 0.3633369 -0.6630077 -0.65452826 0.59865737 0.10087764
+-2.5766528 0.22400019 0.8374413 -0.62714297 -0.48046845 0.6130593 0.67908764 0.21657859
+-1.2935071 0.22400019 1.0919343 -0.27430204 -0.8970687 0.34644783 0.7325371 0.2680749
+-1.4210848 0.22400019 -1.3924581 0.41129172 -0.60820895 -0.6789117 0.614245 0.10814548
+-1.9521799 0.22400019 -1.126045 -0.70010203 -0.5537167 -0.45083794 0.43263742 0.92657316
+-2.2274122 0.22400019 -0.4297089 -0.7312984 -0.6671969 -0.14160144 0.43597075 0.8869815
+-2.230626 0.22640002 -0.41983035 -0.74839973 -0.49738073 -0.4387599 0.43614823 0.88644433
+4.0127363 0.22400019 0.9127198 0.5038301 -0.8556301 0.1185428 0.18772343 0.02667462
+3.5815594 0.22400019 -0.7074967 0.42636088 -0.8999785 -0.09085657 0.24657853 0.0037103465
+-1.0468484 0.22400019 2.382645 -0.58025545 -0.63782334 0.5064435 0.021488441 0.09233946
+-1.11559 0.22400019 1.3025575 -0.38334632 -0.9040218 0.18918258 0.7439689 0.2791134
+-2.2274122 0.22400019 -0.4297089 -0.7312984 -0.6671969 -0.14160144 0.67494655 0.99038863
+-2.2161448 0.22400019 -0.43305972 -0.017521787 -0.99930537 0.032890607 0.67444944 0.9913764
+-2.230626 0.22640002 -0.41983035 -0.74839973 -0.49738073 -0.4387599 0.67444944 0.98951757
+-2.1618967 0.22400019 -0.40970844 -0.0028608302 -0.9999959 -0.000106975036 0.80714715 0.95338464
+-2.1749234 0.22400019 -0.40605244 -0.011426341 -0.9991058 -0.04070532 0.8076674 0.95454615
+-2.230626 0.22640002 -0.41983035 -0.74839973 -0.49738073 -0.4387599 0.80714715 0.9599234
+-2.2161448 0.22400019 -0.43305972 -0.017521787 -0.99930537 0.032890607 0.67331666 0.9900621
+-2.209373 0.22400019 -0.42154086 -0.0558253 -0.9859457 0.15746342 0.6744493 0.98951745
+-2.230626 0.22640002 -0.41983035 -0.74839973 -0.49738073 -0.4387599 0.67444944 0.99153584
+-2.209373 0.22400019 -0.42154086 -0.0558253 -0.9859457 0.15746342 0.80814487 0.9553456
+-2.1618967 0.22400019 -0.40970844 -0.0028608302 -0.9999959 -0.000106975036 0.8076674 0.95992327
+-2.230626 0.22640002 -0.41983035 -0.74839973 -0.49738073 -0.4387599 0.8076674 0.9533845
+-2.1937947 0.22400019 -0.40073627 -0.011439374 -0.9991109 -0.04057865 0.8044694 0.9616473
+-2.2783449 0.22400019 -0.37692034 -0.58131546 -0.51583326 -0.6292762 0.8044694 0.95338464
+-2.230626 0.22640002 -0.41983035 -0.74839973 -0.49738073 -0.4387599 0.807147 0.9587995
+-2.1749234 0.22400019 -0.40605244 -0.011426341 -0.9991058 -0.04070532 0.67240256 0.98951757
+-2.1937947 0.22400019 -0.40073627 -0.011439374 -0.9991109 -0.04057865 0.6733167 0.9911193
+-2.230626 0.22640002 -0.41983035 -0.74839973 -0.49738073 -0.4387599 0.67240256 0.9949199
+3 0 1 2
+3 0 3 4
+3 2 3 0
+3 5 3 2
+3 6 7 8
+3 8 7 9
+3 10 11 12
+3 13 14 15
+3 16 17 18
+3 19 20 21
+3 22 1 23
+3 24 25 26
+3 27 28 29
+3 30 31 27
+3 32 18 17
+3 33 34 35
+3 36 37 38
+3 39 40 13
+3 41 42 43
+3 44 45 46
+3 47 15 14
+3 48 18 32
+3 49 26 50
+3 33 35 51
+3 52 53 54
+3 54 47 14
+3 55 48 56
+3 11 10 57
+3 13 58 59
+3 40 14 13
+3 53 47 54
+3 60 61 62
+3 44 63 64
+3 6 60 65
+3 65 7 6
+3 66 67 54
+3 60 68 61
+3 38 37 69
+3 26 49 70
+3 67 10 12
+3 55 71 48
+3 72 22 23
+3 9 68 8
+3 68 60 6
+3 73 17 74
+3 75 10 67
+3 76 26 77
+3 1 26 76
+3 78 47 79
+3 0 80 81
+3 82 50 83
+3 84 85 86
+3 39 13 59
+3 87 27 29
+3 87 20 88
+3 29 21 87
+3 20 89 88
+3 90 17 16
+3 29 72 91
+3 40 84 86
+3 58 92 59
+3 21 11 19
+3 73 87 88
+3 27 31 2
+3 31 5 2
+3 52 49 53
+3 61 68 9
+3 93 48 94
+3 88 93 94
+3 51 35 95
+3 37 96 69
+3 33 51 41
+3 77 52 54
+3 67 12 77
+3 26 1 0
+3 76 77 12
+3 97 49 82
+3 46 98 99
+3 79 53 97
+3 23 76 72
+3 25 50 26
+3 0 24 26
+3 100 37 36
+3 52 70 49
+3 36 101 102
+3 64 45 44
+3 86 66 40
+3 11 21 91
+3 12 72 76
+3 82 49 50
+3 72 11 91
+3 75 103 89
+3 19 89 20
+3 32 88 94
+3 87 21 20
+3 79 47 53
+3 2 1 22
+3 22 72 29
+3 22 29 28
+3 27 2 28
+3 51 95 42
+3 50 25 83
+3 26 70 77
+3 0 81 24
+3 91 21 29
+3 23 1 76
+3 53 49 97
+3 77 54 67
+3 104 105 106
+3 52 77 70
+3 101 36 38
+3 4 80 0
+3 66 54 14
+3 62 107 60
+3 44 46 108
+3 41 51 42
+3 86 109 66
+3 57 10 75
+3 71 16 18
+3 55 16 71
+3 35 110 95
+3 32 17 73
+3 111 3 5
+3 40 39 84
+3 112 75 67
+3 72 12 11
+3 75 89 19
+3 75 19 57
+3 88 89 93
+3 74 27 73
+3 94 48 32
+3 19 11 57
+3 71 18 48
+3 40 66 14
+3 73 88 32
+3 113 62 61
+3 22 28 2
+3 35 114 110
+3 73 27 87
+3 115 93 89
+3 115 89 103
+3 116 117 118
+3 119 120 121
+3 122 30 74
+3 123 124 122
+3 125 126 127
+3 128 129 130
+3 131 132 133
+3 4 132 134
+3 135 121 136
+3 137 112 86
+3 138 128 139
+3 140 141 142
+3 143 144 145
+3 146 147 148
+3 122 124 30
+3 123 136 121
+3 56 48 93
+3 58 13 15
+3 121 141 140
+3 123 121 124
+3 30 27 74
+3 149 150 151
+3 152 122 74
+3 145 153 154
+3 120 141 121
+3 100 36 102
+3 155 156 153
+3 157 151 118
+3 152 74 17
+3 121 135 119
+3 144 119 145
+3 119 144 120
+3 158 159 160
+3 4 159 132
+3 100 161 162
+3 163 98 164
+3 138 98 45
+3 15 165 149
+3 166 34 33
+3 154 153 167
+3 153 145 155
+3 93 115 56
+3 154 167 164
+3 116 168 117
+3 150 168 116
+3 92 157 118
+3 136 123 169
+3 109 112 67
+3 3 111 160
+3 170 171 127
+3 132 131 34
+3 165 150 149
+3 148 147 172
+3 115 85 173
+3 158 139 159
+3 159 4 160
+3 149 151 157
+3 126 125 148
+3 45 174 129
+3 128 133 159
+3 156 163 167
+3 92 58 157
+3 175 5 142
+3 140 31 124
+3 144 141 120
+3 86 85 137
+3 8 68 6
+3 45 98 46
+3 34 176 35
+3 64 176 174
+3 176 34 177
+3 64 174 45
+3 64 63 176
+3 132 34 166
+3 162 96 100
+3 58 149 157
+3 125 127 171
+3 178 179 180
+3 181 125 171
+3 147 182 172
+3 126 148 172
+3 129 128 138
+3 130 133 128
+3 179 178 183
+3 177 34 131
+3 132 166 134
+3 159 139 128
+3 159 133 132
+3 160 111 175
+3 154 143 145
+3 137 85 115
+3 138 45 129
+3 35 176 114
+3 100 102 161
+3 100 96 37
+3 139 98 138
+3 164 98 158
+3 99 98 184
+3 98 163 184
+3 165 47 78
+3 160 4 3
+3 17 90 152
+3 167 153 156
+3 75 112 103
+3 142 144 143
+3 113 107 62
+3 151 150 116
+3 124 31 30
+3 142 5 140
+3 5 31 140
+3 125 146 148
+3 176 63 114
+3 139 158 98
+3 5 175 111
+3 164 158 160
+3 143 164 160
+3 15 149 58
+3 118 151 116
+3 112 137 103
+3 163 164 167
+3 175 142 143
+3 164 143 154
+3 175 143 160
+3 142 141 144
+3 121 140 124
+3 103 137 115
+3 80 4 134
+3 67 66 109
+3 109 86 112
+3 47 165 15
+3 181 171 170
+3 185 186 187
+3 188 189 190
+3 191 192 193
+3 191 194 192
+3 195 196 197
+3 198 199 200
+3 201 199 198
+3 202 203 204
+3 205 201 206
+3 207 201 205
+3 208 185 209
+3 210 185 208
+3 211 185 210
+3 212 185 211
+3 194 189 213
+3 194 190 189
+3 214 215 216
+3 192 212 217
+3 218 219 220
+3 221 219 218
+3 213 192 194
+3 198 206 201
+3 187 209 185
+3 217 193 192
+3 193 222 191
+3 193 223 222
+3 193 224 223
+3 193 225 224
+3 193 226 225
+3 193 203 226
+3 193 204 203
+3 218 227 221
+3 218 199 227
+3 218 200 199
+3 204 215 202
+3 204 216 215
+3 216 219 214
+3 216 220 219
+3 211 217 212
+3 228 229 85
+3 228 85 84
+3 230 231 84
+3 230 84 39
+3 232 230 39
+3 232 39 59
+3 233 234 90
+3 233 90 16
+3 235 236 55
+3 235 55 56
+3 237 238 173
+3 239 240 16
+3 239 16 55
+3 241 232 59
+3 241 59 92
+3 242 241 92
+3 231 228 84
+3 240 233 16
+3 243 244 122
+3 243 122 152
+3 245 246 119
+3 245 119 135
+3 247 248 136
+3 247 136 169
+3 246 249 119
+3 250 251 168
+3 234 252 152
+3 234 152 90
+3 244 253 122
+3 254 255 118
+3 253 256 123
+3 253 123 122
+3 257 258 145
+3 256 259 169
+3 256 169 123
+3 260 261 262
+3 248 135 136
+3 263 237 173
+3 263 173 85
+3 238 264 115
+3 238 115 173
+3 265 254 118
+3 265 118 117
+3 264 235 56
+3 264 56 115
+3 255 242 92
+3 255 92 118
+3 258 266 155
+3 258 155 145
+3 252 243 152
+3 259 247 169
+3 249 257 145
+3 249 145 119
+3 251 265 117
+3 251 117 168
+3 267 268 269
+3 270 271 272
+3 273 274 275
+3 276 277 278
+3 236 239 55
+3 229 263 85
+3 279 280 281
+3 282 283 284
diff --git a/src/meshes/fox/fox.ts b/src/meshes/fox/fox.ts
new file mode 100644
index 0000000..8296bff
--- /dev/null
+++ b/src/meshes/fox/fox.ts
@@ -0,0 +1,12 @@
+import { Mesh } from "../../renderer/mesh";
+
+// prettier-ignore
+export default new Mesh({
+ colors: null,
+ faces: new Uint16Array([0,1,2,0,3,4,2,3,0,5,3,2,6,7,8,8,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22,1,23,24,25,26,27,28,29,30,31,27,32,18,17,33,34,35,36,37,38,39,40,13,41,42,43,44,45,46,47,15,14,48,18,32,49,26,50,33,35,51,52,53,54,54,47,14,55,48,56,11,10,57,13,58,59,40,14,13,53,47,54,60,61,62,44,63,64,6,60,65,65,7,6,66,67,54,60,68,61,38,37,69,26,49,70,67,10,12,55,71,48,72,22,23,9,68,8,68,60,6,73,17,74,75,10,67,76,26,77,1,26,76,78,47,79,0,80,81,82,50,83,84,85,86,39,13,59,87,27,29,87,20,88,29,21,87,20,89,88,90,17,16,29,72,91,40,84,86,58,92,59,21,11,19,73,87,88,27,31,2,31,5,2,52,49,53,61,68,9,93,48,94,88,93,94,51,35,95,37,96,69,33,51,41,77,52,54,67,12,77,26,1,0,76,77,12,97,49,82,46,98,99,79,53,97,23,76,72,25,50,26,0,24,26,100,37,36,52,70,49,36,101,102,64,45,44,86,66,40,11,21,91,12,72,76,82,49,50,72,11,91,75,103,89,19,89,20,32,88,94,87,21,20,79,47,53,2,1,22,22,72,29,22,29,28,27,2,28,51,95,42,50,25,83,26,70,77,0,81,24,91,21,29,23,1,76,53,49,97,77,54,67,104,105,106,52,77,70,101,36,38,4,80,0,66,54,14,62,107,60,44,46,108,41,51,42,86,109,66,57,10,75,71,16,18,55,16,71,35,110,95,32,17,73,111,3,5,40,39,84,112,75,67,72,12,11,75,89,19,75,19,57,88,89,93,74,27,73,94,48,32,19,11,57,71,18,48,40,66,14,73,88,32,113,62,61,22,28,2,35,114,110,73,27,87,115,93,89,115,89,103,116,117,118,119,120,121,122,30,74,123,124,122,125,126,127,128,129,130,131,132,133,4,132,134,135,121,136,137,112,86,138,128,139,140,141,142,143,144,145,146,147,148,122,124,30,123,136,121,56,48,93,58,13,15,121,141,140,123,121,124,30,27,74,149,150,151,152,122,74,145,153,154,120,141,121,100,36,102,155,156,153,157,151,118,152,74,17,121,135,119,144,119,145,119,144,120,158,159,160,4,159,132,100,161,162,163,98,164,138,98,45,15,165,149,166,34,33,154,153,167,153,145,155,93,115,56,154,167,164,116,168,117,150,168,116,92,157,118,136,123,169,109,112,67,3,111,160,170,171,127,132,131,34,165,150,149,148,147,172,115,85,173,158,139,159,159,4,160,149,151,157,126,125,148,45,174,129,128,133,159,156,163,167,92,58,157,175,5,142,140,31,124,144,141,120,86,85,137,8,68,6,45,98,46,34,176,35,64,176,174,176,34,177,64,174,45,64,63,176,132,34,166,162,96,100,58,149,157,125,127,171,178,179,180,181,125,171,147,182,172,126,148,172,129,128,138,130,133,128,179,178,183,177,34,131,132,166,134,159,139,128,159,133,132,160,111,175,154,143,145,137,85,115,138,45,129,35,176,114,100,102,161,100,96,37,139,98,138,164,98,158,99,98,184,98,163,184,165,47,78,160,4,3,17,90,152,167,153,156,75,112,103,142,144,143,113,107,62,151,150,116,124,31,30,142,5,140,5,31,140,125,146,148,176,63,114,139,158,98,5,175,111,164,158,160,143,164,160,15,149,58,118,151,116,112,137,103,163,164,167,175,142,143,164,143,154,175,143,160,142,141,144,121,140,124,103,137,115,80,4,134,67,66,109,109,86,112,47,165,15,181,171,170,185,186,187,188,189,190,191,192,193,191,194,192,195,196,197,198,199,200,201,199,198,202,203,204,205,201,206,207,201,205,208,185,209,210,185,208,211,185,210,212,185,211,194,189,213,194,190,189,214,215,216,192,212,217,218,219,220,221,219,218,213,192,194,198,206,201,187,209,185,217,193,192,193,222,191,193,223,222,193,224,223,193,225,224,193,226,225,193,203,226,193,204,203,218,227,221,218,199,227,218,200,199,204,215,202,204,216,215,216,219,214,216,220,219,211,217,212,228,229,85,228,85,84,230,231,84,230,84,39,232,230,39,232,39,59,233,234,90,233,90,16,235,236,55,235,55,56,237,238,173,239,240,16,239,16,55,241,232,59,241,59,92,242,241,92,231,228,84,240,233,16,243,244,122,243,122,152,245,246,119,245,119,135,247,248,136,247,136,169,246,249,119,250,251,168,234,252,152,234,152,90,244,253,122,254,255,118,253,256,123,253,123,122,257,258,145,256,259,169,256,169,123,260,261,262,248,135,136,263,237,173,263,173,85,238,264,115,238,115,173,265,254,118,265,118,117,264,235,56,264,56,115,255,242,92,255,92,118,258,266,155,258,155,145,252,243,152,259,247,169,249,257,145,249,145,119,251,265,117,251,117,168,267,268,269,270,271,272,273,274,275,276,277,278,236,239,55,229,263,85,279,280,281,282,283,284]),
+ name: "src/meshes/fox/fox.ply",
+ normals: new Float32Array([0.3475203,-0.1423119,-0.92681,0.5162422,0.12797521,-0.8468272,0.15832935,0.05530619,-0.98583627,-0.34248725,0.027904412,-0.9391081,-0.5169309,-0.31768712,-0.7948945,-0.48697895,-0.1626665,-0.85813236,0.979832,0.13666466,-0.14578043,0.9031805,0.21487509,-0.37160963,0.66321534,0.26724067,-0.6990907,0.6848186,0.23503296,-0.68977004,0.50283414,0.37262148,-0.779943,0.23640795,0.47815725,-0.84585875,0.3647613,0.40136182,-0.8401535,0.3046436,0.23757984,0.92236,0.31008115,0.576068,0.7563038,-0.22806334,0.32389933,0.91819185,0.17951295,-0.316014,-0.931617,-0.17395478,-0.060770363,-0.9828767,0.3371145,-0.028111659,-0.94104385,0.5286752,0.36182427,-0.76784486,0.37282482,0.34924614,-0.8596678,0.04436654,0.3120137,-0.9490411,0.1748497,-0.08175629,-0.981195,0.4760932,0.18387188,-0.8599573,0.77194935,-0.10489054,-0.6269707,0.8878576,0.018637033,-0.45974046,0.8233882,0.00536109,-0.5674533,0.50706327,0.2949509,-0.8098708,0.5776023,0.024086185,-0.8159629,0.20082258,0.4428197,-0.8738313,-0.3673268,-0.008583662,-0.9300523,-0.23037066,-0.14419852,-0.9623597,0.10130113,0.55220604,-0.82753044,-0.30028316,0.6138469,-0.7300836,-0.42857707,0.59847176,-0.67687017,0.2310956,0.77802414,-0.5841861,0.40507296,-0.59645694,-0.69293207,0.018303465,0.44150117,-0.8970739,0.77194935,-0.10489054,-0.6269707,0.6770759,-0.15234865,0.71997094,0.5551748,0.09818922,0.82591754,0.5862696,0.275684,-0.7617652,0.8878576,0.018637033,-0.45974046,0.77194935,-0.10489054,-0.6269707,0.3452935,0.52275664,0.7794215,-0.037781123,0.40868607,0.9118927,0.47639555,0.22756127,0.8492721,0.038687505,0.4890638,0.87138975,0.4779266,0.31795877,-0.8188335,0.9412043,0.3062575,0.14262189,0.985557,-0.050912835,-0.16150954,0.41709664,0.43660966,-0.79712135,0.65320575,0.7567542,-0.025403246,0.5102622,0.5121896,0.6908649,0.5327677,0.8339708,0.14370571,0.50982845,-0.2752561,-0.81505156,0.9362124,0.034893714,-0.34969804,0.49277383,0.474742,-0.729242,-0.10767815,0.15382154,0.98221403,0.53157943,-0.18795584,0.825891,0.3452935,0.52275664,0.7794215,0.73606163,0.6634644,-0.13426952,-0.17794462,0.9747583,-0.13484038,-0.38528097,0.9081675,0.1636775,0.03706524,0.8542405,0.51855505,0.90783143,0.11600388,0.40297043,0.8010637,0.5264299,0.2849009,0.6885465,0.57700217,-0.43928608,0.95855004,0.10577212,0.26456407,0.5862696,0.275684,-0.7617652,0.78829354,0.5408408,-0.2934015,0.21502984,0.04666299,-0.97549206,0.102968186,0.09595936,-0.9900452,-0.42321405,0.5065525,-0.7511954,-0.69715625,-0.08602459,-0.71173936,0.82457936,0.081235796,-0.5598835,0.4377959,0.26956058,-0.85771316,0.6155783,0.5745703,-0.5393813,0.07019434,0.24138543,0.9678872,0.3541473,0.25355586,0.9001605,-0.29064578,-0.724498,-0.62500215,0.375913,-0.73612595,-0.56285685,0.90783143,0.11600388,0.40297043,0.9031805,0.21487509,-0.37160963,0.5472127,-0.29103354,0.7847661,0.87695193,-0.2072897,0.4335738,0.8803676,0.14394727,0.45192042,0.15257555,0.7520019,-0.64125955,0.073696144,0.91218823,-0.40308988,0.48116767,0.69189876,-0.5382877,-0.38885155,-0.2292497,-0.8923223,-0.08802483,0.3184032,-0.94385976,-0.16566989,-0.31949857,0.9329921,0.4088575,0.88988423,-0.20234066,0.23401263,0.7841241,-0.5747935,0.9031805,0.21487509,-0.37160963,-0.30028316,0.6138469,-0.7300836,0.47639555,0.22756127,0.8492721,-0.13893181,0.08481444,0.98666334,0.3541473,0.25355586,0.9001605,-0.6594078,-0.34964943,-0.6655273,0.375913,-0.73612595,-0.56285685,-0.29064578,-0.724498,-0.62500215,0.7611686,0.58185023,-0.28648314,-0.04397583,0.70420456,-0.7086339,0.73606163,0.6634644,-0.13426952,0.6848186,0.23503296,-0.68977004,-0.38528097,0.9081675,0.1636775,0.90783143,0.11600388,0.40297043,0.9180944,0.3928391,0.052727237,0.6848186,0.23503296,-0.68977004,-0.75246775,0.008946161,-0.6585683,0.93610126,0.23180684,-0.26453748,-0.04397583,0.70420456,-0.7086339,-0.04397583,0.70420456,-0.7086339,0.92324126,0.38289523,0.03188642,-0.8208653,0.15153797,0.55065095,-0.6847748,0.31241915,0.6583902,-0.44955286,-0.170653,0.87680095,-0.69434595,0.69967836,-0.16832665,-0.64949834,0.59640735,-0.47164628,-0.72120667,0.6666094,-0.18839571,-0.44213012,-0.017088598,-0.8967881,-0.16689667,0.37004504,-0.9138995,-0.32365012,-0.16409263,-0.93183917,-0.81858766,0.5451293,-0.18096499,-0.992983,0.08945896,0.07734239,-0.21252948,0.5347677,0.81783545,-0.7021046,-0.14130145,0.6979133,-0.992983,0.08945896,0.07734239,-0.9546164,0.028929858,-0.2964296,-0.7311533,0.36524838,-0.5762018,-0.9617006,-0.03754102,-0.27151904,-0.9879483,0.08645398,-0.1283894,-0.78725094,-0.2752617,-0.5517852,-0.74839973,-0.49738073,-0.4387599,-0.6237263,0.711984,-0.32255915,0.9198568,0.38913035,-0.049406413,-0.44723478,0.13983466,0.883418,-0.6689012,-0.23592637,0.7049185,-0.8903412,-0.15419926,-0.42838684,-0.92482555,0.016368585,-0.3800392,-0.8165544,-0.1464694,-0.55837774,-0.87178856,-0.35990623,-0.3323434,-0.517776,0.4540006,-0.7251148,-0.8433312,0.09983585,0.52803904,-0.47634494,-0.05045076,-0.87780994,-0.7311533,0.36524838,-0.5762018,-0.6984636,-0.017294424,-0.71543664,-0.64312565,0.17802551,0.7447794,-0.66986597,-0.026210472,0.7420193,-0.90760005,0.06683492,0.41448176,-0.71550065,-0.2610496,-0.6480061,-0.48163462,-0.16273934,0.86112946,-0.9447443,-0.18422589,0.271144,-0.84864473,-0.16340141,0.5030924,-0.66986597,-0.026210472,0.7420193,-0.44133595,0.045067813,0.8962095,-0.84305483,-0.09319865,0.52969086,-0.96471584,-0.253683,0.070486,-0.90281165,-0.30579108,-0.30236223,-0.78725094,-0.2752617,-0.5517852,-0.747842,0.21194589,-0.6291353,-0.38904643,0.09032617,0.9167791,-0.8832008,-0.12243323,0.45273212,-0.38904643,0.09032617,0.9167791,-0.747842,0.21194589,-0.6291353,-0.4839415,-0.097555116,0.86964566,-0.84864473,-0.16340141,0.5030924,-0.05462312,0.1690641,-0.9840902,0.075866185,0.9794647,-0.18679745,0.02688641,0.9635681,-0.26610863,-0.9546164,0.028929858,-0.2964296,0.94705594,-0.2590572,-0.18966934,-0.21252948,0.5347677,0.81783545,-0.6675564,-0.59708816,-0.444808,0.075866185,0.9794647,-0.18679745,-0.23479536,0.67432845,-0.7001088,-0.23479536,0.67432845,-0.7001088,-0.47634494,-0.05045076,-0.87780994,-0.81858766,0.5451293,-0.18096499,-0.23479536,0.67432845,-0.7001088,-0.9879483,0.08645398,-0.1283894,-0.7311533,0.36524838,-0.5762018,0.07019434,0.24138543,0.9678872,-0.40643814,-0.8098558,-0.42301488,-0.19065972,-0.720445,-0.66678923,0.075374685,-0.7676886,-0.6363747,0.41129172,-0.60820895,-0.6789117,0.3633369,-0.6630077,-0.65452826,-0.52704555,-0.58184344,-0.6194199,-0.017521787,-0.99930537,0.032890607,-0.021521537,-0.94214505,-0.3345139,0.6121442,-0.6924734,-0.38178536,-0.70010203,-0.5537167,-0.45083794,-0.7312984,-0.6671969,-0.14160144,-0.70010203,-0.5537167,-0.45083794,-0.017521787,-0.99930537,0.032890607,0.3288468,-0.8804425,0.34158558,-0.1467376,-0.75445783,0.63973546,0.24385142,-0.7973807,0.55201495,-0.23899291,-0.84482497,0.4786994,-0.80877304,-0.50211614,0.3062115,-0.847515,-0.42922866,-0.3122198,0.5623081,-0.8260273,-0.03858204,0.04242061,-0.8742375,0.4836417,0.407,-0.7800877,0.47519907,-0.12836032,-0.80886763,0.57380897,0.16910498,-0.7943238,-0.5834837,0.12811182,-0.79456544,-0.59350926,0.40930107,-0.86440027,-0.29203552,0.48217154,-0.858188,-0.17613666,-0.57233065,-0.7097642,-0.41069746,0.22967121,-0.49633533,-0.83719915,-0.27430204,-0.8970687,0.34644783,-0.62714297,-0.48046845,0.6130593,0.5038301,-0.8556301,0.1185428,0.42636088,-0.8999785,-0.09085657,0.39348367,-0.810439,0.4340037,-0.38334632,-0.9040218,0.18918258,0.4810456,-0.8009131,0.35655776,-0.68955994,-0.7188539,0.0880689,-0.0558253,-0.9859457,0.15746342,-0.0028608302,-0.9999959,-0.000106975036,-0.011426341,-0.9991058,-0.04070532,-0.011439374,-0.9991109,-0.04057865,-0.58131546,-0.51583326,-0.6292762,-0.58025545,-0.63782334,0.5064435,0.39348367,-0.810439,0.4340037,0.4810456,-0.8009131,0.35655776,0.3288468,-0.8804425,0.34158558,0.24385142,-0.7973807,0.55201495,0.407,-0.7800877,0.47519907,0.075374685,-0.7676886,-0.6363747,-0.19065972,-0.720445,-0.66678923,0.48217154,-0.858188,-0.17613666,0.40930107,-0.86440027,-0.29203552,0.5623081,-0.8260273,-0.03858204,0.6121442,-0.6924734,-0.38178536,0.16910498,-0.7943238,-0.5834837,0.12811182,-0.79456544,-0.59350926,0.04242061,-0.8742375,0.4836417,-0.12836032,-0.80886763,0.57380897,-0.57233065,-0.7097642,-0.41069746,-0.021521537,-0.94214505,-0.3345139,-0.58131546,-0.51583326,-0.6292762,-0.847515,-0.42922866,-0.3122198,-0.52704555,-0.58184344,-0.6194199,-0.70010203,-0.5537167,-0.45083794,-0.80877304,-0.50211614,0.3062115,-0.38334632,-0.9040218,0.18918258,-0.68955994,-0.7188539,0.0880689,-0.40643814,-0.8098558,-0.42301488,0.22967121,-0.49633533,-0.83719915,-0.1467376,-0.75445783,0.63973546,-0.23899291,-0.84482497,0.4786994,0.3633369,-0.6630077,-0.65452826,-0.62714297,-0.48046845,0.6130593,-0.27430204,-0.8970687,0.34644783,0.41129172,-0.60820895,-0.6789117,-0.70010203,-0.5537167,-0.45083794,-0.7312984,-0.6671969,-0.14160144,-0.74839973,-0.49738073,-0.4387599,0.5038301,-0.8556301,0.1185428,0.42636088,-0.8999785,-0.09085657,-0.58025545,-0.63782334,0.5064435,-0.38334632,-0.9040218,0.18918258,-0.7312984,-0.6671969,-0.14160144,-0.017521787,-0.99930537,0.032890607,-0.74839973,-0.49738073,-0.4387599,-0.0028608302,-0.9999959,-0.000106975036,-0.011426341,-0.9991058,-0.04070532,-0.74839973,-0.49738073,-0.4387599,-0.017521787,-0.99930537,0.032890607,-0.0558253,-0.9859457,0.15746342,-0.74839973,-0.49738073,-0.4387599,-0.0558253,-0.9859457,0.15746342,-0.0028608302,-0.9999959,-0.000106975036,-0.74839973,-0.49738073,-0.4387599,-0.011439374,-0.9991109,-0.04057865,-0.58131546,-0.51583326,-0.6292762,-0.74839973,-0.49738073,-0.4387599,-0.011426341,-0.9991058,-0.04070532,-0.011439374,-0.9991109,-0.04057865,-0.74839973,-0.49738073,-0.4387599]),
+ positions: new Float32Array([-0.6999253,6.443001,-0.82603,0.07097474,5.343301,-0.52663046,-0.76262593,4.472701,-1.15393,-1.7783258,5.520501,-0.86433035,-2.2427258,6.713101,-0.82603,-1.5250261,4.4763007,-0.9856301,0.29497454,9.249201,0.16336976,0.06327439,8.8725,-0.28472978,-0.035225682,9.543601,0.14946976,-0.30342564,9.674201,-0.23032992,2.4808748,3.6319008,-0.11143037,2.0297747,3.2159004,-0.4459305,1.5565743,4.603301,-0.21123049,2.1004748,3.2381003,3.2929707,1.8371744,4.748301,2.81227,0.20437472,4.420901,2.9141703,1.8253747,0.4645001,-1.7956301,0.91437465,0.9539002,-2.1209302,2.4374743,1.0497,-1.8992304,2.5767748,2.7875004,-0.6003304,1.7599748,1.8992002,-1.1086301,1.5595742,2.5219004,-1.29143,0.24357454,3.5395007,-0.67183006,0.24817431,4.333201,-0.45933002,-0.3960259,7.7391005,-1.2657304,0.05687409,8.074501,-0.67993015,-0.12432557,6.748201,-0.34603044,-0.06132584,2.9543004,-0.8707303,-0.20062563,3.4773006,-0.68853,0.43317416,2.5253003,-0.46623006,-0.4904259,2.1981003,-0.90393,-1.0552258,3.1734004,-1.06763,1.4597749,1.4790002,-2.0267305,-1.8893259,8.729101,-1.7110304,-2.2624261,9.345001,-1.37473,-0.97242594,9.702102,-0.89533013,-1.2870256,7.527001,-2.5206306,-1.5926256,8.311801,-2.8306303,-0.3960259,7.7391005,-1.2657304,2.5549746,1.4319001,2.9302707,2.773675,2.7475002,3.0280704,-0.94812554,8.5809,-1.5055304,0.05687409,8.074501,-0.67993015,-0.3960259,7.7391005,-1.2657304,-0.40532535,9.700401,0.84696966,-1.540426,8.934701,1.6871705,-0.62042546,7.995201,1.7714701,-0.15842591,5.3485007,2.2917705,3.3480747,1.1927001,-1.4741304,0.23047411,6.9421005,0.8096703,0.17777406,7.816401,-0.13533022,-0.80692565,9.159501,-1.4650301,0.73637474,6.182101,0.90636986,0.16357423,6.238301,1.5856699,2.0266747,5.562201,1.4546701,3.4768748,0.57150006,-1.4508302,4.1452746,0.9685002,-0.7070302,2.576082,3.1560004,-0.31358007,0.7198746,2.4339004,3.54267,2.288975,1.3705001,3.4610705,-0.40532535,9.700401,0.84696966,0.14267427,10.748201,0.011170197,-0.35632557,10.885501,-0.026630403,-1.0288259,10.067701,0.053869635,-1.2105256,9.758201,0.87647027,0.09657441,8.901701,0.59447026,3.0635746,4.299401,1.8075701,2.5929751,4.772801,0.5979699,0.16167451,9.942601,0.37547,-0.94812554,8.5809,-1.5055304,0.47697452,6.306901,0.39987034,3.0665743,0.73340005,-1.42483,0.6858742,3.7022007,-0.62512976,0.044074252,1.8123003,-1.5475305,-0.053825382,1.2451001,-1.5953302,3.2380748,2.4352005,-0.08572999,0.5252747,5.1989007,-0.29223025,0.8465745,5.738801,0.27866977,-0.7709256,5.724101,2.2065706,-0.619426,6.356501,1.9183702,-1.9789258,7.178801,-1.18583,-0.91182566,7.3815007,-1.4608301,0.09657441,8.901701,0.59447026,0.06327439,8.8725,-0.28472978,3.0936747,0.6671002,2.4830706,4.0453753,0.52309996,1.4920702,3.6563747,2.4587002,2.1933703,0.5219742,1.8811003,-1.0851305,1.1984742,1.6896003,-1.65813,2.625175,1.7991003,-0.6557297,0.67027444,0.5334,-1.9347303,1.2843744,3.0958004,-0.5304299,0.77727437,1.2146001,3.4750705,3.4174747,1.7396003,-0.85813,2.3443742,1.5199003,-1.5742303,0.06327439,8.8725,-0.28472978,-1.8893259,8.729101,-1.7110304,-0.62042546,7.995201,1.7714701,-1.219426,6.696401,2.0643702,-0.619426,6.356501,1.9183702,-2.161226,7.667401,-2.4847305,-0.91182566,7.3815007,-1.4608301,-1.9789258,7.178801,-1.18583,3.1734743,1.5024002,0.15137026,-0.7888257,10.067701,-0.3484299,0.14267427,10.748201,0.011170197,-0.30342564,9.674201,-0.23032992,-1.0288259,10.067701,0.053869635,0.09657441,8.901701,0.59447026,3.387675,3.7165008,1.58967,-0.30342564,9.674201,-0.23032992,-2.2445261,4.9454007,-0.66073006,3.6162753,2.8629005,0.8747697,-0.7888257,10.067701,-0.3484299,-0.7888257,10.067701,-0.3484299,4.364375,1.0550001,0.5702698,-0.61192554,1.0255002,2.04657,-1.0520257,0.52869993,2.4247699,-0.0897255,0.5721001,2.6455705,-2.517626,0.78980017,0.25796968,-1.337726,0.8835,0.28996965,-1.4268259,0.95919997,-0.43353048,-0.44272542,1.0345002,-0.70443004,-1.0315259,1.0731,-0.7273301,-1.0638257,2.0252004,-0.7415303,-3.471126,10.565201,0.1122696,-3.4521263,9.519001,0.46967015,-2.878626,9.963901,0.81987005,-2.741226,7.508901,1.3471704,-3.4521263,9.519001,0.46967015,-3.433826,9.038601,0.28866962,-2.882526,9.084501,-0.10313035,-3.3896263,8.113201,-0.3605301,-3.3058262,8.5403,0.07176972,-2.7694259,7.7350006,-1.0115304,-2.230626,0.22640002,-0.41983035,-1.868326,0.75070006,-0.9546304,3.880675,1.3958001,1.1265702,-2.327826,8.2278,1.5766702,-2.5213258,6.882601,1.3467698,-1.4618257,2.4264002,-0.6133301,-1.2621258,1.7734003,0.17966996,-1.4422258,3.0290003,0.4318703,-1.9845258,3.6388009,0.69077003,-1.890426,1.0817002,0.44496998,-2.0575259,0.9955001,0.9599702,-2.964326,9.822501,-0.10223008,-2.882526,9.084501,-0.10313035,-3.092126,9.502201,0.2502701,-0.087125406,3.1274004,2.8989704,-0.8196259,2.3198001,1.7973703,-0.8748258,2.0967002,2.7634706,0.02887421,0.7540002,-1.4195303,-1.665426,1.8197002,1.62437,-2.1923258,3.5194008,1.3925699,-1.186226,0.55610013,1.5514703,-0.8196259,2.3198001,1.7973703,-0.029425815,2.1513002,3.4381702,-2.5888262,6.208601,0.9756699,-3.112326,7.3445005,0.3178696,-2.667426,4.758001,0.018969728,-2.7694259,7.7350006,-1.0115304,-2.392026,8.487902,-1.3364304,-0.8792256,4.817401,2.3403704,-2.6100261,4.707801,1.3596704,-0.8792256,4.817401,2.3403704,-2.392026,8.487902,-1.3364304,-1.8001261,4.085301,1.9035699,-1.186226,0.55610013,1.5514703,-1.569626,0.3742001,-1.4788301,-1.9930261,9.862201,-0.003130341,-3.0411263,10.770401,0.043869786,-3.433826,9.038601,0.28866962,4.2867746,0.52519995,0.41017002,-2.878626,9.963901,0.81987005,-1.9710261,3.9114006,0.01537018,-1.9930261,9.862201,-0.003130341,-2.2901258,9.714901,-0.21963045,-2.2901258,9.714901,-0.21963045,-2.964326,9.822501,-0.10223008,-3.471126,10.565201,0.1122696,-2.2901258,9.714901,-0.21963045,-3.3058262,8.5403,0.07176972,-2.882526,9.084501,-0.10313035,-0.7709256,5.724101,2.2065706,0.58418125,0.22400019,-1.7113466,0.7487328,0.22400019,-1.869269,1.2752382,0.22400019,-1.8116388,-1.4210848,0.22400019,-1.3924581,-1.2286401,0.22400019,-1.2118917,-1.7548681,0.22400019,-1.3470285,-2.2161448,0.22400019,-0.43305972,-0.5065232,0.22400019,-0.5854172,3.6921923,0.22400019,-0.5356896,-1.9521799,0.22400019,-1.126045,-2.2274122,0.22400019,-0.4297089,-1.9521799,0.22400019,-1.126045,-2.2161448,0.22400019,-0.43305972,2.2313638,0.22400019,2.680494,-0.6810555,0.22400019,2.4642336,2.4538667,0.22400019,2.5940027,0.41850665,0.22400019,2.7519977,-2.6425998,0.22400019,0.70022744,-2.7626433,0.22400019,0.07626649,4.1131854,0.22400019,0.46040884,1.955617,0.22400019,2.7750673,2.1960154,0.22400019,2.7574801,0.7445824,0.22400019,2.9373279,2.7569857,0.22400019,-1.5163606,2.100773,0.22400019,-1.6653436,3.4797022,0.22400019,-1.0087174,3.5642383,0.22400019,-0.8515244,-0.37594378,0.22400019,-0.7854573,-1.1313287,0.22400019,-1.2045778,-1.2935071,0.22400019,1.0919343,-2.5766528,0.22400019,0.8374413,4.0127363,0.22400019,0.9127198,3.5815594,0.22400019,-0.7074967,3.4810352,0.22400019,1.8996607,-1.11559,0.22400019,1.3025575,3.8143253,0.22400019,1.5762239,-1.0991356,0.22400019,2.0397234,-2.209373,0.22400019,-0.42154086,-2.1618967,0.22400019,-0.40970844,-2.1749234,0.22400019,-0.40605244,-2.1937947,0.22400019,-0.40073627,-2.2783449,0.22400019,-0.37692034,-1.0468484,0.22400019,2.382645,3.4810352,0.22400019,1.8996607,3.8143253,0.22400019,1.5762239,2.2313638,0.22400019,2.680494,2.4538667,0.22400019,2.5940027,2.1960154,0.22400019,2.7574801,1.2752382,0.22400019,-1.8116388,0.7487328,0.22400019,-1.869269,3.5642383,0.22400019,-0.8515244,3.4797022,0.22400019,-1.0087174,4.1131854,0.22400019,0.46040884,3.6921923,0.22400019,-0.5356896,2.7569857,0.22400019,-1.5163606,2.100773,0.22400019,-1.6653436,1.955617,0.22400019,2.7750673,0.7445824,0.22400019,2.9373279,-0.37594378,0.22400019,-0.7854573,-0.5065232,0.22400019,-0.5854172,-2.2783449,0.22400019,-0.37692034,-2.7626433,0.22400019,0.07626649,-1.7548681,0.22400019,-1.3470285,-1.9521799,0.22400019,-1.126045,-2.6425998,0.22400019,0.70022744,-1.11559,0.22400019,1.3025575,-1.0991356,0.22400019,2.0397234,0.58418125,0.22400019,-1.7113466,-1.1313287,0.22400019,-1.2045778,-0.6810555,0.22400019,2.4642336,0.41850665,0.22400019,2.7519977,-1.2286401,0.22400019,-1.2118917,-2.5766528,0.22400019,0.8374413,-1.2935071,0.22400019,1.0919343,-1.4210848,0.22400019,-1.3924581,-1.9521799,0.22400019,-1.126045,-2.2274122,0.22400019,-0.4297089,-2.230626,0.22640002,-0.41983035,4.0127363,0.22400019,0.9127198,3.5815594,0.22400019,-0.7074967,-1.0468484,0.22400019,2.382645,-1.11559,0.22400019,1.3025575,-2.2274122,0.22400019,-0.4297089,-2.2161448,0.22400019,-0.43305972,-2.230626,0.22640002,-0.41983035,-2.1618967,0.22400019,-0.40970844,-2.1749234,0.22400019,-0.40605244,-2.230626,0.22640002,-0.41983035,-2.2161448,0.22400019,-0.43305972,-2.209373,0.22400019,-0.42154086,-2.230626,0.22640002,-0.41983035,-2.209373,0.22400019,-0.42154086,-2.1618967,0.22400019,-0.40970844,-2.230626,0.22640002,-0.41983035,-2.1937947,0.22400019,-0.40073627,-2.2783449,0.22400019,-0.37692034,-2.230626,0.22640002,-0.41983035,-2.1749234,0.22400019,-0.40605244,-2.1937947,0.22400019,-0.40073627,-2.230626,0.22640002,-0.41983035]),
+ uvs: new Float32Array([0.21851481,0.38709354,0.25122124,0.29925498,0.33613995,0.31277353,0.31780326,0.41546077,0.26634175,0.49754715,0.36926088,0.35428312,0.8862014,0.7660378,0.96414614,0.65773886,0.9142767,0.82184976,0.96414614,0.8656495,0.24378048,0.15517116,0.27324826,0.1538348,0.24071635,0.21034758,0.12782207,0.13377228,0.13686845,0.17050092,0.097095504,0.18026535,0.3456612,0.015984222,0.38372317,0.05219409,0.3173124,0.03967564,0.2669188,0.12665303,0.3150151,0.10144508,0.312529,0.12937495,0.32927862,0.22344446,0.2904697,0.2528519,0.13747068,0.42125323,0.1110152,0.38961607,0.17645767,0.34971166,0.37940347,0.20685007,0.3529383,0.23464157,0.35064337,0.17517665,0.43924242,0.18647039,0.41530237,0.2674248,0.34998143,0.06725915,0.12322961,0.6801839,0.1720783,0.6964544,0.16144735,0.7933706,0.8861246,0.52512723,0.84557533,0.5134298,0.9878913,0.42880467,0.12832226,0.086800925,0.14096868,0.11748978,0.074313566,0.7435197,0.020883663,0.84153533,1.081579e-8,0.77996564,0.32931674,0.8416559,0.35599756,0.7471563,0.4352468,0.76457715,0.09890157,0.21372627,0.28071728,0.038383927,0.12732372,0.2965882,0.11473294,0.36185902,0.110673696,0.76611084,0.1568792,0.258202,0.11916661,0.24799357,0.1670033,0.20147358,0.27564877,0.017370421,0.24627076,0.033188876,0.25064924,0.13463129,0.09065693,0.12818988,0.11538713,0.09199737,0.8276462,0.8879465,0.8977165,0.9073449,0.8979689,0.9335955,0.24703515,0.8216678,0.30523577,0.7905776,0.8020745,0.7431329,0.17493051,0.15400115,0.20319703,0.1803566,0.89068747,0.8602873,0.8669603,0.42128757,0.1696568,0.2862294,0.29085746,0.022808408,0.30401754,0.21331184,0.4063384,0.124203816,0.4319168,0.09517003,0.24068871,0.10983848,0.2422915,0.26877972,0.19642983,0.2589539,0.084621415,0.22762483,0.08997824,0.2432744,0.21659407,0.49825695,0.16409814,0.4431432,0.06007273,0.3584054,0.077401064,0.3881148,0.13976377,0.06055675,0.1772671,0.045047924,0.1689892,0.10318307,0.36747235,0.13334484,0.35129,0.09048066,0.27406374,0.088201545,0.40481266,0.033736143,0.3024185,0.17043002,0.080950305,0.101946086,0.26399732,0.060749806,0.3123137,0.06264582,0.08229262,0.8732247,0.78262734,0.48695683,0.054573745,0.28939876,0.4784059,0.67288846,0.52534187,0.6902852,0.843693,0.54919225,0.967211,0.5381632,0.8863765,0.6507956,0.23814057,0.07682296,0.52430856,0.78790325,0.5076637,0.9781552,0.42495766,0.8044593,0.88358545,0.94791806,0.39027283,0.865766,0.18311635,0.13782379,0.15227878,0.86758876,0.37036988,0.41615537,0.20584682,0.11498356,0.935007,0.9301176,0.19761893,0.83779246,0.20950294,0.045586396,0.0322884,0.11481223,0.02451134,0.09802288,0.048454616,0.09665558,0.6460075,0.21836895,0.5963892,0.2274105,0.5771463,0.1884031,0.5055221,0.114784405,0.5447714,0.15467297,0.48357084,0.21026236,0.75558704,0.9432239,0.8020744,0.9034289,0.7897775,0.96688294,0.36300594,0.6462114,0.27383736,0.69182056,0.27248618,0.6792056,0.2478923,0.6867268,0.25436208,0.6271816,0.26854706,0.6570603,0.2133645,0.5806204,0.637635,0.17406993,0.60493344,0.1558058,0.19796096,0.06852602,0.35857934,0.69122976,0.3951752,0.6194137,0.48257515,0.25476277,0.5577472,0.2591085,0.5101766,0.3366432,0.50301826,0.39985734,0.6224612,0.2508355,0.65923995,0.27131322,0.7339221,0.92058545,0.667627,0.84930974,0.75460386,0.8875665,0.07549074,0.15373975,0.036297202,0.14856292,0.053295545,0.13493255,0.45089763,0.06624607,0.65852106,0.35673973,0.5478699,0.43424743,0.734133,0.3012958,0.69251174,0.422131,0.07396352,0.1281145,0.4061021,0.5678618,0.31435022,0.5997315,0.4114268,0.44731957,0.75763285,0.6744133,0.734765,0.56230044,0.5902533,0.5873184,0.48538992,0.4962032,0.07417127,0.20548928,0.16459617,0.6398786,0.5627961,0.49731115,0.010203981,0.1122183,0.61384606,0.11812159,0.7293909,0.98951745,0.753717,0.961225,0.8020744,0.78846765,0.20760685,0.029241929,0.27992412,0.7168905,0.45012152,0.3856737,0.2468168,0.7547342,0.23586477,0.728986,0.52842814,0.74081594,0.58254737,0.8386313,0.5380133,0.9808106,0.69757915,0.9635888,0.70988774,0.65773886,0.6677008,0.75300074,0.5507923,0.6433447,0.9718312,0.020504208,0.97220457,0.021100836,0.9716987,0.022655101,0.9721315,0.014245303,0.9714647,0.014712902,0.97220457,0.013208317,0.96973413,0.01123883,0.96911705,0.01649964,0.96632093,0.029152708,0.9716613,0.012472974,0.80359983,1.0238159,0.80359983,0.95338476,0.8044696,1.023133,0.95752156,0.022717984,0.96000504,0.01405433,0.95764303,0.02344461,0.95844465,0.017195703,0.9665674,0.0092362035,0.96852803,0.009265589,0.9630468,0.029798763,0.9574091,0.02182542,0.95731115,0.022562819,0.9576798,0.018064456,0.9698729,0.026945414,0.9707365,0.02505687,0.9678838,0.028808849,0.96735567,0.028965177,0.9696391,0.017020183,0.9713813,0.015002267,0.96453613,0.013066204,0.96611136,0.009349244,0.9617433,0.029211031,0.96690965,0.028926747,0.9590955,0.02698438,0.963788,0.013471412,0.95986325,0.028194623,0.96155035,0.013057904,0.9696951,0.011252033,0.9696294,0.011387991,0.96961904,0.011344941,0.9696118,0.01128404,0.969593,0.011013629,0.9604814,0.013000401,0.15420465,0.04102335,0.16792865,0.037144165,0.110636964,0.05624038,0.117879316,0.05280347,0.1069449,0.059347447,0.37604672,0.008110086,0.4070614,0.013023422,0.25538462,0.0031148791,0.2648711,8.450675e-9,0.20259783,0.019268692,0.23897217,0.0057812533,0.3031835,0.0016587148,0.3331248,0.0026185757,0.09809749,0.06282124,0.068156235,0.07761529,0.52157223,0.044851843,0.5435285,0.046751596,0.63853747,0.17621852,0.66334546,0.19258852,0.62489164,0.1247898,0.6287393,0.14086775,0.68118423,0.21481499,-3.3102134e-9,0.10996528,0.013690739,0.09781893,0.42186216,0.014245739,0.6017828,0.094806425,0.030619193,0.091465615,0.057839744,0.08235605,0.59865737,0.10087764,0.67908764,0.21657859,0.7325371,0.2680749,0.614245,0.10814548,0.43263742,0.92657316,0.43597075,0.8869815,0.43614823,0.88644433,0.18772343,0.02667462,0.24657853,0.0037103465,0.021488441,0.09233946,0.7439689,0.2791134,0.67494655,0.99038863,0.67444944,0.9913764,0.67444944,0.98951757,0.80714715,0.95338464,0.8076674,0.95454615,0.80714715,0.9599234,0.67331666,0.9900621,0.6744493,0.98951745,0.67444944,0.99153584,0.80814487,0.9553456,0.8076674,0.95992327,0.8076674,0.9533845,0.8044694,0.9616473,0.8044694,0.95338464,0.807147,0.9587995,0.67240256,0.98951757,0.6733167,0.9911193,0.67240256,0.9949199]),
+ vertexCount: 285
+});
diff --git a/src/meshes/gizmo.ply b/src/meshes/gizmo.ply
new file mode 100644
index 0000000..3b466cd
--- /dev/null
+++ b/src/meshes/gizmo.ply
@@ -0,0 +1,97 @@
+ply
+format ascii 1.0
+comment Created in Blender version 3.6.4
+element vertex 42
+property float x
+property float y
+property float z
+property float nx
+property float ny
+property float nz
+property uchar red
+property uchar green
+property uchar blue
+property uchar alpha
+property float s
+property float t
+element face 36
+property list uchar uint vertex_indices
+end_header
+0 0.05 -0.05 -0.057735033 0.5773503 -0.5773503 0 254 0 255 0.625 0
+1 -0.05 -0.05 0.057735033 -0.5773503 -0.5773503 0 254 0 255 0.375 0.25
+0 -0.05 -0.05 -0.057735033 -0.5773503 -0.5773503 0 254 0 255 0.375 0
+1 0.05 -0.05 0.057735033 0.5773503 -0.5773503 0 254 0 255 0.625 0.25
+1 -0.05 0.05 0.057735033 -0.5773503 0.5773503 0 254 0 255 0.375 0.5
+1 0.05 0.05 0.057735033 0.5773503 0.5773503 0 254 0 255 0.625 0.5
+0 -0.05 0.05 -0.057735033 -0.5773503 0.5773503 0 254 0 255 0.375 0.75
+0 0.05 0.05 -0.057735033 0.5773503 0.5773503 0 254 0 255 0.625 0.75
+0 -0.05 -0.05 -0.057735033 -0.5773503 -0.5773503 0 254 0 255 0.375 1
+0 -0.05 -0.05 -0.057735033 -0.5773503 -0.5773503 0 254 0 255 0.125 0.75
+1 -0.05 -0.05 0.057735033 -0.5773503 -0.5773503 0 254 0 255 0.125 0.5
+1 0.05 -0.05 0.057735033 0.5773503 -0.5773503 0 254 0 255 0.875 0.5
+0 0.05 -0.05 -0.057735033 0.5773503 -0.5773503 0 254 0 255 0.625 1
+0 0.05 -0.05 -0.057735033 0.5773503 -0.5773503 0 254 0 255 0.875 0.75
+-0.05 0.05 0 -0.5773503 0.5773503 -0.057735033 254 0 0 255 0.625 0
+0.05 -0.05 0 0.5773503 -0.5773503 -0.057735033 254 0 0 255 0.375 0.25
+-0.05 -0.05 0 -0.5773503 -0.5773503 -0.057735033 254 0 0 255 0.375 0
+0.05 0.05 0 0.5773503 0.5773503 -0.057735033 254 0 0 255 0.625 0.25
+0.05 -0.05 1 0.5773503 -0.5773503 0.057735033 254 0 0 255 0.375 0.5
+0.05 0.05 1 0.5773503 0.5773503 0.057735033 254 0 0 255 0.625 0.5
+-0.05 -0.05 1 -0.5773503 -0.5773503 0.057735033 254 0 0 255 0.375 0.75
+-0.05 0.05 1 -0.5773503 0.5773503 0.057735033 254 0 0 255 0.625 0.75
+-0.05 -0.05 0 -0.5773503 -0.5773503 -0.057735033 254 0 0 255 0.375 1
+-0.05 -0.05 0 -0.5773503 -0.5773503 -0.057735033 254 0 0 255 0.125 0.75
+0.05 -0.05 0 0.5773503 -0.5773503 -0.057735033 254 0 0 255 0.125 0.5
+0.05 0.05 0 0.5773503 0.5773503 -0.057735033 254 0 0 255 0.875 0.5
+-0.05 0.05 0 -0.5773503 0.5773503 -0.057735033 254 0 0 255 0.625 1
+-0.05 0.05 0 -0.5773503 0.5773503 -0.057735033 254 0 0 255 0.875 0.75
+-0.05 1 -0.05 -0.5773503 0.057735033 -0.5773503 0 0 254 255 0.625 0
+0.05 0 -0.05 0.5773503 -0.057735033 -0.5773503 0 0 254 255 0.375 0.25
+-0.05 0 -0.05 -0.5773503 -0.057735033 -0.5773503 0 0 254 255 0.375 0
+0.05 1 -0.05 0.5773503 0.057735033 -0.5773503 0 0 254 255 0.625 0.25
+0.05 0 0.05 0.5773503 -0.057735033 0.5773503 0 0 254 255 0.375 0.5
+0.05 1 0.05 0.5773503 0.057735033 0.5773503 0 0 254 255 0.625 0.5
+-0.05 0 0.05 -0.5773503 -0.057735033 0.5773503 0 0 254 255 0.375 0.75
+-0.05 1 0.05 -0.5773503 0.057735033 0.5773503 0 0 254 255 0.625 0.75
+-0.05 0 -0.05 -0.5773503 -0.057735033 -0.5773503 0 0 254 255 0.375 1
+-0.05 0 -0.05 -0.5773503 -0.057735033 -0.5773503 0 0 254 255 0.125 0.75
+0.05 0 -0.05 0.5773503 -0.057735033 -0.5773503 0 0 254 255 0.125 0.5
+0.05 1 -0.05 0.5773503 0.057735033 -0.5773503 0 0 254 255 0.875 0.5
+-0.05 1 -0.05 -0.5773503 0.057735033 -0.5773503 0 0 254 255 0.625 1
+-0.05 1 -0.05 -0.5773503 0.057735033 -0.5773503 0 0 254 255 0.875 0.75
+3 0 1 2
+3 3 4 1
+3 5 6 4
+3 7 8 6
+3 4 9 10
+3 11 7 5
+3 0 3 1
+3 3 5 4
+3 5 7 6
+3 7 12 8
+3 4 6 9
+3 11 13 7
+3 14 15 16
+3 17 18 15
+3 19 20 18
+3 21 22 20
+3 18 23 24
+3 25 21 19
+3 14 17 15
+3 17 19 18
+3 19 21 20
+3 21 26 22
+3 18 20 23
+3 25 27 21
+3 28 29 30
+3 31 32 29
+3 33 34 32
+3 35 36 34
+3 32 37 38
+3 39 35 33
+3 28 31 29
+3 31 33 32
+3 33 35 34
+3 35 40 36
+3 32 34 37
+3 39 41 35
diff --git a/src/meshes/gizmo.ts b/src/meshes/gizmo.ts
new file mode 100644
index 0000000..2d70cfc
--- /dev/null
+++ b/src/meshes/gizmo.ts
@@ -0,0 +1,12 @@
+import { Mesh } from "../renderer/mesh";
+
+// prettier-ignore
+export default new Mesh({
+ colors: new Uint8Array([0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,0,254,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,254,0,0,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255,0,0,254,255]),
+ faces: new Uint8Array([0,1,2,3,4,1,5,6,4,7,8,6,4,9,10,11,7,5,0,3,1,3,5,4,5,7,6,7,12,8,4,6,9,11,13,7,14,15,16,17,18,15,19,20,18,21,22,20,18,23,24,25,21,19,14,17,15,17,19,18,19,21,20,21,26,22,18,20,23,25,27,21,28,29,30,31,32,29,33,34,32,35,36,34,32,37,38,39,35,33,28,31,29,31,33,32,33,35,34,35,40,36,32,34,37,39,41,35]),
+ name: "src/meshes/gizmo.ply",
+ normals: new Float32Array([-0.057735033,0.5773503,-0.5773503,0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,0.057735033,0.5773503,-0.5773503,0.057735033,-0.5773503,0.5773503,0.057735033,0.5773503,0.5773503,-0.057735033,-0.5773503,0.5773503,-0.057735033,0.5773503,0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,0.057735033,-0.5773503,-0.5773503,0.057735033,0.5773503,-0.5773503,-0.057735033,0.5773503,-0.5773503,-0.057735033,0.5773503,-0.5773503,-0.5773503,0.5773503,-0.057735033,0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,0.5773503,0.5773503,-0.057735033,0.5773503,-0.5773503,0.057735033,0.5773503,0.5773503,0.057735033,-0.5773503,-0.5773503,0.057735033,-0.5773503,0.5773503,0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,0.5773503,-0.5773503,-0.057735033,0.5773503,0.5773503,-0.057735033,-0.5773503,0.5773503,-0.057735033,-0.5773503,0.5773503,-0.057735033,-0.5773503,0.057735033,-0.5773503,0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,0.5773503,0.057735033,-0.5773503,0.5773503,-0.057735033,0.5773503,0.5773503,0.057735033,0.5773503,-0.5773503,-0.057735033,0.5773503,-0.5773503,0.057735033,0.5773503,-0.5773503,-0.057735033,-0.5773503,-0.5773503,-0.057735033,-0.5773503,0.5773503,-0.057735033,-0.5773503,0.5773503,0.057735033,-0.5773503,-0.5773503,0.057735033,-0.5773503,-0.5773503,0.057735033,-0.5773503]),
+ positions: new Float32Array([0,0.05,-0.05,1,-0.05,-0.05,0,-0.05,-0.05,1,0.05,-0.05,1,-0.05,0.05,1,0.05,0.05,0,-0.05,0.05,0,0.05,0.05,0,-0.05,-0.05,0,-0.05,-0.05,1,-0.05,-0.05,1,0.05,-0.05,0,0.05,-0.05,0,0.05,-0.05,-0.05,0.05,0,0.05,-0.05,0,-0.05,-0.05,0,0.05,0.05,0,0.05,-0.05,1,0.05,0.05,1,-0.05,-0.05,1,-0.05,0.05,1,-0.05,-0.05,0,-0.05,-0.05,0,0.05,-0.05,0,0.05,0.05,0,-0.05,0.05,0,-0.05,0.05,0,-0.05,1,-0.05,0.05,0,-0.05,-0.05,0,-0.05,0.05,1,-0.05,0.05,0,0.05,0.05,1,0.05,-0.05,0,0.05,-0.05,1,0.05,-0.05,0,-0.05,-0.05,0,-0.05,0.05,0,-0.05,0.05,1,-0.05,-0.05,1,-0.05,-0.05,1,-0.05]),
+ uvs: new Float32Array([0.625,0,0.375,0.25,0.375,0,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.125,0.75,0.125,0.5,0.875,0.5,0.625,1,0.875,0.75,0.625,0,0.375,0.25,0.375,0,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.125,0.75,0.125,0.5,0.875,0.5,0.625,1,0.875,0.75,0.625,0,0.375,0.25,0.375,0,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.125,0.75,0.125,0.5,0.875,0.5,0.625,1,0.875,0.75]),
+ vertexCount: 42
+});
diff --git a/src/renderer/color-utils.ts b/src/renderer/color-utils.ts
new file mode 100644
index 0000000..0b6cbbe
--- /dev/null
+++ b/src/renderer/color-utils.ts
@@ -0,0 +1,8 @@
+import { vec4 } from "gl-matrix";
+
+export const rgbToFloat = (
+ r: number,
+ g: number,
+ b: number,
+ a: number = 255
+): vec4 => [r / 255, g / 255, b / 255, a / 255];
diff --git a/src/renderer/editor.ts b/src/renderer/editor.ts
new file mode 100644
index 0000000..fe2cb46
--- /dev/null
+++ b/src/renderer/editor.ts
@@ -0,0 +1,15 @@
+import { Behavior } from "./behavior";
+import { Transform } from "./transform";
+
+type PaneConfig = {
+ name: string;
+ type: "transform" | "float" | "vec3" | "color";
+ onChange: Function;
+};
+
+export class Editor extends Behavior {
+ private panes: PaneConfig[] = [];
+ addTransform(name: string, onChange: (newTransform: Transform) => void) {
+ this.panes.push({ name, type: "transform", onChange });
+ }
+}
diff --git a/src/renderer/gizmo.ts b/src/renderer/gizmo.ts
new file mode 100644
index 0000000..bab4ec6
--- /dev/null
+++ b/src/renderer/gizmo.ts
@@ -0,0 +1,34 @@
+import { WebGLApp } from "./webgl";
+import { Transform, v3 } from "./transform";
+import { Renderable } from "./renderable";
+import { MeshRenderer } from "./mesh-renderer";
+import { Mesh } from "./mesh";
+import { Shader } from "./shader";
+import { basicShaderConfig } from "../common-shaders/basic";
+import basicVert from "../common-shaders/basic.vert";
+import vertexColorsFrag from "../common-shaders/vertex-colors.frag";
+import gizmo from "../meshes/gizmo";
+
+const gizmoShader = (app: WebGLApp) =>
+ new Shader(basicShaderConfig)
+ .vertex(basicVert)
+ .fragment(vertexColorsFrag)
+ .app(app);
+
+export const createGizmo = (
+ app: WebGLApp,
+ camera: Transform,
+ transform?: Transform
+) => {
+ const localTransform = new Transform(
+ transform?.position,
+ transform?.rotation
+ // v3(0.5)
+ );
+
+ const mr = new MeshRenderer(app, gizmo, gizmoShader(app), camera).configure(
+ {}
+ );
+
+ new Renderable(app, localTransform, mr);
+};
diff --git a/src/renderer/helper-textures/black.png b/src/renderer/helper-textures/black.png
new file mode 100644
index 0000000..c4393dd
Binary files /dev/null and b/src/renderer/helper-textures/black.png differ
diff --git a/src/renderer/helper-textures/black.ts b/src/renderer/helper-textures/black.ts
new file mode 100644
index 0000000..04525ef
--- /dev/null
+++ b/src/renderer/helper-textures/black.ts
@@ -0,0 +1,5 @@
+import { Texture } from "../texture";
+import { WebGLApp } from "../webgl";
+import black from "./black.png";
+
+export const createBlackTexture = (app: WebGLApp) => new Texture(app, black);
diff --git a/src/renderer/helper-textures/bump.png b/src/renderer/helper-textures/bump.png
new file mode 100644
index 0000000..a9e3b98
Binary files /dev/null and b/src/renderer/helper-textures/bump.png differ
diff --git a/src/renderer/helper-textures/bump.ts b/src/renderer/helper-textures/bump.ts
new file mode 100644
index 0000000..7fcc1aa
--- /dev/null
+++ b/src/renderer/helper-textures/bump.ts
@@ -0,0 +1,5 @@
+import { Texture } from "../texture";
+import { WebGLApp } from "../webgl";
+import bump from "./bump.png";
+
+export const createBumpTexture = (app: WebGLApp) => new Texture(app, bump);
diff --git a/src/renderer/helper-textures/pink.png b/src/renderer/helper-textures/pink.png
new file mode 100644
index 0000000..be222f2
Binary files /dev/null and b/src/renderer/helper-textures/pink.png differ
diff --git a/src/renderer/helper-textures/pink.ts b/src/renderer/helper-textures/pink.ts
new file mode 100644
index 0000000..fc28674
--- /dev/null
+++ b/src/renderer/helper-textures/pink.ts
@@ -0,0 +1,5 @@
+import { Texture } from "../texture";
+import { WebGLApp } from "../webgl";
+import pink from "./pink.png";
+
+export const createPinkTexture = (app: WebGLApp) => new Texture(app, pink);
diff --git a/src/renderer/helper-textures/white.png b/src/renderer/helper-textures/white.png
new file mode 100644
index 0000000..ceb1f54
Binary files /dev/null and b/src/renderer/helper-textures/white.png differ
diff --git a/src/renderer/helper-textures/white.ts b/src/renderer/helper-textures/white.ts
new file mode 100644
index 0000000..b30bcf7
--- /dev/null
+++ b/src/renderer/helper-textures/white.ts
@@ -0,0 +1,5 @@
+import { Texture } from "../texture";
+import { WebGLApp } from "../webgl";
+import white from "./white.png";
+
+export const createWhiteTexture = (app: WebGLApp) => new Texture(app, white);
diff --git a/src/renderer/mesh-renderer.ts b/src/renderer/mesh-renderer.ts
index 9f8dd00..2f55a47 100644
--- a/src/renderer/mesh-renderer.ts
+++ b/src/renderer/mesh-renderer.ts
@@ -156,8 +156,12 @@ export class MeshRenderer extends Behavior {
// gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
+ const uvOverflow = textureObject.config.uvClamp
+ ? gl.CLAMP_TO_EDGE
+ : gl.REPEAT;
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uvOverflow);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, uvOverflow);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
@@ -174,14 +178,7 @@ export class MeshRenderer extends Behavior {
textures.forEach(([key, tex], index) => {
const uniform = (this.shader.mappings.uniforms as any)[key];
if (!uniform) {
- console.warn("had no uniform to set for", {
- textures,
- key,
- tex,
- uniform,
- index,
- });
- return false;
+ return;
}
gl.activeTexture(intStart + index);
@@ -243,6 +240,8 @@ export class MeshRenderer extends Behavior {
false,
mat4.invert(mat4.create(), transform.toMat4())
);
+
+ this.shader.onPrerender(this.app, time);
}
async onStart(_: never, app: WebGLApp) {
diff --git a/src/renderer/renderable.ts b/src/renderer/renderable.ts
index cee4876..c0e5bef 100644
--- a/src/renderer/renderable.ts
+++ b/src/renderer/renderable.ts
@@ -1,4 +1,5 @@
import { Behavior } from "./behavior";
+import { createGizmo } from "./gizmo";
import { MeshRenderer } from "./mesh-renderer";
import { Transform } from "./transform";
import { WebGLApp } from "./webgl";
@@ -7,9 +8,12 @@ export class Renderable extends Behavior {
constructor(
public app: WebGLApp,
public transform: Transform,
- public renderer: MeshRenderer
+ public renderer: MeshRenderer,
+ enableGizmo: boolean = false
) {
super(app);
+
+ if (enableGizmo) createGizmo(app, renderer.camera, transform);
}
onDraw(time: number) {
diff --git a/src/renderer/shader.ts b/src/renderer/shader.ts
index 0a85fde..a7c6c42 100644
--- a/src/renderer/shader.ts
+++ b/src/renderer/shader.ts
@@ -32,6 +32,7 @@ export type ShaderMapping<
projection: Uniform;
texture0: Uniform;
texture1: Uniform;
+ texture2: Uniform;
time: Uniform;
view: Uniform;
};
@@ -50,6 +51,13 @@ export class Shader {
public mappings: InternalMapping = {} as any;
public textures: Record = {};
+ public materialValues: Record = {};
+ private prerenderHooks: ((
+ app: WebGLApp,
+ shader: Shader,
+ time: number
+ ) => void)[] = [];
+
get gl() {
const gl = this._app?.gl;
if (!gl) {
@@ -76,6 +84,11 @@ export class Shader {
return this;
}
+ prerenderHook(fn: (app: WebGLApp, shader: Shader, time: number) => void) {
+ this.prerenderHooks.push(fn);
+ return this;
+ }
+
attrib(name: string) {
return this.gl.getAttribLocation(this.program as WebGLProgram, name);
}
@@ -101,6 +114,7 @@ export class Shader {
projection: this.uniform(config.uniforms.projection),
texture0: this.uniform(config.uniforms.texture0),
texture1: this.uniform(config.uniforms.texture1),
+ texture2: this.uniform(config.uniforms.texture2),
time: this.uniform(config.uniforms.time),
view: this.uniform(config.uniforms.view),
},
@@ -159,6 +173,12 @@ export class Shader {
use() {
this._app?.gl.useProgram(this.program);
}
+
+ onPrerender(app: WebGLApp, time: number) {
+ for (const fn of this.prerenderHooks) {
+ fn(app, this, time);
+ }
+ }
}
const humanShaderType = (which: number): string => {
diff --git a/src/renderer/texture.ts b/src/renderer/texture.ts
index 8a36a06..95c813e 100644
--- a/src/renderer/texture.ts
+++ b/src/renderer/texture.ts
@@ -1,5 +1,6 @@
import { Behavior } from "./behavior";
import { WebGLApp } from "./webgl";
+import bump from "./helper-textures/bump.png";
export class Texture {
public texture: ImageBitmap | Uint8Array | null = null;
@@ -8,7 +9,8 @@ export class Texture {
constructor(
public app: WebGLApp,
- public url: string
+ public url: string,
+ public config: { uvClamp?: boolean } = {}
) {}
setImage(data: Uint8Array, width: number, height: number) {
@@ -56,22 +58,3 @@ export class Texture {
});
}
}
-
-export const White = (app: WebGLApp) =>
- new Texture(app, "manual").setImage(
- new Uint8Array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
- 2,
- 2
- );
-export const Black = (app: WebGLApp) =>
- new Texture(app, "manual").setImage(
- new Uint8Array([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]),
- 2,
- 2
- );
-export const WhyBroke = (app: WebGLApp) =>
- new Texture(app, "manual").setImage(
- new Uint8Array([1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1]),
- 2,
- 2
- );
diff --git a/src/renderer/webgl.ts b/src/renderer/webgl.ts
index 4bd0f2b..560f0be 100644
--- a/src/renderer/webgl.ts
+++ b/src/renderer/webgl.ts
@@ -1,3 +1,4 @@
+import { Editor } from "./editor";
import { Telemetry } from "./telemetry";
export type WebGPUAppConfig = {
@@ -5,6 +6,8 @@ export type WebGPUAppConfig = {
context?: GPUCanvasConfiguration;
zNear?: number;
zFar?: number;
+ editor?: boolean;
+ telemetry?: boolean;
};
export type RenderHandle = (
@@ -16,6 +19,7 @@ export class WebGLApp {
public canvas: HTMLCanvasElement;
public telemetry?: Telemetry;
public gl: WebGL2RenderingContext;
+ public editor?: Editor;
private loadingMessages: Set = new Set(["[noeidelon] [stage 2]"]);
public registry: {
@@ -48,9 +52,13 @@ export class WebGLApp {
// this.gl.getExtension("OES_element_index_uint"); // default
this.gl.getExtension("EXT_texture_filter_anisotropic");
- if (location.search.includes("telemetry")) {
+ if (location.search.includes("telemetry") || config.telemetry) {
this.telemetry = new Telemetry(this);
}
+
+ if (location.search.includes("editor") || config.editor) {
+ this.editor = new Editor(this);
+ }
} catch (e) {
const main = document.querySelector("main");
if (main) {
diff --git a/tsconfig.json b/tsconfig.json
index 5e21cb1..7d84cf8 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -24,5 +24,6 @@
"strict": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
- }
+ },
+ "exclude": ["html/"]
}