avbd-babylon 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- var globalThis;(globalThis||={}).AVBD=(()=>{var Ba=Object.defineProperty;var Tu=Object.getOwnPropertyDescriptor;var ju=Object.getOwnPropertyNames;var Du=Object.prototype.hasOwnProperty;var Gu=(s,e)=>{for(var t in e)Ba(s,t,{get:e[t],enumerable:!0})},Fu=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ju(e))!Du.call(s,r)&&r!==t&&Ba(s,r,{get:()=>e[r],enumerable:!(i=Tu(e,r))||i.enumerable});return s};var Uu=s=>Fu(Ba({},"__esModule",{value:!0}),s);var jd={};Gu(jd,{AvbdPhysics:()=>ps,AvbdPhysicsAggregate:()=>ms,AvbdPhysicsBody:()=>Rr,AvbdPhysicsConstraint:()=>Pr,AvbdPhysicsHinge:()=>Lr,AvbdScene2D:()=>va,AvbdScene3D:()=>ya,AvbdShapeType:()=>rt,GPUBufferRecycler:()=>Hr,GpuContactSample:()=>Aa,GpuSurfaceParticles:()=>xa,GpuTimer:()=>Wr,INPUT_WORDS:()=>Eu,PARTICLE_BYTE_STRIDE:()=>Ls,WorkerCanvas:()=>wa,addGpuStepPass:()=>_u,cookHeightfield:()=>Mr,cookStaticMesh:()=>zr,createSharedInput:()=>Mu,createSolverPipeline:()=>xu,createWebGPUDevice:()=>Sr,prepareWebGPUDevice3D:()=>Ni,readSharedInput:()=>Iu,sampledContactShader:()=>Pu,seedConstraintColoring:()=>Lu,writeSharedInput:()=>zu});var S=(s=0,e=0,t=0)=>Float64Array.of(s,e,t),jt=(s=0,e=0,t=0,i=1)=>Float64Array.of(s,e,t,i),ae=()=>new Float64Array(9);var Es=s=>s<0?-1:s>0?1:0,Bt=(s,e)=>s<e?s:e,Nu=(s,e)=>s>e?s:e,ce=(s,e,t)=>Nu(e,Bt(t,s)),V=(s,e)=>s[0]*e[0]+s[1]*e[1]+s[2]*e[2],Ne=s=>V(s,s),sr=s=>Math.sqrt(Ne(s));function ct(s,e,t,i){return s[0]=e,s[1]=t,s[2]=i,s}var Li=(s,e,t)=>ct(s,e[0]+t[0],e[1]+t[1],e[2]+t[2]),J=(s,e,t)=>ct(s,e[0]-t[0],e[1]-t[1],e[2]-t[2]),ne=(s,e,t)=>ct(s,e[0]*t,e[1]*t,e[2]*t),_t=(s,e,t)=>ct(s,e[0]/t,e[1]/t,e[2]/t),ee=(s,e)=>ct(s,-e[0],-e[1],-e[2]),Ca=(s,e)=>ct(s,Math.abs(e[0]),Math.abs(e[1]),Math.abs(e[2])),D=(s,e,t,i)=>ct(s,e[0]+t[0]*i,e[1]+t[1]*i,e[2]+t[2]*i),qu=(s,e)=>_t(s,e,sr(e)),Dt=(s,e,t)=>ct(s,e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]);function rr(s,e,t,i,r){return s[0]=e,s[1]=t,s[2]=i,s[3]=r,s}function $r(s,e,t){let i=e[0],r=e[1],o=e[2],a=e[3],n=t[0],l=t[1],c=t[2],u=t[3];return rr(s,a*n+i*u+r*c-o*l,a*l-i*c+r*u+o*n,a*c+i*l-r*n+o*u,a*u-i*n-r*l-o*c)}var Vu=(s,e)=>rr(s,-e[0],-e[1],-e[2],e[3]),Yn=s=>Ne(s)+s[3]*s[3];function Sa(s,e){let t=Yn(e);return rr(s,-e[0]/t,-e[1]/t,-e[2]/t,e[3]/t)}function Wu(s,e){let t=Math.sqrt(Yn(e));return rr(s,e[0]/t,e[1]/t,e[2]/t,e[3]/t)}var ir=new Float64Array(4),Pi=new Float64Array(4);function ut(s,e,t){return $r(ir,e,Sa(ir,t)),ct(s,ir[0]*2,ir[1]*2,ir[2]*2)}function si(s,e,t){return rr(Pi,t[0],t[1],t[2],0),$r(Pi,Pi,e),Wu(s,rr(s,e[0]+Pi[0]*.5,e[1]+Pi[1]*.5,e[2]+Pi[2]*.5,e[3]+Pi[3]*.5))}function le(s,e,t){let i=e[0],r=e[1],o=e[2],a=e[3],n=(r*t[2]-o*t[1])*2,l=(o*t[0]-i*t[2])*2,c=(i*t[1]-r*t[0])*2;return ct(s,t[0]+n*a+(r*c-o*l),t[1]+l*a+(o*n-i*c),t[2]+c*a+(i*l-r*n))}var Xn=new Float64Array(3);function Gt(s,e,t,i){return le(Xn,t,i),Li(s,Xn,e)}function Te(s,e,t){return le(s,Vu(ir,e),t)}function Ce(s,e,t,i){return s.fill(0),s[0]=e,s[4]=t,s[8]=i,s}function ka(s,e){return s[0]=0,s[1]=-e[2],s[2]=e[1],s[3]=e[2],s[4]=0,s[5]=-e[0],s[6]=-e[1],s[7]=e[0],s[8]=0,s}function _i(s,e){let t=e[1],i=e[2],r=e[5];return s[0]=e[0],s[1]=e[3],s[2]=e[6],s[3]=t,s[4]=e[4],s[5]=e[7],s[6]=i,s[7]=r,s[8]=e[8],s}function Ke(s,e,t){let i=e[0],r=e[1],o=e[2],a=e[3],n=e[4],l=e[5],c=e[6],u=e[7],f=e[8],d=t[0],p=t[1],m=t[2],h=t[3],g=t[4],b=t[5],y=t[6],A=t[7],v=t[8];return s[0]=i*d+r*h+o*y,s[1]=i*p+r*g+o*A,s[2]=i*m+r*b+o*v,s[3]=a*d+n*h+l*y,s[4]=a*p+n*g+l*A,s[5]=a*m+n*b+l*v,s[6]=c*d+u*h+f*y,s[7]=c*p+u*g+f*A,s[8]=c*m+u*b+f*v,s}function ue(s,e,t){let i=t[0],r=t[1],o=t[2];return ct(s,e[0]*i+e[1]*r+e[2]*o,e[3]*i+e[4]*r+e[5]*o,e[6]*i+e[7]*r+e[8]*o)}function qe(s,e){for(let t=0;t<9;t++)s[t]+=e[t];return s}function Ei(s,e,t){for(let i=0;i<9;i++)s[i]=e[i]*t;return s}function Qn(s,e){for(let t=0;t<9;t++)s[t]=-e[t];return s}function Ms(s,e,t){for(let i=0;i<3;i++)for(let r=0;r<3;r++)s[i*3+r]=t[r]*e[i];return s}function Kn(s,e){let t=Math.sqrt(e[0]*e[0]+e[3]*e[3]+e[6]*e[6]),i=Math.sqrt(e[1]*e[1]+e[4]*e[4]+e[7]*e[7]),r=Math.sqrt(e[2]*e[2]+e[5]*e[5]+e[8]*e[8]);return Ce(s,t,i,r)}function zs(s,e){let t=Math.abs(e[0])>Math.abs(e[2])?S(-e[1],e[0],0):S(0,-e[2],e[1]);qu(t,t);let i=Dt(S(),e,t);return s[0]=e[0],s[1]=e[1],s[2]=e[2],s.set(t,3),s.set(i,6),s}function Is(s,e,t,i,r,o,a){let n=s[0],l=s[3],c=s[4],u=s[6],f=s[7],d=s[8],p=t[0],m=t[1],h=t[2],g=e[0],b=t[3],y=t[4],A=t[5],v=e[3],x=e[4],w=t[6],B=t[7],L=t[8],M=e[6],I=e[7],E=e[8],k=l/n,P=u/n,C=p/n,_=b/n,z=w/n,R=n,G=c-k*k*R,X=(f-k*P*R)/G,W=(m-k*C*R)/G,U=(y-k*_*R)/G,H=(B-k*z*R)/G,Z=d-(P*P*R+X*X*G),he=(h-P*C*R-X*W*G)/Z,we=(A-P*_*R-X*U*G)/Z,Oe=(L-P*z*R-X*H*G)/Z,$=g-(C*C*R+W*W*G+he*he*Z),Je=(v-C*_*R-W*U*G-he*we*Z)/$,Xe=(M-C*z*R-W*H*G-he*Oe*Z)/$,Be=x-(_*_*R+U*U*G+we*we*Z+Je*Je*$),at=(I-_*z*R-U*H*G-we*Oe*Z-Je*Xe*$)/Be,ri=E-(z*z*R+H*H*G+Oe*Oe*Z+Xe*Xe*$+at*at*Be),Ye=i[0],nt=i[1]-k*Ye,Qe=i[2]-P*Ye-X*nt,lt=r[0]-C*Ye-W*nt-he*Qe,wt=r[1]-_*Ye-U*nt-we*Qe-Je*lt,Ki=r[2]-z*Ye-H*nt-Oe*Qe-Xe*lt-at*wt,Zi=Ye/R,er=nt/G,tr=Qe/Z,Wt=lt/$,Ru=wt/Be,Ou=Ki/ri;a[2]=Ou,a[1]=Ru-at*a[2],a[0]=Wt-Je*a[1]-Xe*a[2],o[2]=tr-he*a[0]-we*a[1]-Oe*a[2],o[1]=er-X*o[2]-W*a[0]-U*a[1]-H*a[2],o[0]=Zi-k*o[1]-P*o[2]-C*a[0]-_*a[1]-z*a[2]}var Et=1,Ve=1e10,Rs=.01,Zn=1e-5,Ze=class{solver;forces=[];positionLin;positionAng=jt();initialLin=S();initialAng=jt();inertialLin=S();inertialAng=jt();velocityLin;velocityAng=S();prevVelocityLin;size;mass;moment;friction;radius;constructor(e,t,i,r,o,a=[0,0,0]){this.solver=e,this.size=S(t[0],t[1],t[2]),this.friction=r,this.positionLin=S(o[0],o[1],o[2]),this.velocityLin=S(a[0],a[1],a[2]),this.prevVelocityLin=S(a[0],a[1],a[2]);let[n,l,c]=this.size;this.mass=n*l*c*i,this.moment=S((l*l+c*c)/12*this.mass,(n*n+c*c)/12*this.mass,(n*n+l*l)/12*this.mass),this.radius=sr([n*.5,l*.5,c*.5]),e.bodies.push(this)}constrainedTo(e){for(let t of this.forces)if(t.bodyA===this&&t.bodyB===e||t.bodyA===e&&t.bodyB===this)return!0;return!1}},Os=()=>({lhsLin:ae(),lhsAng:ae(),lhsCross:ae(),rhsLin:S(),rhsAng:S()}),Ft=class{solver;bodyA;bodyB;constructor(e,t,i){this.solver=e,this.bodyA=t,this.bodyB=i,e.forces.push(this),t?.forces.push(this),i.forces.push(this)}destroy(){let e=this.solver.forces,t=e.indexOf(this);t>=0&&e.splice(t,1),this.unlinkFromBodies()}unlinkFromBodies(){for(let e of[this.bodyA,this.bodyB]){if(!e)continue;let t=e.forces.indexOf(this);t>=0&&e.forces.splice(t,1)}}};var sl=8,el=16,zi=1e-6,La=1e-5,Hu=1e-6,_a=34028234663852886e22,Ts=0,ol=1,js=2;function tl(s){let e=s.positionAng;return{center:s.positionLin,half:ne(S(),s.size,.5),axis:[le(S(),e,[1,0,0]),le(S(),e,[0,1,0]),le(S(),e,[0,0,1])]}}var Mi=(s,e)=>Math.abs(V(s,e));function Ds(s,e){let t=V(e,s.axis[0])>=0?1:-1,i=V(e,s.axis[1])>=0?1:-1,r=V(e,s.axis[2])>=0?1:-1,o=D(S(),s.center,s.axis[0],s.half[0]*t);return D(o,o,s.axis[1],s.half[1]*i),D(o,o,s.axis[2],s.half[2]*r)}function al(s,e){return e===0?{u:s.axis[1],v:s.axis[2],extentU:s.half[1],extentV:s.half[2]}:e===1?{u:s.axis[0],v:s.axis[2],extentU:s.half[0],extentV:s.half[2]}:{u:s.axis[0],v:s.axis[1],extentU:s.half[0],extentV:s.half[1]}}function $u(s,e,t){let i=V(t,s.axis[e])>=0?1:-1,r=ne(S(),s.axis[e],i),o=D(S(),s.center,r,s.half[e]);return{normal:r,center:o,...al(s,e)}}function Ju(s,e){let t=0,i=-_a;for(let r=0;r<3;r++){let o=Mi(s.axis[r],e);o>i&&(i=o,t=r)}return t}function Xu(s,e,t){let i=V(s.axis[e],t)>0?-1:1,r=ne(S(),s.axis[e],i),o=D(S(),s.center,r,s.half[e]),{u:a,v:n,extentU:l,extentV:c}=al(s,e),u=(f,d)=>{let p=D(S(),o,a,f*l);return D(p,p,n,d*c)};return[u(1,1),u(-1,1),u(-1,-1),u(1,-1)]}function Yu(s,e,t){let i=[];if(s.length===0)return i;let r=s[s.length-1],o=V(e,r)-t;for(let a of s){let n=V(e,a)-t,l=o<=La,c=n<=La;if(l!==c){let u=0,f=o-n;Math.abs(f)>zi&&(u=ce(o/f,0,1)),i.length<el&&i.push(D(S(),r,J(S(),a,r),u))}c&&i.length<el&&i.push(a),r=a,o=n}return i}var Gs=class{contacts=[];midpoints=[];bodyA;bodyB;constructor(e,t){this.bodyA=e,this.bodyB=t}add(e,t,i){let r=ne(S(),Li(S(),e,t),.5);for(let n of this.midpoints)if(Ne(J(S(),r,n))<Hu)return;if(this.contacts.length>=sl)return;let{bodyA:o,bodyB:a}=this;this.contacts.push({feature:i,rA:Te(S(),o.positionAng,J(S(),e,o.positionLin)),rB:Te(S(),a.positionAng,J(S(),t,a.positionLin))}),this.midpoints.push(r)}};function Pa(s,e,t,i,r,o,a,n){let l=Ne(i);if(l<zi)return!0;let c=1/Math.sqrt(l),u=ne(S(),i,c);V(u,t)<0&&ee(u,u);let f=Math.abs(V(t,u)),d=s.half[0]*Mi(u,s.axis[0])+s.half[1]*Mi(u,s.axis[1])+s.half[2]*Mi(u,s.axis[2]),p=e.half[0]*Mi(u,e.axis[0])+e.half[1]*Mi(u,e.axis[1])+e.half[2]*Mi(u,e.axis[2]),m=f-(d+p);return m>0?!1:((!n.valid||m>n.separation)&&(n.valid=!0,n.type=r,n.indexA=o,n.indexB=a,n.separation=m,n.normalAB=u),!0)}function il(s,e,t){let i=(e+1)%3,r=(e+2)%3,o=V(t,s.axis[i])>=0?1:-1,a=V(t,s.axis[r])>=0?1:-1,n=D(S(),s.center,s.axis[i],s.half[i]*o);D(n,n,s.axis[r],s.half[r]*a);let l=ne(S(),s.axis[e],s.half[e]);return[J(S(),n,l),Li(S(),n,l)]}function Qu(s,e,t,i){let r=J(S(),e,s),o=J(S(),i,t),a=J(S(),s,t),n=V(r,r),l=V(o,o),c=V(o,a),u=0,f=0;if(n<=zi&&l<=zi)return[s,t];if(n<=zi)f=ce(c/l,0,1);else{let d=V(r,a);if(l<=zi)u=ce(-d/n,0,1);else{let p=V(r,o),m=n*l-p*p;Math.abs(m)>zi&&(u=ce((p*c-d*l)/m,0,1)),f=(p*u+c)/l,f<0?(f=0,u=ce(-d/n,0,1)):f>1&&(f=1,u=ce((p-d)/n,0,1))}}return[D(S(),s,r,u),D(S(),t,o,f)]}function rl(s,e,t,i,r,o,a){let n=r?t:i,l=r?i:t,c=r?a:ee(S(),a),u=$u(n,o,c),f=Ju(l,u.normal),d=Xu(l,f,u.normal),p=[[u.u,u.extentU],[ee(S(),u.u),u.extentU],[u.v,u.extentV],[ee(S(),u.v),u.extentV]];for(let[g,b]of p)if(d=Yu(d,g,V(g,u.center)+b),!d.length)return[];let m=new Gs(s,e),h=(r?Ts:ol)<<24|(o&255)<<16|(f&255)<<8;for(let g=0;g<d.length&&m.contacts.length<sl;g++){let b=d[g],y=V(J(S(),b,u.center),u.normal);if(y>La)continue;let A=D(S(),b,u.normal,-y),v=r?A:b,x=r?b:A;m.add(v,x,h|g&255)}return m.contacts.length||m.add(Ds(t,a),Ds(i,ee(S(),a)),h),m.contacts}function Ku(s,e,t,i,r,o,a){let[n,l]=il(t,r,a),[c,u]=il(i,o,ee(S(),a)),[f,d]=Qu(n,l,c,u),p=new Gs(s,e),m=js<<24|(r&255)<<8|o&255;return p.add(f,d,m),p.contacts.length||p.add(Ds(t,a),Ds(i,ee(S(),a)),m),p.contacts}function nl(s,e,t){let i=tl(s),r=tl(e),o=J(S(),r.center,i.center),a={type:Ts,indexA:0,indexB:0,separation:-_a,normalAB:S(),valid:!1},n={type:js,indexA:0,indexB:0,separation:-_a,normalAB:S(),valid:!1};for(let u=0;u<3;u++)if(!Pa(i,r,o,i.axis[u],Ts,u,-1,a))return[];for(let u=0;u<3;u++)if(!Pa(i,r,o,r.axis[u],ol,-1,u,a))return[];let l=S();for(let u=0;u<3;u++)for(let f=0;f<3;f++)if(Dt(l,i.axis[u],r.axis[f]),!Pa(i,r,o,l,js,u,f,n))return[];if(!a.valid)return[];let c=a;return n.valid&&.95*n.separation>a.separation+.01&&(c=n),zs(t,ee(S(),c.normalAB)),c.type===js?Ku(s,e,i,r,c.indexA,c.indexB,c.normalAB):c.type===Ts?rl(s,e,i,r,!0,c.indexA,c.normalAB):rl(s,e,i,r,!1,c.indexB,c.normalAB)}var ll=S(),cl=S(),ul=S(),fl=S(),dl=S(),hl=S(),Fs=ae(),Ea=ae(),Ma=ae(),Us=ae(),za=ae(),Ia=ae(),Ra=ae(),Ns=ae(),Me=S(),je=S(),Ii=S(),oi=S(),pl=S(),ml=S(),or=0,Jr=0;function gl(s,e,t){for(let i=0;i<3;i++)oi[0]=t[i*3],oi[1]=t[i*3+1],oi[2]=t[i*3+2],Dt(oi,e,oi),s[i*3]=oi[0],s[i*3+1]=oi[1],s[i*3+2]=oi[2];return s}var ai=class extends Ft{contacts=[];basis=ae();friction=0;constructor(e,t,i){super(e,t,i)}get numContacts(){return this.contacts.length}initialize(){let e=this.bodyA,t=this.bodyB,{solver:i}=this;this.friction=Math.sqrt(e.friction*t.friction);let r=this.contacts;this.contacts=nl(e,t,this.basis).map(o=>{let a=r.find(n=>n.feature===o.feature);return a?{feature:o.feature,rA:a.stick?a.rA:o.rA,rB:a.stick?a.rB:o.rB,C0:S(),penalty:a.penalty.slice(),lambda:a.lambda.slice(),stick:a.stick}:{feature:o.feature,rA:o.rA,rB:o.rB,C0:S(),penalty:S(),lambda:S(),stick:!1}});for(let o of this.contacts){Gt(pl,e.positionLin,e.positionAng,o.rA),Gt(ml,t.positionLin,t.positionAng,o.rB),ue(o.C0,this.basis,J(Ii,pl,ml)),o.C0[0]+=Rs;for(let a=0;a<3;a++)o.lambda[a]=o.lambda[a]*i.alpha*i.gamma,o.penalty[a]=ce(o.penalty[a]*i.gamma,Et,Ve)}return this.contacts.length>0}evaluate(e,t){let i=this.bodyA,r=this.bodyB,o=this.basis;le(dl,i.positionAng,e.rA),le(hl,r.positionAng,e.rB),Qn(Fs,o),gl(Ea,dl,o),gl(Ma,hl,Fs),Ce(Us,e.penalty[0],e.penalty[1],e.penalty[2]),ne(Me,e.C0,1-t),D(Me,Me,ue(Ii,o,ll),1),D(Me,Me,ue(Ii,Fs,ul),1),D(Me,Me,ue(Ii,Ea,cl),1),D(Me,Me,ue(Ii,Ma,fl),1),ue(je,Us,Me),D(je,je,e.lambda,1),je[0]=Bt(je[0],0),Jr=Math.abs(je[0])*this.friction,or=Math.sqrt(je[1]*je[1]+je[2]*je[2]),or>Jr&&or>0&&(je[1]*=Jr/or,je[2]*=Jr/or)}computeDisplacements(){let e=this.bodyA,t=this.bodyB;J(ll,e.positionLin,e.initialLin),ut(cl,e.positionAng,e.initialAng),J(ul,t.positionLin,t.initialLin),ut(fl,t.positionAng,t.initialAng)}updatePrimal(e,t,i){this.computeDisplacements();let r=e===this.bodyA;for(let o of this.contacts){this.evaluate(o,t);let a=r?this.basis:Fs,n=r?Ea:Ma;_i(za,a),_i(Ia,n),Ke(Ra,Ia,Us),qe(i.lhsLin,Ke(Ns,Ke(Ns,za,Us),a)),qe(i.lhsAng,Ke(Ns,Ra,n)),qe(i.lhsCross,Ke(Ns,Ra,a)),D(i.rhsLin,i.rhsLin,ue(Ii,za,je),1),D(i.rhsAng,i.rhsAng,ue(Ii,Ia,je),1)}}updateDual(e){let{solver:t}=this;this.computeDisplacements();for(let i of this.contacts)this.evaluate(i,e),i.lambda.set(je),je[0]<0&&(i.penalty[0]=Bt(i.penalty[0]+t.betaLin*Math.abs(Me[0]),Ve)),or<=Jr&&(i.penalty[1]=Bt(i.penalty[1]+t.betaLin*Math.abs(Me[1]),Ve),i.penalty[2]=Bt(i.penalty[2]+t.betaLin*Math.abs(Me[2]),Ve),i.stick=Math.sqrt(Me[1]*Me[1]+Me[2]*Me[2])<Zn)}};var Oa=()=>({dt:1/60,gravity:-10,iterations:10,betaLin:1e4,betaAng:100,alpha:.99,gamma:.999}),ni=class{dt=1/60;gravity=-10;iterations=10;alpha=.99;betaLin=1e4;betaAng=100;gamma=.999;bodies=[];forces=[];constructor(){this.defaultParams()}defaultParams(){Object.assign(this,Oa())}clear(){this.forces=[],this.bodies=[]}pick(e,t){let r=null,o=S(),a=S();for(let n=this.bodies.length-1;n>=0;n--){let l=this.bodies[n];if(l.mass<=0)continue;Te(o,l.positionAng,J(o,e,l.positionLin)),Te(a,l.positionAng,t);let c=0,u=1/0,f=!0;for(let p=0;p<3&&f;p++){let m=l.size[p]*.5;if(Math.abs(a[p])<1e-6){(o[p]<-m||o[p]>m)&&(f=!1);continue}let h=1/a[p],g=(-m-o[p])*h,b=(m-o[p])*h;g>b&&([g,b]=[b,g]),c=Math.max(c,g),u=Math.min(u,b),c>u&&(f=!1)}if(!f)continue;let d=c>=0?c:u;d<0||(!r||d<r.t)&&(r={body:l,local:D(S(),o,a,d),t:d})}return r}sys=Os();dxLin=S();dxAng=S();dp=S();accel=S();step(){let{dt:e,gravity:t,bodies:i,sys:r,dp:o}=this;for(let n=i.length-1;n>=0;n--){let l=i[n];for(let c=n-1;c>=0;c--){let u=i[c];J(o,l.positionLin,u.positionLin);let f=l.radius+u.radius;V(o,o)<=f*f&&!l.constrainedTo(u)&&new ai(this,l,u)}}let a=[];for(let n of this.forces)n.initialize()?a.push(n):n.unlinkFromBodies();this.forces=a;for(let n=i.length-1;n>=0;n--){let l=i[n];D(l.inertialLin,l.positionLin,l.velocityLin,e),l.mass>0&&(l.inertialLin[2]+=t*(e*e)),si(l.inertialAng,l.positionAng,bl(l.velocityAng,e)),_t(this.accel,J(this.accel,l.velocityLin,l.prevVelocityLin),e);let c=this.accel[2]*Es(t),u=ce(c/Math.abs(t),0,1);Number.isFinite(u)||(u=0),l.initialLin.set(l.positionLin),l.initialAng.set(l.positionAng),l.mass>0&&(D(l.positionLin,l.positionLin,l.velocityLin,e),l.positionLin[2]+=t*(u*e*e),si(l.positionAng,l.positionAng,bl(l.velocityAng,e)))}for(let n=0;n<this.iterations;n++){for(let l=i.length-1;l>=0;l--){let c=i[l];if(c.mass<=0)continue;let u=c.mass,f=c.moment;Ce(r.lhsLin,u/(e*e),u/(e*e),u/(e*e)),Ce(r.lhsAng,f[0]/(e*e),f[1]/(e*e),f[2]/(e*e)),r.lhsCross.fill(0),ue(r.rhsLin,r.lhsLin,J(o,c.positionLin,c.inertialLin)),ue(r.rhsAng,r.lhsAng,ut(o,c.positionAng,c.inertialAng));let d=c.forces;for(let p=d.length-1;p>=0;p--)d[p].updatePrimal(c,this.alpha,r);Is(r.lhsLin,r.lhsAng,r.lhsCross,ee(r.rhsLin,r.rhsLin),ee(r.rhsAng,r.rhsAng),this.dxLin,this.dxAng),D(c.positionLin,c.positionLin,this.dxLin,1),si(c.positionAng,c.positionAng,this.dxAng)}for(let l of this.forces)l.updateDual(this.alpha)}for(let n of i)n.prevVelocityLin.set(n.velocityLin),n.mass>0&&(_t(n.velocityLin,J(n.velocityLin,n.positionLin,n.initialLin),e),_t(n.velocityAng,ut(n.velocityAng,n.positionAng,n.initialAng),e))}},Zu=S(),bl=(s,e)=>ne(Zu,s,e);var xe=(s,e)=>[s[0]-e[0],s[1]-e[1],s[2]-e[2]],Mt=(s,e)=>s[0]*e[0]+s[1]*e[1]+s[2]*e[2],Ri=(s,e)=>[s[1]*e[2]-s[2]*e[1],s[2]*e[0]-s[0]*e[2],s[0]*e[1]-s[1]*e[0]],et=s=>Math.sqrt(Mt(s,s));function Xr(s){let e=Ta(s);return!e||e.vertices.length/3<=32?e:Ta(yl(e,32))}function yl(s,e){let[t,i,r,o]=s.rotation,a=f=>{let d=[2*(i*f[2]-r*f[1]),2*(r*f[0]-t*f[2]),2*(t*f[1]-i*f[0])];return[f[0]+o*d[0]+(i*d[2]-r*d[1])+s.center[0],f[1]+o*d[1]+(r*d[0]-t*d[2])+s.center[1],f[2]+o*d[2]+(t*d[1]-i*d[0])+s.center[2]]},n=[];for(let f=0;f<s.vertices.length;f+=3)n.push(a([s.vertices[f],s.vertices[f+1],s.vertices[f+2]]));let l=0;n.forEach((f,d)=>{et(xe(f,s.center))>et(xe(n[l],s.center))&&(l=d)});let c=[l],u=n.map(f=>et(xe(f,n[l])));for(;c.length<e;){let f=0;u.forEach((d,p)=>{d>u[f]&&(f=p)}),c.push(f),n.forEach((d,p)=>{u[p]=Math.min(u[p],et(xe(d,n[f])))})}return c.flatMap(f=>n[f])}function Ta(s){let e=0;for(let v=0;v<s.length;v++)e=Math.max(e,Math.abs(s[v]));let t=Math.max(e,1e-9)*1e-6,i=new Set,r=[];for(let v=0;v+2<s.length;v+=3){let x=[s[v],s[v+1],s[v+2]],w=x.map(B=>Math.round(B/t)).join(",");i.has(w)||(i.add(w),r.push(x))}if(r.length<4)return null;let o=Math.max(e,1e-9)*1e-10,a=0;for(let v=1;v<r.length;v++)r[v][0]<r[a][0]&&(a=v);let n=-1,l=0;for(let v=0;v<r.length;v++){let x=et(xe(r[v],r[a]));x>l&&(l=x,n=v)}if(n<0||l<o)return null;let c=-1;l=0;let u=xe(r[n],r[a]);for(let v=0;v<r.length;v++){let x=et(Ri(u,xe(r[v],r[a])));x>l&&(l=x,c=v)}if(c<0||l<o*et(u))return null;let f=Ri(u,xe(r[c],r[a])),d=-1;l=0;for(let v=0;v<r.length;v++){let x=Math.abs(Mt(f,xe(r[v],r[a])));x>l&&(l=x,d=v)}if(d<0||l<o*et(f))return null;let p=[],m=(v,x,w)=>{let B=Ri(xe(r[x],r[v]),xe(r[w],r[v])),L=et(B)||1,M=[B[0]/L,B[1]/L,B[2]/L];return{v:[v,x,w],n:M,d:Mt(M,r[v])}},g=Mt(f,xe(r[d],r[a]))>0?[a,c,n]:[a,n,c];p.push(m(g[0],g[1],g[2])),p.push(m(g[0],d,g[1])),p.push(m(g[1],d,g[2])),p.push(m(g[2],d,g[0]));let b=new Set([a,n,c,d]),y=r.map((v,x)=>x).filter(v=>!b.has(v)),A=[a,n,c,d].reduce((v,x)=>[v[0]+r[x][0]/4,v[1]+r[x][1]/4,v[2]+r[x][2]/4],[0,0,0]);y.sort((v,x)=>et(xe(r[x],A))-et(xe(r[v],A)));for(let v of y){let x=p.filter(k=>Mt(k.n,r[v])-k.d>o);if(!x.length)continue;let w=new Map;for(let k of p)for(let P=0;P<3;P++)w.set(`${k.v[P]},${k.v[(P+1)%3]}`,k);let B=new Set(x),L=[...x];for(;L.length;){let k=L.pop();for(let P=0;P<3;P++){let C=w.get(`${k.v[(P+1)%3]},${k.v[P]}`);C&&!B.has(C)&&Mt(C.n,r[v])-C.d>-o&&(B.add(C),L.push(C))}}let M=[...B],I=new Set;for(let k of M)for(let P=0;P<3;P++)I.add(`${k.v[P]},${k.v[(P+1)%3]}`);let E=[];for(let k of M)for(let P=0;P<3;P++){let C=k.v[P],_=k.v[(P+1)%3];I.has(`${_},${C}`)||E.push([C,_])}for(let k of M)p.splice(p.indexOf(k),1);for(let[k,P]of E)p.push(m(k,P,v))}return vl(r.flat(),p.flatMap(v=>v.v))}function ja(s,e){let t=vl(s,e);return t&&t.vertices.length/3>32?Ta(yl(t,32)):t}function vl(s,e){let t=[];for(let C=0;C+2<s.length;C+=3)t.push([s[C],s[C+1],s[C+2]]);let i=0;for(let C of t)i=Math.max(i,Math.abs(C[0]),Math.abs(C[1]),Math.abs(C[2]));let r=Math.max(i,1e-9)*1e-5,o=[];for(let C=0;C+2<e.length;C+=3){let _=[e[C],e[C+1],e[C+2]],z=Ri(xe(t[_[1]],t[_[0]]),xe(t[_[2]],t[_[0]])),R=et(z);if(!(R>0))continue;let G=[z[0]/R,z[1]/R,z[2]/R];o.push({v:_,n:G,d:Mt(G,t[_[0]])})}let a=new Map;o.forEach((C,_)=>{for(let z=0;z<3;z++)a.set(`${C.v[z]},${C.v[(z+1)%3]}`,_)});let n=new Array(o.length).fill(-1),l=[];o.forEach((C,_)=>{if(n[_]>=0)return;let z=[_];n[_]=l.length;for(let R=0;R<z.length;R++){let G=o[z[R]];for(let X=0;X<3;X++){let W=a.get(`${G.v[(X+1)%3]},${G.v[X]}`);if(W===void 0||n[W]>=0)continue;let U=o[W];Mt(C.n,U.n)>1-1e-5&&U.v.every(H=>Math.abs(Mt(C.n,t[H])-C.d)<=r)&&(n[W]=l.length,z.push(W))}}l.push(z)});let c=[];for(let C of l){let _=new Set;for(let U of C)for(let H=0;H<3;H++)_.add(`${o[U].v[H]},${o[U].v[(H+1)%3]}`);let z=new Map;for(let U of C)for(let H=0;H<3;H++){let Z=o[U].v[H],he=o[U].v[(H+1)%3];if(!_.has(`${he},${Z}`)){if(z.has(Z))return null;z.set(Z,he)}}let R=[0,0,0];for(let U of C){let H=o[U],Z=Ri(xe(t[H.v[1]],t[H.v[0]]),xe(t[H.v[2]],t[H.v[0]]));R[0]+=Z[0],R[1]+=Z[1],R[2]+=Z[2]}let G=et(R)||1,X=z.keys().next().value,W=[X];for(let U=z.get(X);U!==X&&W.length<=z.size;U=z.get(U))W.push(U);if(W.length!==z.size)return null;c.push({n:[R[0]/G,R[1]/G,R[2]/G],verts:W})}let u=new Map,f=[];for(let C of c)for(let _ of C.verts)u.has(_)||(u.set(_,f.length),f.push(t[_]));for(let C of c)C.verts=C.verts.map(_=>u.get(_));let d=new Set,p=0;for(let C of c)C.verts.forEach((_,z)=>{d.add(`${_},${C.verts[(z+1)%C.verts.length]}`),p++});if(d.size!==p||![...d].every(C=>{let[_,z]=C.split(",");return d.has(`${z},${_}`)})||f.length-d.size/2+c.length!==2)return null;let m=0,h=[0,0,0],g=[0,0,0,0,0,0];for(let C of c){let _=f[C.verts[0]];for(let z=1;z+1<C.verts.length;z++){let R=f[C.verts[z]],G=f[C.verts[z+1]],X=Mt(_,Ri(R,G));m+=X/6;for(let U=0;U<3;U++)h[U]+=X/24*(_[U]+R[U]+G[U]);let W=(U,H)=>X/120*(_[U]*_[H]+R[U]*R[H]+G[U]*G[H]+(_[U]+R[U]+G[U])*(_[H]+R[H]+G[H]));g[0]+=W(0,0),g[1]+=W(1,1),g[2]+=W(2,2),g[3]+=W(0,1),g[4]+=W(0,2),g[5]+=W(1,2)}}if(!(m>0))return null;for(let C=0;C<3;C++)h[C]/=m;g[0]-=m*h[0]*h[0],g[1]-=m*h[1]*h[1],g[2]-=m*h[2]*h[2],g[3]-=m*h[0]*h[1],g[4]-=m*h[0]*h[2],g[5]-=m*h[1]*h[2];let b=g[0]+g[1]+g[2],y=[[b-g[0],-g[3],-g[4]],[-g[3],b-g[1],-g[5]],[-g[4],-g[5],b-g[2]]],{values:A,vectors:v}=ef(y),x=v,w=C=>{let _=xe(C,h);return[x[0][0]*_[0]+x[1][0]*_[1]+x[2][0]*_[2],x[0][1]*_[0]+x[1][1]*_[1]+x[2][1]*_[2],x[0][2]*_[0]+x[1][2]*_[1]+x[2][2]*_[2]]},B=f.map(w),L=new Float32Array(B.flat()),M=c.map(C=>{let _=C.n,z=[x[0][0]*_[0]+x[1][0]*_[1]+x[2][0]*_[2],x[0][1]*_[0]+x[1][1]*_[1]+x[2][1]*_[2],x[0][2]*_[0]+x[1][2]*_[1]+x[2][2]*_[2]],R=-1/0;for(let G of C.verts)R=Math.max(R,Mt(z,B[G]));return{normal:z,d:R,verts:C.verts}}),I=new Map;M.forEach((C,_)=>C.verts.forEach((z,R)=>I.set(`${z},${C.verts[(R+1)%C.verts.length]}`,_)));let E=[];M.forEach((C,_)=>C.verts.forEach((z,R)=>{let G=C.verts[(R+1)%C.verts.length],X=I.get(`${G},${z}`);z<G&&X!==void 0&&E.push([z,G,_,X])}));let k=[0,0,0],P=0;for(let C of B){for(let _=0;_<3;_++)k[_]=Math.max(k[_],2*Math.abs(C[_]));P=Math.max(P,et(C))}return{vertices:L,faces:M,edges:E,volume:m,moments:[A[0],A[1],A[2]],size:k,radius:P,center:h,rotation:tf(x)}}function ef(s){let e=s.map(n=>[...n]),t=[[1,0,0],[0,1,0],[0,0,1]];for(let n=0;n<50&&!(e[0][1]**2+e[0][2]**2+e[1][2]**2<1e-30*(e[0][0]**2+e[1][1]**2+e[2][2]**2+1e-300));n++)for(let c=0;c<3;c++)for(let u=c+1;u<3;u++){if(Math.abs(e[c][u])<1e-300)continue;let f=(e[u][u]-e[c][c])/(2*e[c][u]),d=Math.sign(f||1)/(Math.abs(f)+Math.sqrt(f*f+1)),p=1/Math.sqrt(d*d+1),m=d*p;for(let h=0;h<3;h++){let g=e[h][c],b=e[h][u];e[h][c]=p*g-m*b,e[h][u]=m*g+p*b}for(let h=0;h<3;h++){let g=e[c][h],b=e[u][h];e[c][h]=p*g-m*b,e[u][h]=m*g+p*b}for(let h=0;h<3;h++){let g=t[h][c],b=t[h][u];t[h][c]=p*g-m*b,t[h][u]=m*g+p*b}}let i=[t[0][0],t[1][0],t[2][0]],r=[t[0][1],t[1][1],t[2][1]],o=Ri(i,r),a=[[i[0],r[0],o[0]],[i[1],r[1],o[1]],[i[2],r[2],o[2]]];return{values:[e[0][0],e[1][1],e[2][2]],vectors:a}}function tf(s){let e=s[0][0]+s[1][1]+s[2][2],t,i,r,o;if(e>0){let n=.5/Math.sqrt(e+1);o=.25/n,t=(s[2][1]-s[1][2])*n,i=(s[0][2]-s[2][0])*n,r=(s[1][0]-s[0][1])*n}else if(s[0][0]>s[1][1]&&s[0][0]>s[2][2]){let n=2*Math.sqrt(1+s[0][0]-s[1][1]-s[2][2]);o=(s[2][1]-s[1][2])/n,t=.25*n,i=(s[0][1]+s[1][0])/n,r=(s[0][2]+s[2][0])/n}else if(s[1][1]>s[2][2]){let n=2*Math.sqrt(1+s[1][1]-s[0][0]-s[2][2]);o=(s[0][2]-s[2][0])/n,t=(s[0][1]+s[1][0])/n,i=.25*n,r=(s[1][2]+s[2][1])/n}else{let n=2*Math.sqrt(1+s[2][2]-s[0][0]-s[1][1]);o=(s[1][0]-s[0][1])/n,t=(s[0][2]+s[2][0])/n,i=(s[1][2]+s[2][1])/n,r=.25*n}let a=Math.hypot(t,i,r,o);return[t/a,i/a,r/a,o/a]}var Al=new WeakSet,De=s=>Al.has(s),rf=new WeakSet;var ar=s=>rf.has(s);function nr(s,e,t,i,r,o=[0,0,0]){let a=new Ze(s,[2*e,2*e,2*e],t,i,r,o);a.mass=t>0?4/3*Math.PI*e*e*e*t:0;let n=.4*a.mass*e*e;return a.moment.set([n,n,n]),a.radius=e,Al.add(a),a}var wl=new WeakMap,Ct=s=>wl.get(s);function lr(s,e,t,i,r,o=[0,0,0,1],a=[0,0,0]){if(e.vertices.length/3>32||e.faces.length>255||e.edges.length>255)throw new Error(`hull: ${e.vertices.length/3} vertices, ${e.faces.length} faces, ${e.edges.length} edges (at most ${32} vertices, 255 faces and edges)`);let n=new Ze(s,e.size,t,i,r,a);return n.positionAng.set([o[0],o[1],o[2],o[3]]),n.mass=t>0?e.volume*t:0,n.moment.set(e.moments.map(l=>l*Math.max(t,0))),n.radius=e.radius,wl.set(n,e),n}var Da=`
1
+ var globalThis;(globalThis||={}).AVBD=(()=>{var Ba=Object.defineProperty;var Tu=Object.getOwnPropertyDescriptor;var ju=Object.getOwnPropertyNames;var Du=Object.prototype.hasOwnProperty;var Gu=(s,e)=>{for(var t in e)Ba(s,t,{get:e[t],enumerable:!0})},Fu=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ju(e))!Du.call(s,r)&&r!==t&&Ba(s,r,{get:()=>e[r],enumerable:!(i=Tu(e,r))||i.enumerable});return s};var Uu=s=>Fu(Ba({},"__esModule",{value:!0}),s);var jd={};Gu(jd,{AvbdPhysics:()=>hs,AvbdPhysicsAggregate:()=>ms,AvbdPhysicsBody:()=>Rr,AvbdPhysicsConstraint:()=>Pr,AvbdPhysicsHinge:()=>Lr,AvbdScene2D:()=>va,AvbdScene3D:()=>ya,AvbdShapeType:()=>rt,GPUBufferRecycler:()=>Hr,GpuContactSample:()=>Aa,GpuSurfaceParticles:()=>xa,GpuTimer:()=>Wr,INPUT_WORDS:()=>Eu,PARTICLE_BYTE_STRIDE:()=>Ls,WorkerCanvas:()=>wa,addGpuStepPass:()=>_u,cookHeightfield:()=>Mr,cookStaticMesh:()=>zr,createSharedInput:()=>Mu,createSolverPipeline:()=>xu,createWebGPUDevice:()=>Sr,prepareWebGPUDevice3D:()=>Ni,readSharedInput:()=>Iu,sampledContactShader:()=>Pu,seedConstraintColoring:()=>Lu,writeSharedInput:()=>zu});var S=(s=0,e=0,t=0)=>Float64Array.of(s,e,t),jt=(s=0,e=0,t=0,i=1)=>Float64Array.of(s,e,t,i),ae=()=>new Float64Array(9);var Es=s=>s<0?-1:s>0?1:0,Bt=(s,e)=>s<e?s:e,Nu=(s,e)=>s>e?s:e,ce=(s,e,t)=>Nu(e,Bt(t,s)),V=(s,e)=>s[0]*e[0]+s[1]*e[1]+s[2]*e[2],qe=s=>V(s,s),sr=s=>Math.sqrt(qe(s));function ct(s,e,t,i){return s[0]=e,s[1]=t,s[2]=i,s}var Li=(s,e,t)=>ct(s,e[0]+t[0],e[1]+t[1],e[2]+t[2]),J=(s,e,t)=>ct(s,e[0]-t[0],e[1]-t[1],e[2]-t[2]),ne=(s,e,t)=>ct(s,e[0]*t,e[1]*t,e[2]*t),_t=(s,e,t)=>ct(s,e[0]/t,e[1]/t,e[2]/t),ee=(s,e)=>ct(s,-e[0],-e[1],-e[2]),Ca=(s,e)=>ct(s,Math.abs(e[0]),Math.abs(e[1]),Math.abs(e[2])),D=(s,e,t,i)=>ct(s,e[0]+t[0]*i,e[1]+t[1]*i,e[2]+t[2]*i),qu=(s,e)=>_t(s,e,sr(e)),Dt=(s,e,t)=>ct(s,e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]);function rr(s,e,t,i,r){return s[0]=e,s[1]=t,s[2]=i,s[3]=r,s}function $r(s,e,t){let i=e[0],r=e[1],o=e[2],a=e[3],n=t[0],l=t[1],c=t[2],u=t[3];return rr(s,a*n+i*u+r*c-o*l,a*l-i*c+r*u+o*n,a*c+i*l-r*n+o*u,a*u-i*n-r*l-o*c)}var Vu=(s,e)=>rr(s,-e[0],-e[1],-e[2],e[3]),Yn=s=>qe(s)+s[3]*s[3];function Sa(s,e){let t=Yn(e);return rr(s,-e[0]/t,-e[1]/t,-e[2]/t,e[3]/t)}function Wu(s,e){let t=Math.sqrt(Yn(e));return rr(s,e[0]/t,e[1]/t,e[2]/t,e[3]/t)}var ir=new Float64Array(4),Pi=new Float64Array(4);function ut(s,e,t){return $r(ir,e,Sa(ir,t)),ct(s,ir[0]*2,ir[1]*2,ir[2]*2)}function si(s,e,t){return rr(Pi,t[0],t[1],t[2],0),$r(Pi,Pi,e),Wu(s,rr(s,e[0]+Pi[0]*.5,e[1]+Pi[1]*.5,e[2]+Pi[2]*.5,e[3]+Pi[3]*.5))}function le(s,e,t){let i=e[0],r=e[1],o=e[2],a=e[3],n=(r*t[2]-o*t[1])*2,l=(o*t[0]-i*t[2])*2,c=(i*t[1]-r*t[0])*2;return ct(s,t[0]+n*a+(r*c-o*l),t[1]+l*a+(o*n-i*c),t[2]+c*a+(i*l-r*n))}var Xn=new Float64Array(3);function Gt(s,e,t,i){return le(Xn,t,i),Li(s,Xn,e)}function Te(s,e,t){return le(s,Vu(ir,e),t)}function Ce(s,e,t,i){return s.fill(0),s[0]=e,s[4]=t,s[8]=i,s}function ka(s,e){return s[0]=0,s[1]=-e[2],s[2]=e[1],s[3]=e[2],s[4]=0,s[5]=-e[0],s[6]=-e[1],s[7]=e[0],s[8]=0,s}function _i(s,e){let t=e[1],i=e[2],r=e[5];return s[0]=e[0],s[1]=e[3],s[2]=e[6],s[3]=t,s[4]=e[4],s[5]=e[7],s[6]=i,s[7]=r,s[8]=e[8],s}function Ke(s,e,t){let i=e[0],r=e[1],o=e[2],a=e[3],n=e[4],l=e[5],c=e[6],u=e[7],f=e[8],d=t[0],h=t[1],m=t[2],p=t[3],g=t[4],b=t[5],y=t[6],A=t[7],v=t[8];return s[0]=i*d+r*p+o*y,s[1]=i*h+r*g+o*A,s[2]=i*m+r*b+o*v,s[3]=a*d+n*p+l*y,s[4]=a*h+n*g+l*A,s[5]=a*m+n*b+l*v,s[6]=c*d+u*p+f*y,s[7]=c*h+u*g+f*A,s[8]=c*m+u*b+f*v,s}function ue(s,e,t){let i=t[0],r=t[1],o=t[2];return ct(s,e[0]*i+e[1]*r+e[2]*o,e[3]*i+e[4]*r+e[5]*o,e[6]*i+e[7]*r+e[8]*o)}function Ve(s,e){for(let t=0;t<9;t++)s[t]+=e[t];return s}function Ei(s,e,t){for(let i=0;i<9;i++)s[i]=e[i]*t;return s}function Qn(s,e){for(let t=0;t<9;t++)s[t]=-e[t];return s}function Ms(s,e,t){for(let i=0;i<3;i++)for(let r=0;r<3;r++)s[i*3+r]=t[r]*e[i];return s}function Kn(s,e){let t=Math.sqrt(e[0]*e[0]+e[3]*e[3]+e[6]*e[6]),i=Math.sqrt(e[1]*e[1]+e[4]*e[4]+e[7]*e[7]),r=Math.sqrt(e[2]*e[2]+e[5]*e[5]+e[8]*e[8]);return Ce(s,t,i,r)}function zs(s,e){let t=Math.abs(e[0])>Math.abs(e[2])?S(-e[1],e[0],0):S(0,-e[2],e[1]);qu(t,t);let i=Dt(S(),e,t);return s[0]=e[0],s[1]=e[1],s[2]=e[2],s.set(t,3),s.set(i,6),s}function Is(s,e,t,i,r,o,a){let n=s[0],l=s[3],c=s[4],u=s[6],f=s[7],d=s[8],h=t[0],m=t[1],p=t[2],g=e[0],b=t[3],y=t[4],A=t[5],v=e[3],x=e[4],w=t[6],B=t[7],L=t[8],M=e[6],I=e[7],E=e[8],k=l/n,P=u/n,C=h/n,_=b/n,z=w/n,R=n,G=c-k*k*R,X=(f-k*P*R)/G,W=(m-k*C*R)/G,U=(y-k*_*R)/G,H=(B-k*z*R)/G,Z=d-(P*P*R+X*X*G),pe=(p-P*C*R-X*W*G)/Z,we=(A-P*_*R-X*U*G)/Z,Oe=(L-P*z*R-X*H*G)/Z,$=g-(C*C*R+W*W*G+pe*pe*Z),Je=(v-C*_*R-W*U*G-pe*we*Z)/$,Xe=(M-C*z*R-W*H*G-pe*Oe*Z)/$,Be=x-(_*_*R+U*U*G+we*we*Z+Je*Je*$),at=(I-_*z*R-U*H*G-we*Oe*Z-Je*Xe*$)/Be,ri=E-(z*z*R+H*H*G+Oe*Oe*Z+Xe*Xe*$+at*at*Be),Ye=i[0],nt=i[1]-k*Ye,Qe=i[2]-P*Ye-X*nt,lt=r[0]-C*Ye-W*nt-pe*Qe,wt=r[1]-_*Ye-U*nt-we*Qe-Je*lt,Ki=r[2]-z*Ye-H*nt-Oe*Qe-Xe*lt-at*wt,Zi=Ye/R,er=nt/G,tr=Qe/Z,Wt=lt/$,Ru=wt/Be,Ou=Ki/ri;a[2]=Ou,a[1]=Ru-at*a[2],a[0]=Wt-Je*a[1]-Xe*a[2],o[2]=tr-pe*a[0]-we*a[1]-Oe*a[2],o[1]=er-X*o[2]-W*a[0]-U*a[1]-H*a[2],o[0]=Zi-k*o[1]-P*o[2]-C*a[0]-_*a[1]-z*a[2]}var Et=1,We=1e10,Rs=.01,Zn=1e-5,Ze=class{solver;forces=[];positionLin;positionAng=jt();initialLin=S();initialAng=jt();inertialLin=S();inertialAng=jt();velocityLin;velocityAng=S();prevVelocityLin;size;mass;moment;friction;radius;constructor(e,t,i,r,o,a=[0,0,0]){this.solver=e,this.size=S(t[0],t[1],t[2]),this.friction=r,this.positionLin=S(o[0],o[1],o[2]),this.velocityLin=S(a[0],a[1],a[2]),this.prevVelocityLin=S(a[0],a[1],a[2]);let[n,l,c]=this.size;this.mass=n*l*c*i,this.moment=S((l*l+c*c)/12*this.mass,(n*n+c*c)/12*this.mass,(n*n+l*l)/12*this.mass),this.radius=sr([n*.5,l*.5,c*.5]),e.bodies.push(this)}constrainedTo(e){for(let t of this.forces)if(t.bodyA===this&&t.bodyB===e||t.bodyA===e&&t.bodyB===this)return!0;return!1}},Os=()=>({lhsLin:ae(),lhsAng:ae(),lhsCross:ae(),rhsLin:S(),rhsAng:S()}),Ft=class{solver;bodyA;bodyB;constructor(e,t,i){this.solver=e,this.bodyA=t,this.bodyB=i,e.forces.push(this),t?.forces.push(this),i.forces.push(this)}destroy(){let e=this.solver.forces,t=e.indexOf(this);t>=0&&e.splice(t,1),this.unlinkFromBodies()}unlinkFromBodies(){for(let e of[this.bodyA,this.bodyB]){if(!e)continue;let t=e.forces.indexOf(this);t>=0&&e.forces.splice(t,1)}}};var sl=8,el=16,zi=1e-6,La=1e-5,Hu=1e-6,_a=34028234663852886e22,Ts=0,ol=1,js=2;function tl(s){let e=s.positionAng;return{center:s.positionLin,half:ne(S(),s.size,.5),axis:[le(S(),e,[1,0,0]),le(S(),e,[0,1,0]),le(S(),e,[0,0,1])]}}var Mi=(s,e)=>Math.abs(V(s,e));function Ds(s,e){let t=V(e,s.axis[0])>=0?1:-1,i=V(e,s.axis[1])>=0?1:-1,r=V(e,s.axis[2])>=0?1:-1,o=D(S(),s.center,s.axis[0],s.half[0]*t);return D(o,o,s.axis[1],s.half[1]*i),D(o,o,s.axis[2],s.half[2]*r)}function al(s,e){return e===0?{u:s.axis[1],v:s.axis[2],extentU:s.half[1],extentV:s.half[2]}:e===1?{u:s.axis[0],v:s.axis[2],extentU:s.half[0],extentV:s.half[2]}:{u:s.axis[0],v:s.axis[1],extentU:s.half[0],extentV:s.half[1]}}function $u(s,e,t){let i=V(t,s.axis[e])>=0?1:-1,r=ne(S(),s.axis[e],i),o=D(S(),s.center,r,s.half[e]);return{normal:r,center:o,...al(s,e)}}function Ju(s,e){let t=0,i=-_a;for(let r=0;r<3;r++){let o=Mi(s.axis[r],e);o>i&&(i=o,t=r)}return t}function Xu(s,e,t){let i=V(s.axis[e],t)>0?-1:1,r=ne(S(),s.axis[e],i),o=D(S(),s.center,r,s.half[e]),{u:a,v:n,extentU:l,extentV:c}=al(s,e),u=(f,d)=>{let h=D(S(),o,a,f*l);return D(h,h,n,d*c)};return[u(1,1),u(-1,1),u(-1,-1),u(1,-1)]}function Yu(s,e,t){let i=[];if(s.length===0)return i;let r=s[s.length-1],o=V(e,r)-t;for(let a of s){let n=V(e,a)-t,l=o<=La,c=n<=La;if(l!==c){let u=0,f=o-n;Math.abs(f)>zi&&(u=ce(o/f,0,1)),i.length<el&&i.push(D(S(),r,J(S(),a,r),u))}c&&i.length<el&&i.push(a),r=a,o=n}return i}var Gs=class{contacts=[];midpoints=[];bodyA;bodyB;constructor(e,t){this.bodyA=e,this.bodyB=t}add(e,t,i){let r=ne(S(),Li(S(),e,t),.5);for(let n of this.midpoints)if(qe(J(S(),r,n))<Hu)return;if(this.contacts.length>=sl)return;let{bodyA:o,bodyB:a}=this;this.contacts.push({feature:i,rA:Te(S(),o.positionAng,J(S(),e,o.positionLin)),rB:Te(S(),a.positionAng,J(S(),t,a.positionLin))}),this.midpoints.push(r)}};function Pa(s,e,t,i,r,o,a,n){let l=qe(i);if(l<zi)return!0;let c=1/Math.sqrt(l),u=ne(S(),i,c);V(u,t)<0&&ee(u,u);let f=Math.abs(V(t,u)),d=s.half[0]*Mi(u,s.axis[0])+s.half[1]*Mi(u,s.axis[1])+s.half[2]*Mi(u,s.axis[2]),h=e.half[0]*Mi(u,e.axis[0])+e.half[1]*Mi(u,e.axis[1])+e.half[2]*Mi(u,e.axis[2]),m=f-(d+h);return m>0?!1:((!n.valid||m>n.separation)&&(n.valid=!0,n.type=r,n.indexA=o,n.indexB=a,n.separation=m,n.normalAB=u),!0)}function il(s,e,t){let i=(e+1)%3,r=(e+2)%3,o=V(t,s.axis[i])>=0?1:-1,a=V(t,s.axis[r])>=0?1:-1,n=D(S(),s.center,s.axis[i],s.half[i]*o);D(n,n,s.axis[r],s.half[r]*a);let l=ne(S(),s.axis[e],s.half[e]);return[J(S(),n,l),Li(S(),n,l)]}function Qu(s,e,t,i){let r=J(S(),e,s),o=J(S(),i,t),a=J(S(),s,t),n=V(r,r),l=V(o,o),c=V(o,a),u=0,f=0;if(n<=zi&&l<=zi)return[s,t];if(n<=zi)f=ce(c/l,0,1);else{let d=V(r,a);if(l<=zi)u=ce(-d/n,0,1);else{let h=V(r,o),m=n*l-h*h;Math.abs(m)>zi&&(u=ce((h*c-d*l)/m,0,1)),f=(h*u+c)/l,f<0?(f=0,u=ce(-d/n,0,1)):f>1&&(f=1,u=ce((h-d)/n,0,1))}}return[D(S(),s,r,u),D(S(),t,o,f)]}function rl(s,e,t,i,r,o,a){let n=r?t:i,l=r?i:t,c=r?a:ee(S(),a),u=$u(n,o,c),f=Ju(l,u.normal),d=Xu(l,f,u.normal),h=[[u.u,u.extentU],[ee(S(),u.u),u.extentU],[u.v,u.extentV],[ee(S(),u.v),u.extentV]];for(let[g,b]of h)if(d=Yu(d,g,V(g,u.center)+b),!d.length)return[];let m=new Gs(s,e),p=(r?Ts:ol)<<24|(o&255)<<16|(f&255)<<8;for(let g=0;g<d.length&&m.contacts.length<sl;g++){let b=d[g],y=V(J(S(),b,u.center),u.normal);if(y>La)continue;let A=D(S(),b,u.normal,-y),v=r?A:b,x=r?b:A;m.add(v,x,p|g&255)}return m.contacts.length||m.add(Ds(t,a),Ds(i,ee(S(),a)),p),m.contacts}function Ku(s,e,t,i,r,o,a){let[n,l]=il(t,r,a),[c,u]=il(i,o,ee(S(),a)),[f,d]=Qu(n,l,c,u),h=new Gs(s,e),m=js<<24|(r&255)<<8|o&255;return h.add(f,d,m),h.contacts.length||h.add(Ds(t,a),Ds(i,ee(S(),a)),m),h.contacts}function nl(s,e,t){let i=tl(s),r=tl(e),o=J(S(),r.center,i.center),a={type:Ts,indexA:0,indexB:0,separation:-_a,normalAB:S(),valid:!1},n={type:js,indexA:0,indexB:0,separation:-_a,normalAB:S(),valid:!1};for(let u=0;u<3;u++)if(!Pa(i,r,o,i.axis[u],Ts,u,-1,a))return[];for(let u=0;u<3;u++)if(!Pa(i,r,o,r.axis[u],ol,-1,u,a))return[];let l=S();for(let u=0;u<3;u++)for(let f=0;f<3;f++)if(Dt(l,i.axis[u],r.axis[f]),!Pa(i,r,o,l,js,u,f,n))return[];if(!a.valid)return[];let c=a;return n.valid&&.95*n.separation>a.separation+.01&&(c=n),zs(t,ee(S(),c.normalAB)),c.type===js?Ku(s,e,i,r,c.indexA,c.indexB,c.normalAB):c.type===Ts?rl(s,e,i,r,!0,c.indexA,c.normalAB):rl(s,e,i,r,!1,c.indexB,c.normalAB)}var ll=S(),cl=S(),ul=S(),fl=S(),dl=S(),pl=S(),Fs=ae(),Ea=ae(),Ma=ae(),Us=ae(),za=ae(),Ia=ae(),Ra=ae(),Ns=ae(),Me=S(),je=S(),Ii=S(),oi=S(),hl=S(),ml=S(),or=0,Jr=0;function gl(s,e,t){for(let i=0;i<3;i++)oi[0]=t[i*3],oi[1]=t[i*3+1],oi[2]=t[i*3+2],Dt(oi,e,oi),s[i*3]=oi[0],s[i*3+1]=oi[1],s[i*3+2]=oi[2];return s}var ai=class extends Ft{contacts=[];basis=ae();friction=0;constructor(e,t,i){super(e,t,i)}get numContacts(){return this.contacts.length}initialize(){let e=this.bodyA,t=this.bodyB,{solver:i}=this;this.friction=Math.sqrt(e.friction*t.friction);let r=this.contacts;this.contacts=nl(e,t,this.basis).map(o=>{let a=r.find(n=>n.feature===o.feature);return a?{feature:o.feature,rA:a.stick?a.rA:o.rA,rB:a.stick?a.rB:o.rB,C0:S(),penalty:a.penalty.slice(),lambda:a.lambda.slice(),stick:a.stick}:{feature:o.feature,rA:o.rA,rB:o.rB,C0:S(),penalty:S(),lambda:S(),stick:!1}});for(let o of this.contacts){Gt(hl,e.positionLin,e.positionAng,o.rA),Gt(ml,t.positionLin,t.positionAng,o.rB),ue(o.C0,this.basis,J(Ii,hl,ml)),o.C0[0]+=Rs;for(let a=0;a<3;a++)o.lambda[a]=o.lambda[a]*i.alpha*i.gamma,o.penalty[a]=ce(o.penalty[a]*i.gamma,Et,We)}return this.contacts.length>0}evaluate(e,t){let i=this.bodyA,r=this.bodyB,o=this.basis;le(dl,i.positionAng,e.rA),le(pl,r.positionAng,e.rB),Qn(Fs,o),gl(Ea,dl,o),gl(Ma,pl,Fs),Ce(Us,e.penalty[0],e.penalty[1],e.penalty[2]),ne(Me,e.C0,1-t),D(Me,Me,ue(Ii,o,ll),1),D(Me,Me,ue(Ii,Fs,ul),1),D(Me,Me,ue(Ii,Ea,cl),1),D(Me,Me,ue(Ii,Ma,fl),1),ue(je,Us,Me),D(je,je,e.lambda,1),je[0]=Bt(je[0],0),Jr=Math.abs(je[0])*this.friction,or=Math.sqrt(je[1]*je[1]+je[2]*je[2]),or>Jr&&or>0&&(je[1]*=Jr/or,je[2]*=Jr/or)}computeDisplacements(){let e=this.bodyA,t=this.bodyB;J(ll,e.positionLin,e.initialLin),ut(cl,e.positionAng,e.initialAng),J(ul,t.positionLin,t.initialLin),ut(fl,t.positionAng,t.initialAng)}updatePrimal(e,t,i){this.computeDisplacements();let r=e===this.bodyA;for(let o of this.contacts){this.evaluate(o,t);let a=r?this.basis:Fs,n=r?Ea:Ma;_i(za,a),_i(Ia,n),Ke(Ra,Ia,Us),Ve(i.lhsLin,Ke(Ns,Ke(Ns,za,Us),a)),Ve(i.lhsAng,Ke(Ns,Ra,n)),Ve(i.lhsCross,Ke(Ns,Ra,a)),D(i.rhsLin,i.rhsLin,ue(Ii,za,je),1),D(i.rhsAng,i.rhsAng,ue(Ii,Ia,je),1)}}updateDual(e){let{solver:t}=this;this.computeDisplacements();for(let i of this.contacts)this.evaluate(i,e),i.lambda.set(je),je[0]<0&&(i.penalty[0]=Bt(i.penalty[0]+t.betaLin*Math.abs(Me[0]),We)),or<=Jr&&(i.penalty[1]=Bt(i.penalty[1]+t.betaLin*Math.abs(Me[1]),We),i.penalty[2]=Bt(i.penalty[2]+t.betaLin*Math.abs(Me[2]),We),i.stick=Math.sqrt(Me[1]*Me[1]+Me[2]*Me[2])<Zn)}};var Oa=()=>({dt:1/60,gravity:-10,iterations:10,betaLin:1e4,betaAng:100,alpha:.99,gamma:.999}),ni=class{dt=1/60;gravity=-10;iterations=10;alpha=.99;betaLin=1e4;betaAng=100;gamma=.999;bodies=[];forces=[];constructor(){this.defaultParams()}defaultParams(){Object.assign(this,Oa())}clear(){this.forces=[],this.bodies=[]}pick(e,t){let r=null,o=S(),a=S();for(let n=this.bodies.length-1;n>=0;n--){let l=this.bodies[n];if(l.mass<=0)continue;Te(o,l.positionAng,J(o,e,l.positionLin)),Te(a,l.positionAng,t);let c=0,u=1/0,f=!0;for(let h=0;h<3&&f;h++){let m=l.size[h]*.5;if(Math.abs(a[h])<1e-6){(o[h]<-m||o[h]>m)&&(f=!1);continue}let p=1/a[h],g=(-m-o[h])*p,b=(m-o[h])*p;g>b&&([g,b]=[b,g]),c=Math.max(c,g),u=Math.min(u,b),c>u&&(f=!1)}if(!f)continue;let d=c>=0?c:u;d<0||(!r||d<r.t)&&(r={body:l,local:D(S(),o,a,d),t:d})}return r}sys=Os();dxLin=S();dxAng=S();dp=S();accel=S();step(){let{dt:e,gravity:t,bodies:i,sys:r,dp:o}=this;for(let n=i.length-1;n>=0;n--){let l=i[n];for(let c=n-1;c>=0;c--){let u=i[c];J(o,l.positionLin,u.positionLin);let f=l.radius+u.radius;V(o,o)<=f*f&&!l.constrainedTo(u)&&new ai(this,l,u)}}let a=[];for(let n of this.forces)n.initialize()?a.push(n):n.unlinkFromBodies();this.forces=a;for(let n=i.length-1;n>=0;n--){let l=i[n];D(l.inertialLin,l.positionLin,l.velocityLin,e),l.mass>0&&(l.inertialLin[2]+=t*(e*e)),si(l.inertialAng,l.positionAng,bl(l.velocityAng,e)),_t(this.accel,J(this.accel,l.velocityLin,l.prevVelocityLin),e);let c=this.accel[2]*Es(t),u=ce(c/Math.abs(t),0,1);Number.isFinite(u)||(u=0),l.initialLin.set(l.positionLin),l.initialAng.set(l.positionAng),l.mass>0&&(D(l.positionLin,l.positionLin,l.velocityLin,e),l.positionLin[2]+=t*(u*e*e),si(l.positionAng,l.positionAng,bl(l.velocityAng,e)))}for(let n=0;n<this.iterations;n++){for(let l=i.length-1;l>=0;l--){let c=i[l];if(c.mass<=0)continue;let u=c.mass,f=c.moment;Ce(r.lhsLin,u/(e*e),u/(e*e),u/(e*e)),Ce(r.lhsAng,f[0]/(e*e),f[1]/(e*e),f[2]/(e*e)),r.lhsCross.fill(0),ue(r.rhsLin,r.lhsLin,J(o,c.positionLin,c.inertialLin)),ue(r.rhsAng,r.lhsAng,ut(o,c.positionAng,c.inertialAng));let d=c.forces;for(let h=d.length-1;h>=0;h--)d[h].updatePrimal(c,this.alpha,r);Is(r.lhsLin,r.lhsAng,r.lhsCross,ee(r.rhsLin,r.rhsLin),ee(r.rhsAng,r.rhsAng),this.dxLin,this.dxAng),D(c.positionLin,c.positionLin,this.dxLin,1),si(c.positionAng,c.positionAng,this.dxAng)}for(let l of this.forces)l.updateDual(this.alpha)}for(let n of i)n.prevVelocityLin.set(n.velocityLin),n.mass>0&&(_t(n.velocityLin,J(n.velocityLin,n.positionLin,n.initialLin),e),_t(n.velocityAng,ut(n.velocityAng,n.positionAng,n.initialAng),e))}},Zu=S(),bl=(s,e)=>ne(Zu,s,e);var xe=(s,e)=>[s[0]-e[0],s[1]-e[1],s[2]-e[2]],Mt=(s,e)=>s[0]*e[0]+s[1]*e[1]+s[2]*e[2],Ri=(s,e)=>[s[1]*e[2]-s[2]*e[1],s[2]*e[0]-s[0]*e[2],s[0]*e[1]-s[1]*e[0]],et=s=>Math.sqrt(Mt(s,s));function Xr(s){let e=Ta(s);return!e||e.vertices.length/3<=32?e:Ta(yl(e,32))}function yl(s,e){let[t,i,r,o]=s.rotation,a=f=>{let d=[2*(i*f[2]-r*f[1]),2*(r*f[0]-t*f[2]),2*(t*f[1]-i*f[0])];return[f[0]+o*d[0]+(i*d[2]-r*d[1])+s.center[0],f[1]+o*d[1]+(r*d[0]-t*d[2])+s.center[1],f[2]+o*d[2]+(t*d[1]-i*d[0])+s.center[2]]},n=[];for(let f=0;f<s.vertices.length;f+=3)n.push(a([s.vertices[f],s.vertices[f+1],s.vertices[f+2]]));let l=0;n.forEach((f,d)=>{et(xe(f,s.center))>et(xe(n[l],s.center))&&(l=d)});let c=[l],u=n.map(f=>et(xe(f,n[l])));for(;c.length<e;){let f=0;u.forEach((d,h)=>{d>u[f]&&(f=h)}),c.push(f),n.forEach((d,h)=>{u[h]=Math.min(u[h],et(xe(d,n[f])))})}return c.flatMap(f=>n[f])}function Ta(s){let e=0;for(let v=0;v<s.length;v++)e=Math.max(e,Math.abs(s[v]));let t=Math.max(e,1e-9)*1e-6,i=new Set,r=[];for(let v=0;v+2<s.length;v+=3){let x=[s[v],s[v+1],s[v+2]],w=x.map(B=>Math.round(B/t)).join(",");i.has(w)||(i.add(w),r.push(x))}if(r.length<4)return null;let o=Math.max(e,1e-9)*1e-10,a=0;for(let v=1;v<r.length;v++)r[v][0]<r[a][0]&&(a=v);let n=-1,l=0;for(let v=0;v<r.length;v++){let x=et(xe(r[v],r[a]));x>l&&(l=x,n=v)}if(n<0||l<o)return null;let c=-1;l=0;let u=xe(r[n],r[a]);for(let v=0;v<r.length;v++){let x=et(Ri(u,xe(r[v],r[a])));x>l&&(l=x,c=v)}if(c<0||l<o*et(u))return null;let f=Ri(u,xe(r[c],r[a])),d=-1;l=0;for(let v=0;v<r.length;v++){let x=Math.abs(Mt(f,xe(r[v],r[a])));x>l&&(l=x,d=v)}if(d<0||l<o*et(f))return null;let h=[],m=(v,x,w)=>{let B=Ri(xe(r[x],r[v]),xe(r[w],r[v])),L=et(B)||1,M=[B[0]/L,B[1]/L,B[2]/L];return{v:[v,x,w],n:M,d:Mt(M,r[v])}},g=Mt(f,xe(r[d],r[a]))>0?[a,c,n]:[a,n,c];h.push(m(g[0],g[1],g[2])),h.push(m(g[0],d,g[1])),h.push(m(g[1],d,g[2])),h.push(m(g[2],d,g[0]));let b=new Set([a,n,c,d]),y=r.map((v,x)=>x).filter(v=>!b.has(v)),A=[a,n,c,d].reduce((v,x)=>[v[0]+r[x][0]/4,v[1]+r[x][1]/4,v[2]+r[x][2]/4],[0,0,0]);y.sort((v,x)=>et(xe(r[x],A))-et(xe(r[v],A)));for(let v of y){let x=h.filter(k=>Mt(k.n,r[v])-k.d>o);if(!x.length)continue;let w=new Map;for(let k of h)for(let P=0;P<3;P++)w.set(`${k.v[P]},${k.v[(P+1)%3]}`,k);let B=new Set(x),L=[...x];for(;L.length;){let k=L.pop();for(let P=0;P<3;P++){let C=w.get(`${k.v[(P+1)%3]},${k.v[P]}`);C&&!B.has(C)&&Mt(C.n,r[v])-C.d>-o&&(B.add(C),L.push(C))}}let M=[...B],I=new Set;for(let k of M)for(let P=0;P<3;P++)I.add(`${k.v[P]},${k.v[(P+1)%3]}`);let E=[];for(let k of M)for(let P=0;P<3;P++){let C=k.v[P],_=k.v[(P+1)%3];I.has(`${_},${C}`)||E.push([C,_])}for(let k of M)h.splice(h.indexOf(k),1);for(let[k,P]of E)h.push(m(k,P,v))}return vl(r.flat(),h.flatMap(v=>v.v))}function ja(s,e){let t=vl(s,e);return t&&t.vertices.length/3>32?Ta(yl(t,32)):t}function vl(s,e){let t=[];for(let C=0;C+2<s.length;C+=3)t.push([s[C],s[C+1],s[C+2]]);let i=0;for(let C of t)i=Math.max(i,Math.abs(C[0]),Math.abs(C[1]),Math.abs(C[2]));let r=Math.max(i,1e-9)*1e-5,o=[];for(let C=0;C+2<e.length;C+=3){let _=[e[C],e[C+1],e[C+2]],z=Ri(xe(t[_[1]],t[_[0]]),xe(t[_[2]],t[_[0]])),R=et(z);if(!(R>0))continue;let G=[z[0]/R,z[1]/R,z[2]/R];o.push({v:_,n:G,d:Mt(G,t[_[0]])})}let a=new Map;o.forEach((C,_)=>{for(let z=0;z<3;z++)a.set(`${C.v[z]},${C.v[(z+1)%3]}`,_)});let n=new Array(o.length).fill(-1),l=[];o.forEach((C,_)=>{if(n[_]>=0)return;let z=[_];n[_]=l.length;for(let R=0;R<z.length;R++){let G=o[z[R]];for(let X=0;X<3;X++){let W=a.get(`${G.v[(X+1)%3]},${G.v[X]}`);if(W===void 0||n[W]>=0)continue;let U=o[W];Mt(C.n,U.n)>1-1e-5&&U.v.every(H=>Math.abs(Mt(C.n,t[H])-C.d)<=r)&&(n[W]=l.length,z.push(W))}}l.push(z)});let c=[];for(let C of l){let _=new Set;for(let U of C)for(let H=0;H<3;H++)_.add(`${o[U].v[H]},${o[U].v[(H+1)%3]}`);let z=new Map;for(let U of C)for(let H=0;H<3;H++){let Z=o[U].v[H],pe=o[U].v[(H+1)%3];if(!_.has(`${pe},${Z}`)){if(z.has(Z))return null;z.set(Z,pe)}}let R=[0,0,0];for(let U of C){let H=o[U],Z=Ri(xe(t[H.v[1]],t[H.v[0]]),xe(t[H.v[2]],t[H.v[0]]));R[0]+=Z[0],R[1]+=Z[1],R[2]+=Z[2]}let G=et(R)||1,X=z.keys().next().value,W=[X];for(let U=z.get(X);U!==X&&W.length<=z.size;U=z.get(U))W.push(U);if(W.length!==z.size)return null;c.push({n:[R[0]/G,R[1]/G,R[2]/G],verts:W})}let u=new Map,f=[];for(let C of c)for(let _ of C.verts)u.has(_)||(u.set(_,f.length),f.push(t[_]));for(let C of c)C.verts=C.verts.map(_=>u.get(_));let d=new Set,h=0;for(let C of c)C.verts.forEach((_,z)=>{d.add(`${_},${C.verts[(z+1)%C.verts.length]}`),h++});if(d.size!==h||![...d].every(C=>{let[_,z]=C.split(",");return d.has(`${z},${_}`)})||f.length-d.size/2+c.length!==2)return null;let m=0,p=[0,0,0],g=[0,0,0,0,0,0];for(let C of c){let _=f[C.verts[0]];for(let z=1;z+1<C.verts.length;z++){let R=f[C.verts[z]],G=f[C.verts[z+1]],X=Mt(_,Ri(R,G));m+=X/6;for(let U=0;U<3;U++)p[U]+=X/24*(_[U]+R[U]+G[U]);let W=(U,H)=>X/120*(_[U]*_[H]+R[U]*R[H]+G[U]*G[H]+(_[U]+R[U]+G[U])*(_[H]+R[H]+G[H]));g[0]+=W(0,0),g[1]+=W(1,1),g[2]+=W(2,2),g[3]+=W(0,1),g[4]+=W(0,2),g[5]+=W(1,2)}}if(!(m>0))return null;for(let C=0;C<3;C++)p[C]/=m;g[0]-=m*p[0]*p[0],g[1]-=m*p[1]*p[1],g[2]-=m*p[2]*p[2],g[3]-=m*p[0]*p[1],g[4]-=m*p[0]*p[2],g[5]-=m*p[1]*p[2];let b=g[0]+g[1]+g[2],y=[[b-g[0],-g[3],-g[4]],[-g[3],b-g[1],-g[5]],[-g[4],-g[5],b-g[2]]],{values:A,vectors:v}=ef(y),x=v,w=C=>{let _=xe(C,p);return[x[0][0]*_[0]+x[1][0]*_[1]+x[2][0]*_[2],x[0][1]*_[0]+x[1][1]*_[1]+x[2][1]*_[2],x[0][2]*_[0]+x[1][2]*_[1]+x[2][2]*_[2]]},B=f.map(w),L=new Float32Array(B.flat()),M=c.map(C=>{let _=C.n,z=[x[0][0]*_[0]+x[1][0]*_[1]+x[2][0]*_[2],x[0][1]*_[0]+x[1][1]*_[1]+x[2][1]*_[2],x[0][2]*_[0]+x[1][2]*_[1]+x[2][2]*_[2]],R=-1/0;for(let G of C.verts)R=Math.max(R,Mt(z,B[G]));return{normal:z,d:R,verts:C.verts}}),I=new Map;M.forEach((C,_)=>C.verts.forEach((z,R)=>I.set(`${z},${C.verts[(R+1)%C.verts.length]}`,_)));let E=[];M.forEach((C,_)=>C.verts.forEach((z,R)=>{let G=C.verts[(R+1)%C.verts.length],X=I.get(`${G},${z}`);z<G&&X!==void 0&&E.push([z,G,_,X])}));let k=[0,0,0],P=0;for(let C of B){for(let _=0;_<3;_++)k[_]=Math.max(k[_],2*Math.abs(C[_]));P=Math.max(P,et(C))}return{vertices:L,faces:M,edges:E,volume:m,moments:[A[0],A[1],A[2]],size:k,radius:P,center:p,rotation:tf(x)}}function ef(s){let e=s.map(n=>[...n]),t=[[1,0,0],[0,1,0],[0,0,1]];for(let n=0;n<50&&!(e[0][1]**2+e[0][2]**2+e[1][2]**2<1e-30*(e[0][0]**2+e[1][1]**2+e[2][2]**2+1e-300));n++)for(let c=0;c<3;c++)for(let u=c+1;u<3;u++){if(Math.abs(e[c][u])<1e-300)continue;let f=(e[u][u]-e[c][c])/(2*e[c][u]),d=Math.sign(f||1)/(Math.abs(f)+Math.sqrt(f*f+1)),h=1/Math.sqrt(d*d+1),m=d*h;for(let p=0;p<3;p++){let g=e[p][c],b=e[p][u];e[p][c]=h*g-m*b,e[p][u]=m*g+h*b}for(let p=0;p<3;p++){let g=e[c][p],b=e[u][p];e[c][p]=h*g-m*b,e[u][p]=m*g+h*b}for(let p=0;p<3;p++){let g=t[p][c],b=t[p][u];t[p][c]=h*g-m*b,t[p][u]=m*g+h*b}}let i=[t[0][0],t[1][0],t[2][0]],r=[t[0][1],t[1][1],t[2][1]],o=Ri(i,r),a=[[i[0],r[0],o[0]],[i[1],r[1],o[1]],[i[2],r[2],o[2]]];return{values:[e[0][0],e[1][1],e[2][2]],vectors:a}}function tf(s){let e=s[0][0]+s[1][1]+s[2][2],t,i,r,o;if(e>0){let n=.5/Math.sqrt(e+1);o=.25/n,t=(s[2][1]-s[1][2])*n,i=(s[0][2]-s[2][0])*n,r=(s[1][0]-s[0][1])*n}else if(s[0][0]>s[1][1]&&s[0][0]>s[2][2]){let n=2*Math.sqrt(1+s[0][0]-s[1][1]-s[2][2]);o=(s[2][1]-s[1][2])/n,t=.25*n,i=(s[0][1]+s[1][0])/n,r=(s[0][2]+s[2][0])/n}else if(s[1][1]>s[2][2]){let n=2*Math.sqrt(1+s[1][1]-s[0][0]-s[2][2]);o=(s[0][2]-s[2][0])/n,t=(s[0][1]+s[1][0])/n,i=.25*n,r=(s[1][2]+s[2][1])/n}else{let n=2*Math.sqrt(1+s[2][2]-s[0][0]-s[1][1]);o=(s[1][0]-s[0][1])/n,t=(s[0][2]+s[2][0])/n,i=(s[1][2]+s[2][1])/n,r=.25*n}let a=Math.hypot(t,i,r,o);return[t/a,i/a,r/a,o/a]}var Al=new WeakSet,De=s=>Al.has(s),rf=new WeakSet;var ar=s=>rf.has(s);function nr(s,e,t,i,r,o=[0,0,0]){let a=new Ze(s,[2*e,2*e,2*e],t,i,r,o);a.mass=t>0?4/3*Math.PI*e*e*e*t:0;let n=.4*a.mass*e*e;return a.moment.set([n,n,n]),a.radius=e,Al.add(a),a}var wl=new WeakMap,Ct=s=>wl.get(s);function lr(s,e,t,i,r,o=[0,0,0,1],a=[0,0,0]){if(e.vertices.length/3>32||e.faces.length>255||e.edges.length>255)throw new Error(`hull: ${e.vertices.length/3} vertices, ${e.faces.length} faces, ${e.edges.length} edges (at most ${32} vertices, 255 faces and edges)`);let n=new Ze(s,e.size,t,i,r,a);return n.positionAng.set([o[0],o[1],o[2],o[3]]),n.mass=t>0?e.volume*t:0,n.moment.set(e.moments.map(l=>l*Math.max(t,0))),n.radius=e.radius,wl.set(n,e),n}var Da=`
2
2
  const T_NONE = 0;
3
3
 
4
4
  const MAX_COLORS = 64u;
@@ -233,7 +233,7 @@ fn addBlocks(@builtin(workgroup_id) wid: vec3u, @builtin(local_invocation_id) li
233
233
  if (base < sp.n) { data[sp.offset + base] += add; }
234
234
  if (base + 1u < sp.n) { data[sp.offset + base + 1u] += add; }
235
235
  }
236
- `,tt=class{levels=[];buffers=[];scanPipeline;addPipeline;constructor(e,t,i,r){let o=e.createShaderModule({label:"prefix scan",code:sf}),a=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]}),n=e.createPipelineLayout({bindGroupLayouts:[a]});this.scanPipeline=e.createComputePipeline({label:"scanBlocks",layout:n,compute:{module:o,entryPoint:"scanBlocks"}}),this.addPipeline=e.createComputePipeline({label:"addBlocks",layout:n,compute:{module:o,entryPoint:"addBlocks"}});let l=t,c=i,u=r;for(;;){let f=Math.max(1,Math.ceil(u/512)),d=e.createBuffer({label:`scan sums ${this.levels.length}`,size:Math.max(f,4)*4,usage:GPUBufferUsage.STORAGE}),p=e.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});new Uint32Array(p.getMappedRange()).set([c,u,0,0]),p.unmap(),this.buffers.push(d,p);let m=e.createBindGroup({layout:a,entries:[{binding:0,resource:{buffer:p}},{binding:1,resource:{buffer:l}},{binding:2,resource:{buffer:d}}]});if(this.levels.push({n:u,blocks:f,group:m}),f===1)break;l=d,c=0,u=f}}encode(e){e.setPipeline(this.scanPipeline);for(let t of this.levels)e.setBindGroup(0,t.group),e.dispatchWorkgroups(t.blocks);e.setPipeline(this.addPipeline);for(let t=this.levels.length-2;t>=0;t--)e.setBindGroup(0,this.levels[t].group),e.dispatchWorkgroups(this.levels[t].blocks)}destroy(){for(let e of this.buffers)e.destroy()}};var of=`
236
+ `,tt=class{levels=[];buffers=[];scanPipeline;addPipeline;constructor(e,t,i,r){let o=e.createShaderModule({label:"prefix scan",code:sf}),a=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]}),n=e.createPipelineLayout({bindGroupLayouts:[a]});this.scanPipeline=e.createComputePipeline({label:"scanBlocks",layout:n,compute:{module:o,entryPoint:"scanBlocks"}}),this.addPipeline=e.createComputePipeline({label:"addBlocks",layout:n,compute:{module:o,entryPoint:"addBlocks"}});let l=t,c=i,u=r;for(;;){let f=Math.max(1,Math.ceil(u/512)),d=e.createBuffer({label:`scan sums ${this.levels.length}`,size:Math.max(f,4)*4,usage:GPUBufferUsage.STORAGE}),h=e.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});new Uint32Array(h.getMappedRange()).set([c,u,0,0]),h.unmap(),this.buffers.push(d,h);let m=e.createBindGroup({layout:a,entries:[{binding:0,resource:{buffer:h}},{binding:1,resource:{buffer:l}},{binding:2,resource:{buffer:d}}]});if(this.levels.push({n:u,blocks:f,group:m}),f===1)break;l=d,c=0,u=f}}encode(e){e.setPipeline(this.scanPipeline);for(let t of this.levels)e.setBindGroup(0,t.group),e.dispatchWorkgroups(t.blocks);e.setPipeline(this.addPipeline);for(let t=this.levels.length-2;t>=0;t--)e.setBindGroup(0,this.levels[t].group),e.dispatchWorkgroups(this.levels[t].blocks)}destroy(){for(let e of this.buffers)e.destroy()}};var of=`
237
237
  alias TopoItem = Contact;
238
238
 
239
239
  fn topoCount() -> u32 {
@@ -532,7 +532,7 @@ fn colorScatter(@builtin(global_invocation_id) gid: vec3u, @builtin(workgroup_id
532
532
  let slot = atomicLoad(&color[params.colorHistOffset + col * params.colorGroups + wid.x]) + state(params.stateBOffset, b);
533
533
  atomicStore(&color[params.colorBodiesOffset + slot], b);
534
534
  }
535
- `,Qr=Ti(Ut,of);var af=jt(),zt=ae(),Vs=ae(),ji=ae(),Ga=ae(),cr=ae(),Fa=ae(),ft=ae(),Ws=ae(),Kr=ae(),ye=S(),ze=S(),ve=S(),li=S(),ur=S();function Ua(s,e,t){return Ce(s,-t[e],-t[e],-t[e]),s[e]+=t[0],s[3+e]+=t[1],s[6+e]+=t[2],s}var Hs=(s,e,t)=>ct(s,Bt(e[0],t),Bt(e[1],t),Bt(e[2],t)),ke=class extends Ft{rA;rB;C0Lin=S();C0Ang=S();penaltyLin=S();penaltyAng=S();lambdaLin=S();lambdaAng=S();stiffnessLin;stiffnessAng;fracture;torqueArm;broken=!1;constructor(e,t,i,r,o,a=1/0,n=0,l=1/0){super(e,t,i),this.rA=S(r[0],r[1],r[2]),this.rB=S(o[0],o[1],o[2]),this.stiffnessLin=a,this.stiffnessAng=n,this.fracture=l;let c=t?t.size:[0,0,0];this.torqueArm=Ne([c[0]+i.size[0],c[1]+i.size[1],c[2]+i.size[2]])}evaluateLin(e){let{bodyA:t,bodyB:i}=this;return t?Gt(li,t.positionLin,t.positionAng,this.rA):li.set(this.rA),J(e,li,Gt(ur,i.positionLin,i.positionAng,this.rB))}evaluateAng(e){return ut(e,this.bodyA?this.bodyA.positionAng:af,this.bodyB.positionAng),ne(e,e,this.torqueArm)}initialize(){let{solver:e}=this;this.evaluateLin(this.C0Lin),this.evaluateAng(this.C0Ang);for(let t=0;t<3;t++)this.lambdaLin[t]=this.lambdaLin[t]*e.alpha*e.gamma,this.lambdaAng[t]=this.lambdaAng[t]*e.alpha*e.gamma,this.penaltyLin[t]=ce(this.penaltyLin[t]*e.gamma,Et,Ve),this.penaltyAng[t]=ce(this.penaltyAng[t]*e.gamma,Et,Ve);return Hs(this.penaltyLin,this.penaltyLin,this.stiffnessLin),Hs(this.penaltyAng,this.penaltyAng,this.stiffnessAng),!this.broken}updatePrimal(e,t,i){let r=e===this.bodyA;if(Ne(this.penaltyLin)>0){Ce(zt,this.penaltyLin[0],this.penaltyLin[1],this.penaltyLin[2]),this.evaluateLin(ye),this.stiffnessLin===1/0&&D(ye,ye,this.C0Lin,-t),ue(ze,zt,ye),D(ze,ze,this.lambdaLin,1);let o=r?1:-1;Ce(Vs,o,o,o),r?ka(ji,ee(ve,le(ve,this.bodyA.positionAng,this.rA))):ka(ji,le(ve,this.bodyB.positionAng,this.rB)),_i(Ga,Vs),_i(cr,ji),Ke(Fa,cr,zt),qe(i.lhsLin,Ke(ft,Ke(ft,Ga,zt),Vs)),qe(i.lhsAng,Ke(ft,Fa,ji)),qe(i.lhsCross,Ke(ft,Fa,Vs)),r?le(ve,this.bodyA.positionAng,this.rA):ee(ve,le(ve,this.bodyB.positionAng,this.rB)),Ei(Ws,Ua(Kr,0,ve),ze[0]),qe(Ws,Ei(Kr,Ua(Kr,1,ve),ze[1])),qe(Ws,Ei(Kr,Ua(Kr,2,ve),ze[2])),qe(i.lhsAng,Kn(ft,Ws)),D(i.rhsLin,i.rhsLin,ue(ve,Ga,ze),1),D(i.rhsAng,i.rhsAng,ue(ve,cr,ze),1)}if(Ne(this.penaltyAng)>0){Ce(zt,this.penaltyAng[0],this.penaltyAng[1],this.penaltyAng[2]),this.evaluateAng(ye),this.stiffnessAng===1/0&&D(ye,ye,this.C0Ang,-t),ue(ze,zt,ye),D(ze,ze,this.lambdaAng,1);let o=(r?1:-1)*this.torqueArm;Ce(ji,o,o,o),_i(cr,ji),qe(i.lhsAng,Ke(ft,Ke(ft,cr,zt),ji)),D(i.rhsAng,i.rhsAng,ue(ve,cr,ze),1)}}updateDual(e){let{solver:t}=this;Ne(this.penaltyLin)>0&&(Ce(zt,this.penaltyLin[0],this.penaltyLin[1],this.penaltyLin[2]),this.evaluateLin(ye),this.stiffnessLin===1/0&&(D(ye,ye,this.C0Lin,-e),ue(ze,zt,ye),D(this.lambdaLin,ze,this.lambdaLin,1)),D(this.penaltyLin,this.penaltyLin,Ca(ve,ye),t.betaLin),Hs(this.penaltyLin,this.penaltyLin,Bt(this.stiffnessLin,Ve))),Ne(this.penaltyAng)>0&&(Ce(zt,this.penaltyAng[0],this.penaltyAng[1],this.penaltyAng[2]),this.evaluateAng(ye),this.stiffnessAng===1/0&&(D(ye,ye,this.C0Ang,-e),ue(ze,zt,ye),D(this.lambdaAng,ze,this.lambdaAng,1)),D(this.penaltyAng,this.penaltyAng,Ca(ve,ye),t.betaAng),Hs(this.penaltyAng,this.penaltyAng,Bt(this.stiffnessAng,Ve))),Ne(this.lambdaAng)>this.fracture*this.fracture&&(this.penaltyLin.fill(0),this.penaltyAng.fill(0),this.lambdaLin.fill(0),this.lambdaAng.fill(0),this.broken=!0)}},dt=class extends Ft{rA;rB;rest;stiffness;constructor(e,t,i,r,o,a,n=-1){super(e,t,i),this.rA=S(r[0],r[1],r[2]),this.rB=S(o[0],o[1],o[2]),this.stiffness=a,this.rest=n,this.rest<0&&(Gt(li,t.positionLin,t.positionAng,this.rA),Gt(ur,i.positionLin,i.positionAng,this.rB),this.rest=sr(J(ye,li,ur)))}initialize(){return!0}updatePrimal(e,t,i){let r=this.bodyA,o=this.bodyB;Gt(li,r.positionLin,r.positionAng,this.rA),Gt(ur,o.positionLin,o.positionAng,this.rB);let a=J(ye,li,ur),n=sr(a);if(n<=1e-6)return;let l=_t(ze,a,n),c=n-this.rest,u=this.stiffness*c,f=li,d=ur;e===r?(le(ve,r.positionAng,this.rA),f.set(l),Dt(d,ve,l)):(le(ve,o.positionAng,this.rB),ee(f,l),ee(d,Dt(d,ve,l))),qe(i.lhsLin,Ei(ft,Ms(ft,f,f),this.stiffness)),qe(i.lhsAng,Ei(ft,Ms(ft,d,d),this.stiffness)),qe(i.lhsCross,Ei(ft,Ms(ft,d,f),this.stiffness)),D(i.rhsLin,i.rhsLin,ne(ve,f,u),1),D(i.rhsAng,i.rhsAng,ne(ve,d,u),1)}updateDual(){}},$s=class extends Ft{initialize(){return!0}updatePrimal(){}updateDual(){}};var We=40,fr=0,Zr=4,Bl=8,Cl=12,Na=16,qa=20,Sl=24,kl=28,Va=32,Wa=36,pe=32,ci=0,es=4,dr=8,hr=12,Pl=16,Ll=20,ui=24,pr=28,Nt=8;var Js=4,Ht=16,mr=0,Xs=4,Ys=8,Qs=12,ts=2147483648,gr=6,nf=7,_l=0,Ha=1,$a=2,Ks=3,is=1,br=2,rs=1,ss=2,os=4,as=8,ns=16,lf=.1,El=.002,Ml=.002,cf=.05,ls=44,ge=`
535
+ `,Qr=Ti(Ut,of);var af=jt(),zt=ae(),Vs=ae(),ji=ae(),Ga=ae(),cr=ae(),Fa=ae(),ft=ae(),Ws=ae(),Kr=ae(),ye=S(),ze=S(),ve=S(),li=S(),ur=S();function Ua(s,e,t){return Ce(s,-t[e],-t[e],-t[e]),s[e]+=t[0],s[3+e]+=t[1],s[6+e]+=t[2],s}var Hs=(s,e,t)=>ct(s,Bt(e[0],t),Bt(e[1],t),Bt(e[2],t)),ke=class extends Ft{rA;rB;C0Lin=S();C0Ang=S();penaltyLin=S();penaltyAng=S();lambdaLin=S();lambdaAng=S();stiffnessLin;stiffnessAng;fracture;torqueArm;broken=!1;constructor(e,t,i,r,o,a=1/0,n=0,l=1/0){super(e,t,i),this.rA=S(r[0],r[1],r[2]),this.rB=S(o[0],o[1],o[2]),this.stiffnessLin=a,this.stiffnessAng=n,this.fracture=l;let c=t?t.size:[0,0,0];this.torqueArm=qe([c[0]+i.size[0],c[1]+i.size[1],c[2]+i.size[2]])}evaluateLin(e){let{bodyA:t,bodyB:i}=this;return t?Gt(li,t.positionLin,t.positionAng,this.rA):li.set(this.rA),J(e,li,Gt(ur,i.positionLin,i.positionAng,this.rB))}evaluateAng(e){return ut(e,this.bodyA?this.bodyA.positionAng:af,this.bodyB.positionAng),ne(e,e,this.torqueArm)}initialize(){let{solver:e}=this;this.evaluateLin(this.C0Lin),this.evaluateAng(this.C0Ang);for(let t=0;t<3;t++)this.lambdaLin[t]=this.lambdaLin[t]*e.alpha*e.gamma,this.lambdaAng[t]=this.lambdaAng[t]*e.alpha*e.gamma,this.penaltyLin[t]=ce(this.penaltyLin[t]*e.gamma,Et,We),this.penaltyAng[t]=ce(this.penaltyAng[t]*e.gamma,Et,We);return Hs(this.penaltyLin,this.penaltyLin,this.stiffnessLin),Hs(this.penaltyAng,this.penaltyAng,this.stiffnessAng),!this.broken}updatePrimal(e,t,i){let r=e===this.bodyA;if(qe(this.penaltyLin)>0){Ce(zt,this.penaltyLin[0],this.penaltyLin[1],this.penaltyLin[2]),this.evaluateLin(ye),this.stiffnessLin===1/0&&D(ye,ye,this.C0Lin,-t),ue(ze,zt,ye),D(ze,ze,this.lambdaLin,1);let o=r?1:-1;Ce(Vs,o,o,o),r?ka(ji,ee(ve,le(ve,this.bodyA.positionAng,this.rA))):ka(ji,le(ve,this.bodyB.positionAng,this.rB)),_i(Ga,Vs),_i(cr,ji),Ke(Fa,cr,zt),Ve(i.lhsLin,Ke(ft,Ke(ft,Ga,zt),Vs)),Ve(i.lhsAng,Ke(ft,Fa,ji)),Ve(i.lhsCross,Ke(ft,Fa,Vs)),r?le(ve,this.bodyA.positionAng,this.rA):ee(ve,le(ve,this.bodyB.positionAng,this.rB)),Ei(Ws,Ua(Kr,0,ve),ze[0]),Ve(Ws,Ei(Kr,Ua(Kr,1,ve),ze[1])),Ve(Ws,Ei(Kr,Ua(Kr,2,ve),ze[2])),Ve(i.lhsAng,Kn(ft,Ws)),D(i.rhsLin,i.rhsLin,ue(ve,Ga,ze),1),D(i.rhsAng,i.rhsAng,ue(ve,cr,ze),1)}if(qe(this.penaltyAng)>0){Ce(zt,this.penaltyAng[0],this.penaltyAng[1],this.penaltyAng[2]),this.evaluateAng(ye),this.stiffnessAng===1/0&&D(ye,ye,this.C0Ang,-t),ue(ze,zt,ye),D(ze,ze,this.lambdaAng,1);let o=(r?1:-1)*this.torqueArm;Ce(ji,o,o,o),_i(cr,ji),Ve(i.lhsAng,Ke(ft,Ke(ft,cr,zt),ji)),D(i.rhsAng,i.rhsAng,ue(ve,cr,ze),1)}}updateDual(e){let{solver:t}=this;qe(this.penaltyLin)>0&&(Ce(zt,this.penaltyLin[0],this.penaltyLin[1],this.penaltyLin[2]),this.evaluateLin(ye),this.stiffnessLin===1/0&&(D(ye,ye,this.C0Lin,-e),ue(ze,zt,ye),D(this.lambdaLin,ze,this.lambdaLin,1)),D(this.penaltyLin,this.penaltyLin,Ca(ve,ye),t.betaLin),Hs(this.penaltyLin,this.penaltyLin,Bt(this.stiffnessLin,We))),qe(this.penaltyAng)>0&&(Ce(zt,this.penaltyAng[0],this.penaltyAng[1],this.penaltyAng[2]),this.evaluateAng(ye),this.stiffnessAng===1/0&&(D(ye,ye,this.C0Ang,-e),ue(ze,zt,ye),D(this.lambdaAng,ze,this.lambdaAng,1)),D(this.penaltyAng,this.penaltyAng,Ca(ve,ye),t.betaAng),Hs(this.penaltyAng,this.penaltyAng,Bt(this.stiffnessAng,We))),qe(this.lambdaAng)>this.fracture*this.fracture&&(this.penaltyLin.fill(0),this.penaltyAng.fill(0),this.lambdaLin.fill(0),this.lambdaAng.fill(0),this.broken=!0)}},dt=class extends Ft{rA;rB;rest;stiffness;constructor(e,t,i,r,o,a,n=-1){super(e,t,i),this.rA=S(r[0],r[1],r[2]),this.rB=S(o[0],o[1],o[2]),this.stiffness=a,this.rest=n,this.rest<0&&(Gt(li,t.positionLin,t.positionAng,this.rA),Gt(ur,i.positionLin,i.positionAng,this.rB),this.rest=sr(J(ye,li,ur)))}initialize(){return!0}updatePrimal(e,t,i){let r=this.bodyA,o=this.bodyB;Gt(li,r.positionLin,r.positionAng,this.rA),Gt(ur,o.positionLin,o.positionAng,this.rB);let a=J(ye,li,ur),n=sr(a);if(n<=1e-6)return;let l=_t(ze,a,n),c=n-this.rest,u=this.stiffness*c,f=li,d=ur;e===r?(le(ve,r.positionAng,this.rA),f.set(l),Dt(d,ve,l)):(le(ve,o.positionAng,this.rB),ee(f,l),ee(d,Dt(d,ve,l))),Ve(i.lhsLin,Ei(ft,Ms(ft,f,f),this.stiffness)),Ve(i.lhsAng,Ei(ft,Ms(ft,d,d),this.stiffness)),Ve(i.lhsCross,Ei(ft,Ms(ft,d,f),this.stiffness)),D(i.rhsLin,i.rhsLin,ne(ve,f,u),1),D(i.rhsAng,i.rhsAng,ne(ve,d,u),1)}updateDual(){}},$s=class extends Ft{initialize(){return!0}updatePrimal(){}updateDual(){}};var He=40,fr=0,Zr=4,Bl=8,Cl=12,Na=16,qa=20,Sl=24,kl=28,Va=32,Wa=36,he=32,ci=0,es=4,dr=8,pr=12,Pl=16,Ll=20,ui=24,hr=28,Nt=8;var Js=4,Ht=16,mr=0,Xs=4,Ys=8,Qs=12,ts=2147483648,gr=6,nf=7,_l=0,Ha=1,$a=2,Ks=3,is=1,br=2,rs=1,ss=2,os=4,as=8,ns=16,lf=.1,El=.002,Ml=.002,cf=.05,ls=44,ge=`
536
536
  // Shared by every 3D module (avbd3d/gpu/layout.ts)
537
537
  ${Da}
538
538
  const T_JOINT = ${is};
@@ -2418,7 +2418,7 @@ fn updateVelocities(@builtin(global_invocation_id) gid: vec3u) {
2418
2418
  bodies[i].vel.w = prevUp;
2419
2419
  }
2420
2420
  }
2421
- `;function to(s,e){let t=0,i=s.length-1;for(;t<i;){let r=s[e],o=t,a=i;do{for(;s[o]<r;)o++;for(;r<s[a];)a--;if(o<=a){let n=s[o];s[o]=s[a],s[a]=n,o++,a--}}while(o<=a);a<e&&(t=o),e<o&&(i=a)}return s[e]}function Xa(s){let e=s.length,t=e>0?to(s,e>>1):1,i=0;for(let r=0;r<e;r++)s[r]<=2*t&&(i=Math.max(i,s[r]));return e>64&&(i=Math.max(i,to(s,e-64-1))),i}var $t=s=>s===1/0?3e38:s===-1/0?-3e38:s,ht=s=>Math.ceil(s/64),Tl=s=>2**Math.ceil(Math.log2(Math.max(s,2))),uf=s=>Math.max(s,1)*We*4,ff=8,io=3,df=8,hf=1.6,pf=.8,mf=2,gf=[0,0,1],bf=()=>({...Oa(),matchNearest:!0,faceBias:!0,reuseContacts:!0,startAtRest:!0,massPenalty:!0,windSpeed:0,windAngle:0,windGust:.4,windPressure:.72,up:[0,1,0]});function yf(s,e){let t=s.vertices.length/3,i=s.faces.length,r=s.faces.reduce((m,h)=>m+h.verts.length,0),o=Math.ceil(r/4),a=s.edges.length,n=new Float32Array((2+t+2*i+o+a)*4),l=new Uint32Array(n.buffer),c=e+2,u=c+t,f=u+2*i,d=f+o;l.set([c,t,u,i,d,a,f,0],0);for(let m=0;m<t;m++)n.set(s.vertices.subarray(m*3,m*3+3),(2+m)*4);let p=0;return s.faces.forEach((m,h)=>{let g=(2+t+2*h)*4;n.set(m.normal,g),n[g+3]=m.d,l[g+4]=p,l[g+5]=m.verts.length;for(let b of m.verts)l[(2+t+2*i)*4+p++]=b}),s.edges.forEach((m,h)=>l.set(m,(2+t+2*i+o+h)*4)),n}var Ya=.001;function vf(s,e){let t=s.length,i=s.map(y=>{let A=y;return[A.group??4294967295,A.collidesWith??4294967295]}),r=i.map(([y,A])=>y!==0&&A!==0),o=s.map(y=>[0,1,2].map(A=>{let v=[0,0,0];return v[A]=1,le(S(),y.positionAng,v)})),a=s.map((y,A)=>{if(De(y))return[y.radius,y.radius,y.radius];let v=[0,0,0];for(let x=0;x<3;x++)for(let w=0;w<3;w++)v[w]+=y.size[x]*.5*Math.abs(o[A][x][w]);return v}),n=Xa(Float64Array.from(s,y=>y.radius)),l=Math.max(2*n,.001),c=(y,A)=>{let v=s[y],x=s[A];if(v.mass<=0&&x.mass<=0||!(i[y][0]&i[A][1])||!(i[A][0]&i[y][1]))return!1;let w=v.positionLin[0]-x.positionLin[0],B=v.positionLin[1]-x.positionLin[1],L=v.positionLin[2]-x.positionLin[2];if(!(Math.abs(w)<=a[y][0]+a[A][0]&&Math.abs(B)<=a[y][1]+a[A][1]&&Math.abs(L)<=a[y][2]+a[A][2]))return!1;let M=v.radius+x.radius;return w*w+B*B+L*L<=M*M},u=(y,A)=>y[0]*A[0]+y[1]*A[1]+y[2]*A[2],f=(y,A)=>{let v=s[y],x=s[A],w=[0,1,2].map(E=>x.positionLin[E]-v.positionLin[E]),[B,L]=[De(v),De(x)];if(B&&L)return Math.hypot(w[0],w[1],w[2])<=v.radius+x.radius+Ya;if(B||L){let[E,k,P]=B?[A,v.radius,-1]:[y,x.radius,1],C=0;for(let _=0;_<3;_++){let z=Math.abs(P*u(w,o[E][_]))-s[E].size[_]*.5;z>0&&(C+=z*z)}return C<=(k+Ya)**2}let M=(E,k)=>s[E].size[0]*.5*Math.abs(u(o[E][0],k))+s[E].size[1]*.5*Math.abs(u(o[E][1],k))+s[E].size[2]*.5*Math.abs(u(o[E][2],k)),I=E=>{let k=Math.hypot(E[0],E[1],E[2]);return k<1e-6?!1:Math.abs(u(w,E))-M(y,E)-M(A,E)>Ya*k};for(let E=0;E<3;E++)if(I(o[y][E])||I(o[A][E]))return!1;for(let E of o[y])for(let k of o[A])if(I([E[1]*k[2]-E[2]*k[1],E[2]*k[0]-E[0]*k[2],E[0]*k[1]-E[1]*k[0]]))return!1;return!0},d=new Set,p=new Map,m=(y,A,v)=>(y*73856093^A*19349663^v*83492791)>>>0,h=y=>[0,1,2].map(A=>Math.floor(s[y].positionLin[A]/l));for(let y=0;y<t;y++){if(!r[y])continue;if(s[y].radius>n){d.add(y);continue}let[A,v,x]=h(y),w=m(A,v,x),B=p.get(w);B?B.push(y):p.set(w,[y])}let g=0,b=0;for(let y=0;y<t;y++){if(!r[y]||d.has(y))continue;let[A,v,x]=h(y);for(let w=-1;w<=1;w++)for(let B=-1;B<=1;B++)for(let L=-1;L<=1;L++)for(let M of p.get(m(A+L,v+B,x+w))??[])M<y&&c(y,M)&&(g++,f(y,M)&&(b++,e[y]++,e[M]++))}for(let y of d)for(let A=0;A<t;A++)r[A]&&A!==y&&(!d.has(A)||A<y)&&c(y,A)&&(g++,f(y,A)&&(b++,e[y]++,e[A]++));return{pairs:g,touching:b}}function xf(s){let e=[1/0,1/0,1/0],t=[-1/0,-1/0,-1/0];for(let o of s)for(let a=0;a<3;a++)e[a]=Math.min(e[a],o.positionLin[a]),t[a]=Math.max(t[a],o.positionLin[a]);let i=o=>{let a=o&1023;return a=(a|a<<16)&50331903,a=(a|a<<8)&50393103,a=(a|a<<4)&51130563,a=(a|a<<2)&153391689,a},r=s.map(o=>{let a=[0,1,2].map(n=>Math.min(1023,Math.floor((o.positionLin[n]-e[n])/Math.max(t[n]-e[n],1e-9)*1024)));return(i(a[0])|i(a[1])<<1|i(a[2])<<2)>>>0});return s.map((o,a)=>a).sort((o,a)=>r[o]-r[a]||o-a)}var Pe=()=>GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST,ro=class{device;params=bf();bodyCount=0;bodyCapacity;bodies=[];hulls;hullBuffer;get hullStorage(){return this.hullBuffer}hullCapacity=4096;hullTop=0;hullSlots=new Map;contactShaders;hullShaders=!1;hullFree=[];refToGpu;jointCount=0;jointCapacity=0;info=new Int32Array(0);pairCapacity=0;manifoldCapacity=0;contactCapacity=0;colorCap=12;fixedColors=null;primalLanes=[2**31,2**15,2**12];splitPasses=!1;shrinkVotes=0;colorRounds;get colorHistOffset(){return 3*this.bodyCapacity+65}bodyBuffer;ownsBodyBuffer;jointBuffer;infoBuffer;contactBuffers;manifoldBuffers;pairBuffer;tableBuffer;gridBuffer;staticBuffer=null;filterBuffer;get filterStorage(){return this.filterBuffer}counterBuffer;get contactStorage(){let e=1-this.parity;return{manifolds:this.manifoldBuffers[e],contacts:this.contactBuffers[e],counters:this.counterBuffer}}argsBuffer;adjBuffer=null;colorBuffer;paramsBuffer;refBuffer;stepCount=0;passBuffer=null;passEntries=0;parity=0;tableSize;hashSize=0;cellSize=1;maxSmallRadius=0;largeCount=0;noCollideCount=0;radiiDirty=!0;noCollideDirty=!0;large=[];entries=[];pendingEntries=[];releasedSlots=new Set;freeSlots=[];layouts;pipes={};groups;passGroup=null;gridScan;colorHistScan;colorGroups;adjScan=null;timing;timingCallback=null;timingBusy=!1;destroyed=!1;constructor(e,t,i={}){this.device=e;let{dt:r,gravity:o,iterations:a,alpha:n,betaLin:l,betaAng:c,gamma:u}=t;if(Object.assign(this.params,{dt:r,gravity:o,iterations:a,alpha:n,betaLin:l,betaAng:c,gamma:u,up:gf}),this.bodyCount=t.bodies.length,this.colorRounds=i.colorRounds??16,this.ownsBodyBuffer=!i.bodyBuffer,this.bodyCapacity=i.bodyBuffer?Math.floor(i.bodyBuffer.size/(We*4)):Math.max(i.bodyCapacity??this.bodyCount+1024,this.bodyCount,1),this.bodyCapacity<this.bodyCount)throw new Error("body buffer too small");this.bodyBuffer=i.bodyBuffer??e.createBuffer({label:"bodies 3d",size:uf(this.bodyCapacity),usage:Pe()}),this.filterBuffer=e.createBuffer({label:"collision filters",size:Math.max(this.bodyCapacity,1)*8,usage:Pe()}),e.queue.writeBuffer(this.filterBuffer,0,new Uint32Array(Math.max(this.bodyCapacity,1)*2).fill(4294967295));let f=this.bodyCapacity;this.tableSize=Tl(2*f),this.gridBuffer=e.createBuffer({label:"grid 3d",size:(2*this.tableSize+1+4*f)*4,usage:Pe()}),this.counterBuffer=e.createBuffer({label:"counters",size:64,usage:Pe()}),this.argsBuffer=e.createBuffer({label:"indirect args",size:816,usage:Pe()|GPUBufferUsage.INDIRECT}),this.colorGroups=Math.ceil(f/256),this.colorBuffer=e.createBuffer({label:"colours",size:(3*f+65+64*this.colorGroups+1)*4,usage:Pe()}),this.paramsBuffer=e.createBuffer({label:"params 3d",size:ls*4,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.refBuffer=e.createBuffer({label:"reference poses",size:f*32,usage:Pe()}),this.hulls=(i.hulls??!0)&&e.limits.maxStorageBuffersPerShaderStage>=9,this.hullBuffer=e.createBuffer({label:"hulls",size:this.hullCapacity*16,usage:Pe()}),e.queue.writeBuffer(this.colorBuffer,0,new Uint32Array(f).fill(255));let d=2*Se.length;this.timing=e.features.has("timestamp-query")?{querySet:e.createQuerySet({type:"timestamp",count:d}),resolve:e.createBuffer({size:d*8,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),read:e.createBuffer({size:d*8,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST})}:null,this.layouts=this.createLayouts(),this.createPipelines(i.shaders??{}),this.gridScan=new tt(e,this.gridBuffer,0,this.tableSize+1),this.colorHistScan=new tt(e,this.colorBuffer,this.colorHistOffset,64*this.colorGroups+1);let p=i.spatialSort===!1?t.bodies.map((w,B)=>B):xf(t.bodies);this.refToGpu=new Int32Array(p.length),p.forEach((w,B)=>this.refToGpu[w]=B);let m=new Map(t.bodies.map((w,B)=>[w,this.refToGpu[B]])),h=t.forces.filter(w=>w instanceof ke||w instanceof dt);for(let w of t.forces){if(!(w instanceof $s))continue;let B=m.get(w.bodyA),L=m.get(w.bodyB);this.pendingEntries.push([Math.max(B,L),Math.min(B,L),4294967295])}this.allocateJoints(Math.max(h.length+256,i.capacity?.joints??0));for(let w of h)this.writeJoint(this.jointCount++,w,m);let g=new Int32Array(t.bodies.length),{pairs:b,touching:y}=vf(t.bodies,g),A=new Map(t.bodies.map((w,B)=>[w,B]));for(let w of h)w.bodyA&&g[A.get(w.bodyA)]++,g[A.get(w.bodyB)]++;let v=0;t.bodies.forEach((w,B)=>{w.mass>0&&(v=Math.max(v,g[B]))}),this.colorCap=Math.min(64,Math.max(df,v+1+io,i.capacity?.colors??0));let x=i.capacity??{};this.allocateContacts(Math.max(8192,4*f,ff*y,x.contacts??0),Math.max(4096,4*f,2*b,x.pairs??0),Math.max(4096,f,hf*y,x.manifolds??0)),this.writeBodies(0,p.map(w=>t.bodies[w]))}gpuIndex(e){return e<this.refToGpu.length?this.refToGpu[e]:e}createLayouts(){let e=this.device,t=(a,n)=>e.createBindGroupLayout({label:a,entries:n.map((l,c)=>({binding:c,visibility:GPUShaderStage.COMPUTE,buffer:{type:l}}))}),i="read-only-storage",r="storage",o="uniform";return{broad:t("broadphase 3d",[o,i,r,r,r,i,i,i]),contacts:t("contacts 3d",[o,i,i,r,i,r,i,r,r,...this.hulls?[i]:[]]),topo:t("topology 3d",[o,i,i,i,i,r,r,r]),solve:t("solve 3d",[o,r,r,i,r,i,i,i,i]),pass:e.createBindGroupLayout({label:"pass",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform",hasDynamicOffset:!0,minBindingSize:16}}]}),args:t("args 3d",[o,i,i,r]),refs:t("refs 3d",[o,r,r])}}createPipelines(e){let t=this.device,i=(o,a,n)=>{let l=t.createShaderModule({code:o}),c=t.createPipelineLayout({bindGroupLayouts:a});for(let u of n)this.pipes[u]=t.createComputePipeline({label:u,layout:c,compute:{module:l,entryPoint:u}})},r=this.layouts;i(fi,[r.broad],["beginFrame","gridCount","gridScatter","findPairs"]),i(e.refs??eo,[r.refs],["updateRefs"]),i(e.contacts??Il,[r.contacts],["hashInsert","narrowphase"]),this.contactShaders={make:o=>i(o,[r.contacts],["hashInsert","narrowphase"]),custom:!!e.contacts},i(e.topology??Ti(ge,yr),[r.topo],["degreeJoints","degreeContacts","fillJoints","fillContacts","sortAdjacency","colorCompact","colorMark","colorRoundAB","colorRoundBA","colorCount","colorStarts","colorScatter"]),i(e.solve??Ge,[r.solve,r.pass],["warmStartJoints","warmStartBodies","primal","dual","updateVelocities"]),i(Yr(ge,Zs),[r.args],["argsPrev","argsPairs","argsContacts","argsColors"])}allocateJoints(e){let t=this.device,i=t.createBuffer({label:"joints 3d",size:Math.max(e,1)*pe*4,usage:Pe()}),r=t.createBuffer({label:"joint info",size:Math.max(e,1)*16,usage:Pe()});if(this.jointBuffer){let a=t.createCommandEncoder();a.copyBufferToBuffer(this.jointBuffer,0,i,0,this.jointCapacity*pe*4),a.copyBufferToBuffer(this.infoBuffer,0,r,0,this.jointCapacity*16),t.queue.submit([a.finish()]),this.jointBuffer.destroy(),this.infoBuffer.destroy()}let o=new Int32Array(e*4);o.set(this.info.subarray(0,Math.min(this.info.length,o.length))),this.info=o,this.jointBuffer=i,this.infoBuffer=r,this.jointCapacity=e,this.contactBuffers&&this.rebuildBindings()}allocateContacts(e,t,i){let r=this.device,o=r.limits.maxStorageBufferBindingSize,a=Math.min(Math.ceil(e),Math.floor(o/(Ht*4))),n=Math.min(Math.ceil(t),Math.floor(o/8)),l=Math.min(Math.ceil(i),n,Math.floor(o/(Nt*4))),c={contacts:this.contactBuffers,manifolds:this.manifoldBuffers,contactCapacity:this.contactCapacity,manifoldCapacity:this.manifoldCapacity};for(let u of[this.pairBuffer,this.tableBuffer])u?.destroy();if(this.contactCapacity=a,this.pairCapacity=n,this.manifoldCapacity=l,this.hashSize=Tl(2*l),this.pairBuffer=r.createBuffer({label:"pairs",size:n*8,usage:Pe()}),this.tableBuffer=r.createBuffer({label:"manifold hash",size:this.hashSize*4,usage:Pe()}),this.contactBuffers=[0,1].map(u=>r.createBuffer({label:`contacts 3d ${u}`,size:a*Ht*4,usage:Pe()})),this.manifoldBuffers=[0,1].map(u=>r.createBuffer({label:`manifolds 3d ${u}`,size:l*Nt*4,usage:Pe()})),c.contacts){let u=r.createCommandEncoder(),f=Math.min(c.contactCapacity,a)*Ht*4,d=Math.min(c.manifoldCapacity,l)*Nt*4;c.contacts.forEach((p,m)=>u.copyBufferToBuffer(p,0,this.contactBuffers[m],0,f)),c.manifolds.forEach((p,m)=>u.copyBufferToBuffer(p,0,this.manifoldBuffers[m],0,d)),r.queue.submit([u.finish()]),[...c.contacts,...c.manifolds].forEach(p=>p.destroy())}this.rebuildBindings()}rebuildBindings(){let e=this.device,t=this.bodyCapacity;this.adjBuffer?.destroy(),this.adjBuffer=e.createBuffer({label:"adjacency",size:(2*t+1+2*(this.jointCapacity+this.manifoldCapacity))*4,usage:Pe()}),this.adjScan?.destroy(),this.adjScan=new tt(e,this.adjBuffer,0,this.bodyCount+1),this.staticBuffer??=e.createBuffer({label:"statics",size:16,usage:Pe()});let i=(d,p)=>e.createBindGroup({layout:d,entries:p.map((m,h)=>({binding:h,resource:{buffer:m}}))}),r=this.paramsBuffer,[o,a]=this.contactBuffers,[n,l]=this.manifoldBuffers,c=this.adjBuffer,u=this.tableBuffer,f=this.counterBuffer;this.groups={broad:i(this.layouts.broad,[r,this.bodyBuffer,this.gridBuffer,this.pairBuffer,f,this.staticBuffer,this.jointBuffer,this.filterBuffer]),contacts:[i(this.layouts.contacts,[r,this.bodyBuffer,this.pairBuffer,o,a,n,l,u,f,...this.hulls?[this.hullBuffer]:[]]),i(this.layouts.contacts,[r,this.bodyBuffer,this.pairBuffer,a,o,l,n,u,f,...this.hulls?[this.hullBuffer]:[]])],topo:[n,l].map(d=>i(this.layouts.topo,[r,this.bodyBuffer,this.jointBuffer,this.infoBuffer,d,f,c,this.colorBuffer])),solve:[0,1].map(d=>i(this.layouts.solve,[r,this.bodyBuffer,this.jointBuffer,this.infoBuffer,[o,a][d],c,this.colorBuffer,f,[n,l][d]])),args:i(this.layouts.args,[r,this.counterBuffer,this.colorBuffer,this.argsBuffer]),refs:i(this.layouts.refs,[r,this.bodyBuffer,this.refBuffer])}}writeBodies(e,t){let i=new Float32Array(Math.max(t.length,1)*We);t.forEach((r,o)=>{let a=this.pack(r,i,o*We,this.bodies[e+o]?.hull);this.bodies[e+o]?.radius!==a.radius&&(this.radiiDirty=!0),this.bodies[e+o]=a}),this.device.queue.writeBuffer(this.bodyBuffer,e*We*4,i,0,t.length*We)}rewriteFixed(e,t,i,r,o){if(!e.length)return;let a=new Float32Array(We),n={positionLin:[0,0,0],positionAng:[0,0,0,1],initialLin:[0,0,0],initialAng:[0,0,0,1],inertialLin:[0,0,0],inertialAng:[0,0,0,1],velocityLin:[0,0,0],prevVelocityLin:[0,0,0],velocityAng:[0,0,0],size:[i[0],i[1],i[2]],mass:0,moment:[0,0,0],friction:r,radius:Math.hypot(i[0]/2,i[1]/2,i[2]/2)},l=this.pack(n,a,0);for(let c=0;c<e.length;){let u=c+1;for(;u<e.length&&e[u]===e[u-1]+1;)u++;let f=new Float32Array((u-c)*We);for(let d=c;d<u;d++){let p=(d-c)*We;f.set(a,p);for(let h=0;h<3;h++)f[p+fr+h]=t[3*d+h];if(o)for(let h=0;h<4;h++)f[p+Zr+h]=o[4*d+h];let m=this.bodies[e[d]];m?.radius!==l.radius&&(this.radiiDirty=!0),m?.hull&&this.releaseHull(m.hull),this.bodies[e[d]]={...l,size:[...l.size]}}this.device.queue.writeBuffer(this.bodyBuffer,e[c]*We*4,f),this.device.queue.writeBuffer(this.colorBuffer,e[c]*4,new Uint32Array(u-c).fill(255)),c=u}}pack(e,t,i,r){{t.set(e.positionLin,i+fr),t[i+fr+3]=e.friction,t.set(e.positionAng,i+Zr),t.set(e.size,i+Na),t[i+Na+3]=e.mass,t.set(e.moment,i+qa),t[i+qa+3]=e.radius,t.set(e.initialLin,i+Bl),t.set(e.initialAng,i+Cl),t.set(e.inertialLin,i+Sl),t.set(e.inertialAng,i+kl),t.set(e.velocityLin,i+Va);let o=this.params.up;t[i+Va+3]=e.prevVelocityLin[0]*o[0]+e.prevVelocityLin[1]*o[1]+e.prevVelocityLin[2]*o[2],t.set(e.velocityAng,i+Wa);let a=De(e),n=this.hulls?Ct(e):void 0;r&&r!==n&&this.releaseHull(r);let l=n?r===n?this.hullSlots.get(n).offset:this.acquireHull(n):-1;return t[i+Wa+3]=a?Ha:l>=0?Ks+l:ar(e)?$a:_l,{radius:e.radius,dynamic:e.mass>0,sphere:a,size:[e.size[0],e.size[1],e.size[2]],hull:n}}}writeJoint(e,t,i){let r=new Float32Array(pe),o=t.bodyA?i.get(t.bodyA):-1,a=i.get(t.bodyB);t instanceof ke?(r.set(t.penaltyLin,ci),r[ci+3]=$t(t.broken?0:t.stiffnessLin),r.set(t.penaltyAng,es),r[es+3]=$t(t.broken?0:t.stiffnessAng),r.set(t.lambdaLin,dr),r[dr+3]=$t(t.fracture),r.set(t.lambdaAng,hr),r[hr+3]=t.torqueArm,r.set(t.C0Lin,Pl),r.set(t.C0Ang,Ll),r.set(t.rA,ui),r.set(t.rB,pr)):(r[ci+3]=t.stiffness,r.set(t.rA,ui),r[ui+3]=t.rest,r.set(t.rB,pr)),this.info.set([t instanceof ke?is:br,o,a,0],e*4),this.device.queue.writeBuffer(this.jointBuffer,e*pe*4,r),this.device.queue.writeBuffer(this.infoBuffer,e*16,this.info,e*4,4),this.noCollide(o,a,e)}noCollide(e,t,i){e<0||(this.pendingEntries.push([Math.max(e,t),Math.min(e,t),i]),this.noCollideDirty=!0)}uploadStatics(){if(this.radiiDirty){let r=this.bodyCount,o=new Float64Array(r);for(let c=0;c<r;c++)o[c]=this.bodies[c].radius;let a=Xa(o),n=1/0;for(let c=0;c<r;c++)o[c]>a&&(n=Math.min(n,o[c]));let l=n===1/0?a*1.5:(a+n)/2;this.maxSmallRadius=l,this.cellSize=Math.max(2*a*(1+1e-4),.001),this.large=[];for(let c=0;c<r;c++)this.bodies[c].radius>l&&this.large.push(c);this.radiiDirty=!1}if(this.noCollideDirty){let r=(l,c)=>l[0]-c[0]||l[1]-c[1],o=this.releasedSlots.size?this.entries.filter(l=>!this.releasedSlots.has(l[2])):this.entries;this.releasedSlots.clear();let a=this.pendingEntries.sort(r);this.pendingEntries=[];let n=[];for(let l=0,c=0;l<o.length||c<a.length;)c>=a.length||l<o.length&&r(o[l],a[c])<=0?n.push(o[l++]):n.push(a[c++]);this.entries=n,this.noCollideDirty=!1}let{large:e,entries:t}=this;this.largeCount=e.length,this.noCollideCount=t.length;let i=new Uint32Array(Math.max(e.length+3*t.length,4));i.set(e,0),t.forEach((r,o)=>i.set(r,e.length+3*o)),this.staticBuffer.size<i.byteLength&&(this.staticBuffer.destroy(),this.staticBuffer=this.device.createBuffer({label:"statics",size:i.byteLength,usage:Pe()}),this.rebuildBindings()),this.device.queue.writeBuffer(this.staticBuffer,0,i)}seedFrom(e){if(this.refToGpu.some((m,h)=>m!==h))throw new Error("seedFrom needs spatialSort: false");let t=new Map(e.bodies.map((m,h)=>[m,h]));this.writeBodies(0,e.bodies);let i=0;for(let m of e.forces)(m instanceof ke||m instanceof dt)&&this.writeJoint(i++,m,t);if(i!==this.jointCount)throw new Error("seedFrom: joints differ from the reference");let r=e.forces.filter(m=>m instanceof ai),o=r.reduce((m,h)=>m+h.contacts.length,0);if(o>this.contactCapacity||r.length>this.manifoldCapacity)throw new Error("seedFrom: too many contacts");let a=new ArrayBuffer(Math.max(o,1)*Ht*4),n=new Uint32Array(a),l=new Float32Array(a),c=new ArrayBuffer(Math.max(r.length,1)*Nt*4),u=new Uint32Array(c),f=new Float32Array(c),d=0;r.forEach((m,h)=>{u.set([t.get(m.bodyA),t.get(m.bodyB),d,m.contacts.length],h*Nt),f.set([m.basis[0],m.basis[1],m.basis[2],m.friction],h*Nt+Js);for(let g of m.contacts){let b=d++*Ht;l.set(g.rA,b+mr),n[b+mr+3]=g.feature>>>0|(g.stick?ts:0),l.set([...g.rB,g.C0[0]],b+Xs),l.set([...g.penalty,g.C0[1]],b+Ys),l.set([...g.lambda,g.C0[2]],b+Qs)}}),this.device.queue.writeBuffer(this.contactBuffers[1-this.parity],0,a),this.device.queue.writeBuffer(this.manifoldBuffers[1-this.parity],0,c);let p=new Uint32Array(16);p[1]=o,p[gr]=r.length,this.device.queue.writeBuffer(this.counterBuffer,0,p)}sequentialColors(){let e=new Uint32Array(this.bodyCount).fill(255),t=0;for(let i=this.bodyCount-1;i>=0;i--)this.bodies[i].dynamic&&(e[i]=t++);if(t>64)throw new Error(`sequentialColors: ${t} dynamic bodies, at most ${64}`);return e}acquireHull(e){!this.hullShaders&&!this.contactShaders.custom&&(this.contactShaders.make(Rl),this.hullShaders=!0);let t=this.hullSlots.get(e);if(t)return t.refs++,t.offset;let i=2+e.vertices.length/3+2*e.faces.length+Math.ceil(e.faces.reduce((a,n)=>a+n.verts.length,0)/4)+e.edges.length,r=-1,o=this.hullFree.findIndex(a=>a.size>=i);if(o>=0){let a=this.hullFree[o];r=a.offset,a.size===i?this.hullFree.splice(o,1):Object.assign(a,{offset:a.offset+i,size:a.size-i})}else r=this.hullTop,this.hullTop+=i,this.hullTop>this.hullCapacity&&this.growHulls(this.hullTop);if(r+Ks>=2**24)throw new Error("hull buffer beyond 2^24 vec4s");return this.device.queue.writeBuffer(this.hullBuffer,r*16,yf(e,r)),this.hullSlots.set(e,{offset:r,size:i,refs:1}),r}releaseHull(e){let t=this.hullSlots.get(e);if(!t||--t.refs>0)return;this.hullSlots.delete(e),this.hullFree.push({offset:t.offset,size:t.size}),this.hullFree.sort((r,o)=>r.offset-o.offset);let i=[];for(let r of this.hullFree){let o=i[i.length-1];o&&o.offset+o.size===r.offset?o.size+=r.size:i.push({...r})}this.hullFree=i}growHulls(e){let t=this.hullCapacity;for(;t<e;)t*=2;let i=this.device.createBuffer({label:"hulls",size:t*16,usage:Pe()}),r=this.device.createCommandEncoder();r.copyBufferToBuffer(this.hullBuffer,0,i,0,this.hullCapacity*16),this.device.queue.submit([r.finish()]),this.hullBuffer.destroy(),this.hullBuffer=i,this.hullCapacity=t,this.contactBuffers&&this.rebuildBindings()}addBody(e){return this.addBodies([e])}addBodies(e){let t=Math.min(e.length,this.bodyCapacity-this.bodyCount);if(t<=0)return-1;let i=this.bodyCount;return this.bodyCount+=t,this.writeBodies(i,e.slice(0,t)),this.device.queue.writeBuffer(this.colorBuffer,i*4,new Uint32Array(t).fill(255)),this.adjScan.destroy(),this.adjScan=new tt(this.device,this.adjBuffer,0,this.bodyCount+1),i}appendJoint(e,t,i,r,o,a){let n=this.jointCount;n>=this.jointCapacity&&this.allocateJoints(this.jointCapacity*2),this.jointCount++;let l=new Float32Array(pe);l[ci+3]=$t(o),l[es+3]=$t(a),l[dr+3]=3e38,l.set([i[0],i[1],i[2]],ui),l.set([r[0],r[1],r[2]],pr);let c=e>=0?this.bodies[e].size:[0,0,0],u=this.bodies[t].size;return l[hr+3]=(c[0]+u[0])**2+(c[1]+u[1])**2+(c[2]+u[2])**2,this.info.set([is,e,t,0],n*4),this.device.queue.writeBuffer(this.jointBuffer,n*pe*4,l),this.device.queue.writeBuffer(this.infoBuffer,n*16,this.info,n*4,4),this.noCollide(e,t,n),n}appendJoints(e,t,i=!1){return this.appendConstraints(e.length,(r,o)=>{let{a,b:n,rA:l,rB:c,angular:u}=e[r];o[ci+3]=3e38,o[es+3]=u===void 0?3e38:$t(u),o[dr+3]=i?-$t(t):$t(t),o.set([l[0],l[1],l[2]],ui),o.set([c[0],c[1],c[2]],pr);let[f,d]=[this.bodies[a].size,this.bodies[n].size];return o[hr+3]=(f[0]+d[0])**2+(f[1]+d[1])**2+(f[2]+d[2])**2,[is,a,n]})}appendSprings(e){return this.appendConstraints(e.length,(t,i)=>{let{a:r,b:o,rA:a,rB:n,stiffness:l,rest:c}=e[t];return i[ci+3]=$t(l),i.set([a[0],a[1],a[2],c],ui),i.set([n[0],n[1],n[2]],pr),[br,r,o]})}appendConstraints(e,t){let i=[];if(this.freeSlots.length)for(this.freeSlots.sort((n,l)=>l-n);i.length<e&&this.freeSlots.length;)i.push(this.freeSlots.pop());let r=e-i.length,o=this.jointCapacity;for(;this.jointCount+r>o;)o*=2;o>this.jointCapacity&&this.allocateJoints(o);for(let n=0;n<r;n++)i.push(this.jointCount++);let a=new Float32Array(e*pe);for(let n=0;n<e;n++){let[l,c,u]=t(n,a.subarray(n*pe,(n+1)*pe));this.info.set([l,c,u,0],i[n]*4),this.releasedSlots.delete(i[n]),this.noCollide(c,u,i[n])}for(let n=0;n<e;){let l=n+1;for(;l<e&&i[l]===i[l-1]+1;)l++;this.device.queue.writeBuffer(this.jointBuffer,i[n]*pe*4,a,n*pe,(l-n)*pe),this.device.queue.writeBuffer(this.infoBuffer,i[n]*16,this.info,i[n]*4,(l-n)*4),n=l}return i}releaseJoints(e){let t=[...new Set(Array.from(e))].filter(r=>r<this.jointCount&&this.info[r*4]!==0).sort((r,o)=>r-o);if(!t.length)return;for(let r of t)this.info.set([0,-1,-1,0],r*4),this.releasedSlots.add(r),this.freeSlots.push(r);let i=new Float32Array(0);for(let r=0;r<t.length;){let o=r+1;for(;o<t.length&&t[o]===t[o-1]+1;)o++;i.length<(o-r)*pe&&(i=new Float32Array((o-r)*pe)),this.device.queue.writeBuffer(this.jointBuffer,t[r]*pe*4,i,0,(o-r)*pe),this.device.queue.writeBuffer(this.infoBuffer,t[r]*16,this.info,t[r]*4,(o-r)*4),r=o}this.noCollideDirty=!0}rewriteBodies(e,t){for(let i=0;i<e.length;){let r=i+1;for(;r<e.length&&e[r]===e[r-1]+1;)r++;this.writeBodies(e[i],t.slice(i,r)),this.device.queue.writeBuffer(this.colorBuffer,e[i]*4,new Uint32Array(r-i).fill(255)),i=r}}setFilters(e,t,i){for(let r=0;r<e.length;){let o=r+1;for(;o<e.length&&e[o]===e[o-1]+1;)o++;let a=new Uint32Array(2*(o-r));for(let n=r;n<o;n++)a.set([t[n]>>>0,i[n]>>>0],2*(n-r));this.device.queue.writeBuffer(this.filterBuffer,e[r]*8,a),r=o}}setWorldAnchor(e,t){this.device.queue.writeBuffer(this.jointBuffer,(e*pe+ui)*4,new Float32Array([t[0],t[1],t[2]]))}disableConstraint(e){this.device.queue.writeBuffer(this.jointBuffer,(e*pe+ci)*4,new Float32Array(8)),this.device.queue.writeBuffer(this.jointBuffer,(e*pe+dr)*4,new Float32Array(3)),this.device.queue.writeBuffer(this.jointBuffer,(e*pe+hr)*4,new Float32Array(3))}profileNextStep(e){this.timing&&!this.timingBusy&&(this.timingCallback=e)}writeParams(){let e=this.params,t=this.bodyCapacity,i=new ArrayBuffer(ls*4),r=new Float32Array(i),o=new Uint32Array(i);r[0]=e.dt,r[1]=e.gravity,r[2]=e.betaLin,r[3]=e.betaAng,r[4]=e.gamma,r[5]=e.alpha,o[6]=(e.matchNearest?rs:0)|(e.faceBias?ss:0)|(e.reuseContacts?os:0)|(e.startAtRest?as:0)|(e.massPenalty?ns:0),o[7]=this.bodyCount,o[8]=this.jointCount,o[9]=this.colorCap,r[10]=this.cellSize,o[11]=this.tableSize-1,r[12]=this.maxSmallRadius,o[13]=this.largeCount,o[14]=this.noCollideCount,o[15]=this.pairCapacity,o[16]=this.contactCapacity,o[17]=this.hashSize-1,o[18]=t+1,o[19]=2*t+1,o[20]=this.tableSize+1,o[21]=2*this.tableSize+1,o[22]=2*this.tableSize+1+t,o[23]=t,o[24]=this.colorHistOffset,o[25]=2*t,o[26]=this.colorGroups,o[27]=2*t+65,o[28]=this.colorRounds,o[29]=this.manifoldCapacity,o[30]=this.stepCount;let a=n=>Math.min(31,Math.max(0,Math.round(Math.log2(n))));o[31]=a(this.primalLanes[0])|a(this.primalLanes[1])<<8|a(this.primalLanes[2])<<16,r.set([e.windSpeed*Math.cos(e.windAngle),e.windSpeed*Math.sin(e.windAngle),0,e.windPressure,e.windGust],32),r.set([e.up[0],e.up[1],e.up[2],0],40),this.device.queue.writeBuffer(this.paramsBuffer,0,i)}writePassConstants(e,t){let i=this.colorCap+1,r=Math.max(e*i,1);(r>this.passEntries||!this.passGroup)&&(this.passBuffer?.destroy(),this.passBuffer=this.device.createBuffer({label:"pass constants",size:r*256,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.passEntries=r,this.passGroup=this.device.createBindGroup({layout:this.layouts.pass,entries:[{binding:0,resource:{buffer:this.passBuffer,size:16}}]}));let o=new ArrayBuffer(r*256),a=new Uint32Array(o),n=new Float32Array(o);for(let l=0;l<e;l++)for(let c=0;c<=this.colorCap;c++){let u=(l*i+c)*256/4;a[u]=c,n[u+1]=t}this.device.queue.writeBuffer(this.passBuffer,0,o)}step(){(this.radiiDirty||this.noCollideDirty)&&this.uploadStatics();let e=this.params;this.fixedColors&&(this.device.queue.writeBuffer(this.colorBuffer,0,this.fixedColors),this.colorCap=Math.max(1,...this.fixedColors.map(y=>y===255?0:y+1))),this.stepCount++,this.writeParams(),this.writePassConstants(e.iterations,e.alpha);let t=this.parity,i=this.bodyCapacity,r=this.bodyCount,o=this.jointCount,a=this.device.createCommandEncoder({label:"avbd3d step"});a.clearBuffer(this.gridBuffer,0,(2*this.tableSize+1)*4),a.clearBuffer(this.tableBuffer),a.clearBuffer(this.adjBuffer,0,(2*i+1)*4);let n=this.timingCallback!==null&&this.timing!==null,l,c=0,u=n||this.splitPasses,f=()=>{l&&!u||(l?.end(),l=a.beginComputePass({label:u?Se[c]:"avbd3d step",timestampWrites:n?{querySet:this.timing.querySet,beginningOfPassWriteIndex:2*c,endOfPassWriteIndex:2*c+1}:void 0}),c++)},d=this.groups,p=(y,A,v)=>{v<=0||(l.setPipeline(this.pipes[y]),l.setBindGroup(0,A),l.dispatchWorkgroups(v))},m=(y,A,v)=>{l.setPipeline(this.pipes[y]),l.setBindGroup(0,A),l.dispatchWorkgroupsIndirect(this.argsBuffer,v*4)};if(f(),p("beginFrame",d.broad,1),e.reuseContacts&&p("updateRefs",d.refs,ht(r)),p("argsPrev",d.args,1),m("hashInsert",d.contacts[t],6),p("gridCount",d.broad,ht(r)),this.gridScan.encode(l),p("gridScatter",d.broad,ht(r)),p("findPairs",d.broad,ht(r)),p("argsPairs",d.args,1),m("narrowphase",d.contacts[t],0),p("argsContacts",d.args,1),f(),p("degreeJoints",d.topo[t],ht(o)),m("degreeContacts",d.topo[t],3),this.adjScan.encode(l),p("fillJoints",d.topo[t],ht(o)),m("fillContacts",d.topo[t],3),p("sortAdjacency",d.topo[t],ht(r)),f(),!this.fixedColors){p("colorCompact",d.topo[t],ht(r)),p("colorMark",d.topo[t],ht(r));for(let y=0;y<this.colorRounds;y++)p(y%2===0?"colorRoundAB":"colorRoundBA",d.topo[t],ht(r))}p("colorCount",d.topo[t],this.colorGroups),this.colorHistScan.encode(l),p("colorStarts",d.topo[t],1),p("argsColors",d.args,1),p("colorScatter",d.topo[t],this.colorGroups),f();let h=this.colorCap+1,g=y=>l.setBindGroup(1,this.passGroup,[y*256]);l.setBindGroup(0,d.solve[t]),g(0),o>0&&(l.setPipeline(this.pipes.warmStartJoints),l.dispatchWorkgroups(ht(o))),l.setPipeline(this.pipes.warmStartBodies),l.dispatchWorkgroups(ht(r));for(let y=0;y<e.iterations;y++){l.setPipeline(this.pipes.primal);for(let A=0;A<this.colorCap;A++)g(y*h+A),l.dispatchWorkgroupsIndirect(this.argsBuffer,(12+3*A)*4);g(y*h+this.colorCap),l.setPipeline(this.pipes.dual),l.dispatchWorkgroupsIndirect(this.argsBuffer,36)}l.setPipeline(this.pipes.updateVelocities),l.dispatchWorkgroups(ht(r)),l.end();let b=2*Se.length;if(n){let{querySet:y,resolve:A,read:v}=this.timing;a.resolveQuerySet(y,0,b,A,0),a.copyBufferToBuffer(A,0,v,0,b*8)}if(this.device.queue.submit([a.finish()]),this.parity=1-t,n){let y=this.timingCallback;this.timingCallback=null,this.timingBusy=!0;let A=this.timing.read;A.mapAsync(GPUMapMode.READ).then(()=>{let v=new BigUint64Array(A.getMappedRange()).slice();if(A.unmap(),this.timingBusy=!1,this.destroyed)return this.releaseTiming();let x=(B,L)=>Number(v[L]-v[B])/1e6,w={total:x(0,b-1)};Se.forEach((B,L)=>w[B]=x(2*L,2*L+1)),y(w)},()=>{this.timingBusy=!1,this.destroyed&&this.releaseTiming()})}}async readBodies(){return new Float32Array(await this.read(this.bodyBuffer,this.bodyCount*We*4))}async readJoints(){return new Float32Array(await this.read(this.jointBuffer,this.jointCount*pe*4))}async readCounters(){let e=new Uint32Array(await this.read(this.counterBuffer,64));return{pairs:e[0],contacts:e[1],manifolds:e[gr],overflow:e[3],clashes:e[4],colors:e[5]}}async readContactList(){let e=await this.readCounters(),t=Math.min(e.manifolds,this.manifoldCapacity),i=Math.min(e.contacts,this.contactCapacity),r=1-this.parity,[o,a]=await Promise.all([this.read(this.manifoldBuffers[r],t*Nt*4),this.read(this.contactBuffers[r],i*Ht*4)]),n=new Uint32Array(o),l=new Float32Array(o),c=new Uint32Array(a),u=new Float32Array(a),f=[];for(let d=0;d<t;d++){let p=d*Nt,m=[...l.subarray(p+Js,p+Js+3)];for(let h=n[p+2];h<n[p+2]+(n[p+3]&15);h++){let g=h*Ht,b=c[g+mr+3];f.push({a:n[p],b:n[p+1],feature:(b&~ts)>>>0,stick:(b&ts)!==0,rA:[...u.subarray(g+mr,g+mr+3)],rB:[...u.subarray(g+Xs,g+Xs+3)],pen:[...u.subarray(g+Ys,g+Ys+3)],lam:[...u.subarray(g+Qs,g+Qs+3)],normal:m})}}return f}async readPairs(){let{pairs:e}=await this.readCounters();return new Uint32Array(await this.read(this.pairBuffer,Math.min(e,this.pairCapacity)*8))}jointInfo(){return this.info.subarray(0,this.jointCount*4)}adapt(e){if(this.fixedColors)return;let t=e.colors;e.clashes>0&&(this.colorRounds=Math.min(32,this.colorRounds*2)),e.clashes>0||this.colorCap-t<2?(this.colorCap=Math.min(64,Math.max(t+io+2,this.colorCap+4)),this.shrinkVotes=0):t+io+2<this.colorCap||this.colorRounds>4?++this.shrinkVotes>=3&&(this.colorCap=Math.min(64,t+io),this.colorRounds=Math.max(4,this.colorRounds-4),this.shrinkVotes=0):this.shrinkVotes=0;let i=(n,l,c)=>(e.overflow&c)!==0||n>pf*l?Math.max(mf*n,1.25*l):l,r=i(e.contacts,this.contactCapacity,2),o=i(e.pairs,this.pairCapacity,1),a=i(e.manifolds,this.manifoldCapacity,4);this.capacityCanGrow(r,o,a)&&this.allocateContacts(r,o,a)}capacityCanGrow(e,t,i){let r=this.device.limits.maxStorageBufferBindingSize;return Math.min(e,r/(Ht*4))>this.contactCapacity||Math.min(t,r/8)>this.pairCapacity||Math.min(i,t,r/(Nt*4))>this.manifoldCapacity}async read(e,t){if(t===0)return new ArrayBuffer(0);let i=this.device.createBuffer({size:t,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),r=this.device.createCommandEncoder();r.copyBufferToBuffer(e,0,i,0,t),this.device.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ);let o=i.getMappedRange().slice(0);return i.unmap(),i.destroy(),o}releaseTiming(){this.timing?.resolve.destroy(),this.timing?.read.destroy(),this.timing?.querySet.destroy()}destroy(){this.ownsBodyBuffer&&this.bodyBuffer.destroy();let e=[this.jointBuffer,this.infoBuffer,...this.contactBuffers,...this.manifoldBuffers,this.pairBuffer,this.tableBuffer,this.gridBuffer,this.staticBuffer,this.counterBuffer,this.argsBuffer,this.adjBuffer,this.colorBuffer,this.paramsBuffer,this.refBuffer,this.hullBuffer,this.passBuffer,this.filterBuffer];for(let t of e)t?.destroy();this.destroyed=!0,this.timingBusy||this.releaseTiming(),this.gridScan.destroy(),this.colorHistScan.destroy(),this.adjScan?.destroy()}};var jl=` e.C = vec3f(
2421
+ `;function to(s,e){let t=0,i=s.length-1;for(;t<i;){let r=s[e],o=t,a=i;do{for(;s[o]<r;)o++;for(;r<s[a];)a--;if(o<=a){let n=s[o];s[o]=s[a],s[a]=n,o++,a--}}while(o<=a);a<e&&(t=o),e<o&&(i=a)}return s[e]}function Xa(s){let e=s.length,t=e>0?to(s,e>>1):1,i=0;for(let r=0;r<e;r++)s[r]<=2*t&&(i=Math.max(i,s[r]));return e>64&&(i=Math.max(i,to(s,e-64-1))),i}var $t=s=>s===1/0?3e38:s===-1/0?-3e38:s,pt=s=>Math.ceil(s/64),Tl=s=>2**Math.ceil(Math.log2(Math.max(s,2))),uf=s=>Math.max(s,1)*He*4,ff=8,io=3,df=8,pf=1.6,hf=.8,mf=2,gf=[0,0,1],bf=()=>({...Oa(),matchNearest:!0,faceBias:!0,reuseContacts:!0,startAtRest:!0,massPenalty:!0,windSpeed:0,windAngle:0,windGust:.4,windPressure:.72,up:[0,1,0]});function yf(s,e){let t=s.vertices.length/3,i=s.faces.length,r=s.faces.reduce((m,p)=>m+p.verts.length,0),o=Math.ceil(r/4),a=s.edges.length,n=new Float32Array((2+t+2*i+o+a)*4),l=new Uint32Array(n.buffer),c=e+2,u=c+t,f=u+2*i,d=f+o;l.set([c,t,u,i,d,a,f,0],0);for(let m=0;m<t;m++)n.set(s.vertices.subarray(m*3,m*3+3),(2+m)*4);let h=0;return s.faces.forEach((m,p)=>{let g=(2+t+2*p)*4;n.set(m.normal,g),n[g+3]=m.d,l[g+4]=h,l[g+5]=m.verts.length;for(let b of m.verts)l[(2+t+2*i)*4+h++]=b}),s.edges.forEach((m,p)=>l.set(m,(2+t+2*i+o+p)*4)),n}var Ya=.001;function vf(s,e){let t=s.length,i=s.map(y=>{let A=y;return[A.group??4294967295,A.collidesWith??4294967295]}),r=i.map(([y,A])=>y!==0&&A!==0),o=s.map(y=>[0,1,2].map(A=>{let v=[0,0,0];return v[A]=1,le(S(),y.positionAng,v)})),a=s.map((y,A)=>{if(De(y))return[y.radius,y.radius,y.radius];let v=[0,0,0];for(let x=0;x<3;x++)for(let w=0;w<3;w++)v[w]+=y.size[x]*.5*Math.abs(o[A][x][w]);return v}),n=Xa(Float64Array.from(s,y=>y.radius)),l=Math.max(2*n,.001),c=(y,A)=>{let v=s[y],x=s[A];if(v.mass<=0&&x.mass<=0||!(i[y][0]&i[A][1])||!(i[A][0]&i[y][1]))return!1;let w=v.positionLin[0]-x.positionLin[0],B=v.positionLin[1]-x.positionLin[1],L=v.positionLin[2]-x.positionLin[2];if(!(Math.abs(w)<=a[y][0]+a[A][0]&&Math.abs(B)<=a[y][1]+a[A][1]&&Math.abs(L)<=a[y][2]+a[A][2]))return!1;let M=v.radius+x.radius;return w*w+B*B+L*L<=M*M},u=(y,A)=>y[0]*A[0]+y[1]*A[1]+y[2]*A[2],f=(y,A)=>{let v=s[y],x=s[A],w=[0,1,2].map(E=>x.positionLin[E]-v.positionLin[E]),[B,L]=[De(v),De(x)];if(B&&L)return Math.hypot(w[0],w[1],w[2])<=v.radius+x.radius+Ya;if(B||L){let[E,k,P]=B?[A,v.radius,-1]:[y,x.radius,1],C=0;for(let _=0;_<3;_++){let z=Math.abs(P*u(w,o[E][_]))-s[E].size[_]*.5;z>0&&(C+=z*z)}return C<=(k+Ya)**2}let M=(E,k)=>s[E].size[0]*.5*Math.abs(u(o[E][0],k))+s[E].size[1]*.5*Math.abs(u(o[E][1],k))+s[E].size[2]*.5*Math.abs(u(o[E][2],k)),I=E=>{let k=Math.hypot(E[0],E[1],E[2]);return k<1e-6?!1:Math.abs(u(w,E))-M(y,E)-M(A,E)>Ya*k};for(let E=0;E<3;E++)if(I(o[y][E])||I(o[A][E]))return!1;for(let E of o[y])for(let k of o[A])if(I([E[1]*k[2]-E[2]*k[1],E[2]*k[0]-E[0]*k[2],E[0]*k[1]-E[1]*k[0]]))return!1;return!0},d=new Set,h=new Map,m=(y,A,v)=>(y*73856093^A*19349663^v*83492791)>>>0,p=y=>[0,1,2].map(A=>Math.floor(s[y].positionLin[A]/l));for(let y=0;y<t;y++){if(!r[y])continue;if(s[y].radius>n){d.add(y);continue}let[A,v,x]=p(y),w=m(A,v,x),B=h.get(w);B?B.push(y):h.set(w,[y])}let g=0,b=0;for(let y=0;y<t;y++){if(!r[y]||d.has(y))continue;let[A,v,x]=p(y);for(let w=-1;w<=1;w++)for(let B=-1;B<=1;B++)for(let L=-1;L<=1;L++)for(let M of h.get(m(A+L,v+B,x+w))??[])M<y&&c(y,M)&&(g++,f(y,M)&&(b++,e[y]++,e[M]++))}for(let y of d)for(let A=0;A<t;A++)r[A]&&A!==y&&(!d.has(A)||A<y)&&c(y,A)&&(g++,f(y,A)&&(b++,e[y]++,e[A]++));return{pairs:g,touching:b}}function xf(s){let e=[1/0,1/0,1/0],t=[-1/0,-1/0,-1/0];for(let o of s)for(let a=0;a<3;a++)e[a]=Math.min(e[a],o.positionLin[a]),t[a]=Math.max(t[a],o.positionLin[a]);let i=o=>{let a=o&1023;return a=(a|a<<16)&50331903,a=(a|a<<8)&50393103,a=(a|a<<4)&51130563,a=(a|a<<2)&153391689,a},r=s.map(o=>{let a=[0,1,2].map(n=>Math.min(1023,Math.floor((o.positionLin[n]-e[n])/Math.max(t[n]-e[n],1e-9)*1024)));return(i(a[0])|i(a[1])<<1|i(a[2])<<2)>>>0});return s.map((o,a)=>a).sort((o,a)=>r[o]-r[a]||o-a)}var Pe=()=>GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST,ro=class{device;params=bf();bodyCount=0;bodyCapacity;bodies=[];hulls;hullBuffer;get hullStorage(){return this.hullBuffer}hullCapacity=4096;hullTop=0;hullSlots=new Map;contactShaders;hullShaders=!1;hullFree=[];refToGpu;jointCount=0;jointCapacity=0;info=new Int32Array(0);pairCapacity=0;manifoldCapacity=0;contactCapacity=0;colorCap=12;fixedColors=null;primalLanes=[2**31,2**15,2**12];splitPasses=!1;shrinkVotes=0;colorRounds;get colorHistOffset(){return 3*this.bodyCapacity+65}bodyBuffer;ownsBodyBuffer;jointBuffer;infoBuffer;contactBuffers;manifoldBuffers;pairBuffer;tableBuffer;gridBuffer;staticBuffer=null;filterBuffer;get filterStorage(){return this.filterBuffer}counterBuffer;get contactStorage(){let e=1-this.parity;return{manifolds:this.manifoldBuffers[e],contacts:this.contactBuffers[e],counters:this.counterBuffer}}argsBuffer;adjBuffer=null;colorBuffer;paramsBuffer;refBuffer;stepCount=0;passBuffer=null;passEntries=0;parity=0;tableSize;hashSize=0;cellSize=1;maxSmallRadius=0;largeCount=0;noCollideCount=0;radiiDirty=!0;noCollideDirty=!0;large=[];entries=[];pendingEntries=[];releasedSlots=new Set;freeSlots=[];layouts;pipes={};groups;passGroup=null;gridScan;colorHistScan;colorGroups;adjScan=null;timing;timingCallback=null;timingBusy=!1;destroyed=!1;constructor(e,t,i={}){this.device=e;let{dt:r,gravity:o,iterations:a,alpha:n,betaLin:l,betaAng:c,gamma:u}=t;if(Object.assign(this.params,{dt:r,gravity:o,iterations:a,alpha:n,betaLin:l,betaAng:c,gamma:u,up:gf}),this.bodyCount=t.bodies.length,this.colorRounds=i.colorRounds??16,this.ownsBodyBuffer=!i.bodyBuffer,this.bodyCapacity=i.bodyBuffer?Math.floor(i.bodyBuffer.size/(He*4)):Math.max(i.bodyCapacity??this.bodyCount+1024,this.bodyCount,1),this.bodyCapacity<this.bodyCount)throw new Error("body buffer too small");this.bodyBuffer=i.bodyBuffer??e.createBuffer({label:"bodies 3d",size:uf(this.bodyCapacity),usage:Pe()}),this.filterBuffer=e.createBuffer({label:"collision filters",size:Math.max(this.bodyCapacity,1)*8,usage:Pe()}),e.queue.writeBuffer(this.filterBuffer,0,new Uint32Array(Math.max(this.bodyCapacity,1)*2).fill(4294967295));let f=this.bodyCapacity;this.tableSize=Tl(2*f),this.gridBuffer=e.createBuffer({label:"grid 3d",size:(2*this.tableSize+1+4*f)*4,usage:Pe()}),this.counterBuffer=e.createBuffer({label:"counters",size:64,usage:Pe()}),this.argsBuffer=e.createBuffer({label:"indirect args",size:816,usage:Pe()|GPUBufferUsage.INDIRECT}),this.colorGroups=Math.ceil(f/256),this.colorBuffer=e.createBuffer({label:"colours",size:(3*f+65+64*this.colorGroups+1)*4,usage:Pe()}),this.paramsBuffer=e.createBuffer({label:"params 3d",size:ls*4,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.refBuffer=e.createBuffer({label:"reference poses",size:f*32,usage:Pe()}),this.hulls=(i.hulls??!0)&&e.limits.maxStorageBuffersPerShaderStage>=9,this.hullBuffer=e.createBuffer({label:"hulls",size:this.hullCapacity*16,usage:Pe()}),e.queue.writeBuffer(this.colorBuffer,0,new Uint32Array(f).fill(255));let d=2*Se.length;this.timing=e.features.has("timestamp-query")?{querySet:e.createQuerySet({type:"timestamp",count:d}),resolve:e.createBuffer({size:d*8,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),read:e.createBuffer({size:d*8,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST})}:null,this.layouts=this.createLayouts(),this.createPipelines(i.shaders??{}),this.gridScan=new tt(e,this.gridBuffer,0,this.tableSize+1),this.colorHistScan=new tt(e,this.colorBuffer,this.colorHistOffset,64*this.colorGroups+1);let h=i.spatialSort===!1?t.bodies.map((w,B)=>B):xf(t.bodies);this.refToGpu=new Int32Array(h.length),h.forEach((w,B)=>this.refToGpu[w]=B);let m=new Map(t.bodies.map((w,B)=>[w,this.refToGpu[B]])),p=t.forces.filter(w=>w instanceof ke||w instanceof dt);for(let w of t.forces){if(!(w instanceof $s))continue;let B=m.get(w.bodyA),L=m.get(w.bodyB);this.pendingEntries.push([Math.max(B,L),Math.min(B,L),4294967295])}this.allocateJoints(Math.max(p.length+256,i.capacity?.joints??0));for(let w of p)this.writeJoint(this.jointCount++,w,m);let g=new Int32Array(t.bodies.length),{pairs:b,touching:y}=vf(t.bodies,g),A=new Map(t.bodies.map((w,B)=>[w,B]));for(let w of p)w.bodyA&&g[A.get(w.bodyA)]++,g[A.get(w.bodyB)]++;let v=0;t.bodies.forEach((w,B)=>{w.mass>0&&(v=Math.max(v,g[B]))}),this.colorCap=Math.min(64,Math.max(df,v+1+io,i.capacity?.colors??0));let x=i.capacity??{};this.allocateContacts(Math.max(8192,4*f,ff*y,x.contacts??0),Math.max(4096,4*f,2*b,x.pairs??0),Math.max(4096,f,pf*y,x.manifolds??0)),this.writeBodies(0,h.map(w=>t.bodies[w]))}gpuIndex(e){return e<this.refToGpu.length?this.refToGpu[e]:e}createLayouts(){let e=this.device,t=(a,n)=>e.createBindGroupLayout({label:a,entries:n.map((l,c)=>({binding:c,visibility:GPUShaderStage.COMPUTE,buffer:{type:l}}))}),i="read-only-storage",r="storage",o="uniform";return{broad:t("broadphase 3d",[o,i,r,r,r,i,i,i]),contacts:t("contacts 3d",[o,i,i,r,i,r,i,r,r,...this.hulls?[i]:[]]),topo:t("topology 3d",[o,i,i,i,i,r,r,r]),solve:t("solve 3d",[o,r,r,i,r,i,i,i,i]),pass:e.createBindGroupLayout({label:"pass",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform",hasDynamicOffset:!0,minBindingSize:16}}]}),args:t("args 3d",[o,i,i,r]),refs:t("refs 3d",[o,r,r])}}createPipelines(e){let t=this.device,i=(o,a,n)=>{let l=t.createShaderModule({code:o}),c=t.createPipelineLayout({bindGroupLayouts:a});for(let u of n)this.pipes[u]=t.createComputePipeline({label:u,layout:c,compute:{module:l,entryPoint:u}})},r=this.layouts;i(fi,[r.broad],["beginFrame","gridCount","gridScatter","findPairs"]),i(e.refs??eo,[r.refs],["updateRefs"]),i(e.contacts??Il,[r.contacts],["hashInsert","narrowphase"]),this.contactShaders={make:o=>i(o,[r.contacts],["hashInsert","narrowphase"]),custom:!!e.contacts},i(e.topology??Ti(ge,yr),[r.topo],["degreeJoints","degreeContacts","fillJoints","fillContacts","sortAdjacency","colorCompact","colorMark","colorRoundAB","colorRoundBA","colorCount","colorStarts","colorScatter"]),i(e.solve??Ge,[r.solve,r.pass],["warmStartJoints","warmStartBodies","primal","dual","updateVelocities"]),i(Yr(ge,Zs),[r.args],["argsPrev","argsPairs","argsContacts","argsColors"])}allocateJoints(e){let t=this.device,i=t.createBuffer({label:"joints 3d",size:Math.max(e,1)*he*4,usage:Pe()}),r=t.createBuffer({label:"joint info",size:Math.max(e,1)*16,usage:Pe()});if(this.jointBuffer){let a=t.createCommandEncoder();a.copyBufferToBuffer(this.jointBuffer,0,i,0,this.jointCapacity*he*4),a.copyBufferToBuffer(this.infoBuffer,0,r,0,this.jointCapacity*16),t.queue.submit([a.finish()]),this.jointBuffer.destroy(),this.infoBuffer.destroy()}let o=new Int32Array(e*4);o.set(this.info.subarray(0,Math.min(this.info.length,o.length))),this.info=o,this.jointBuffer=i,this.infoBuffer=r,this.jointCapacity=e,this.contactBuffers&&this.rebuildBindings()}allocateContacts(e,t,i){let r=this.device,o=r.limits.maxStorageBufferBindingSize,a=Math.min(Math.ceil(e),Math.floor(o/(Ht*4))),n=Math.min(Math.ceil(t),Math.floor(o/8)),l=Math.min(Math.ceil(i),n,Math.floor(o/(Nt*4))),c={contacts:this.contactBuffers,manifolds:this.manifoldBuffers,contactCapacity:this.contactCapacity,manifoldCapacity:this.manifoldCapacity};for(let u of[this.pairBuffer,this.tableBuffer])u?.destroy();if(this.contactCapacity=a,this.pairCapacity=n,this.manifoldCapacity=l,this.hashSize=Tl(2*l),this.pairBuffer=r.createBuffer({label:"pairs",size:n*8,usage:Pe()}),this.tableBuffer=r.createBuffer({label:"manifold hash",size:this.hashSize*4,usage:Pe()}),this.contactBuffers=[0,1].map(u=>r.createBuffer({label:`contacts 3d ${u}`,size:a*Ht*4,usage:Pe()})),this.manifoldBuffers=[0,1].map(u=>r.createBuffer({label:`manifolds 3d ${u}`,size:l*Nt*4,usage:Pe()})),c.contacts){let u=r.createCommandEncoder(),f=Math.min(c.contactCapacity,a)*Ht*4,d=Math.min(c.manifoldCapacity,l)*Nt*4;c.contacts.forEach((h,m)=>u.copyBufferToBuffer(h,0,this.contactBuffers[m],0,f)),c.manifolds.forEach((h,m)=>u.copyBufferToBuffer(h,0,this.manifoldBuffers[m],0,d)),r.queue.submit([u.finish()]),[...c.contacts,...c.manifolds].forEach(h=>h.destroy())}this.rebuildBindings()}rebuildBindings(){let e=this.device,t=this.bodyCapacity;this.adjBuffer?.destroy(),this.adjBuffer=e.createBuffer({label:"adjacency",size:(2*t+1+2*(this.jointCapacity+this.manifoldCapacity))*4,usage:Pe()}),this.adjScan?.destroy(),this.adjScan=new tt(e,this.adjBuffer,0,this.bodyCount+1),this.staticBuffer??=e.createBuffer({label:"statics",size:16,usage:Pe()});let i=(d,h)=>e.createBindGroup({layout:d,entries:h.map((m,p)=>({binding:p,resource:{buffer:m}}))}),r=this.paramsBuffer,[o,a]=this.contactBuffers,[n,l]=this.manifoldBuffers,c=this.adjBuffer,u=this.tableBuffer,f=this.counterBuffer;this.groups={broad:i(this.layouts.broad,[r,this.bodyBuffer,this.gridBuffer,this.pairBuffer,f,this.staticBuffer,this.jointBuffer,this.filterBuffer]),contacts:[i(this.layouts.contacts,[r,this.bodyBuffer,this.pairBuffer,o,a,n,l,u,f,...this.hulls?[this.hullBuffer]:[]]),i(this.layouts.contacts,[r,this.bodyBuffer,this.pairBuffer,a,o,l,n,u,f,...this.hulls?[this.hullBuffer]:[]])],topo:[n,l].map(d=>i(this.layouts.topo,[r,this.bodyBuffer,this.jointBuffer,this.infoBuffer,d,f,c,this.colorBuffer])),solve:[0,1].map(d=>i(this.layouts.solve,[r,this.bodyBuffer,this.jointBuffer,this.infoBuffer,[o,a][d],c,this.colorBuffer,f,[n,l][d]])),args:i(this.layouts.args,[r,this.counterBuffer,this.colorBuffer,this.argsBuffer]),refs:i(this.layouts.refs,[r,this.bodyBuffer,this.refBuffer])}}writeBodies(e,t){let i=new Float32Array(Math.max(t.length,1)*He);t.forEach((r,o)=>{let a=this.pack(r,i,o*He,this.bodies[e+o]?.hull);this.bodies[e+o]?.radius!==a.radius&&(this.radiiDirty=!0),this.bodies[e+o]=a}),this.device.queue.writeBuffer(this.bodyBuffer,e*He*4,i,0,t.length*He)}rewriteFixed(e,t,i,r,o){if(!e.length)return;let a=new Float32Array(He),n={positionLin:[0,0,0],positionAng:[0,0,0,1],initialLin:[0,0,0],initialAng:[0,0,0,1],inertialLin:[0,0,0],inertialAng:[0,0,0,1],velocityLin:[0,0,0],prevVelocityLin:[0,0,0],velocityAng:[0,0,0],size:[i[0],i[1],i[2]],mass:0,moment:[0,0,0],friction:r,radius:Math.hypot(i[0]/2,i[1]/2,i[2]/2)},l=this.pack(n,a,0);for(let c=0;c<e.length;){let u=c+1;for(;u<e.length&&e[u]===e[u-1]+1;)u++;let f=new Float32Array((u-c)*He);for(let d=c;d<u;d++){let h=(d-c)*He;f.set(a,h);for(let p=0;p<3;p++)f[h+fr+p]=t[3*d+p];if(o)for(let p=0;p<4;p++)f[h+Zr+p]=o[4*d+p];let m=this.bodies[e[d]];m?.radius!==l.radius&&(this.radiiDirty=!0),m?.hull&&this.releaseHull(m.hull),this.bodies[e[d]]={...l,size:[...l.size]}}this.device.queue.writeBuffer(this.bodyBuffer,e[c]*He*4,f),this.device.queue.writeBuffer(this.colorBuffer,e[c]*4,new Uint32Array(u-c).fill(255)),c=u}}pack(e,t,i,r){{t.set(e.positionLin,i+fr),t[i+fr+3]=e.friction,t.set(e.positionAng,i+Zr),t.set(e.size,i+Na),t[i+Na+3]=e.mass,t.set(e.moment,i+qa),t[i+qa+3]=e.radius,t.set(e.initialLin,i+Bl),t.set(e.initialAng,i+Cl),t.set(e.inertialLin,i+Sl),t.set(e.inertialAng,i+kl),t.set(e.velocityLin,i+Va);let o=this.params.up;t[i+Va+3]=e.prevVelocityLin[0]*o[0]+e.prevVelocityLin[1]*o[1]+e.prevVelocityLin[2]*o[2],t.set(e.velocityAng,i+Wa);let a=De(e),n=this.hulls?Ct(e):void 0;r&&r!==n&&this.releaseHull(r);let l=n?r===n?this.hullSlots.get(n).offset:this.acquireHull(n):-1;return t[i+Wa+3]=a?Ha:l>=0?Ks+l:ar(e)?$a:_l,{radius:e.radius,dynamic:e.mass>0,sphere:a,size:[e.size[0],e.size[1],e.size[2]],hull:n}}}writeJoint(e,t,i){let r=new Float32Array(he),o=t.bodyA?i.get(t.bodyA):-1,a=i.get(t.bodyB);t instanceof ke?(r.set(t.penaltyLin,ci),r[ci+3]=$t(t.broken?0:t.stiffnessLin),r.set(t.penaltyAng,es),r[es+3]=$t(t.broken?0:t.stiffnessAng),r.set(t.lambdaLin,dr),r[dr+3]=$t(t.fracture),r.set(t.lambdaAng,pr),r[pr+3]=t.torqueArm,r.set(t.C0Lin,Pl),r.set(t.C0Ang,Ll),r.set(t.rA,ui),r.set(t.rB,hr)):(r[ci+3]=t.stiffness,r.set(t.rA,ui),r[ui+3]=t.rest,r.set(t.rB,hr)),this.info.set([t instanceof ke?is:br,o,a,0],e*4),this.device.queue.writeBuffer(this.jointBuffer,e*he*4,r),this.device.queue.writeBuffer(this.infoBuffer,e*16,this.info,e*4,4),this.noCollide(o,a,e)}noCollide(e,t,i){e<0||(this.pendingEntries.push([Math.max(e,t),Math.min(e,t),i]),this.noCollideDirty=!0)}uploadStatics(){if(this.radiiDirty){let r=this.bodyCount,o=new Float64Array(r);for(let c=0;c<r;c++)o[c]=this.bodies[c].radius;let a=Xa(o),n=1/0;for(let c=0;c<r;c++)o[c]>a&&(n=Math.min(n,o[c]));let l=n===1/0?a*1.5:(a+n)/2;this.maxSmallRadius=l,this.cellSize=Math.max(2*a*(1+1e-4),.001),this.large=[];for(let c=0;c<r;c++)this.bodies[c].radius>l&&this.large.push(c);this.radiiDirty=!1}if(this.noCollideDirty){let r=(l,c)=>l[0]-c[0]||l[1]-c[1],o=this.releasedSlots.size?this.entries.filter(l=>!this.releasedSlots.has(l[2])):this.entries;this.releasedSlots.clear();let a=this.pendingEntries.sort(r);this.pendingEntries=[];let n=[];for(let l=0,c=0;l<o.length||c<a.length;)c>=a.length||l<o.length&&r(o[l],a[c])<=0?n.push(o[l++]):n.push(a[c++]);this.entries=n,this.noCollideDirty=!1}let{large:e,entries:t}=this;this.largeCount=e.length,this.noCollideCount=t.length;let i=new Uint32Array(Math.max(e.length+3*t.length,4));i.set(e,0),t.forEach((r,o)=>i.set(r,e.length+3*o)),this.staticBuffer.size<i.byteLength&&(this.staticBuffer.destroy(),this.staticBuffer=this.device.createBuffer({label:"statics",size:i.byteLength,usage:Pe()}),this.rebuildBindings()),this.device.queue.writeBuffer(this.staticBuffer,0,i)}seedFrom(e){if(this.refToGpu.some((m,p)=>m!==p))throw new Error("seedFrom needs spatialSort: false");let t=new Map(e.bodies.map((m,p)=>[m,p]));this.writeBodies(0,e.bodies);let i=0;for(let m of e.forces)(m instanceof ke||m instanceof dt)&&this.writeJoint(i++,m,t);if(i!==this.jointCount)throw new Error("seedFrom: joints differ from the reference");let r=e.forces.filter(m=>m instanceof ai),o=r.reduce((m,p)=>m+p.contacts.length,0);if(o>this.contactCapacity||r.length>this.manifoldCapacity)throw new Error("seedFrom: too many contacts");let a=new ArrayBuffer(Math.max(o,1)*Ht*4),n=new Uint32Array(a),l=new Float32Array(a),c=new ArrayBuffer(Math.max(r.length,1)*Nt*4),u=new Uint32Array(c),f=new Float32Array(c),d=0;r.forEach((m,p)=>{u.set([t.get(m.bodyA),t.get(m.bodyB),d,m.contacts.length],p*Nt),f.set([m.basis[0],m.basis[1],m.basis[2],m.friction],p*Nt+Js);for(let g of m.contacts){let b=d++*Ht;l.set(g.rA,b+mr),n[b+mr+3]=g.feature>>>0|(g.stick?ts:0),l.set([...g.rB,g.C0[0]],b+Xs),l.set([...g.penalty,g.C0[1]],b+Ys),l.set([...g.lambda,g.C0[2]],b+Qs)}}),this.device.queue.writeBuffer(this.contactBuffers[1-this.parity],0,a),this.device.queue.writeBuffer(this.manifoldBuffers[1-this.parity],0,c);let h=new Uint32Array(16);h[1]=o,h[gr]=r.length,this.device.queue.writeBuffer(this.counterBuffer,0,h)}sequentialColors(){let e=new Uint32Array(this.bodyCount).fill(255),t=0;for(let i=this.bodyCount-1;i>=0;i--)this.bodies[i].dynamic&&(e[i]=t++);if(t>64)throw new Error(`sequentialColors: ${t} dynamic bodies, at most ${64}`);return e}acquireHull(e){!this.hullShaders&&!this.contactShaders.custom&&(this.contactShaders.make(Rl),this.hullShaders=!0);let t=this.hullSlots.get(e);if(t)return t.refs++,t.offset;let i=2+e.vertices.length/3+2*e.faces.length+Math.ceil(e.faces.reduce((a,n)=>a+n.verts.length,0)/4)+e.edges.length,r=-1,o=this.hullFree.findIndex(a=>a.size>=i);if(o>=0){let a=this.hullFree[o];r=a.offset,a.size===i?this.hullFree.splice(o,1):Object.assign(a,{offset:a.offset+i,size:a.size-i})}else r=this.hullTop,this.hullTop+=i,this.hullTop>this.hullCapacity&&this.growHulls(this.hullTop);if(r+Ks>=2**24)throw new Error("hull buffer beyond 2^24 vec4s");return this.device.queue.writeBuffer(this.hullBuffer,r*16,yf(e,r)),this.hullSlots.set(e,{offset:r,size:i,refs:1}),r}releaseHull(e){let t=this.hullSlots.get(e);if(!t||--t.refs>0)return;this.hullSlots.delete(e),this.hullFree.push({offset:t.offset,size:t.size}),this.hullFree.sort((r,o)=>r.offset-o.offset);let i=[];for(let r of this.hullFree){let o=i[i.length-1];o&&o.offset+o.size===r.offset?o.size+=r.size:i.push({...r})}this.hullFree=i}growHulls(e){let t=this.hullCapacity;for(;t<e;)t*=2;let i=this.device.createBuffer({label:"hulls",size:t*16,usage:Pe()}),r=this.device.createCommandEncoder();r.copyBufferToBuffer(this.hullBuffer,0,i,0,this.hullCapacity*16),this.device.queue.submit([r.finish()]),this.hullBuffer.destroy(),this.hullBuffer=i,this.hullCapacity=t,this.contactBuffers&&this.rebuildBindings()}addBody(e){return this.addBodies([e])}addBodies(e){let t=Math.min(e.length,this.bodyCapacity-this.bodyCount);if(t<=0)return-1;let i=this.bodyCount;return this.bodyCount+=t,this.writeBodies(i,e.slice(0,t)),this.device.queue.writeBuffer(this.colorBuffer,i*4,new Uint32Array(t).fill(255)),this.adjScan.destroy(),this.adjScan=new tt(this.device,this.adjBuffer,0,this.bodyCount+1),i}appendJoint(e,t,i,r,o,a){let n=this.jointCount;n>=this.jointCapacity&&this.allocateJoints(this.jointCapacity*2),this.jointCount++;let l=new Float32Array(he);l[ci+3]=$t(o),l[es+3]=$t(a),l[dr+3]=3e38,l.set([i[0],i[1],i[2]],ui),l.set([r[0],r[1],r[2]],hr);let c=e>=0?this.bodies[e].size:[0,0,0],u=this.bodies[t].size;return l[pr+3]=(c[0]+u[0])**2+(c[1]+u[1])**2+(c[2]+u[2])**2,this.info.set([is,e,t,0],n*4),this.device.queue.writeBuffer(this.jointBuffer,n*he*4,l),this.device.queue.writeBuffer(this.infoBuffer,n*16,this.info,n*4,4),this.noCollide(e,t,n),n}appendJoints(e,t,i=!1){return this.appendConstraints(e.length,(r,o)=>{let{a,b:n,rA:l,rB:c,angular:u}=e[r];o[ci+3]=3e38,o[es+3]=u===void 0?3e38:$t(u),o[dr+3]=i?-$t(t):$t(t),o.set([l[0],l[1],l[2]],ui),o.set([c[0],c[1],c[2]],hr);let[f,d]=[this.bodies[a].size,this.bodies[n].size];return o[pr+3]=(f[0]+d[0])**2+(f[1]+d[1])**2+(f[2]+d[2])**2,[is,a,n]})}appendSprings(e){return this.appendConstraints(e.length,(t,i)=>{let{a:r,b:o,rA:a,rB:n,stiffness:l,rest:c}=e[t];return i[ci+3]=$t(l),i.set([a[0],a[1],a[2],c],ui),i.set([n[0],n[1],n[2]],hr),[br,r,o]})}appendConstraints(e,t){let i=[];if(this.freeSlots.length)for(this.freeSlots.sort((n,l)=>l-n);i.length<e&&this.freeSlots.length;)i.push(this.freeSlots.pop());let r=e-i.length,o=this.jointCapacity;for(;this.jointCount+r>o;)o*=2;o>this.jointCapacity&&this.allocateJoints(o);for(let n=0;n<r;n++)i.push(this.jointCount++);let a=new Float32Array(e*he);for(let n=0;n<e;n++){let[l,c,u]=t(n,a.subarray(n*he,(n+1)*he));this.info.set([l,c,u,0],i[n]*4),this.releasedSlots.delete(i[n]),this.noCollide(c,u,i[n])}for(let n=0;n<e;){let l=n+1;for(;l<e&&i[l]===i[l-1]+1;)l++;this.device.queue.writeBuffer(this.jointBuffer,i[n]*he*4,a,n*he,(l-n)*he),this.device.queue.writeBuffer(this.infoBuffer,i[n]*16,this.info,i[n]*4,(l-n)*4),n=l}return i}releaseJoints(e){let t=[...new Set(Array.from(e))].filter(r=>r<this.jointCount&&this.info[r*4]!==0).sort((r,o)=>r-o);if(!t.length)return;for(let r of t)this.info.set([0,-1,-1,0],r*4),this.releasedSlots.add(r),this.freeSlots.push(r);let i=new Float32Array(0);for(let r=0;r<t.length;){let o=r+1;for(;o<t.length&&t[o]===t[o-1]+1;)o++;i.length<(o-r)*he&&(i=new Float32Array((o-r)*he)),this.device.queue.writeBuffer(this.jointBuffer,t[r]*he*4,i,0,(o-r)*he),this.device.queue.writeBuffer(this.infoBuffer,t[r]*16,this.info,t[r]*4,(o-r)*4),r=o}this.noCollideDirty=!0}rewriteBodies(e,t){for(let i=0;i<e.length;){let r=i+1;for(;r<e.length&&e[r]===e[r-1]+1;)r++;this.writeBodies(e[i],t.slice(i,r)),this.device.queue.writeBuffer(this.colorBuffer,e[i]*4,new Uint32Array(r-i).fill(255)),i=r}}setFilters(e,t,i){for(let r=0;r<e.length;){let o=r+1;for(;o<e.length&&e[o]===e[o-1]+1;)o++;let a=new Uint32Array(2*(o-r));for(let n=r;n<o;n++)a.set([t[n]>>>0,i[n]>>>0],2*(n-r));this.device.queue.writeBuffer(this.filterBuffer,e[r]*8,a),r=o}}setWorldAnchor(e,t){this.device.queue.writeBuffer(this.jointBuffer,(e*he+ui)*4,new Float32Array([t[0],t[1],t[2]]))}disableConstraint(e){this.device.queue.writeBuffer(this.jointBuffer,(e*he+ci)*4,new Float32Array(8)),this.device.queue.writeBuffer(this.jointBuffer,(e*he+dr)*4,new Float32Array(3)),this.device.queue.writeBuffer(this.jointBuffer,(e*he+pr)*4,new Float32Array(3))}profileNextStep(e){this.timing&&!this.timingBusy&&(this.timingCallback=e)}writeParams(){let e=this.params,t=this.bodyCapacity,i=new ArrayBuffer(ls*4),r=new Float32Array(i),o=new Uint32Array(i);r[0]=e.dt,r[1]=e.gravity,r[2]=e.betaLin,r[3]=e.betaAng,r[4]=e.gamma,r[5]=e.alpha,o[6]=(e.matchNearest?rs:0)|(e.faceBias?ss:0)|(e.reuseContacts?os:0)|(e.startAtRest?as:0)|(e.massPenalty?ns:0),o[7]=this.bodyCount,o[8]=this.jointCount,o[9]=this.colorCap,r[10]=this.cellSize,o[11]=this.tableSize-1,r[12]=this.maxSmallRadius,o[13]=this.largeCount,o[14]=this.noCollideCount,o[15]=this.pairCapacity,o[16]=this.contactCapacity,o[17]=this.hashSize-1,o[18]=t+1,o[19]=2*t+1,o[20]=this.tableSize+1,o[21]=2*this.tableSize+1,o[22]=2*this.tableSize+1+t,o[23]=t,o[24]=this.colorHistOffset,o[25]=2*t,o[26]=this.colorGroups,o[27]=2*t+65,o[28]=this.colorRounds,o[29]=this.manifoldCapacity,o[30]=this.stepCount;let a=n=>Math.min(31,Math.max(0,Math.round(Math.log2(n))));o[31]=a(this.primalLanes[0])|a(this.primalLanes[1])<<8|a(this.primalLanes[2])<<16,r.set([e.windSpeed*Math.cos(e.windAngle),e.windSpeed*Math.sin(e.windAngle),0,e.windPressure,e.windGust],32),r.set([e.up[0],e.up[1],e.up[2],0],40),this.device.queue.writeBuffer(this.paramsBuffer,0,i)}writePassConstants(e,t){let i=this.colorCap+1,r=Math.max(e*i,1);(r>this.passEntries||!this.passGroup)&&(this.passBuffer?.destroy(),this.passBuffer=this.device.createBuffer({label:"pass constants",size:r*256,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.passEntries=r,this.passGroup=this.device.createBindGroup({layout:this.layouts.pass,entries:[{binding:0,resource:{buffer:this.passBuffer,size:16}}]}));let o=new ArrayBuffer(r*256),a=new Uint32Array(o),n=new Float32Array(o);for(let l=0;l<e;l++)for(let c=0;c<=this.colorCap;c++){let u=(l*i+c)*256/4;a[u]=c,n[u+1]=t}this.device.queue.writeBuffer(this.passBuffer,0,o)}step(){(this.radiiDirty||this.noCollideDirty)&&this.uploadStatics();let e=this.params;this.fixedColors&&(this.device.queue.writeBuffer(this.colorBuffer,0,this.fixedColors),this.colorCap=Math.max(1,...this.fixedColors.map(y=>y===255?0:y+1))),this.stepCount++,this.writeParams(),this.writePassConstants(e.iterations,e.alpha);let t=this.parity,i=this.bodyCapacity,r=this.bodyCount,o=this.jointCount,a=this.device.createCommandEncoder({label:"avbd3d step"});a.clearBuffer(this.gridBuffer,0,(2*this.tableSize+1)*4),a.clearBuffer(this.tableBuffer),a.clearBuffer(this.adjBuffer,0,(2*i+1)*4);let n=this.timingCallback!==null&&this.timing!==null,l,c=0,u=n||this.splitPasses,f=()=>{l&&!u||(l?.end(),l=a.beginComputePass({label:u?Se[c]:"avbd3d step",timestampWrites:n?{querySet:this.timing.querySet,beginningOfPassWriteIndex:2*c,endOfPassWriteIndex:2*c+1}:void 0}),c++)},d=this.groups,h=(y,A,v)=>{v<=0||(l.setPipeline(this.pipes[y]),l.setBindGroup(0,A),l.dispatchWorkgroups(v))},m=(y,A,v)=>{l.setPipeline(this.pipes[y]),l.setBindGroup(0,A),l.dispatchWorkgroupsIndirect(this.argsBuffer,v*4)};if(f(),h("beginFrame",d.broad,1),e.reuseContacts&&h("updateRefs",d.refs,pt(r)),h("argsPrev",d.args,1),m("hashInsert",d.contacts[t],6),h("gridCount",d.broad,pt(r)),this.gridScan.encode(l),h("gridScatter",d.broad,pt(r)),h("findPairs",d.broad,pt(r)),h("argsPairs",d.args,1),m("narrowphase",d.contacts[t],0),h("argsContacts",d.args,1),f(),h("degreeJoints",d.topo[t],pt(o)),m("degreeContacts",d.topo[t],3),this.adjScan.encode(l),h("fillJoints",d.topo[t],pt(o)),m("fillContacts",d.topo[t],3),h("sortAdjacency",d.topo[t],pt(r)),f(),!this.fixedColors){h("colorCompact",d.topo[t],pt(r)),h("colorMark",d.topo[t],pt(r));for(let y=0;y<this.colorRounds;y++)h(y%2===0?"colorRoundAB":"colorRoundBA",d.topo[t],pt(r))}h("colorCount",d.topo[t],this.colorGroups),this.colorHistScan.encode(l),h("colorStarts",d.topo[t],1),h("argsColors",d.args,1),h("colorScatter",d.topo[t],this.colorGroups),f();let p=this.colorCap+1,g=y=>l.setBindGroup(1,this.passGroup,[y*256]);l.setBindGroup(0,d.solve[t]),g(0),o>0&&(l.setPipeline(this.pipes.warmStartJoints),l.dispatchWorkgroups(pt(o))),l.setPipeline(this.pipes.warmStartBodies),l.dispatchWorkgroups(pt(r));for(let y=0;y<e.iterations;y++){l.setPipeline(this.pipes.primal);for(let A=0;A<this.colorCap;A++)g(y*p+A),l.dispatchWorkgroupsIndirect(this.argsBuffer,(12+3*A)*4);g(y*p+this.colorCap),l.setPipeline(this.pipes.dual),l.dispatchWorkgroupsIndirect(this.argsBuffer,36)}l.setPipeline(this.pipes.updateVelocities),l.dispatchWorkgroups(pt(r)),l.end();let b=2*Se.length;if(n){let{querySet:y,resolve:A,read:v}=this.timing;a.resolveQuerySet(y,0,b,A,0),a.copyBufferToBuffer(A,0,v,0,b*8)}if(this.device.queue.submit([a.finish()]),this.parity=1-t,n){let y=this.timingCallback;this.timingCallback=null,this.timingBusy=!0;let A=this.timing.read;A.mapAsync(GPUMapMode.READ).then(()=>{let v=new BigUint64Array(A.getMappedRange()).slice();if(A.unmap(),this.timingBusy=!1,this.destroyed)return this.releaseTiming();let x=(B,L)=>Number(v[L]-v[B])/1e6,w={total:x(0,b-1)};Se.forEach((B,L)=>w[B]=x(2*L,2*L+1)),y(w)},()=>{this.timingBusy=!1,this.destroyed&&this.releaseTiming()})}}async readBodies(){return new Float32Array(await this.read(this.bodyBuffer,this.bodyCount*He*4))}async readJoints(){return new Float32Array(await this.read(this.jointBuffer,this.jointCount*he*4))}async readCounters(){let e=new Uint32Array(await this.read(this.counterBuffer,64));return{pairs:e[0],contacts:e[1],manifolds:e[gr],overflow:e[3],clashes:e[4],colors:e[5]}}async readContactList(){let e=await this.readCounters(),t=Math.min(e.manifolds,this.manifoldCapacity),i=Math.min(e.contacts,this.contactCapacity),r=1-this.parity,[o,a]=await Promise.all([this.read(this.manifoldBuffers[r],t*Nt*4),this.read(this.contactBuffers[r],i*Ht*4)]),n=new Uint32Array(o),l=new Float32Array(o),c=new Uint32Array(a),u=new Float32Array(a),f=[];for(let d=0;d<t;d++){let h=d*Nt,m=[...l.subarray(h+Js,h+Js+3)];for(let p=n[h+2];p<n[h+2]+(n[h+3]&15);p++){let g=p*Ht,b=c[g+mr+3];f.push({a:n[h],b:n[h+1],feature:(b&~ts)>>>0,stick:(b&ts)!==0,rA:[...u.subarray(g+mr,g+mr+3)],rB:[...u.subarray(g+Xs,g+Xs+3)],pen:[...u.subarray(g+Ys,g+Ys+3)],lam:[...u.subarray(g+Qs,g+Qs+3)],normal:m})}}return f}async readPairs(){let{pairs:e}=await this.readCounters();return new Uint32Array(await this.read(this.pairBuffer,Math.min(e,this.pairCapacity)*8))}jointInfo(){return this.info.subarray(0,this.jointCount*4)}adapt(e){if(this.fixedColors)return;let t=e.colors;e.clashes>0&&(this.colorRounds=Math.min(32,this.colorRounds*2)),e.clashes>0||this.colorCap-t<2?(this.colorCap=Math.min(64,Math.max(t+io+2,this.colorCap+4)),this.shrinkVotes=0):t+io+2<this.colorCap||this.colorRounds>4?++this.shrinkVotes>=3&&(this.colorCap=Math.min(64,t+io),this.colorRounds=Math.max(4,this.colorRounds-4),this.shrinkVotes=0):this.shrinkVotes=0;let i=(n,l,c)=>(e.overflow&c)!==0||n>hf*l?Math.max(mf*n,1.25*l):l,r=i(e.contacts,this.contactCapacity,2),o=i(e.pairs,this.pairCapacity,1),a=i(e.manifolds,this.manifoldCapacity,4);this.capacityCanGrow(r,o,a)&&this.allocateContacts(r,o,a)}capacityCanGrow(e,t,i){let r=this.device.limits.maxStorageBufferBindingSize;return Math.min(e,r/(Ht*4))>this.contactCapacity||Math.min(t,r/8)>this.pairCapacity||Math.min(i,t,r/(Nt*4))>this.manifoldCapacity}async read(e,t){if(t===0)return new ArrayBuffer(0);let i=this.device.createBuffer({size:t,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),r=this.device.createCommandEncoder();r.copyBufferToBuffer(e,0,i,0,t),this.device.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ);let o=i.getMappedRange().slice(0);return i.unmap(),i.destroy(),o}releaseTiming(){this.timing?.resolve.destroy(),this.timing?.read.destroy(),this.timing?.querySet.destroy()}destroy(){this.ownsBodyBuffer&&this.bodyBuffer.destroy();let e=[this.jointBuffer,this.infoBuffer,...this.contactBuffers,...this.manifoldBuffers,this.pairBuffer,this.tableBuffer,this.gridBuffer,this.staticBuffer,this.counterBuffer,this.argsBuffer,this.adjBuffer,this.colorBuffer,this.paramsBuffer,this.refBuffer,this.hullBuffer,this.passBuffer,this.filterBuffer];for(let t of e)t?.destroy();this.destroyed=!0,this.timingBusy||this.releaseTiming(),this.gridScan.destroy(),this.colorHistScan.destroy(),this.adjScan?.destroy()}};var jl=` e.C = vec3f(
2422
2422
  k.c0x * keep + dot(n, A.dLin) - dot(n, B.dLin) + dot(cross(e.rAW, n), A.dAng) + dot(cross(e.rBW, -n), B.dAng),
2423
2423
  k.c0y * keep + dot(t1, A.dLin) - dot(t1, B.dLin) + dot(cross(e.rAW, t1), A.dAng) + dot(cross(e.rBW, -t1), B.dAng),
2424
2424
  k.c0z * keep + dot(t2, A.dLin) - dot(t2, B.dLin) + dot(cross(e.rAW, t2), A.dAng) + dot(cross(e.rBW, -t2), B.dAng));`;if(Ge.split(jl).length!==2)throw Error("Pinned contact evaluation changed; review the app kernel variant");var us=Ge.replace(jl,` let delta = A.dLin - B.dLin + cross(A.dAng, e.rAW) - cross(B.dAng, e.rBW);
@@ -2472,18 +2472,18 @@ fn rotate(q:vec4f,v:vec3f)->vec3f {let t=2.*cross(q.xyz,v);return v+q.w*t+cross(
2472
2472
  joints[slot].rA.w=length(pa-pb);
2473
2473
  }
2474
2474
  }
2475
- `;function hi(s){let e=new ArrayBuffer(s*4);return{f:new Float32Array(e),u:new Uint32Array(e),previous:new Uint32Array(s),buffer:null,uploads:0,bytes:0}}function Qt(s,e,t){let{u:i,previous:r}=t,o=0,a=i.length-1;if(t.buffer===e){for(;o<=a&&i[o]===r[o];)o++;for(;a>=o&&i[a]===r[a];)a--;if(o>a)return}s.queue.writeBuffer(e,o*4,i,o,a-o+1),r.set(i),t.buffer=e,t.uploads++,t.bytes+=(a-o+1)*4}var Gl=`// Conservative GPU sleeping. Resting contacts form supports from the ground
2475
+ `;function pi(s){let e=new ArrayBuffer(s*4);return{f:new Float32Array(e),u:new Uint32Array(e),previous:new Uint32Array(s),buffer:null,uploads:0,bytes:0}}function Qt(s,e,t){let{u:i,previous:r}=t,o=0,a=i.length-1;if(t.buffer===e){for(;o<=a&&i[o]===r[o];)o++;for(;a>=o&&i[a]===r[a];)a--;if(o>a)return}s.queue.writeBuffer(e,o*4,i,o,a-o+1),r.set(i),t.buffer=e,t.uploads++,t.bytes+=(a-o+1)*4}var Gl=`// Conservative GPU sleeping. Resting contacts form supports from the ground
2476
2476
  // upward. Any impact, moving joint endpoint or explicit edit wakes the world.
2477
2477
  // This deliberately favors reliable waking over finely partitioned islands.
2478
2478
  struct Body { pos:vec4f,rot:vec4f,initialPos:vec4f,initialRot:vec4f,size:vec4f,moment:vec4f,inertialPos:vec4f,inertialRot:vec4f,velocity:vec4f,angular:vec4f }
2479
2479
  struct State { mass:f32, quiet:f32, asleep:u32, support:atomic<u32>, eligible:u32, pad0:u32, pad1:u32, pad2:u32 }
2480
2480
  struct Manifold { ids:vec4u, geo:vec4f }
2481
- struct Params { count:u32,joints:u32,manifolds:u32,forceWake:u32,speed:f32,delay:f32,dt:f32,gravity:f32,up:vec4f }
2481
+ struct Params { count:u32,joints:u32,manifolds:u32,forceWake:u32,speed:f32,delay:f32,dt:f32,gravity:f32,up:vec3f,pairs:u32 }
2482
2482
  @group(0) @binding(0) var<storage,read_write> bodies:array<Body>;
2483
2483
  @group(0) @binding(1) var<storage,read_write> states:array<State>;
2484
2484
  @group(0) @binding(2) var<storage,read> info:array<vec4i>;
2485
2485
  @group(0) @binding(3) var<storage,read> manifolds:array<Manifold>;
2486
- @group(0) @binding(4) var<storage,read> counters:array<u32>;
2486
+ @group(0) @binding(4) var<storage,read_write> counters:array<u32>;
2487
2487
  @group(0) @binding(5) var<storage,read_write> globals:array<atomic<u32>>;
2488
2488
  @group(0) @binding(6) var<uniform> params:Params;
2489
2489
  fn speed(i:u32)->f32 {return length(bodies[i].velocity.xyz)+length(bodies[i].angular.xyz)*bodies[i].moment.w;}
@@ -2493,7 +2493,7 @@ fn wake(i:u32) {if(states[i].mass>0.){bodies[i].size.w=states[i].mass;states[i].
2493
2493
  if(params.forceWake!=0u||atomicLoad(&globals[0])!=0u||(states[i].pad2&2u)!=0u){wake(i);}
2494
2494
  atomicStore(&states[i].support,0u);
2495
2495
  }
2496
- @compute @workgroup_size(1) fn clear() {atomicStore(&globals[0],0u);atomicStore(&globals[1],0u);}
2496
+ @compute @workgroup_size(1) fn clear() {atomicStore(&globals[0],0u);atomicStore(&globals[1],0u);atomicStore(&globals[2],0u);atomicStore(&globals[3],0u);}
2497
2497
  fn impact(a:u32,b:u32) {
2498
2498
  if(states[a].asleep!=0u && states[b].asleep==0u && speed(b)>2.*params.speed){atomicStore(&globals[0],1u);}
2499
2499
  }
@@ -2502,11 +2502,15 @@ fn signalWake(i:u32){atomicStore(&globals[0],1u);}
2502
2502
  let i=id.x;if(i>=min(counters[6],params.manifolds)){return;}
2503
2503
  let m=manifolds[i];if((m.ids.w&15u)==0u || (m.ids.w&0x80000000u)!=0u){return;}
2504
2504
  let a=m.ids.x;let b=m.ids.y;
2505
- manifoldImpact(m);
2505
+ manifoldImpact(m,false);
2506
2506
  let up=dot(m.geo.xyz,params.up.xyz);
2507
2507
  if(up>0.3){support(a,b);}
2508
2508
  if(up < -0.3){support(b,a);}
2509
2509
  }
2510
+ @compute @workgroup_size(64) fn applyImpact(@builtin(global_invocation_id) id:vec3u){
2511
+ let i=id.x;if(i>=params.count || states[i].asleep==0u || atomicLoad(&globals[0])==0u){return;}
2512
+ wake(i);atomicAdd(&globals[2],1u);
2513
+ }
2510
2514
  @compute @workgroup_size(64) fn joints(@builtin(global_invocation_id) id:vec3u) {
2511
2515
  let i=id.x;if(i>=params.joints){return;}let j=info[i];if(j.x==0||j.y<0){return;}
2512
2516
  impact(u32(j.y),u32(j.z));impact(u32(j.z),u32(j.y));
@@ -2528,12 +2532,12 @@ fn signalWake(i:u32){atomicStore(&globals[0],1u);}
2528
2532
  `;var Fl=`struct Body { pos:vec4f,rot:vec4f,initialPos:vec4f,initialRot:vec4f,size:vec4f,moment:vec4f,inertialPos:vec4f,inertialRot:vec4f,velocity:vec4f,angular:vec4f }
2529
2533
  struct State { mass:f32, quiet:f32, asleep:u32, support:atomic<u32>, eligible:u32, parent:atomic<u32>, wake:atomic<u32>, pad2:u32 }
2530
2534
  struct Manifold { ids:vec4u, geo:vec4f }
2531
- struct Params { count:u32,joints:u32,manifolds:u32,forceWake:u32,speed:f32,delay:f32,dt:f32,gravity:f32,up:vec4f }
2535
+ struct Params { count:u32,joints:u32,manifolds:u32,forceWake:u32,speed:f32,delay:f32,dt:f32,gravity:f32,up:vec3f,pairs:u32 }
2532
2536
  @group(0) @binding(0) var<storage,read_write> bodies:array<Body>;
2533
2537
  @group(0) @binding(1) var<storage,read_write> states:array<State>;
2534
2538
  @group(0) @binding(2) var<storage,read> info:array<vec4i>;
2535
2539
  @group(0) @binding(3) var<storage,read> manifolds:array<Manifold>;
2536
- @group(0) @binding(4) var<storage,read> counters:array<u32>;
2540
+ @group(0) @binding(4) var<storage,read_write> counters:array<u32>;
2537
2541
  @group(0) @binding(5) var<storage,read_write> globals:array<atomic<u32>>;
2538
2542
  @group(0) @binding(6) var<uniform> params:Params;
2539
2543
  fn speed(i:u32)->f32 {return length(bodies[i].velocity.xyz)+length(bodies[i].angular.xyz)*bodies[i].moment.w;}
@@ -2549,7 +2553,7 @@ fn wake(i:u32) {if(states[i].mass>0.){bodies[i].size.w=states[i].mass;states[i].
2549
2553
  atomicStore(&states[i].wake,0u);
2550
2554
  atomicStore(&states[i].support,0u);
2551
2555
  }
2552
- @compute @workgroup_size(1) fn clear() {atomicStore(&globals[0],0u);atomicStore(&globals[1],0u);}
2556
+ @compute @workgroup_size(1) fn clear() {atomicStore(&globals[0],0u);atomicStore(&globals[1],0u);atomicStore(&globals[2],0u);atomicStore(&globals[3],0u);}
2553
2557
  // Gather old roots before before() resets awake parents. Separate dispatches
2554
2558
  // prevent another workgroup from clearing a wake request before it is consumed.
2555
2559
  @compute @workgroup_size(64) fn requestWake(@builtin(global_invocation_id) id:vec3u){
@@ -2563,12 +2567,12 @@ fn wake(i:u32) {if(states[i].mass>0.){bodies[i].size.w=states[i].mass;states[i].
2563
2567
  fn impact(a:u32,b:u32) {
2564
2568
  if(states[a].asleep!=0u && states[b].asleep==0u && speed(b)>2.*params.speed){signalWake(a);}
2565
2569
  }
2566
- fn signalWake(i:u32){let r=root(i);if(r<params.count){atomicOr(&states[r].wake,1u);}else{atomicStore(&globals[0],1u);}}
2570
+ fn signalWake(i:u32){atomicStore(&globals[3],1u);let r=root(i);if(r<params.count){atomicOr(&states[r].wake,1u);}else{atomicStore(&globals[0],1u);}}
2567
2571
  @compute @workgroup_size(64) fn contacts(@builtin(global_invocation_id) id:vec3u) {
2568
2572
  let i=id.x;if(i>=min(counters[6],params.manifolds)){return;}
2569
2573
  let m=manifolds[i];if((m.ids.w&15u)==0u || (m.ids.w&0x80000000u)!=0u){return;}
2570
2574
  let a=m.ids.x;let b=m.ids.y;
2571
- manifoldImpact(m);
2575
+ manifoldImpact(m,false);
2572
2576
  let up=dot(m.geo.xyz,params.up.xyz);
2573
2577
  if(up>0.3){support(a,b);}
2574
2578
  if(up < -0.3){support(b,a);}
@@ -2577,6 +2581,17 @@ fn signalWake(i:u32){let r=root(i);if(r<params.count){atomicOr(&states[r].wake,1
2577
2581
  if(states[a].mass<=0. && speed(a)<=params.speed && up< -0.3 && states[b].mass>0.){atomicOr(&states[root(b)].wake,2u);}
2578
2582
  }
2579
2583
  }
2584
+ // Restore the complete old sleeping island before topology and warm starting.
2585
+ // The spatial structures retain every body, so only pair/contact generation
2586
+ // needs a conditional refresh when static sleepers become dynamic again.
2587
+ @compute @workgroup_size(64) fn applyImpact(@builtin(global_invocation_id) id:vec3u){
2588
+ if(atomicLoad(&globals[3])==0u && atomicLoad(&globals[0])==0u){return;}
2589
+ let i=id.x;if(i>=params.count || states[i].asleep==0u){return;}
2590
+ let r=root(i);
2591
+ if(r>=params.count || atomicLoad(&globals[0])!=0u || (atomicLoad(&states[min(r,params.count-1u)].wake)&1u)!=0u){
2592
+ wake(i);atomicAdd(&globals[2],1u);
2593
+ }
2594
+ }
2580
2595
  @compute @workgroup_size(64) fn joints(@builtin(global_invocation_id) id:vec3u) {
2581
2596
  let i=id.x;if(i>=params.joints){return;}let j=info[i];if(j.x==0||j.y<0){return;}
2582
2597
  impact(u32(j.y),u32(j.z));impact(u32(j.z),u32(j.y));
@@ -2654,6 +2669,7 @@ fn connect(a:u32,b:u32) {
2654
2669
  }
2655
2670
  `;var Ul=`struct Contact {rA:vec3f,key:u32,rB:vec3f,c0x:f32,pen:vec3f,c0y:f32,lam:vec3f,c0z:f32}
2656
2671
  @group(0) @binding(7) var<storage,read> contactPoints:array<Contact>;
2672
+ @group(0) @binding(8) var<storage,read_write> refreshArgs:array<u32>;
2657
2673
  fn rotated(q:vec4f,r:vec3f)->vec3f {return r+2.*cross(q.xyz,cross(q.xyz,r)+q.w*r);}
2658
2674
  fn contactVelocity(i:u32,r:vec3f,previous:bool)->vec3f {
2659
2675
  // Prediction is skipped while asleep. The last inertial target can retain
@@ -2673,21 +2689,48 @@ fn contactVelocity(i:u32,r:vec3f,previous:bool)->vec3f {
2673
2689
  }
2674
2690
  return v+cross(w,rotated(q,r));
2675
2691
  }
2676
- fn manifoldImpact(m:Manifold){
2692
+ fn manifoldImpact(m:Manifold,beforeSolve:bool){
2677
2693
  let a=m.ids.x;let b=m.ids.y;
2678
2694
  if(states[a].asleep==states[b].asleep){return;}
2679
2695
  // A rotating face can approach at one corner while its first contact recedes.
2680
2696
  for(var k=0u;k<(m.ids.w&15u);k++){
2681
2697
  let c=contactPoints[m.ids.z+k];
2682
- contactImpact(a,b,m.geo.xyz,c.rA,c.rB);contactImpact(b,a,-m.geo.xyz,c.rB,c.rA);
2698
+ contactImpact(a,b,m.geo.xyz,c.rA,c.rB,beforeSolve);contactImpact(b,a,-m.geo.xyz,c.rB,c.rA,beforeSolve);
2683
2699
  }
2684
2700
  }
2685
- fn contactImpact(a:u32,b:u32,n:vec3f,rA:vec3f,rB:vec3f) {
2701
+ fn contactImpact(a:u32,b:u32,n:vec3f,rA:vec3f,rB:vec3f,beforeSolve:bool) {
2686
2702
  if(states[a].asleep==0u || states[b].asleep!=0u){return;}
2687
- let incoming=dot(contactVelocity(b,rB,true)-contactVelocity(a,rA,true),n);
2703
+ // Before prediction, velocity is already the incoming velocity. Inertial
2704
+ // targets still belong to the previous step and must not be read here.
2705
+ var incoming=0.;
2706
+ if(!beforeSolve){incoming=dot(contactVelocity(b,rB,true)-contactVelocity(a,rA,true),n);}
2688
2707
  let outgoing=dot(contactVelocity(b,rB,false)-contactVelocity(a,rA,false),n);
2689
2708
  if(max(incoming,outgoing)>2.*params.speed){signalWake(a);}
2690
2709
  }
2710
+ @compute @workgroup_size(64) fn impactContacts(@builtin(global_invocation_id) id:vec3u){
2711
+ let i=id.x;if(i>=min(counters[6],params.manifolds)){return;}
2712
+ let m=manifolds[i];if((m.ids.w&15u)==0u || (m.ids.w&0x80000000u)!=0u){return;}
2713
+ manifoldImpact(m,true);
2714
+ }
2715
+ @compute @workgroup_size(64) fn impactJoints(@builtin(global_invocation_id) id:vec3u){
2716
+ let i=id.x;if(i>=params.joints){return;}let j=info[i];if(j.x==0||j.y<0){return;}
2717
+ impact(u32(j.y),u32(j.z));impact(u32(j.z),u32(j.y));
2718
+ }
2719
+ @compute @workgroup_size(1) fn preparePairs(){
2720
+ let changed=atomicLoad(&globals[2])!=0u;
2721
+ refreshArgs[0]=select(0u,(params.count+63u)/64u,changed);
2722
+ refreshArgs[1]=1u;refreshArgs[2]=1u;
2723
+ if(changed){counters[0]=0u;counters[1]=0u;counters[6]=0u;}
2724
+ }
2725
+ @compute @workgroup_size(1) fn prepareWake(){
2726
+ let requested=atomicLoad(&globals[0])!=0u || atomicLoad(&globals[3])!=0u;
2727
+ refreshArgs[0]=select(0u,(params.count+63u)/64u,requested);
2728
+ refreshArgs[1]=1u;refreshArgs[2]=1u;
2729
+ }
2730
+ @compute @workgroup_size(1) fn prepareNarrowphase(){
2731
+ refreshArgs[3]=select(0u,(min(counters[0],params.pairs)+63u)/64u,atomicLoad(&globals[2])!=0u);
2732
+ refreshArgs[4]=1u;refreshArgs[5]=1u;
2733
+ }
2691
2734
  fn support(a:u32,b:u32) {
2692
2735
  // Grounded, quiet awake bodies can support the next course. This lets a stack
2693
2736
  // accumulate quiet time together instead of stopping one course at a time.
@@ -2695,14 +2738,14 @@ fn support(a:u32,b:u32) {
2695
2738
  atomicStore(&states[a].support,1u);
2696
2739
  }
2697
2740
  }
2698
- `;var an=class{constructor(e){this.device=e,this.targets=new Map,this.bits=new Float32Array(1),this.words=new Uint32Array(this.bits.buffer)}target(e){let t=this.targets.get(e);return t||this.targets.set(e,t={pending:new Map}),t}uint(e,t,i){this.target(e).pending.set(t,i>>>0)}float(e,t,i){this.bits[0]=i,this.uint(e,t,this.words[0])}get pending(){for(let e of this.targets.values())if(e.pending.size)return!0;return!1}flush(e){let t=this.device,i=e,r=0,o=0,a=0,n=0;for(let[l,c]of this.targets){let u=c.pending.size;if(!u)continue;(!c.data||c.data.length<u*2)&&(c.data=new Uint32Array(Math.max(u*2,(c.data?.length??0)*2,128)));let f=Array.from(c.pending.keys()),d=!0;for(let m=1;m<u;m++)if(f[m]<f[m-1]){d=!1;break}d||f.sort((m,h)=>m-h);let p=1;for(let m=1;m<u;m++)f[m]!==f[m-1]+1&&p++;if(p<=4||u<=8){for(let m=0;m<u;m++)c.data[m]=c.pending.get(f[m]);for(let m=0;m<u;){let h=m+1;for(;h<u&&f[h]===f[h-1]+1;)h++;t.queue.writeBuffer(l,f[m]*4,c.data.buffer,m*4,(h-m)*4),r++,m=h}n+=u*4}else{let m=u*8,h=Math.min(t.limits.maxBufferSize,t.limits.maxStorageBufferBindingSize);if(m>h)throw Error("Property batch exceeds GPU buffer limits");for(let A=0;A<u;A++)c.data[A*2]=f[A],c.data[A*2+1]=c.pending.get(f[A]);(!c.upload||c.upload.size<m)&&(c.upload?.destroy(),c.upload=t.createBuffer({size:Math.min(h,m*2),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),c.group=null),t.queue.writeBuffer(c.upload,0,c.data.buffer,0,m),this.pipeline??=t.createComputePipeline({layout:"auto",compute:{entryPoint:"applyEdits",module:t.createShaderModule({code:`
2741
+ `;var an=class{constructor(e){this.device=e,this.targets=new Map,this.bits=new Float32Array(1),this.words=new Uint32Array(this.bits.buffer)}target(e){let t=this.targets.get(e);return t||this.targets.set(e,t={pending:new Map}),t}uint(e,t,i){this.target(e).pending.set(t,i>>>0)}float(e,t,i){this.bits[0]=i,this.uint(e,t,this.words[0])}get pending(){for(let e of this.targets.values())if(e.pending.size)return!0;return!1}flush(e){let t=this.device,i=e,r=0,o=0,a=0,n=0;for(let[l,c]of this.targets){let u=c.pending.size;if(!u)continue;(!c.data||c.data.length<u*2)&&(c.data=new Uint32Array(Math.max(u*2,(c.data?.length??0)*2,128)));let f=Array.from(c.pending.keys()),d=!0;for(let m=1;m<u;m++)if(f[m]<f[m-1]){d=!1;break}d||f.sort((m,p)=>m-p);let h=1;for(let m=1;m<u;m++)f[m]!==f[m-1]+1&&h++;if(h<=4||u<=8){for(let m=0;m<u;m++)c.data[m]=c.pending.get(f[m]);for(let m=0;m<u;){let p=m+1;for(;p<u&&f[p]===f[p-1]+1;)p++;t.queue.writeBuffer(l,f[m]*4,c.data.buffer,m*4,(p-m)*4),r++,m=p}n+=u*4}else{let m=u*8,p=Math.min(t.limits.maxBufferSize,t.limits.maxStorageBufferBindingSize);if(m>p)throw Error("Property batch exceeds GPU buffer limits");for(let A=0;A<u;A++)c.data[A*2]=f[A],c.data[A*2+1]=c.pending.get(f[A]);(!c.upload||c.upload.size<m)&&(c.upload?.destroy(),c.upload=t.createBuffer({size:Math.min(p,m*2),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),c.group=null),t.queue.writeBuffer(c.upload,0,c.data.buffer,0,m),this.pipeline??=t.createComputePipeline({layout:"auto",compute:{entryPoint:"applyEdits",module:t.createShaderModule({code:`
2699
2742
  @group(0) @binding(0) var<storage,read_write> outputWords:array<u32>;
2700
2743
  @group(0) @binding(1) var<storage,read> edits:array<vec2u>;
2701
2744
  @compute @workgroup_size(64) fn applyEdits(@builtin(global_invocation_id) id:vec3u){
2702
2745
  let i=id.x+id.y*${t.limits.maxComputeWorkgroupsPerDimension*64}u;
2703
2746
  if(i>=arrayLength(&edits)){return;}let edit=edits[i];outputWords[edit.x]=edit.y;
2704
- }`})}}),(!c.group||c.bytes!==m)&&(c.group=t.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:l}},{binding:1,resource:{buffer:c.upload,size:m}}]}),c.bytes=m),i??=t.createCommandEncoder({label:"AVBD property edits"});let g=i.beginComputePass();g.setPipeline(this.pipeline),g.setBindGroup(0,c.group);let b=Math.ceil(u/64),y=t.limits.maxComputeWorkgroupsPerDimension;g.dispatchWorkgroups(Math.min(b,y),Math.ceil(b/y)),g.end(),r++,o++,n+=m}a+=u,c.pending.clear()}!e&&i&&t.queue.submit([i.finish()]),a&&(this.lastBatch={words:a,writes:r,dispatches:o,uploadedBytes:n,submissions:!e&&i?1:0})}destroy(){for(let e of this.targets.values())e.upload?.destroy();this.targets.clear()}forget(e){this.targets.get(e)?.upload?.destroy(),this.targets.delete(e)}};function oe(s){return s.propertyEdits??=new an(s.device)}var Fi=class{constructor(e,t={}){if(this.world=e,this.device=e.device,this.speed=t.speedThreshold??.03,this.delay=t.timeThreshold??.5,t.startAsleep!==void 0&&typeof t.startAsleep!="boolean")throw Error("startAsleep must be a boolean");if(t.islands!==void 0&&typeof t.islands!="boolean")throw Error("Sleep islands must be a boolean");if(this.islands=t.islands??(e.gpu.bodyCount>=4096&&!e.gpu.portableContactMath&&!e.gpu.dispatchIsolation),this.initializing=!!t.startAsleep&&this.islands,!Number.isFinite(this.speed)||this.speed<=0||!Number.isFinite(this.delay)||this.delay<=0)throw Error("Sleep speedThreshold and timeThreshold must be positive and finite");let i=this.device,r=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC;this.state=i.createBuffer({size:e.capacity*32,usage:r}),this.globals=i.createBuffer({size:8,usage:r}),this.params=i.createBuffer({size:48,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=i.createShaderModule({code:`${this.islands?Fl:Gl}
2705
- ${Ul}`});this.layout=i.createBindGroupLayout({entries:["storage","storage","read-only-storage","read-only-storage","read-only-storage","storage","uniform","read-only-storage"].map((c,u)=>({binding:u,visibility:GPUShaderStage.COMPUTE,buffer:{type:c}}))});let a=i.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipelines=Object.fromEntries(["before","clear",...this.islands?["requestWake","gatherWake","connectContacts","connectJoints","activity"]:[],"contacts","joints","rest"].map(c=>[c,i.createComputePipeline({layout:a,compute:{module:o,entryPoint:c}})]));let n=new Float32Array(e.capacity*8),l=new Uint32Array(n.buffer);for(let c of e.aggregates)if(!c.disposed){let u=(c.gpuSlot??e.gpu.gpuIndex(c.index))*8;n[u]=c.rigid.mass,l[u+4]=c.allowSleep===!1||c.rigid.allowSleep===!1?0:1,this.islands&&(l[u+5]=u/8)}i.queue.writeBuffer(this.state,0,n),this.wakeRequested=!1}register(e,t,i=!0){let r=new Float32Array([t,0,0,0,0,0,0,0]);new Uint32Array(r.buffer)[4]=i?1:0,this.islands&&(new Uint32Array(r.buffer)[5]=e);let o=new Uint32Array(r.buffer),a=oe(this.world.gpu);for(let n=0;n<8;n++)a.uint(this.state,e*8+n,o[n]);this.wakeRequested=!0}bindContacts(){let e=this.world.gpu,t=e.contactStorage,i=[e.bodyBuffer,this.state,e.infoBuffer,t.manifolds,t.counters,this.globals,this.params,t.contacts],r=this.groups?.find(o=>o.buffers.every((a,n)=>a===i[n]));r||(r={buffers:i,group:this.device.createBindGroup({layout:this.layout,entries:i.map((o,a)=>({binding:a,resource:{buffer:o}}))})},this.groups=[...(this.groups??[]).slice(-1),r]),this.group=r.group}before(e){this.world.gpu.flushPropertyEdits(e);let{gpu:t}=this.world,i=this.paramData??=hi(12),{u:r,f:o}=i;r[0]=t.bodyCount,r[1]=t.jointCount,r[2]=t.manifoldCapacity,r[3]=Number(this.wakeRequested)|(this.initializing?2:0),o[4]=this.speed,o[5]=this.delay,o[6]=t.params.dt,o[7]=t.params.gravity,o[8]=t.params.up[0],o[9]=t.params.up[1],o[10]=t.params.up[2],Qt(this.device,this.params,i),this.wakeRequested=!1,this.bindContacts(),this.run([...this.islands&&this.localWakeRequested?[["requestWake",t.bodyCount],["gatherWake",t.bodyCount]]:[],["before",t.bodyCount],["clear",1]],e),this.localWakeRequested=!1}wakeBody(e){if(!Number.isInteger(e)||e<0||e>=this.world.gpu.bodyCount)throw Error("Sleeping wake requires a live GPU body index");oe(this.world.gpu).uint(this.state,e*8+7,2),this.localWakeRequested=!0}after(e){let t=this.world.gpu;this.bindContacts(),this.run([...this.islands?[["connectContacts",t.manifoldCapacity],["connectJoints",t.jointCount]]:[],["contacts",t.manifoldCapacity],["joints",t.jointCount],...this.islands?[["activity",t.bodyCount]]:[],["rest",t.bodyCount]],e),this.initializing=!1}run(e,t){let i=t??this.device.createCommandEncoder(),r=i.beginComputePass();r.setBindGroup(0,this.group);for(let[o,a]of e)a&&(r.setPipeline(this.pipelines[o]),r.dispatchWorkgroups(o==="clear"?1:Math.ceil(a/64)));r.end(),t||this.device.queue.submit([i.finish()])}async readStats(){let e=this.device,t=e.createBuffer({size:8,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});try{let i=e.createCommandEncoder();i.copyBufferToBuffer(this.globals,0,t,0,8),e.queue.submit([i.finish()]),await t.mapAsync(GPUMapMode.READ);let r=new Uint32Array(t.getMappedRange());return{sleeping:r[1],wakeRequested:!!r[0]}}finally{t.destroy()}}dispose(){this.world.gpu.propertyEdits?.forget(this.state),this.state.destroy(),this.globals.destroy(),this.params.destroy()}};function Sf(s){s=s.replaceAll("bodies[","localBodies["),s=s.replace("var<storage, read_write> bodies: array<Body>;","var<storage, read_write> globalBodies: array<Body>;");let e=s.indexOf(`@compute @workgroup_size(64)
2747
+ }`})}}),(!c.group||c.bytes!==m)&&(c.group=t.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:l}},{binding:1,resource:{buffer:c.upload,size:m}}]}),c.bytes=m),i??=t.createCommandEncoder({label:"AVBD property edits"});let g=i.beginComputePass();g.setPipeline(this.pipeline),g.setBindGroup(0,c.group);let b=Math.ceil(u/64),y=t.limits.maxComputeWorkgroupsPerDimension;g.dispatchWorkgroups(Math.min(b,y),Math.ceil(b/y)),g.end(),r++,o++,n+=m}a+=u,c.pending.clear()}!e&&i&&t.queue.submit([i.finish()]),a&&(this.lastBatch={words:a,writes:r,dispatches:o,uploadedBytes:n,submissions:!e&&i?1:0})}destroy(){for(let e of this.targets.values())e.upload?.destroy();this.targets.clear()}forget(e){this.targets.get(e)?.upload?.destroy(),this.targets.delete(e)}};function oe(s){return s.propertyEdits??=new an(s.device)}var Fi=class{constructor(e,t={}){if(this.world=e,this.device=e.device,this.speed=t.speedThreshold??.03,this.delay=t.timeThreshold??.5,t.startAsleep!==void 0&&typeof t.startAsleep!="boolean")throw Error("startAsleep must be a boolean");if(t.islands!==void 0&&typeof t.islands!="boolean")throw Error("Sleep islands must be a boolean");if(this.islands=t.islands??(e.gpu.bodyCount>=4096&&!e.gpu.portableContactMath&&!e.gpu.dispatchIsolation),this.initializing=!!t.startAsleep&&this.islands,!Number.isFinite(this.speed)||this.speed<=0||!Number.isFinite(this.delay)||this.delay<=0)throw Error("Sleep speedThreshold and timeThreshold must be positive and finite");let i=this.device,r=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC;this.state=i.createBuffer({size:e.capacity*32,usage:r}),this.globals=i.createBuffer({size:16,usage:r}),this.refreshArgs=i.createBuffer({size:24,usage:r|GPUBufferUsage.INDIRECT}),this.params=i.createBuffer({size:48,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=i.createShaderModule({code:`${this.islands?Fl:Gl}
2748
+ ${Ul}`});this.layout=i.createBindGroupLayout({entries:["storage","storage","read-only-storage","read-only-storage","storage","storage","uniform","read-only-storage","storage"].map((c,u)=>({binding:u,visibility:GPUShaderStage.COMPUTE,buffer:{type:c}}))});let a=i.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipelines=Object.fromEntries(["before","clear",...this.islands?["requestWake","gatherWake","connectContacts","connectJoints","activity"]:[],"contacts","joints","rest","impactContacts","impactJoints","prepareWake","preparePairs","prepareNarrowphase"].map(c=>[c,i.createComputePipeline({layout:a,compute:{module:o,entryPoint:c}})])),this.pipelines.applyImpact=i.createComputePipeline({layout:"auto",compute:{module:o,entryPoint:"applyImpact"}});let n=new Float32Array(e.capacity*8),l=new Uint32Array(n.buffer);for(let c of e.aggregates)if(!c.disposed){let u=(c.gpuSlot??e.gpu.gpuIndex(c.index))*8;n[u]=c.rigid.mass,l[u+4]=c.allowSleep===!1||c.rigid.allowSleep===!1?0:1,this.islands&&(l[u+5]=u/8)}i.queue.writeBuffer(this.state,0,n),this.wakeRequested=!1}register(e,t,i=!0){let r=new Float32Array([t,0,0,0,0,0,0,0]);new Uint32Array(r.buffer)[4]=i?1:0,this.islands&&(new Uint32Array(r.buffer)[5]=e);let o=new Uint32Array(r.buffer),a=oe(this.world.gpu);for(let n=0;n<8;n++)a.uint(this.state,e*8+n,o[n]);this.wakeRequested=!0}bindContacts(e){let t=this.world.gpu,i=e===void 0?t.contactStorage:{manifolds:t.manifoldBuffers[e],contacts:t.contactBuffers[e],counters:t.counterBuffer},r=[t.bodyBuffer,this.state,t.infoBuffer,i.manifolds,i.counters,this.globals,this.params,i.contacts,this.refreshArgs],o=this.groups?.find(a=>a.buffers.every((n,l)=>n===r[l]));o||(o={buffers:r,impactGroup:this.device.createBindGroup({layout:this.pipelines.applyImpact.getBindGroupLayout(0),entries:[0,1,5,6].map(a=>({binding:a,resource:{buffer:r[a]}}))}),group:this.device.createBindGroup({layout:this.layout,entries:r.map((a,n)=>({binding:n,resource:{buffer:a}}))})},this.groups=[...(this.groups??[]).slice(-1),o]),this.group=o.group,this.impactGroup=o.impactGroup}before(e){this.world.gpu.flushPropertyEdits(e);let{gpu:t}=this.world,i=this.paramData??=pi(12),{u:r,f:o}=i;r[0]=t.bodyCount,r[1]=t.jointCount,r[2]=t.manifoldCapacity,r[3]=Number(this.wakeRequested)|(this.initializing?2:0),o[4]=this.speed,o[5]=this.delay,o[6]=t.params.dt,o[7]=t.params.gravity,o[8]=t.params.up[0],o[9]=t.params.up[1],o[10]=t.params.up[2],r[11]=t.pairCapacity,Qt(this.device,this.params,i),this.wakeRequested=!1,this.bindContacts(),this.run([...this.islands&&this.localWakeRequested?[["requestWake",t.bodyCount],["gatherWake",t.bodyCount]]:[],["before",t.bodyCount],["clear",1]],e),this.localWakeRequested=!1}wakeBody(e){if(!Number.isInteger(e)||e<0||e>=this.world.gpu.bodyCount)throw Error("Sleeping wake requires a live GPU body index");oe(this.world.gpu).uint(this.state,e*8+7,2),this.localWakeRequested=!0}encodeImpact(e,t){let i=this.world.gpu;this.bindContacts(t),e.setBindGroup(0,this.group),e.setPipeline(this.pipelines.impactContacts),e.dispatchWorkgroupsIndirect(i.argsBuffer,12),i.jointCount&&(e.setPipeline(this.pipelines.impactJoints),e.dispatchWorkgroups(Math.ceil(i.jointCount/64))),e.setPipeline(this.pipelines.prepareWake),e.dispatchWorkgroups(1),e.setBindGroup(0,this.impactGroup),e.setPipeline(this.pipelines.applyImpact),e.dispatchWorkgroupsIndirect(this.refreshArgs,0),e.setBindGroup(0,this.group),e.setPipeline(this.pipelines.preparePairs),e.dispatchWorkgroups(1)}encodeRefreshArgs(e){e.setBindGroup(0,this.group),e.setPipeline(this.pipelines.prepareNarrowphase),e.dispatchWorkgroups(1)}after(e){let t=this.world.gpu;this.bindContacts(),this.run([...this.islands?[["connectContacts",t.manifoldCapacity],["connectJoints",t.jointCount]]:[],["contacts",t.manifoldCapacity],["joints",t.jointCount],...this.islands?[["activity",t.bodyCount]]:[],["rest",t.bodyCount]],e),this.initializing=!1}run(e,t){let i=t??this.device.createCommandEncoder(),r=i.beginComputePass();r.setBindGroup(0,this.group);for(let[o,a]of e)a&&(r.setPipeline(this.pipelines[o]),r.dispatchWorkgroups(o==="clear"?1:Math.ceil(a/64)));r.end(),t||this.device.queue.submit([i.finish()])}async readStats(){let e=this.device,t=e.createBuffer({size:8,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});try{let i=e.createCommandEncoder();i.copyBufferToBuffer(this.globals,0,t,0,8),e.queue.submit([i.finish()]),await t.mapAsync(GPUMapMode.READ);let r=new Uint32Array(t.getMappedRange());return{sleeping:r[1],wakeRequested:!!r[0]}}finally{t.destroy()}}dispose(){this.world.gpu.propertyEdits?.forget(this.state),this.state.destroy(),this.globals.destroy(),this.refreshArgs.destroy(),this.params.destroy()}};function Sf(s){s=s.replaceAll("bodies[","localBodies["),s=s.replace("var<storage, read_write> bodies: array<Body>;","var<storage, read_write> globalBodies: array<Body>;");let e=s.indexOf(`@compute @workgroup_size(64)
2706
2749
  fn primal(`),t=s.indexOf(`
2707
2750
  /**`,e);if(e<0||t<e)throw Error("Review small-group primal integration");let i=s.slice(e,t).replace(`@compute @workgroup_size(64)
2708
2751
  `,"").replace("fn primal(@builtin(local_invocation_id) lid: vec3u, @builtin(workgroup_id) wid: vec3u)","fn localPrimal(lid: vec3u, wid: vec3u, col: u32)").replaceAll("pc.color","col");return s.slice(0,e)+i+s.slice(t)+`
@@ -3096,10 +3139,10 @@ fn findTreePairs(@builtin(global_invocation_id) gid:vec3u) {
3096
3139
  at=links[build.escapeOffset+at];
3097
3140
  } else {at=node.left;}
3098
3141
  }
3099
- }`,no=class{constructor(e,t,{rebuildInterval:i=64}={}){if(!Number.isInteger(i)||i<1)throw Error("BVH rebuildInterval must be a positive integer");if(this.device=e,this.capacity=t.bodyCapacity,this.capacity>16*e.limits.maxComputeWorkgroupsPerDimension)throw Error("H-PLOC capacity exceeds the adapter dispatch limit; select the grid");this.bodyBuffer=t.bodyBuffer,this.rebuildInterval=i,this.nodeCapacity=2*this.capacity+16*Math.ceil(Math.log2(Math.max(2,this.capacity)))+32,this.buffers=[],this.uniforms=[],this.stats={builds:0,refits:0,nodes:0,extraBytes:0};let r=(u,f,d=_f())=>{if(d&GPUBufferUsage.STORAGE&&f>e.limits.maxStorageBufferBindingSize)throw Error(`${u} exceeds the adapter storage binding limit`);let p=e.createBuffer({label:u,size:Math.max(16,f),usage:d});return this.buffers.push(p),this.stats.extraBytes+=p.size,p};this.nodes=r("H-PLOC nodes",this.nodeCapacity*32),this.links=r("H-PLOC parents and escape links",this.nodeCapacity*8),this.keys=[r("Morton keys A",this.capacity*8),r("Morton keys B",this.capacity*8)],this.clusters=r("H-PLOC level roots",this.capacity*8+128),this.bounds=r("H-PLOC scene bounds",(Rt(this.capacity)*2+256)*16),this.sortBlocks=Rt(this.capacity),this.hist=r("Morton radix counts",this.sortBlocks*16*4),this.scan=new tt(e,this.hist,0,this.sortBlocks*16);let o=(u,f)=>({binding:u,visibility:GPUShaderStage.COMPUTE,buffer:{type:f}});this.layout=e.createBindGroupLayout({entries:[o(0,"uniform"),o(1,"read-only-storage"),...Array.from({length:5},(u,f)=>o(f+2,"storage"))]}),this.extraLayout=e.createBindGroupLayout({entries:[o(0,"uniform"),o(1,"read-only-storage")]});let a=e.createShaderModule({label:"portable H-PLOC",code:ge+ao+`
3142
+ }`,no=class{constructor(e,t,{rebuildInterval:i=64}={}){if(!Number.isInteger(i)||i<1)throw Error("BVH rebuildInterval must be a positive integer");if(this.device=e,this.capacity=t.bodyCapacity,this.capacity>16*e.limits.maxComputeWorkgroupsPerDimension)throw Error("H-PLOC capacity exceeds the adapter dispatch limit; select the grid");this.bodyBuffer=t.bodyBuffer,this.rebuildInterval=i,this.nodeCapacity=2*this.capacity+16*Math.ceil(Math.log2(Math.max(2,this.capacity)))+32,this.buffers=[],this.uniforms=[],this.stats={builds:0,refits:0,nodes:0,extraBytes:0};let r=(u,f,d=_f())=>{if(d&GPUBufferUsage.STORAGE&&f>e.limits.maxStorageBufferBindingSize)throw Error(`${u} exceeds the adapter storage binding limit`);let h=e.createBuffer({label:u,size:Math.max(16,f),usage:d});return this.buffers.push(h),this.stats.extraBytes+=h.size,h};this.nodes=r("H-PLOC nodes",this.nodeCapacity*32),this.links=r("H-PLOC parents and escape links",this.nodeCapacity*8),this.keys=[r("Morton keys A",this.capacity*8),r("Morton keys B",this.capacity*8)],this.clusters=r("H-PLOC level roots",this.capacity*8+128),this.bounds=r("H-PLOC scene bounds",(Rt(this.capacity)*2+256)*16),this.sortBlocks=Rt(this.capacity),this.hist=r("Morton radix counts",this.sortBlocks*16*4),this.scan=new tt(e,this.hist,0,this.sortBlocks*16);let o=(u,f)=>({binding:u,visibility:GPUShaderStage.COMPUTE,buffer:{type:f}});this.layout=e.createBindGroupLayout({entries:[o(0,"uniform"),o(1,"read-only-storage"),...Array.from({length:5},(u,f)=>o(f+2,"storage"))]}),this.extraLayout=e.createBindGroupLayout({entries:[o(0,"uniform"),o(1,"read-only-storage")]});let a=e.createShaderModule({label:"portable H-PLOC",code:ge+ao+`
3100
3143
  @compute @workgroup_size(128)
3101
3144
  fn initializeLinks(@builtin(global_invocation_id) gid:vec3u){if(gid.x<build.escapeOffset){links[gid.x]=0xffffffffu;}}
3102
- `}),n=e.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipes=Object.fromEntries(["leaves","refitLeaves","reduceBounds","mortonCodes","seedClusters","miniHploc","refitTreelets","ropes","initializeLinks"].map(u=>[u,e.createComputePipeline({layout:n,compute:{module:a,entryPoint:u}})]));let l=e.createShaderModule({label:"stable Morton radix",code:ql});this.sortLayout=e.createBindGroupLayout({entries:[o(0,"uniform"),o(1,"read-only-storage"),o(2,"storage"),o(3,"storage")]});let c=e.createPipelineLayout({bindGroupLayouts:[this.sortLayout]});this.sortPipes=Object.fromEntries(["countDigits","scatterDigits"].map(u=>[u,e.createComputePipeline({layout:c,compute:{module:l,entryPoint:u}})])),this.traverse=e.createComputePipeline({label:"H-PLOC collision traversal",layout:e.createPipelineLayout({bindGroupLayouts:[t.layouts.broad,this.extraLayout]}),compute:{module:e.createShaderModule({code:zf}),entryPoint:"findTreePairs"}}),this.configure(t.bodyCount)}uniform(e){let t=this.device.createBuffer({size:e.length*4,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});return new Uint32Array(t.getMappedRange()).set(e),t.unmap(),this.uniforms.push(t),t}configure(e){if(e===this.count)return;if(e>this.capacity)throw Error("H-PLOC body capacity exceeded");for(let d of this.uniforms)d.destroy();this.uniforms=[],this.count=e,this.built=!1,this.stepsSinceBuild=0;let t=[],i=e,r=e,o=0,a=e,n=e===0?Ef:0;for(;i>1;){let d=Math.ceil(i/16);t.push({inputCount:i,nodeBase:r,inputOffset:o,outputOffset:a,blocks:d}),d===1&&(n=r+i-2),r+=d*15,o=a,a+=d,i=d}this.stats.nodes=e?2*e-1:0;let l=(d={})=>{let p=this.uniform([e,d.nodeBase??0,d.inputOffset??0,d.outputOffset??0,n,this.sortBlocks,0,d.boundsOffset??0,d.inputCount??e,this.nodeCapacity,0,0]);return{group:this.device.createBindGroup({layout:this.layout,entries:[p,this.bodyBuffer,this.nodes,this.keys[0],this.bounds,this.links,this.clusters].map((h,g)=>({binding:g,resource:{buffer:h}}))}),buffer:p}};this.base=l(),this.levels=t.map(d=>({...d,...l(d)})),this.reductions=[];let c=Rt(e),u=0,f=c*2;for(;c>1;){let d=Rt(c);this.reductions.push({blocks:d,...l({inputCount:c,inputOffset:u,outputOffset:f})}),u=f,f+=d*2,c=d}this.morton=l({boundsOffset:u}),this.sortGroups=Array.from({length:8},(d,p)=>{let m=this.uniform([e,this.sortBlocks,p*4,0]);return this.device.createBindGroup({layout:this.sortLayout,entries:[m,this.keys[p%2],this.keys[1-p%2],this.hist].map((h,g)=>({binding:g,resource:{buffer:h}}))})}),this.extra=this.device.createBindGroup({layout:this.extraLayout,entries:[{binding:0,resource:{buffer:this.base.buffer}},{binding:1,resource:{buffer:this.links}}]}),this.broadBuffers=null}encodeBuild(e){let t=(r,o,a)=>{e.setPipeline(this.pipes[r]),e.setBindGroup(0,o),e.dispatchWorkgroups(a)},i=!this.built||this.stepsSinceBuild>=this.rebuildInterval;if(this.lastRebuilt=i,t(i?"leaves":"refitLeaves",this.base.group,Rt(this.count)),i){t("initializeLinks",this.base.group,Rt(this.nodeCapacity));for(let r of this.reductions)t("reduceBounds",r.group,r.blocks);t("mortonCodes",this.morton.group,Rt(this.count));for(let r of this.sortGroups)e.setPipeline(this.sortPipes.countDigits),e.setBindGroup(0,r),e.dispatchWorkgroups(this.sortBlocks),this.scan.encode(e),e.setPipeline(this.sortPipes.scatterDigits),e.setBindGroup(0,r),e.dispatchWorkgroups(this.sortBlocks);t("seedClusters",this.base.group,Rt(this.count));for(let r of this.levels)t("miniHploc",r.group,r.blocks);t("ropes",this.base.group,Rt(this.nodeCapacity)),this.built=!0,this.stepsSinceBuild=0,this.stats.builds++}else{for(let r of this.levels)t("refitTreelets",r.group,Rt(r.blocks,64));this.stats.refits++}this.stepsSinceBuild++}encodePairs(e,t){this.configure(t.bodyCount);let i=[t.paramsBuffer,t.bodyBuffer,this.nodes,t.pairBuffer,t.counterBuffer,t.staticBuffer,t.jointBuffer,t.filterBuffer];(!this.broadBuffers||i.some((r,o)=>r!==this.broadBuffers[o]))&&(this.broadBuffers=i,this.broad=this.device.createBindGroup({layout:t.layouts.broad,entries:i.map((r,o)=>({binding:o,resource:{buffer:r}}))})),e.setPipeline(this.traverse),e.setBindGroup(0,this.broad),e.setBindGroup(1,this.extra),e.dispatchWorkgroups(Rt(this.count,64))}destroy(){this.scan.destroy();for(let e of[...this.buffers,...this.uniforms])e.destroy()}};function Wl(s,e={}){let t,i,r=!0,o=new Map,a=l=>{if(!i&&!l)return;let c=e.timestampWrites,u=s.beginComputePass({...e,timestampWrites:c&&(r||l)?{querySet:c.querySet,...r&&c.beginningOfPassWriteIndex!==void 0?{beginningOfPassWriteIndex:c.beginningOfPassWriteIndex}:{},...l&&c.endOfPassWriteIndex!==void 0?{endOfPassWriteIndex:c.endOfPassWriteIndex}:{}}:void 0});if(i){u.setPipeline(i.pipeline);for(let[f,d]of i.bindings)u.setBindGroup(f,...d);u[i.method](...i.args)}u.end(),i=null,r=!1},n=(l,c)=>{a(!1),i={pipeline:t,bindings:new Map(o),method:l,args:c}};return{setPipeline(l){t=l},setBindGroup(l,c,u){o.set(l,u===void 0?[c]:[c,[...u]])},dispatchWorkgroups(...l){n("dispatchWorkgroups",l)},dispatchWorkgroupsIndirect(...l){n("dispatchWorkgroupsIndirect",l)},end(){a(!0)}}}var mt=s=>Math.ceil(s/64);function Hl(s){(s.radiiDirty||s.noCollideDirty)&&s.uploadStatics();let e=s.params;s.fixedColors&&(s.device.queue.writeBuffer(s.colorBuffer,0,s.fixedColors),s.colorCap=Math.max(1,...s.fixedColors.map(k=>k===255?0:k+1))),s.stepCount++,s.writeParams(),s.writePassConstants(e.iterations,e.alpha);let t=s.parity,i=s.bodyCapacity,r=s.bodyCount,o=s.jointCount,a=s.groups,n=s.device.createCommandEncoder({label:"AVBD app step"});s.encodeStepPrelude?.(n),s.bvh||n.clearBuffer(s.gridBuffer,0,(2*s.tableSize+1)*4),n.clearBuffer(s.tableBuffer),n.clearBuffer(s.adjBuffer,0,(2*i+1)*4);let l=!!s.detailCallback,c=l||s.timingCallback!==null&&s.timing!==null,u=c||s.splitPasses,f=l?s.detailTiming:s.timing,d=[],p,m,h,g=(k,P)=>{if(p&&!l&&(m===P||!u))return;p?.end(),m=P;let C=l?d.length:Se.indexOf(P);d.push({name:k,aggregate:P});let _={label:k,timestampWrites:c?{querySet:f.querySet,beginningOfPassWriteIndex:C*2,endOfPassWriteIndex:C*2+1}:void 0};p=s.dispatchIsolation?Wl(n,_):n.beginComputePass(_),h=void 0},b=k=>{h!==k&&(p.setBindGroup(0,k),h=k)},y=(k,P,C)=>{C<=0||(p.setPipeline(s.pipes[k]),b(P),p.dispatchWorkgroups(C))},A=(k,P,C)=>{p.setPipeline(s.pipes[k]),b(P),p.dispatchWorkgroupsIndirect(s.argsBuffer,C*4)};if(g("contactCache","collision"),y("beginFrame",a.broad,1),e.reuseContacts&&y("updateRefs",a.refs,mt(r)),y("argsPrev",a.args,1),A("hashInsert",a.contacts[t],6),g("broadphaseBuild","collision"),s.bvh?(s.bvh.configure(r),s.bvh.encodeBuild(p),h=void 0):(y("gridCount",a.broad,mt(r)),s.gridScan.encode(p),h=void 0,y("gridScatter",a.broad,mt(r))),g("broadphasePairs","collision"),s.bvh?(s.bvh.encodePairs(p,s),h=void 0):y("findPairs",a.broad,mt(r)),g("narrowphase","collision"),y("argsPairs",a.args,1),A("narrowphase",a.contacts[t],0),y("argsContacts",a.args,1),g("adjacency","adjacency"),y("degreeJoints",a.topo[t],mt(o)),A("degreeContacts",a.topo[t],3),s.adjScan.encode(p),h=void 0,y("fillJoints",a.topo[t],mt(o)),A("fillContacts",a.topo[t],3),y("sortAdjacency",a.topo[t],mt(r)),g("coloring","coloring"),!s.fixedColors){y("colorCompact",a.topo[t],mt(r)),y("colorMark",a.topo[t],mt(r));for(let k=0;k<s.colorRounds;k++)y(k%2===0?"colorRoundAB":"colorRoundBA",a.topo[t],mt(r))}y("colorCount",a.topo[t],s.colorGroups),s.colorHistScan.encode(p),h=void 0,y("colorStarts",a.topo[t],1),y("argsColors",a.args,1),y("colorScatter",a.topo[t],s.colorGroups);let v=s.passOffsets??=[0],x,w,B,L=k=>{w===p&&B===k||(v[0]=k*256,p.setBindGroup(1,s.passGroup,v),w=p,B=k)},M=()=>{x!==p&&(p.setBindGroup(0,a.solve[t]),x=p)};if(g("warmStart","solve"),M(),L(0),o>0&&(p.setPipeline(s.pipes.warmStartJoints),p.dispatchWorkgroups(mt(o))),p.setPipeline(s.pipes.warmStartBodies),r&&p.dispatchWorkgroups(mt(r)),s.smallGroupPipeline)g("smallGroupSolve","solve"),M(),L(0),p.setPipeline(s.smallGroupPipeline),p.dispatchWorkgroups(1);else for(let k=0;k<e.iterations;k++){g("bodySolve","solve"),M(),p.setPipeline(s.pipes.primal);for(let P=0;P<s.colorCap;P++)L(k*(s.colorCap+1)+P),p.dispatchWorkgroupsIndirect(s.argsBuffer,(12+3*P)*4);g("contactUpdate","solve"),M(),L(k*(s.colorCap+1)+s.colorCap),p.setPipeline(s.pipes.dual),p.dispatchWorkgroupsIndirect(s.argsBuffer,36)}g("velocities","solve"),M(),L(0),p.setPipeline(s.pipes.updateVelocities),r&&p.dispatchWorkgroups(mt(r)),p.end();let I=2*(l?d.length:Se.length);if(c&&(n.resolveQuerySet(f.querySet,0,I,f.resolve,0),n.copyBufferToBuffer(f.resolve,0,f.read,0,I*8)),s.parity=1-t,s.encodeStepPostlude?.(n),s.device.queue.submit([n.finish()]),!c)return;let E=l?s.detailCallback:s.timingCallback;l?s.detailCallback=null:s.timingCallback=null,s.timingBusy=!0,f.read.mapAsync(GPUMapMode.READ).then(()=>{let k=new BigUint64Array(f.read.getMappedRange()).slice();if(f.read.unmap(),s.timingBusy=!1,s.destroyed){s.releaseAppTiming(),s.releaseTiming();return}let P=(_,z)=>Number(k[z]-k[_])/1e6,C={total:P(0,I-1),broadphase:s.broadphase,bvhRebuilt:s.bvh?.lastRebuilt??!1};if(l){C.details={};for(let[_,z]of d.entries()){let R=P(_*2,_*2+1);C[z.aggregate]=(C[z.aggregate]??0)+R,C.details[z.name]=(C.details[z.name]??0)+R}}else Se.forEach((_,z)=>C[_]=P(z*2,z*2+1));E(C)},k=>{s.timingBusy=!1,s.profileErrors.push(k.message),s.destroyed&&(s.releaseAppTiming(),s.releaseTiming())})}function lo(s){let e=s.indexOf(`@compute @workgroup_size(256)
3145
+ `}),n=e.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipes=Object.fromEntries(["leaves","refitLeaves","reduceBounds","mortonCodes","seedClusters","miniHploc","refitTreelets","ropes","initializeLinks"].map(u=>[u,e.createComputePipeline({layout:n,compute:{module:a,entryPoint:u}})]));let l=e.createShaderModule({label:"stable Morton radix",code:ql});this.sortLayout=e.createBindGroupLayout({entries:[o(0,"uniform"),o(1,"read-only-storage"),o(2,"storage"),o(3,"storage")]});let c=e.createPipelineLayout({bindGroupLayouts:[this.sortLayout]});this.sortPipes=Object.fromEntries(["countDigits","scatterDigits"].map(u=>[u,e.createComputePipeline({layout:c,compute:{module:l,entryPoint:u}})])),this.traverse=e.createComputePipeline({label:"H-PLOC collision traversal",layout:e.createPipelineLayout({bindGroupLayouts:[t.layouts.broad,this.extraLayout]}),compute:{module:e.createShaderModule({code:zf}),entryPoint:"findTreePairs"}}),this.configure(t.bodyCount)}uniform(e){let t=this.device.createBuffer({size:e.length*4,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});return new Uint32Array(t.getMappedRange()).set(e),t.unmap(),this.uniforms.push(t),t}configure(e){if(e===this.count)return;if(e>this.capacity)throw Error("H-PLOC body capacity exceeded");for(let d of this.uniforms)d.destroy();this.uniforms=[],this.count=e,this.built=!1,this.stepsSinceBuild=0;let t=[],i=e,r=e,o=0,a=e,n=e===0?Ef:0;for(;i>1;){let d=Math.ceil(i/16);t.push({inputCount:i,nodeBase:r,inputOffset:o,outputOffset:a,blocks:d}),d===1&&(n=r+i-2),r+=d*15,o=a,a+=d,i=d}this.stats.nodes=e?2*e-1:0;let l=(d={})=>{let h=this.uniform([e,d.nodeBase??0,d.inputOffset??0,d.outputOffset??0,n,this.sortBlocks,0,d.boundsOffset??0,d.inputCount??e,this.nodeCapacity,0,0]);return{group:this.device.createBindGroup({layout:this.layout,entries:[h,this.bodyBuffer,this.nodes,this.keys[0],this.bounds,this.links,this.clusters].map((p,g)=>({binding:g,resource:{buffer:p}}))}),buffer:h}};this.base=l(),this.levels=t.map(d=>({...d,...l(d)})),this.reductions=[];let c=Rt(e),u=0,f=c*2;for(;c>1;){let d=Rt(c);this.reductions.push({blocks:d,...l({inputCount:c,inputOffset:u,outputOffset:f})}),u=f,f+=d*2,c=d}this.morton=l({boundsOffset:u}),this.sortGroups=Array.from({length:8},(d,h)=>{let m=this.uniform([e,this.sortBlocks,h*4,0]);return this.device.createBindGroup({layout:this.sortLayout,entries:[m,this.keys[h%2],this.keys[1-h%2],this.hist].map((p,g)=>({binding:g,resource:{buffer:p}}))})}),this.extra=this.device.createBindGroup({layout:this.extraLayout,entries:[{binding:0,resource:{buffer:this.base.buffer}},{binding:1,resource:{buffer:this.links}}]}),this.broadBuffers=null}encodeBuild(e){let t=(r,o,a)=>{e.setPipeline(this.pipes[r]),e.setBindGroup(0,o),e.dispatchWorkgroups(a)},i=!this.built||this.stepsSinceBuild>=this.rebuildInterval;if(this.lastRebuilt=i,t(i?"leaves":"refitLeaves",this.base.group,Rt(this.count)),i){t("initializeLinks",this.base.group,Rt(this.nodeCapacity));for(let r of this.reductions)t("reduceBounds",r.group,r.blocks);t("mortonCodes",this.morton.group,Rt(this.count));for(let r of this.sortGroups)e.setPipeline(this.sortPipes.countDigits),e.setBindGroup(0,r),e.dispatchWorkgroups(this.sortBlocks),this.scan.encode(e),e.setPipeline(this.sortPipes.scatterDigits),e.setBindGroup(0,r),e.dispatchWorkgroups(this.sortBlocks);t("seedClusters",this.base.group,Rt(this.count));for(let r of this.levels)t("miniHploc",r.group,r.blocks);t("ropes",this.base.group,Rt(this.nodeCapacity)),this.built=!0,this.stepsSinceBuild=0,this.stats.builds++}else{for(let r of this.levels)t("refitTreelets",r.group,Rt(r.blocks,64));this.stats.refits++}this.stepsSinceBuild++}encodePairs(e,t,i){this.configure(t.bodyCount);let r=[t.paramsBuffer,t.bodyBuffer,this.nodes,t.pairBuffer,t.counterBuffer,t.staticBuffer,t.jointBuffer,t.filterBuffer];(!this.broadBuffers||r.some((o,a)=>o!==this.broadBuffers[a]))&&(this.broadBuffers=r,this.broad=this.device.createBindGroup({layout:t.layouts.broad,entries:r.map((o,a)=>({binding:a,resource:{buffer:o}}))})),e.setPipeline(this.traverse),e.setBindGroup(0,this.broad),e.setBindGroup(1,this.extra),i?e.dispatchWorkgroupsIndirect(i,0):e.dispatchWorkgroups(Rt(this.count,64))}destroy(){this.scan.destroy();for(let e of[...this.buffers,...this.uniforms])e.destroy()}};function Wl(s,e={}){let t,i,r=!0,o=new Map,a=l=>{if(!i&&!l)return;let c=e.timestampWrites,u=s.beginComputePass({...e,timestampWrites:c&&(r||l)?{querySet:c.querySet,...r&&c.beginningOfPassWriteIndex!==void 0?{beginningOfPassWriteIndex:c.beginningOfPassWriteIndex}:{},...l&&c.endOfPassWriteIndex!==void 0?{endOfPassWriteIndex:c.endOfPassWriteIndex}:{}}:void 0});if(i){u.setPipeline(i.pipeline);for(let[f,d]of i.bindings)u.setBindGroup(f,...d);u[i.method](...i.args)}u.end(),i=null,r=!1},n=(l,c)=>{a(!1),i={pipeline:t,bindings:new Map(o),method:l,args:c}};return{setPipeline(l){t=l},setBindGroup(l,c,u){o.set(l,u===void 0?[c]:[c,[...u]])},dispatchWorkgroups(...l){n("dispatchWorkgroups",l)},dispatchWorkgroupsIndirect(...l){n("dispatchWorkgroupsIndirect",l)},end(){a(!0)}}}var mt=s=>Math.ceil(s/64);function Hl(s){(s.radiiDirty||s.noCollideDirty)&&s.uploadStatics();let e=s.params;s.fixedColors&&(s.device.queue.writeBuffer(s.colorBuffer,0,s.fixedColors),s.colorCap=Math.max(1,...s.fixedColors.map(k=>k===255?0:k+1))),s.stepCount++,s.writeParams(),s.writePassConstants(e.iterations,e.alpha);let t=s.parity,i=s.bodyCapacity,r=s.bodyCount,o=s.jointCount,a=s.groups,n=s.device.createCommandEncoder({label:"AVBD app step"});s.encodeStepPrelude?.(n),s.bvh||n.clearBuffer(s.gridBuffer,0,(2*s.tableSize+1)*4),n.clearBuffer(s.tableBuffer),n.clearBuffer(s.adjBuffer,0,(2*i+1)*4);let l=!!s.detailCallback,c=l||s.timingCallback!==null&&s.timing!==null,u=c||s.splitPasses,f=l?s.detailTiming:s.timing,d=[],h,m,p,g=(k,P)=>{if(h&&!l&&(m===P||!u))return;h?.end(),m=P;let C=l?d.length:Se.indexOf(P);d.push({name:k,aggregate:P});let _={label:k,timestampWrites:c?{querySet:f.querySet,beginningOfPassWriteIndex:C*2,endOfPassWriteIndex:C*2+1}:void 0};h=s.dispatchIsolation?Wl(n,_):n.beginComputePass(_),p=void 0},b=k=>{p!==k&&(h.setBindGroup(0,k),p=k)},y=(k,P,C)=>{C<=0||(h.setPipeline(s.pipes[k]),b(P),h.dispatchWorkgroups(C))},A=(k,P,C)=>{h.setPipeline(s.pipes[k]),b(P),h.dispatchWorkgroupsIndirect(s.argsBuffer,C*4)};if(g("contactCache","collision"),y("beginFrame",a.broad,1),e.reuseContacts&&y("updateRefs",a.refs,mt(r)),y("argsPrev",a.args,1),A("hashInsert",a.contacts[t],6),g("broadphaseBuild","collision"),s.bvh?(s.bvh.configure(r),s.bvh.encodeBuild(h),p=void 0):(y("gridCount",a.broad,mt(r)),s.gridScan.encode(h),p=void 0,y("gridScatter",a.broad,mt(r))),g("broadphasePairs","collision"),s.bvh?(s.bvh.encodePairs(h,s),p=void 0):y("findPairs",a.broad,mt(r)),g("narrowphase","collision"),y("argsPairs",a.args,1),A("narrowphase",a.contacts[t],0),y("argsContacts",a.args,1),s.sleeping&&(g("impactWake","collision"),s.sleeping.encodeImpact(h,t),s.bvh?s.bvh.encodePairs(h,s,s.sleeping.refreshArgs):(h.setPipeline(s.pipes.findPairs),h.setBindGroup(0,a.broad),h.dispatchWorkgroupsIndirect(s.sleeping.refreshArgs,0)),s.sleeping.encodeRefreshArgs(h),h.setPipeline(s.pipes.narrowphase),h.setBindGroup(0,a.contacts[t]),h.dispatchWorkgroupsIndirect(s.sleeping.refreshArgs,12),p=void 0,y("argsContacts",a.args,1)),g("adjacency","adjacency"),y("degreeJoints",a.topo[t],mt(o)),A("degreeContacts",a.topo[t],3),s.adjScan.encode(h),p=void 0,y("fillJoints",a.topo[t],mt(o)),A("fillContacts",a.topo[t],3),y("sortAdjacency",a.topo[t],mt(r)),g("coloring","coloring"),!s.fixedColors){y("colorCompact",a.topo[t],mt(r)),y("colorMark",a.topo[t],mt(r));for(let k=0;k<s.colorRounds;k++)y(k%2===0?"colorRoundAB":"colorRoundBA",a.topo[t],mt(r))}y("colorCount",a.topo[t],s.colorGroups),s.colorHistScan.encode(h),p=void 0,y("colorStarts",a.topo[t],1),y("argsColors",a.args,1),y("colorScatter",a.topo[t],s.colorGroups);let v=s.passOffsets??=[0],x,w,B,L=k=>{w===h&&B===k||(v[0]=k*256,h.setBindGroup(1,s.passGroup,v),w=h,B=k)},M=()=>{x!==h&&(h.setBindGroup(0,a.solve[t]),x=h)};if(g("warmStart","solve"),M(),L(0),o>0&&(h.setPipeline(s.pipes.warmStartJoints),h.dispatchWorkgroups(mt(o))),h.setPipeline(s.pipes.warmStartBodies),r&&h.dispatchWorkgroups(mt(r)),s.smallGroupPipeline)g("smallGroupSolve","solve"),M(),L(0),h.setPipeline(s.smallGroupPipeline),h.dispatchWorkgroups(1);else for(let k=0;k<e.iterations;k++){g("bodySolve","solve"),M(),h.setPipeline(s.pipes.primal);for(let P=0;P<s.colorCap;P++)L(k*(s.colorCap+1)+P),h.dispatchWorkgroupsIndirect(s.argsBuffer,(12+3*P)*4);g("contactUpdate","solve"),M(),L(k*(s.colorCap+1)+s.colorCap),h.setPipeline(s.pipes.dual),h.dispatchWorkgroupsIndirect(s.argsBuffer,36)}g("velocities","solve"),M(),L(0),h.setPipeline(s.pipes.updateVelocities),r&&h.dispatchWorkgroups(mt(r)),h.end();let I=2*(l?d.length:Se.length);if(c&&(n.resolveQuerySet(f.querySet,0,I,f.resolve,0),n.copyBufferToBuffer(f.resolve,0,f.read,0,I*8)),s.parity=1-t,s.encodeStepPostlude?.(n),s.device.queue.submit([n.finish()]),!c)return;let E=l?s.detailCallback:s.timingCallback;l?s.detailCallback=null:s.timingCallback=null,s.timingBusy=!0,f.read.mapAsync(GPUMapMode.READ).then(()=>{let k=new BigUint64Array(f.read.getMappedRange()).slice();if(f.read.unmap(),s.timingBusy=!1,s.destroyed){s.releaseAppTiming(),s.releaseTiming();return}let P=(_,z)=>Number(k[z]-k[_])/1e6,C={total:P(0,I-1),broadphase:s.broadphase,bvhRebuilt:s.bvh?.lastRebuilt??!1};if(l){C.details={};for(let[_,z]of d.entries()){let R=P(_*2,_*2+1);C[z.aggregate]=(C[z.aggregate]??0)+R,C.details[z.name]=(C.details[z.name]??0)+R}}else Se.forEach((_,z)=>C[_]=P(z*2,z*2+1));E(C)},k=>{s.timingBusy=!1,s.profileErrors.push(k.message),s.destroyed&&(s.releaseAppTiming(),s.releaseTiming())})}function lo(s){let e=s.indexOf(`@compute @workgroup_size(256)
3103
3146
  fn colorCount(`),t=s.indexOf(`
3104
3147
  // 5.`,e);if(e<0||t<e)throw Error("Pinned color buckets changed; review the bitset rank kernel");return s.slice(0,e).replace(`var<workgroup> hist: array<atomic<u32>, 64>;
3105
3148
  var<workgroup> chunkColors: array<u32, 256>;
@@ -3171,7 +3214,7 @@ fn colorCount(@builtin(global_invocation_id) gid:vec3u,
3171
3214
  return;
3172
3215
  }
3173
3216
  for (var i = lo + 1u; i < hi; i++) {`);function fn(s){return s.replace("return m.ids.w & 15u;","return select(m.ids.w & 15u, 0u, (m.ids.w & 0x80000000u) != 0u);").replace("bodies[i].initialPos = pos;","bodies[i].initialPos = vec4f(pos.xyz, bodies[i].initialPos.w);")}function uo(s){return s.replace("let generated = prev.ids.w >> 4u;","let generated = (prev.ids.w >> 4u) & 0x07ffffffu;").replace("reuseContacts(a, b))","bodies[a].initialPos.w == 0.0 && bodies[b].initialPos.w == 0.0 && reuseContacts(a, b))").replace("count | (params.step << 4u)","count | ((params.step & 0x07ffffffu) << 4u) | select(0u, 0x80000000u, bodies[a].initialPos.w != 0.0 || bodies[b].initialPos.w != 0.0)")}function dn(s=Ti(ge,yr)){return s.replaceAll("if (gid.x >= topoCount()) { return; }",`if (gid.x >= topoCount()) { return; }
3174
- if ((contacts[gid.x].ids.w & 0x80000000u) != 0u) { return; }`)}function hn(s){let e=s.device,t=e.createShaderModule({code:`
3217
+ if ((contacts[gid.x].ids.w & 0x80000000u) != 0u) { return; }`)}function pn(s){let e=s.device,t=e.createShaderModule({code:`
3175
3218
  @group(0) @binding(0) var<storage,read_write> records:array<vec4f>;
3176
3219
  @compute @workgroup_size(64) fn clear(@builtin(global_invocation_id) id:vec3u){
3177
3220
  if(id.x*10u+2u>=arrayLength(&records)){return;}
@@ -3262,7 +3305,7 @@ fn pointVelocity(i:u32,r:vec3f,incoming:bool)->vec3f {
3262
3305
  let i=id.x;if(i>=cfg.count || bodies[i].size.w<=0.){return;}
3263
3306
  bodies[i].vel=velocities[i].linear;bodies[i].angVel=velocities[i].angular;
3264
3307
  }
3265
- `;var wr=class{constructor(e,{code:t=Tf,dimension:i=3}={}){this.solver=e,this.dimension=i,this.device=e.device,this.active=new Set;let r=this.device,o=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST;this.materials=r.createBuffer({size:e.bodyCapacity*4,usage:o}),this.velocities=r.createBuffer({size:e.bodyCapacity*64,usage:o}),this.params=r.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.layout=r.createBindGroupLayout({entries:["uniform","storage","storage","read-only-storage","read-only-storage","read-only-storage","read-only-storage","read-only-storage","storage"].map((l,c)=>({binding:c,visibility:GPUShaderStage.COMPUTE,buffer:{type:l}}))});let a=r.createShaderModule({code:t}),n=r.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipes=Object.fromEntries(["captureIncoming","captureSolved","initialize","pairs","apply","writeBack"].map(l=>[l,r.createComputePipeline({layout:n,compute:{module:a,entryPoint:l}})]))}set(e,t){if(!Number.isFinite(t)||t<0||t>1)throw Error("restitution must be between 0 and 1");t>0?this.active.add(e):this.active.delete(e),oe(this.solver).float(this.materials,e,t)}bind(){let e=this.solver,t=this.device,i=this.dimension===3?e.contactStorage:{manifolds:e.contactBuffers[1-e.parity],contacts:e.contactBuffers[1-e.parity],counters:e.counterBuffer},r=this.dimension===3?e.manifoldCapacity:e.contactCapacity;this.capacity!==r&&(this.bounce?.destroy(),this.capacity=r,this.bounce=t.createBuffer({size:Math.max(1,this.capacity)*48,usage:GPUBufferUsage.STORAGE}));let o=[this.params,e.bodyBuffer,this.velocities,this.materials,i.manifolds,i.contacts,e.adjBuffer,i.counters,this.bounce];(!this.buffers||o.some((c,u)=>c!==this.buffers[u]))&&(this.buffers=o,this.group=t.createBindGroup({layout:this.layout,entries:o.map((c,u)=>({binding:u,resource:{buffer:c}}))}));let a=this.paramData??=hi(8),{u:n,f:l}=a;n[0]=e.bodyCount,n[1]=e.jointCount,n[2]=r,n[3]=2*e.bodyCapacity+1,l[4]=1,l[5]=e.params.dt,Qt(t,this.params,a)}run(e,t){this.bind();let i=t??this.device.createCommandEncoder(),r=i.beginComputePass();r.setBindGroup(0,this.group);for(let o of e)r.setPipeline(this.pipes[o]),r.dispatchWorkgroups(Math.max(1,Math.ceil((o==="initialize"||o==="pairs"?this.capacity:this.solver.bodyCount)/64)));r.end(),t||this.device.queue.submit([i.finish()])}before(e){this.active.size&&this.run(Rf,e)}after(e){this.active.size&&this.run(Of,e)}destroy(){for(let e of["materials","velocities","params","bounce"])this[e]?.destroy()}};var Kl=new WeakMap,fs=s=>Kl.get(s);function Br(s,e){Kl.set(s,e)}var pn=(s,e,t)=>{if(s.split(e).length!==2)throw Error("Pinned angular solver layout changed");return s.replace(e,t)};function mn(s){return s=pn(s,"fn addJoint(acc: ptr<function, Acc>, j: u32, alpha: f32, i: u32) {",`
3308
+ `;var wr=class{constructor(e,{code:t=Tf,dimension:i=3}={}){this.solver=e,this.dimension=i,this.device=e.device,this.active=new Set;let r=this.device,o=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST;this.materials=r.createBuffer({size:e.bodyCapacity*4,usage:o}),this.velocities=r.createBuffer({size:e.bodyCapacity*64,usage:o}),this.params=r.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.layout=r.createBindGroupLayout({entries:["uniform","storage","storage","read-only-storage","read-only-storage","read-only-storage","read-only-storage","read-only-storage","storage"].map((l,c)=>({binding:c,visibility:GPUShaderStage.COMPUTE,buffer:{type:l}}))});let a=r.createShaderModule({code:t}),n=r.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipes=Object.fromEntries(["captureIncoming","captureSolved","initialize","pairs","apply","writeBack"].map(l=>[l,r.createComputePipeline({layout:n,compute:{module:a,entryPoint:l}})]))}set(e,t){if(!Number.isFinite(t)||t<0||t>1)throw Error("restitution must be between 0 and 1");t>0?this.active.add(e):this.active.delete(e),oe(this.solver).float(this.materials,e,t)}bind(){let e=this.solver,t=this.device,i=this.dimension===3?e.contactStorage:{manifolds:e.contactBuffers[1-e.parity],contacts:e.contactBuffers[1-e.parity],counters:e.counterBuffer},r=this.dimension===3?e.manifoldCapacity:e.contactCapacity;this.capacity!==r&&(this.bounce?.destroy(),this.capacity=r,this.bounce=t.createBuffer({size:Math.max(1,this.capacity)*48,usage:GPUBufferUsage.STORAGE}));let o=[this.params,e.bodyBuffer,this.velocities,this.materials,i.manifolds,i.contacts,e.adjBuffer,i.counters,this.bounce];(!this.buffers||o.some((c,u)=>c!==this.buffers[u]))&&(this.buffers=o,this.group=t.createBindGroup({layout:this.layout,entries:o.map((c,u)=>({binding:u,resource:{buffer:c}}))}));let a=this.paramData??=pi(8),{u:n,f:l}=a;n[0]=e.bodyCount,n[1]=e.jointCount,n[2]=r,n[3]=2*e.bodyCapacity+1,l[4]=1,l[5]=e.params.dt,Qt(t,this.params,a)}run(e,t){this.bind();let i=t??this.device.createCommandEncoder(),r=i.beginComputePass();r.setBindGroup(0,this.group);for(let o of e)r.setPipeline(this.pipes[o]),r.dispatchWorkgroups(Math.max(1,Math.ceil((o==="initialize"||o==="pairs"?this.capacity:this.solver.bodyCount)/64)));r.end(),t||this.device.queue.submit([i.finish()])}before(e){this.active.size&&this.run(Rf,e)}after(e){this.active.size&&this.run(Of,e)}destroy(){for(let e of["materials","velocities","params","bounce"])this[e]?.destroy()}};var Kl=new WeakMap,fs=s=>Kl.get(s);function Br(s,e){Kl.set(s,e)}var hn=(s,e,t)=>{if(s.split(e).length!==2)throw Error("Pinned angular solver layout changed");return s.replace(e,t)};function mn(s){return s=hn(s,"fn addJoint(acc: ptr<function, Acc>, j: u32, alpha: f32, i: u32) {",`
3266
3309
  fn angularFrame(k:Joint,a:i32,b:i32)->mat3x3f {
3267
3310
  let qa=rotA(a);let axis=qrotate(qa,k.rA.xyz);
3268
3311
  let ta=qrotate(qa,k.c0Lin.xyz);let tb=qrotate(bodies[b].rot,k.c0Ang.xyz);
@@ -3313,9 +3356,9 @@ fn dualAngular(j:u32){
3313
3356
  }
3314
3357
  `+`
3315
3358
  fn addJoint(acc: ptr<function, Acc>, j: u32, alpha: f32, i: u32) {
3316
- if(info[j].x==3 || info[j].x==4){if(joints[j].penLin.w!=0.){addAngular(acc,j,alpha,i);}return;}`),s=pn(s," if (j >= params.jointCount || info[j].x != T_JOINT) { return; }",` if(j>=params.jointCount){return;}
3359
+ if(info[j].x==3 || info[j].x==4){if(joints[j].penLin.w!=0.){addAngular(acc,j,alpha,i);}return;}`),s=hn(s," if (j >= params.jointCount || info[j].x != T_JOINT) { return; }",` if(j>=params.jointCount){return;}
3317
3360
  if(info[j].x==3 || info[j].x==4){warmAngular(j);return;}
3318
- if(info[j].x!=T_JOINT){return;}`),pn(s,"fn dualJoint(j: u32) {",`fn dualJoint(j: u32) {
3361
+ if(info[j].x!=T_JOINT){return;}`),hn(s,"fn dualJoint(j: u32) {",`fn dualJoint(j: u32) {
3319
3362
  if(info[j].x==3 || info[j].x==4){dualAngular(j);return;}`)}function kt({type:s,axisA:e=[0,1,0],axisB:t=[0,1,0],speed:i=1,maxTorque:r=100,minAngle:o=-Math.PI,maxAngle:a=Math.PI}={}){let n=l=>{let c=l&&typeof l.x=="number"?[l.x,l.y,l.z]:Array.from(l),u=Math.hypot(...c);if(c.length!==3||!c.every(Number.isFinite)||u<1e-8)throw Error("Angular axis requires three finite, nonzero components");return c.map(f=>f/u)};if(s!=="motor"&&s!=="limit")throw Error("Invalid angular constraint type");if(!Number.isFinite(i)||!Number.isFinite(r)||r<0)throw Error("Motor speed must be finite and maxTorque nonnegative");if(!Number.isFinite(o)||!Number.isFinite(a)||o<-Math.PI||a>Math.PI||o>a)throw Error("Hinge angles must be ordered within -PI..PI radians");return{type:s,axisA:n(e),axisB:n(t),speed:i,maxTorque:r,minAngle:o,maxAngle:a}}var Zl=`struct Body { pos:vec4f,rot:vec4f,initialPos:vec4f,initialRot:vec4f,size:vec4f,moment:vec4f,inertialPos:vec4f,inertialRot:vec4f,velocity:vec4f,angular:vec4f }
3320
3363
  struct Joint {penLin:vec4f,penAng:vec4f,lamLin:vec4f,lamAng:vec4f,c0Lin:vec4f,c0Ang:vec4f,rA:vec4f,rB:vec4f}
3321
3364
  @group(0) @binding(0) var<storage,read> bodies:array<Body>;
@@ -3334,7 +3377,7 @@ fn rotate(q:vec4f,v:vec3f)->vec3f{let t=2.*cross(q.xyz,v);return v+q.w*t+cross(q
3334
3377
  if(length(tangentB)<1.e-6){tangentB=select(vec3f(0.,-axisB.z,axisB.y),vec3f(-axisB.y,axisB.x,0.),abs(axisB.x)>abs(axisB.z));}
3335
3378
  joints[j].c0Lin=vec4f(tangent,0.);joints[j].c0Ang=vec4f(normalize(tangentB),0.);
3336
3379
  }
3337
- `;var ec=new WeakSet,Fe=s=>ec.has(s);function Cr(s,e,t,i=1,r=.6,o=[0,0,0]){if(!Number.isFinite(e)||e<=0||!Number.isFinite(t)||t<2*e)throw Error("Capsule height must be at least twice its positive radius");if(!Number.isFinite(i)||i<0)throw Error("Capsule density must be nonnegative");let a=new Ze(s,[2*e,t,2*e],i,r,o),n=t-2*e,l=Math.PI*e*e*n*i,c=4/3*Math.PI*e**3*i;a.mass=l+c;let u=l*e**2/2+c*2*e**2/5,f=l*(n**2/12+e**2/4)+c*(2*e**2/5+n**2/4+3*n*e/8);return a.moment.set([f,u,f]),a.radius=t/2,ec.add(a),a}var tc=`// Exact rounded capsule geometry. Shape -1: radius=size.x/2, segment along Y,
3380
+ `;var ec=new WeakSet,Ue=s=>ec.has(s);function Cr(s,e,t,i=1,r=.6,o=[0,0,0]){if(!Number.isFinite(e)||e<=0||!Number.isFinite(t)||t<2*e)throw Error("Capsule height must be at least twice its positive radius");if(!Number.isFinite(i)||i<0)throw Error("Capsule density must be nonnegative");let a=new Ze(s,[2*e,t,2*e],i,r,o),n=t-2*e,l=Math.PI*e*e*n*i,c=4/3*Math.PI*e**3*i;a.mass=l+c;let u=l*e**2/2+c*2*e**2/5,f=l*(n**2/12+e**2/4)+c*(2*e**2/5+n**2/4+3*n*e/8);return a.moment.set([f,u,f]),a.radius=t/2,ec.add(a),a}var tc=`// Exact rounded capsule geometry. Shape -1: radius=size.x/2, segment along Y,
3338
3381
  // half-length=size.y/2-radius. No tessellation, endpoint-only collision test,
3339
3382
  // shape storage buffer or iterative support search for capsule/sphere/box.
3340
3383
  struct Capsule {a:vec3f,b:vec3f,r:f32}
@@ -3613,26 +3656,26 @@ fn nearest(@builtin(global_invocation_id) id:vec3u){if(id.x>=params.head.x||igno
3613
3656
  fn owner(@builtin(global_invocation_id) id:vec3u){if(id.x>=params.head.x||ignored(id.x)){return;}let h=trace(id.x,queries[id.y]);if(h.t>=0.&&bitcast<u32>(max(0.,h.t))==atomicLoad(&best[id.y*2u])){atomicMin(&best[id.y*2u+1u],id.x);}}
3614
3657
  @compute @workgroup_size(64)
3615
3658
  fn finish(@builtin(global_invocation_id) id:vec3u){if(id.x>=params.head.y){return;}let index=atomicLoad(&best[id.x*2u+1u]);if(index==0xffffffffu){hits[id.x*2u]=vec4f(0.,0.,0.,-1.);return;}let h=trace(index,queries[id.x]);hits[id.x*2u]=vec4f(h.n,max(0.,h.t));hits[id.x*2u+1u]=vec4f(bitcast<f32>(index),0.,0.,0.);}
3616
- `;var pi=class{constructor(e,t=3){this.solver=e,this.dimension=t,this.jobs=new Set,this.idle=[],this.destroyed=!1;let i=e.device,r=i.createShaderModule({label:`AVBD ${t}D queries`,code:t===2?bn.replace("const DIM=3u;","const DIM=2u;").replace("const STRIDE=10u;","const STRIDE=6u;"):bn});this.layout=i.createBindGroupLayout({entries:["read-only-storage","read-only-storage","read-only-storage","storage","storage","uniform","read-only-storage"].map((a,n)=>({binding:n,visibility:GPUShaderStage.COMPUTE,buffer:{type:a}}))});let o=i.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipes=Object.fromEntries(["nearest","owner","finish"].map(a=>[a,i.createComputePipeline({layout:o,compute:{module:r,entryPoint:a}})])),this.dummy=i.createBuffer({size:16,usage:GPUBufferUsage.STORAGE})}acquire(e){if(this.destroyed)throw Error("GPU queries have been destroyed");let t=this.idle.findIndex(r=>r.capacity>=e),i=t>=0?this.idle.splice(t,1)[0]:this.idle.pop()??{};if(!i.capacity||i.capacity<e){let r=Math.min(65535,Math.max(e,(i.capacity??0)*2,16));for(let[o,a,n]of[["queryBuffer",r*32,GPUBufferUsage.STORAGE],["best",r*8,GPUBufferUsage.STORAGE],["hits",r*32,GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC],["uniform",96,GPUBufferUsage.UNIFORM],["read",r*32,GPUBufferUsage.MAP_READ]])i[o]?.destroy(),i[o]=this.solver.device.createBuffer({size:a,usage:n|GPUBufferUsage.COPY_DST});i.capacity=r,i.buffers=null,i.data=new Float32Array(r*8),i.initial=new Uint32Array(r*2),i.params=new Uint32Array(24)}return this.jobs.add(i),i}release(e){if(e.read.unmap(),!this.destroyed&&e.capacity*104<=2*1024*1024&&this.idle.length<2)this.idle.push(e);else{for(let t of["queryBuffer","best","hits","uniform","read"])e[t].destroy();this.jobs.delete(e)}}async cast(e,{ignore:t=[],collidesWith:i=4294967295,includeTriggers:r=!0,maxDistance:o}={}){if(this.destroyed)throw Error("GPU queries have been destroyed");let a=this.solver,n=a.device,l=this.dimension;if(!Number.isInteger(i)||i<0||i>4294967295)throw Error("Query mask must be an unsigned 32-bit integer");if(typeof r!="boolean")throw Error("includeTriggers must be boolean");if(t.length>16||t.some(d=>!Number.isInteger(d)||d<0||d>=a.bodyCount))throw Error("Queries can ignore up to 16 live body indices");if(e.length>Math.min(65535,n.limits.maxComputeWorkgroupsPerDimension))throw Error("Too many queries in one batch");let c=e.map(d=>{let p=Array.from(d.origin),m=Array.from(d.direction),h=d.radius??0,g=d.maxDistance??o??3e38;if(p.length!==l||m.length!==l||![...p,...m].every(Number.isFinite)||Math.hypot(...m)===0)throw Error(`A query requires ${l} finite components and a nonzero direction`);if(!Number.isFinite(h)||h<0||!Number.isFinite(g)||g<0)throw Error("Query radius and maximum distance must be finite and nonnegative");let b=Math.hypot(...m);return{origin:p,direction:m.map(y=>y/b),radius:h,maxDistance:g}});if(!c.length)return[];let u=c.length,f=this.acquire(u);try{let d=f.data;c.forEach((I,E)=>{d.set([...I.origin,...Array(3-l).fill(0),I.maxDistance,...I.direction,...Array(3-l).fill(0),I.radius],E*8)});let p=f.params;p.fill(0),p.set([a.bodyCount,u,t.length,i,r?0:1,l===3||a.filters?1:0,a.sensorsEnabled?1:0,l===2&&a.shapeBuffer?1:0]),p.set(t,8);let m=f.initial;for(let I=0;I<u;I++)m.set([2139095040,4294967295],I*2);let{queryBuffer:h,best:g,hits:b,uniform:y,read:A}=f;n.queue.writeBuffer(h,0,d.buffer,0,u*32),n.queue.writeBuffer(g,0,m.buffer,0,u*8),n.queue.writeBuffer(y,0,p);let v=[a.bodyBuffer,l===3?a.hullStorage:a.shapeBuffer??this.dummy,h,g,b,y,l===3?a.filterStorage:a.filters??this.dummy];(!f.buffers||v.some((I,E)=>I!==f.buffers[E]))&&(f.group=n.createBindGroup({layout:this.layout,entries:v.map((I,E)=>({binding:E,resource:{buffer:I}}))}),f.buffers=v);let x=n.createCommandEncoder(),w=x.beginComputePass();w.setBindGroup(0,f.group);for(let I of["nearest","owner"])w.setPipeline(this.pipes[I]),w.dispatchWorkgroups(Math.ceil(a.bodyCount/64),u);w.setPipeline(this.pipes.finish),w.dispatchWorkgroups(Math.ceil(u/64)),w.end(),x.copyBufferToBuffer(b,0,A,0,u*32),n.queue.submit([x.finish()]),await A.mapAsync(GPUMapMode.READ,0,u*32);let B=A.getMappedRange(0,u*32),L=new Float32Array(B),M=new Uint32Array(B);return c.map((I,E)=>{let k=L[E*8+3];if(k<0)return null;let P=Array.from(L.slice(E*8,E*8+l)),C=I.origin.map((_,z)=>_+k*I.direction[z]);return{index:M[E*8+4],distance:k,normal:P,center:C,point:C.map((_,z)=>_-I.radius*P[z])}})}finally{this.release(f)}}destroy(){this.destroyed=!0;for(let e of this.jobs)for(let t of["queryBuffer","best","hits","uniform","read"])e[t].destroy();this.jobs.clear(),this.idle.length=0,this.dummy.destroy()}};function fo(s,e){let t=this.passConstantCache??={alphas:[]},i=t.iterations!==s||t.colors!==this.colorCap||t.buffer!==this.passBuffer||!this.passGroup;for(let n=0;n<s;n++){let l=typeof e=="function"?e(n):e;t.alphas[n]!==l&&(i=!0),t.alphas[n]=l}if(!i)return;let r=this.colorCap+1,o=Math.max(s*r,1),a=o*256;(o>this.passEntries||!this.passGroup)&&(this.passBuffer?.destroy(),this.passBuffer=this.device.createBuffer({label:"AVBD pass constants",size:a,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.passEntries=o,this.passGroup=this.device.createBindGroup({layout:this.layouts.pass,entries:[{binding:0,resource:{buffer:this.passBuffer,size:16}}]})),(!t.data||t.data.byteLength<a)&&(t.data=new ArrayBuffer(Math.max(a,(t.data?.byteLength??0)*2)),t.u32=new Uint32Array(t.data),t.f32=new Float32Array(t.data)),t.u32[2]=s;for(let n=0;n<s;n++)for(let l=0;l<=this.colorCap;l++){let c=(n*r+l)*256/4;t.u32[c]=l,t.u32[c+2]=s,t.f32[c+1]=t.alphas[n]}this.device.queue.writeBuffer(this.passBuffer,0,t.data,0,a),t.iterations=s,t.colors=this.colorCap,t.buffer=this.passBuffer,t.uploads=(t.uploads??0)+1}function ac(s,e){return s.stepParamsCache??=hi(e)}function nc(s,e,t){let i=s.bodyCapacity;t[7]=s.bodyCount,t[8]=s.jointCount,t[9]=s.colorCap,e[10]=s.cellSize,t[11]=s.tableSize-1,e[12]=s.maxSmallRadius,t[13]=s.largeCount,t[14]=s.noCollideCount,t[15]=s.pairCapacity,t[16]=s.contactCapacity,t[17]=s.hashSize-1,t[18]=i+1,t[19]=2*i+1,t[20]=s.tableSize+1,t[21]=2*s.tableSize+1,t[22]=2*s.tableSize+1+i,t[23]=i,t[24]=s.colorHistOffset,t[25]=2*i,t[26]=s.colorGroups,t[27]=2*i+65,t[28]=s.colorRounds}function lc(s,e){let t=ac(this,32),{f:i,u:r}=t,o=this.params;i[0]=o.dt,i[1]=o.gravity,i[2]=o.beta,i[3]=o.gamma,i[4]=s,i[5]=o.vbdStiffness,r[6]=(o.vbd?1:0)|(o.stiffnessRescale?2:0)|(e?4:0)|(o.matchNearest?8:0),nc(this,i,r),Qt(this.device,this.paramsBuffer,t)}function cc(){let s=ac(this,ls),{f:e,u:t}=s,i=this.params;e[0]=i.dt,e[1]=i.gravity,e[2]=i.betaLin,e[3]=i.betaAng,e[4]=i.gamma,e[5]=i.alpha,t[6]=(i.matchNearest?rs:0)|(i.faceBias?ss:0)|(i.reuseContacts?os:0)|(i.startAtRest?as:0)|(i.massPenalty?ns:0),nc(this,e,t),t[29]=this.manifoldCapacity,t[30]=this.stepCount;let r=o=>Math.min(31,Math.max(0,Math.round(Math.log2(o))));t[31]=r(this.primalLanes[0])|r(this.primalLanes[1])<<8|r(this.primalLanes[2])<<16,e[32]=i.windSpeed*Math.cos(i.windAngle),e[33]=i.windSpeed*Math.sin(i.windAngle),e[34]=0,e[35]=i.windPressure,e[36]=i.windGust,e[40]=i.up[0],e[41]=i.up[1],e[42]=i.up[2],e[43]=0,Qt(this.device,this.paramsBuffer,s)}function uc(s){let e=(i,r)=>{if(s.split(i).length!==2)throw Error("Review packed Newton accumulator integration");s=s.replace(i,r)};e(` lin: mat3x3f,
3659
+ `;var hi=class{constructor(e,t=3){this.solver=e,this.dimension=t,this.jobs=new Set,this.idle=[],this.destroyed=!1;let i=e.device,r=i.createShaderModule({label:`AVBD ${t}D queries`,code:t===2?bn.replace("const DIM=3u;","const DIM=2u;").replace("const STRIDE=10u;","const STRIDE=6u;"):bn});this.layout=i.createBindGroupLayout({entries:["read-only-storage","read-only-storage","read-only-storage","storage","storage","uniform","read-only-storage"].map((a,n)=>({binding:n,visibility:GPUShaderStage.COMPUTE,buffer:{type:a}}))});let o=i.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipes=Object.fromEntries(["nearest","owner","finish"].map(a=>[a,i.createComputePipeline({layout:o,compute:{module:r,entryPoint:a}})])),this.dummy=i.createBuffer({size:16,usage:GPUBufferUsage.STORAGE})}acquire(e){if(this.destroyed)throw Error("GPU queries have been destroyed");let t=this.idle.findIndex(r=>r.capacity>=e),i=t>=0?this.idle.splice(t,1)[0]:this.idle.pop()??{};if(!i.capacity||i.capacity<e){let r=Math.min(65535,Math.max(e,(i.capacity??0)*2,16));for(let[o,a,n]of[["queryBuffer",r*32,GPUBufferUsage.STORAGE],["best",r*8,GPUBufferUsage.STORAGE],["hits",r*32,GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC],["uniform",96,GPUBufferUsage.UNIFORM],["read",r*32,GPUBufferUsage.MAP_READ]])i[o]?.destroy(),i[o]=this.solver.device.createBuffer({size:a,usage:n|GPUBufferUsage.COPY_DST});i.capacity=r,i.buffers=null,i.data=new Float32Array(r*8),i.initial=new Uint32Array(r*2),i.params=new Uint32Array(24)}return this.jobs.add(i),i}release(e){if(e.read.unmap(),!this.destroyed&&e.capacity*104<=2*1024*1024&&this.idle.length<2)this.idle.push(e);else{for(let t of["queryBuffer","best","hits","uniform","read"])e[t].destroy();this.jobs.delete(e)}}async cast(e,{ignore:t=[],collidesWith:i=4294967295,includeTriggers:r=!0,maxDistance:o}={}){if(this.destroyed)throw Error("GPU queries have been destroyed");let a=this.solver,n=a.device,l=this.dimension;if(!Number.isInteger(i)||i<0||i>4294967295)throw Error("Query mask must be an unsigned 32-bit integer");if(typeof r!="boolean")throw Error("includeTriggers must be boolean");if(t.length>16||t.some(d=>!Number.isInteger(d)||d<0||d>=a.bodyCount))throw Error("Queries can ignore up to 16 live body indices");if(e.length>Math.min(65535,n.limits.maxComputeWorkgroupsPerDimension))throw Error("Too many queries in one batch");let c=e.map(d=>{let h=Array.from(d.origin),m=Array.from(d.direction),p=d.radius??0,g=d.maxDistance??o??3e38;if(h.length!==l||m.length!==l||![...h,...m].every(Number.isFinite)||Math.hypot(...m)===0)throw Error(`A query requires ${l} finite components and a nonzero direction`);if(!Number.isFinite(p)||p<0||!Number.isFinite(g)||g<0)throw Error("Query radius and maximum distance must be finite and nonnegative");let b=Math.hypot(...m);return{origin:h,direction:m.map(y=>y/b),radius:p,maxDistance:g}});if(!c.length)return[];let u=c.length,f=this.acquire(u);try{let d=f.data;c.forEach((I,E)=>{d.set([...I.origin,...Array(3-l).fill(0),I.maxDistance,...I.direction,...Array(3-l).fill(0),I.radius],E*8)});let h=f.params;h.fill(0),h.set([a.bodyCount,u,t.length,i,r?0:1,l===3||a.filters?1:0,a.sensorsEnabled?1:0,l===2&&a.shapeBuffer?1:0]),h.set(t,8);let m=f.initial;for(let I=0;I<u;I++)m.set([2139095040,4294967295],I*2);let{queryBuffer:p,best:g,hits:b,uniform:y,read:A}=f;n.queue.writeBuffer(p,0,d.buffer,0,u*32),n.queue.writeBuffer(g,0,m.buffer,0,u*8),n.queue.writeBuffer(y,0,h);let v=[a.bodyBuffer,l===3?a.hullStorage:a.shapeBuffer??this.dummy,p,g,b,y,l===3?a.filterStorage:a.filters??this.dummy];(!f.buffers||v.some((I,E)=>I!==f.buffers[E]))&&(f.group=n.createBindGroup({layout:this.layout,entries:v.map((I,E)=>({binding:E,resource:{buffer:I}}))}),f.buffers=v);let x=n.createCommandEncoder(),w=x.beginComputePass();w.setBindGroup(0,f.group);for(let I of["nearest","owner"])w.setPipeline(this.pipes[I]),w.dispatchWorkgroups(Math.ceil(a.bodyCount/64),u);w.setPipeline(this.pipes.finish),w.dispatchWorkgroups(Math.ceil(u/64)),w.end(),x.copyBufferToBuffer(b,0,A,0,u*32),n.queue.submit([x.finish()]),await A.mapAsync(GPUMapMode.READ,0,u*32);let B=A.getMappedRange(0,u*32),L=new Float32Array(B),M=new Uint32Array(B);return c.map((I,E)=>{let k=L[E*8+3];if(k<0)return null;let P=Array.from(L.slice(E*8,E*8+l)),C=I.origin.map((_,z)=>_+k*I.direction[z]);return{index:M[E*8+4],distance:k,normal:P,center:C,point:C.map((_,z)=>_-I.radius*P[z])}})}finally{this.release(f)}}destroy(){this.destroyed=!0;for(let e of this.jobs)for(let t of["queryBuffer","best","hits","uniform","read"])e[t].destroy();this.jobs.clear(),this.idle.length=0,this.dummy.destroy()}};function fo(s,e){let t=this.passConstantCache??={alphas:[]},i=t.iterations!==s||t.colors!==this.colorCap||t.buffer!==this.passBuffer||!this.passGroup;for(let n=0;n<s;n++){let l=typeof e=="function"?e(n):e;t.alphas[n]!==l&&(i=!0),t.alphas[n]=l}if(!i)return;let r=this.colorCap+1,o=Math.max(s*r,1),a=o*256;(o>this.passEntries||!this.passGroup)&&(this.passBuffer?.destroy(),this.passBuffer=this.device.createBuffer({label:"AVBD pass constants",size:a,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.passEntries=o,this.passGroup=this.device.createBindGroup({layout:this.layouts.pass,entries:[{binding:0,resource:{buffer:this.passBuffer,size:16}}]})),(!t.data||t.data.byteLength<a)&&(t.data=new ArrayBuffer(Math.max(a,(t.data?.byteLength??0)*2)),t.u32=new Uint32Array(t.data),t.f32=new Float32Array(t.data)),t.u32[2]=s;for(let n=0;n<s;n++)for(let l=0;l<=this.colorCap;l++){let c=(n*r+l)*256/4;t.u32[c]=l,t.u32[c+2]=s,t.f32[c+1]=t.alphas[n]}this.device.queue.writeBuffer(this.passBuffer,0,t.data,0,a),t.iterations=s,t.colors=this.colorCap,t.buffer=this.passBuffer,t.uploads=(t.uploads??0)+1}function ac(s,e){return s.stepParamsCache??=pi(e)}function nc(s,e,t){let i=s.bodyCapacity;t[7]=s.bodyCount,t[8]=s.jointCount,t[9]=s.colorCap,e[10]=s.cellSize,t[11]=s.tableSize-1,e[12]=s.maxSmallRadius,t[13]=s.largeCount,t[14]=s.noCollideCount,t[15]=s.pairCapacity,t[16]=s.contactCapacity,t[17]=s.hashSize-1,t[18]=i+1,t[19]=2*i+1,t[20]=s.tableSize+1,t[21]=2*s.tableSize+1,t[22]=2*s.tableSize+1+i,t[23]=i,t[24]=s.colorHistOffset,t[25]=2*i,t[26]=s.colorGroups,t[27]=2*i+65,t[28]=s.colorRounds}function lc(s,e){let t=ac(this,32),{f:i,u:r}=t,o=this.params;i[0]=o.dt,i[1]=o.gravity,i[2]=o.beta,i[3]=o.gamma,i[4]=s,i[5]=o.vbdStiffness,r[6]=(o.vbd?1:0)|(o.stiffnessRescale?2:0)|(e?4:0)|(o.matchNearest?8:0),nc(this,i,r),Qt(this.device,this.paramsBuffer,t)}function cc(){let s=ac(this,ls),{f:e,u:t}=s,i=this.params;e[0]=i.dt,e[1]=i.gravity,e[2]=i.betaLin,e[3]=i.betaAng,e[4]=i.gamma,e[5]=i.alpha,t[6]=(i.matchNearest?rs:0)|(i.faceBias?ss:0)|(i.reuseContacts?os:0)|(i.startAtRest?as:0)|(i.massPenalty?ns:0),nc(this,e,t),t[29]=this.manifoldCapacity,t[30]=this.stepCount;let r=o=>Math.min(31,Math.max(0,Math.round(Math.log2(o))));t[31]=r(this.primalLanes[0])|r(this.primalLanes[1])<<8|r(this.primalLanes[2])<<16,e[32]=i.windSpeed*Math.cos(i.windAngle),e[33]=i.windSpeed*Math.sin(i.windAngle),e[34]=0,e[35]=i.windPressure,e[36]=i.windGust,e[40]=i.up[0],e[41]=i.up[1],e[42]=i.up[2],e[43]=0,Qt(this.device,this.paramsBuffer,s)}function uc(s){let e=(i,r)=>{if(s.split(i).length!==2)throw Error("Review packed Newton accumulator integration");s=s.replace(i,r)};e(` lin: mat3x3f,
3617
3660
  ang: mat3x3f,`,` lin: mat2x3f,
3618
3661
  ang: mat2x3f,`),e("fn addRow(acc:",`fn symmetricOuter(v: vec3f) -> mat2x3f {
3619
3662
  return mat2x3f(v * v, vec3f(v.y * v.x, v.z * v.x, v.z * v.y));
3620
3663
  }
3621
3664
 
3622
- fn addRow(acc:`),e("outer(l, l) * k","symmetricOuter(l) * k"),e("outer(a, a) * k","symmetricOuter(a) * k"),e("mat3x3f(vec3f(g.x, 0.0, 0.0), vec3f(0.0, g.y, 0.0), vec3f(0.0, 0.0, g.z))","mat2x3f(g, vec3f(0.0))"),e("mat3x3f(vec3f(m, 0.0, 0.0), vec3f(0.0, m, 0.0), vec3f(0.0, 0.0, m))","mat2x3f(vec3f(m), vec3f(0.0))"),e("mat3x3f(vec3f(I.x, 0.0, 0.0), vec3f(0.0, I.y, 0.0), vec3f(0.0, 0.0, I.z))","mat2x3f(I, vec3f(0.0))");let t={"0][0":"0][0","0][1":"1][0","0][2":"1][1","1][1":"0][1","1][2":"1][2","2][2":"0][2"};return s=s.replace(/acc\.(lin|ang)\[(\d)\]\[(\d)\]/g,(i,r,o,a)=>{let n=t[`${o}][${a}`];if(!n)throw Error("Unexpected Newton accumulator entry");return`acc.${r}[${n}]`}),s}var vn=["pos","rot","initialPos","initialRot","size","moment","inertialPos","inertialRot","vel","angVel"],Uf=/bodies\[([^\]]+)\]\.([A-Za-z]+)/g;function Nf(s){let e=new Map;for(let t of s.matchAll(/\bfn (\w+)\(/g)){let i=t.index,r=s.indexOf("{",i),o=1,a=r+1;for(;o&&a<s.length;a++)s[a]==="{"&&o++,s[a]==="}"&&o--;if(o)throw Error("Review compact body function boundaries");e.set(t[1],{start:i,brace:r,end:a,text:s.slice(i,a),body:s.slice(r+1,a-1)})}return e}function xn(s){let e=Nf(s),t=m=>{let h=e.get(m);if(!h)throw Error(`Review compact body integration: ${m}`);return h},i=(m,h)=>m.replace(Uf,(g,b,y)=>{let A=vn.indexOf(y);if(A<0)throw Error(`Review compact body field: ${y}`);return h?`bodies[compactBodySlot(u32(${b}), ${A}u)]`:`bodies[u32(${b}) * 10u + ${A}u]`}),r=m=>[...m.matchAll(/\b(\w+)\s*\(/g)].map(h=>h[1]).filter(h=>e.has(h)),o=new Set([...e].filter(([,m])=>m.body.includes("bodies[")).map(([m])=>m)),a;do{a=!1;for(let[m,h]of e)!o.has(m)&&r(h.body).some(g=>o.has(g))&&(o.add(m),a=!0)}while(a);let n=new Set,l=m=>{for(let h of r(t(m).body))!o.has(h)||n.has(h)||(n.add(h),l(h))};l("warmStartJoints"),l("warmStartBodies");let c=m=>m.replace(/\b(\w+)(?=\s*\()/g,h=>n.has(h)?`${h}BodyRecords`:h),u=[...n].map(m=>c(i(t(m).text,!1))).join(`
3665
+ fn addRow(acc:`),e("outer(l, l) * k","symmetricOuter(l) * k"),e("outer(a, a) * k","symmetricOuter(a) * k"),e("mat3x3f(vec3f(g.x, 0.0, 0.0), vec3f(0.0, g.y, 0.0), vec3f(0.0, 0.0, g.z))","mat2x3f(g, vec3f(0.0))"),e("mat3x3f(vec3f(m, 0.0, 0.0), vec3f(0.0, m, 0.0), vec3f(0.0, 0.0, m))","mat2x3f(vec3f(m), vec3f(0.0))"),e("mat3x3f(vec3f(I.x, 0.0, 0.0), vec3f(0.0, I.y, 0.0), vec3f(0.0, 0.0, I.z))","mat2x3f(I, vec3f(0.0))");let t={"0][0":"0][0","0][1":"1][0","0][2":"1][1","1][1":"0][1","1][2":"1][2","2][2":"0][2"};return s=s.replace(/acc\.(lin|ang)\[(\d)\]\[(\d)\]/g,(i,r,o,a)=>{let n=t[`${o}][${a}`];if(!n)throw Error("Unexpected Newton accumulator entry");return`acc.${r}[${n}]`}),s}var vn=["pos","rot","initialPos","initialRot","size","moment","inertialPos","inertialRot","vel","angVel"],Uf=/bodies\[([^\]]+)\]\.([A-Za-z]+)/g;function Nf(s){let e=new Map;for(let t of s.matchAll(/\bfn (\w+)\(/g)){let i=t.index,r=s.indexOf("{",i),o=1,a=r+1;for(;o&&a<s.length;a++)s[a]==="{"&&o++,s[a]==="}"&&o--;if(o)throw Error("Review compact body function boundaries");e.set(t[1],{start:i,brace:r,end:a,text:s.slice(i,a),body:s.slice(r+1,a-1)})}return e}function xn(s){let e=Nf(s),t=m=>{let p=e.get(m);if(!p)throw Error(`Review compact body integration: ${m}`);return p},i=(m,p)=>m.replace(Uf,(g,b,y)=>{let A=vn.indexOf(y);if(A<0)throw Error(`Review compact body field: ${y}`);return p?`bodies[compactBodySlot(u32(${b}), ${A}u)]`:`bodies[u32(${b}) * 10u + ${A}u]`}),r=m=>[...m.matchAll(/\b(\w+)\s*\(/g)].map(p=>p[1]).filter(p=>e.has(p)),o=new Set([...e].filter(([,m])=>m.body.includes("bodies[")).map(([m])=>m)),a;do{a=!1;for(let[m,p]of e)!o.has(m)&&r(p.body).some(g=>o.has(g))&&(o.add(m),a=!0)}while(a);let n=new Set,l=m=>{for(let p of r(t(m).body))!o.has(p)||n.has(p)||(n.add(p),l(p))};l("warmStartJoints"),l("warmStartBodies");let c=m=>m.replace(/\b(\w+)(?=\s*\()/g,p=>n.has(p)?`${p}BodyRecords`:p),u=[...n].map(m=>c(i(t(m).text,!1))).join(`
3623
3666
 
3624
- `),f=(m,h)=>{let g=t(m).body;for(let y of[" if (!solverStepValid()) { return; }"," let i = gid.x;"," if (i >= params.bodyCount) { return; }"]){if(g.split(y).length!==2)throw Error(`Review compact body entry: ${m}`);g=g.replace(y,"")}g=g.replace(/bodies\[i\]\.([A-Za-z]+)/g,"value.$1"),h||(g=c(g));let b=(y,A)=>A?`compactBodySlot(i, ${y}u)`:`i * 10u + ${y}u`;return`fn ${m}(@builtin(global_invocation_id) gid: vec3u) {
3667
+ `),f=(m,p)=>{let g=t(m).body;for(let y of[" if (!solverStepValid()) { return; }"," let i = gid.x;"," if (i >= params.bodyCount) { return; }"]){if(g.split(y).length!==2)throw Error(`Review compact body entry: ${m}`);g=g.replace(y,"")}g=g.replace(/bodies\[i\]\.([A-Za-z]+)/g,"value.$1"),p||(g=c(g));let b=(y,A)=>A?`compactBodySlot(i, ${y}u)`:`i * 10u + ${y}u`;return`fn ${m}(@builtin(global_invocation_id) gid: vec3u) {
3625
3668
  let i = gid.x;
3626
3669
  let allocated = i < params.stateBOffset;
3627
3670
  var value: Body;
3628
- if (allocated) { value = Body(${vn.map((y,A)=>`bodies[${b(A,h)}]`).join(", ")}); }
3671
+ if (allocated) { value = Body(${vn.map((y,A)=>`bodies[${b(A,p)}]`).join(", ")}); }
3629
3672
  if (i < params.bodyCount && solverStepValid()) { ${g} }
3630
3673
  // All threads finish reading their tile before any thread overwrites it.
3631
3674
  // Inactive and unused records participate, including a partial final tile.
3632
3675
  storageBarrier();
3633
- if (allocated) { ${vn.map((y,A)=>`bodies[${b(A,!h)}] = value.${y};`).join(`
3676
+ if (allocated) { ${vn.map((y,A)=>`bodies[${b(A,!p)}] = value.${y};`).join(`
3634
3677
  `)} }
3635
- }`},d=[[t("warmStartJoints"),c(i(t("warmStartJoints").text,!1))],[t("warmStartBodies"),f("warmStartBodies",!1)],[t("updateVelocities"),f("updateVelocities",!0)]].sort(([m],[h])=>h.start-m.start);for(let[m,h]of d)s=s.slice(0,m.start)+h+s.slice(m.end);let p="var<storage, read_write> bodies: array<Body>;";if(s.split(p).length!==2)throw Error("Review compact body storage binding");return s=s.replace(p,"var<storage, read_write> bodies: array<vec4f>;"),i(s,!0)+`
3678
+ }`},d=[[t("warmStartJoints"),c(i(t("warmStartJoints").text,!1))],[t("warmStartBodies"),f("warmStartBodies",!1)],[t("updateVelocities"),f("updateVelocities",!0)]].sort(([m],[p])=>p.start-m.start);for(let[m,p]of d)s=s.slice(0,m.start)+p+s.slice(m.end);let h="var<storage, read_write> bodies: array<Body>;";if(s.split(h).length!==2)throw Error("Review compact body storage binding");return s=s.replace(h,"var<storage, read_write> bodies: array<vec4f>;"),i(s,!0)+`
3636
3679
  ${u}
3637
3680
  fn compactBodySlot(i: u32, field: u32) -> u32 {
3638
3681
  let tile = i / 64u * 64u;
@@ -3640,15 +3683,15 @@ fn compactBodySlot(i: u32, field: u32) -> u32 {
3640
3683
  if (field < 4u) { return tile * 10u + (i % 64u) * 4u + field; }
3641
3684
  return tile * 10u + width * 4u + (i % 64u) * 6u + field - 4u;
3642
3685
  }
3643
- `}var ho=256;function fc(s){let e=(t,i)=>{if(s.split(t).length!==2)throw Error("Review parallel dual integration");s=s.replace(t,i)};return e("fn dualManifold(m: u32) {","fn dualManifold(m: u32, lane: u32) {"),e("for (var c = mf.ids.z; c < end; c++) {","for (var c = mf.ids.z + lane; c < end; c += 4u) {"),e(` let id = gid.x;
3686
+ `}var po=256;function fc(s){let e=(t,i)=>{if(s.split(t).length!==2)throw Error("Review parallel dual integration");s=s.replace(t,i)};return e("fn dualManifold(m: u32) {","fn dualManifold(m: u32, lane: u32) {"),e("for (var c = mf.ids.z; c < end; c++) {","for (var c = mf.ids.z + lane; c < end; c += 4u) {"),e(` let id = gid.x;
3644
3687
  if (id < params.jointCount) { dualJoint(id); }
3645
- else if (id - params.jointCount < manifoldCount()) { dualManifold(id - params.jointCount); }`,` let id = (gid.x + gid.y * ${ho*64}u) / 4u;
3688
+ else if (id - params.jointCount < manifoldCount()) { dualManifold(id - params.jointCount); }`,` let id = (gid.x + gid.y * ${po*64}u) / 4u;
3646
3689
  let lane = gid.x % 4u;
3647
3690
  if (id < params.jointCount) { if (lane == 0u) { dualJoint(id); } }
3648
3691
  else if (id - params.jointCount < manifoldCount()) { dualManifold(id - params.jointCount, lane); }`),s}function An(s,e){let t=s.dualArgPipelines??={serial:s.pipes.argsContacts};if(e&&!t.parallel){let i=Yr(ge,Zs),r="setArgs(IA_CONSTRAINTS, params.jointCount + items);";if(i.split(r).length!==2)throw Error("Review parallel contact dispatch sizing");let o=i.replace(r,`let blocks = groupsFor((params.jointCount + items) * 4u);
3649
- args[IA_CONSTRAINTS] = min(blocks, ${ho}u);
3650
- args[IA_CONSTRAINTS + 1u] = max(1u, (blocks + ${ho-1}u) / ${ho}u);
3651
- args[IA_CONSTRAINTS + 2u] = 1u;`);t.parallel=s.device.createComputePipeline({layout:s.device.createPipelineLayout({bindGroupLayouts:[s.layouts.args]}),compute:{module:s.device.createShaderModule({code:o}),entryPoint:"argsContacts"}})}s.pipes.argsContacts=e?t.parallel:t.serial,s.parallelDual=e}var wn=new WeakMap;function po(s){return wn.get(s)}function dc(s,e){e?wn.set(s,Object.freeze({...e})):wn.delete(s)}function Bn(s){let e=s.indexOf("/** A partial system per body slot handed between lanes (primal). */"),t=s.indexOf("fn accumulate(",e),i=s.lastIndexOf("/**",t);if(e<0||t<0||i<=e)throw Error("3D primal layout changed; review the compatibility kernel");return s.slice(0,e)+`
3692
+ args[IA_CONSTRAINTS] = min(blocks, ${po}u);
3693
+ args[IA_CONSTRAINTS + 1u] = max(1u, (blocks + ${po-1}u) / ${po}u);
3694
+ args[IA_CONSTRAINTS + 2u] = 1u;`);t.parallel=s.device.createComputePipeline({layout:s.device.createPipelineLayout({bindGroupLayouts:[s.layouts.args]}),compute:{module:s.device.createShaderModule({code:o}),entryPoint:"argsContacts"}})}s.pipes.argsContacts=e?t.parallel:t.serial,s.parallelDual=e}var wn=new WeakMap;function ho(s){return wn.get(s)}function dc(s,e){e?wn.set(s,Object.freeze({...e})):wn.delete(s)}function Bn(s){let e=s.indexOf("/** A partial system per body slot handed between lanes (primal). */"),t=s.indexOf("fn accumulate(",e),i=s.lastIndexOf("/**",t);if(e<0||t<0||i<=e)throw Error("3D primal layout changed; review the compatibility kernel");return s.slice(0,e)+`
3652
3695
  @compute @workgroup_size(64)
3653
3696
  fn primal(@builtin(global_invocation_id) gid: vec3u) {
3654
3697
  let start = color[params.colorStartOffset + pc.color];
@@ -3658,7 +3701,7 @@ fn primal(@builtin(global_invocation_id) gid: vec3u) {
3658
3701
  finishBody(i, accumulate(i, 0u, 1u));
3659
3702
  }
3660
3703
 
3661
- `+s.slice(i)}function mi(s,e,t){if(s.split(e).length!==2)throw Error("3D contact layout changed; review the compatibility kernel");return s.replace(e,t)}function mo(s,e,t){let i=new RegExp(`struct ${e} \\{[^}]*\\}`,"g");if([...s.matchAll(i)].length!==1)throw Error(`Expected one 3D ${e} layout`);return s.replace(i,t)}function hc(s,e,t){let i=`fn ${e}(`;if(s.split(i).length!==2)throw Error(`Expected one 3D ${e} function`);let r=s.indexOf(i),a=s.indexOf("{",r)+1,n=1;for(;a<s.length&&n;a++)s[a]==="{"&&n++,s[a]==="}"&&n--;if(n)throw Error(`Incomplete 3D ${e} function`);return s.slice(0,r)+t(s.slice(r,a))+s.slice(a)}function Cn(s){s=mo(s,"PairBody",`struct PairBody {
3704
+ `+s.slice(i)}function mi(s,e,t){if(s.split(e).length!==2)throw Error("3D contact layout changed; review the compatibility kernel");return s.replace(e,t)}function mo(s,e,t){let i=new RegExp(`struct ${e} \\{[^}]*\\}`,"g");if([...s.matchAll(i)].length!==1)throw Error(`Expected one 3D ${e} layout`);return s.replace(i,t)}function pc(s,e,t){let i=`fn ${e}(`;if(s.split(i).length!==2)throw Error(`Expected one 3D ${e} function`);let r=s.indexOf(i),a=s.indexOf("{",r)+1,n=1;for(;a<s.length&&n;a++)s[a]==="{"&&n++,s[a]==="}"&&n--;if(n)throw Error(`Incomplete 3D ${e} function`);return s.slice(0,r)+t(s.slice(r,a))+s.slice(a)}function Cn(s){s=mo(s,"PairBody",`struct PairBody {
3662
3705
  ids: vec4u,
3663
3706
  rot: vec4f,
3664
3707
  dLin: vec4f,
@@ -3668,7 +3711,7 @@ fn primal(@builtin(global_invocation_id) gid: vec3u) {
3668
3711
  anchorB: vec4f, // xyz: anchor, w: normal error
3669
3712
  penalty: vec4f, // xyz: penalties, w: first tangent error
3670
3713
  force: vec4f, // xyz: forces, w: second tangent error
3671
- }`);let e={rA:"bitcast<vec3f>(k.anchorA.xyz)",rB:"k.anchorB.xyz",key:"k.anchorA.w",c0x:"k.anchorB.w",c0y:"k.penalty.w",c0z:"k.force.w",pen:"k.penalty.xyz",lam:"k.force.xyz"};for(let t of["evalContact","accumulate","dualManifold"])s=hc(s,t,i=>i.replace(/\bk\.(rA|rB|key|c0x|c0y|c0z|pen|lam)\b/g,(r,o)=>e[o]));return s=mi(s,"contacts[c].lam = e.F;","contacts[c].force = vec4f(e.F, k.force.w);"),s=mi(s,"contacts[c].key =","contacts[c].anchorA.w ="),s=mi(s,"contacts[c].pen = pen;","contacts[c].penalty = vec4f(pen, k.penalty.w);"),s=hc(s,"evalContact",t=>{t=mi(t,` var e: ContactEval;
3714
+ }`);let e={rA:"bitcast<vec3f>(k.anchorA.xyz)",rB:"k.anchorB.xyz",key:"k.anchorA.w",c0x:"k.anchorB.w",c0y:"k.penalty.w",c0z:"k.force.w",pen:"k.penalty.xyz",lam:"k.force.xyz"};for(let t of["evalContact","accumulate","dualManifold"])s=pc(s,t,i=>i.replace(/\bk\.(rA|rB|key|c0x|c0y|c0z|pen|lam)\b/g,(r,o)=>e[o]));return s=mi(s,"contacts[c].lam = e.F;","contacts[c].force = vec4f(e.F, k.force.w);"),s=mi(s,"contacts[c].key =","contacts[c].anchorA.w ="),s=mi(s,"contacts[c].pen = pen;","contacts[c].penalty = vec4f(pen, k.penalty.w);"),s=pc(s,"evalContact",t=>{t=mi(t,` var e: ContactEval;
3672
3715
  `,""),t=mi(t," e.rAW ="," let rAW ="),t=mi(t," e.rBW ="," let rBW ="),t=t.replaceAll("e.rAW","rAW").replaceAll("e.rBW","rBW"),t=mi(t," e.C ="," let C =");let i=t.indexOf(" var F ="),r=t.indexOf(" return e;",i);if(i<0||r<0)throw Error("Expected 3D contact force projection");return t.slice(0,i)+` let raw = k.penalty.xyz * C + k.force.xyz;
3673
3716
  let normalForce = select(0.0, raw.x, raw.x < 0.0);
3674
3717
  let bounds = abs(normalForce) * friction;
@@ -3686,7 +3729,7 @@ fn primal(@builtin(global_invocation_id) gid: vec3u) {
3686
3729
  C: vec4f,
3687
3730
  F: vec4f,
3688
3731
  limits: vec4f, // x: tangent force length, y: Coulomb bound
3689
- }`),s=s.replace(/\b(ev|e)\.(rAW|rBW|C|F)\b/g,"$1.$2.xyz").replace(/\be\.frictionScale\b/g,"e.limits.x").replace(/\be\.bounds\b/g,"e.limits.y"),s=mo(s,"PassConstants","struct PassConstants { data: vec4u, }"),s.replaceAll("pc.color","pc.data.x").replaceAll("pc.alpha","bitcast<f32>(pc.data.y)")}function pc(s){if(!s.includes("struct Poly"))return s;let e=`@compute @workgroup_size(64)
3732
+ }`),s=s.replace(/\b(ev|e)\.(rAW|rBW|C|F)\b/g,"$1.$2.xyz").replace(/\be\.frictionScale\b/g,"e.limits.x").replace(/\be\.bounds\b/g,"e.limits.y"),s=mo(s,"PassConstants","struct PassConstants { data: vec4u, }"),s.replaceAll("pc.color","pc.data.x").replaceAll("pc.alpha","bitcast<f32>(pc.data.y)")}function hc(s){if(!s.includes("struct Poly"))return s;let e=`@compute @workgroup_size(64)
3690
3733
  fn narrowphase(@builtin(global_invocation_id) gid: vec3u)`;if(s.split(e).length!==2)throw Error("3D hull narrowphase changed; review the compatibility kernel");return s.replace(e,"fn narrowphasePair(gid: vec3u)")+`
3691
3734
  @compute @workgroup_size(32)
3692
3735
  fn narrowphase(@builtin(global_invocation_id) gid: vec3u) {
@@ -3694,9 +3737,9 @@ fn narrowphase(@builtin(global_invocation_id) gid: vec3u) {
3694
3737
  narrowphasePair(vec3u(gid.x * 2u + offset, 0u, 0u));
3695
3738
  }
3696
3739
  }
3697
- `}function mc(s,e){return e==="points"&&(s=uc(s)),(e==="points"||e==="optimized")&&(s=fc(s)),s}var gi=class extends ro{writeParams(){cc.call(this)}writePassConstants(e,t){fo.call(this,e,t)}constructor(e,t,i={}){if(i.smallGroups!==void 0&&typeof i.smallGroups!="boolean")throw Error("smallGroups must be a boolean");let r=po(e),o=i.scalarPrimal??r?.scalarPrimal??!1,a=i.portableContactMath??r?.portableContactMath??!1,n=t.forces.some(v=>fs(v)),l=t.forces.some(v=>{let x=Ui(v);return x&&(Number.isFinite(x.breakStrain)||Number.isFinite(x.breakForce))}),c={requested:i.solverMode??"auto",contactScheduling:i.contactScheduling??"manifolds",custom:!!i.shaders?.solve},u=Ar({...c,bodyCount:t.bodies.length,constraintCount:t.forces.filter(v=>v instanceof ke||v instanceof dt).length}),f=u.selected==="custom"?i.shaders.solve:u.selected==="optimized"?us:u.selected==="points"?so:void 0,d=r?.broadphase??i.broadphase??"auto";if(!["grid","hploc","auto"].includes(d))throw Error("broadphase must be 'grid', 'hploc' or 'auto'");let p=i.bvh?.rebuildInterval??64;if(!Number.isInteger(p)||p<1)throw Error("BVH rebuildInterval must be a positive integer");for(let[v,x]of[["minimumColors",64],["minimumColorRounds",32]]){let w=i[v]??0;if(!Number.isInteger(w)||w<0||w>x)throw Error(`${v} must be an integer between 0 and ${x}`);if(v==="minimumColorRounds"&&w%2)throw Error("minimumColorRounds must be even")}let m=mc(f??Ge,u.selected),h=sn(on(n?mn(l?oo(m):m):l?oo(m):m));o&&(h=Bn(h)),a&&(h=Cn(h)),u.selected==="points"&&!o&&!a&&!r?.dispatchIsolation&&(h=xn(h));let g=!i.shaders?.contacts&&i.hulls!==!1&&e.limits.maxStorageBuffersPerShaderStage>=9&&t.bodies.some(v=>Ct(v)),b=!i.shaders?.contacts&&t.bodies.some(v=>Fe(v)),y=!i.shaders?.contacts&&t.bodies.some(v=>v.isTrigger);y&&(h=fn(h));let A=v=>(b&&(v=gn(v)),y&&(v=uo(v)),v=Ql(v),a?pc(v):v);if(super(e,t,{...i,shaders:{...i.shaders,contacts:i.shaders?.contacts??A(vr(g)),solve:h,refs:i.shaders?.refs??(i.shaders?.contacts?void 0:Yl(eo)),topology:i.shaders?.topology??(y?dn():void 0)}}),this.solverPolicy=c,this.scalarPrimal=o,this.portableContactMath=a,y&&(this.sensorsEnabled=!0,hn(this)),o&&(this.primalLanes=[1,1,1]),this.dispatchIsolation=r?.dispatchIsolation??!1,!i.shaders?.contacts){this.contactShaders.custom=!1,this.hullShaders=g,this.capsulesEnabled=b;let v=this.contactShaders.make;this.contactShaders.make=x=>v(A(x))}this.springFracture=l,this.angularConstraints=n,this.customSolveSource=i.shaders?.solve,t.forces.forEach((v,x)=>{let w=Ui(v);w&&this.setSpringMaterial(x,w)}),this.adaptiveScheduling=o?!1:i.adaptiveScheduling??!0,this.defaultPrimalLanes=[...this.primalLanes],this.cacheAdjacencyKeys=i.cacheAdjacencyKeys,this.smallGroups=i.smallGroups,this.adjacencyPipelines={original:this.pipes.sortAdjacency},this.selectAdjacencyPipeline(),this.solverDecision=u,this.solvePipelineCache=new Map([[u.selected,Object.fromEntries(["warmStartJoints","warmStartBodies","primal","dual","updateVelocities"].map(v=>[v,this.pipes[v]]))]]),An(this,u.selected==="points"||u.selected==="optimized"),this.minimumColors=i.minimumColors??0,this.minimumColorRounds=i.minimumColorRounds??4,this.colorCap=Math.max(this.minimumColors,this.colorCap),this.colorRounds=Math.max(this.minimumColorRounds,this.colorRounds),this.broadphaseRequested=d,this.broadphase=d==="hploc"?"hploc":"grid",this.bvhOptions=i.bvh??{},this.bvh=null,this.detailCallback=null,this.detailTiming=null,this.profileErrors=[],this.selectBroadphase(),t.forces.forEach((v,x)=>{let w=fs(v);w&&this.setAngularConstraint(x,w)}),t.bodies.forEach((v,x)=>{Fe(v)&&this.installCapsule(this.gpuIndex(x))})}installCapsule(e){if(!this.capsulesEnabled){if(this.contactShaders.custom)throw Error("Analytic capsules require the built-in contact kernel");this.capsulesEnabled=!0;let t=this.contactShaders.make;this.contactShaders.make=i=>t(gn(i)),this.contactShaders.make(vr(this.hullShaders??!1))}this.device.queue.writeBuffer(this.bodyBuffer,e*160+156,new Float32Array([-1]))}async raycast(e,t,i={}){let[r]=await this.raycastAll([{origin:e,direction:t,maxDistance:i.maxDistance}],i);return r}raycastAll(e,t={}){return this.flushPropertyEdits(),this.shapeQueries??=new pi(this),this.shapeQueries.cast(e.map(i=>({...i,radius:0})),t)}async sphereCast(e,t,i,r={}){let[o]=await this.sphereCastAll([{origin:e,radius:t,direction:i,maxDistance:r.maxDistance}],r);return o}sphereCastAll(e,t={}){return this.flushPropertyEdits(),this.shapeQueries??=new pi(this),this.shapeQueries.cast(e,t)}selectBroadphase(){if(this.broadphaseRequested!=="auto"){this.broadphaseDecision={requested:this.broadphaseRequested,selected:this.broadphase,reason:"Explicit selection"};return}let e=new Float64Array(this.bodyCount),t=0,i=0,r=0;for(let d=0;d<this.bodyCount;d++){let p=this.bodies[d];if(p.radius>0&&(e[t++]=p.radius),p.dynamic){i++;let[m,h,g]=p.size,b=Math.min(m,h,g),y=Math.max(m,h,g),A=m+h+g-b-y;!p.sphere&&!p.hull&&b<=.4*A&&A>=.5*y&&r++}}let o=t?to(e.subarray(0,t),t>>1):1,a=this.cellSize/(2*o),n=this.jointCount-this.freeSlots.length,l=i?r/i:0,c=this.bodyCapacity<=16*this.device.limits.maxComputeWorkgroupsPerDimension&&(2*this.bodyCapacity+16*Math.ceil(Math.log2(Math.max(2,this.bodyCapacity)))+32)*32<=this.device.limits.maxStorageBufferBindingSize,u=n>=this.bodyCount&&l>=.25,f=c&&this.bodyCount>=1e4&&(a>=4||u);this.broadphase=f?"hploc":"grid",this.broadphaseDecision={requested:"auto",selected:this.broadphase,bodyCount:this.bodyCount,cellRatio:a,constraintCount:n,thinPlateFraction:l,reason:c?f?u?"Many linked thin plates; the tree avoids empty grid-cell space":"Large grid cells contain many smaller objects":"Grid retained for this body count and size distribution":"The GPU tree exceeds this adapter's limits; the grid is used"}}step(){co(this,Jl),this.selectAdjacencyPipeline(),this.selectSolver(),Nl(this),this.radiiDirty&&(this.uploadStatics(),this.selectBroadphase()),this.broadphaseRequested==="auto"&&this.broadphaseDecision.constraintCount!==this.jointCount-this.freeSlots.length&&this.selectBroadphase(),this.broadphase==="grid"&&this.bvh&&(this.bvh.destroy(),this.bvh=null),this.broadphase==="hploc"&&(!this.bvh||this.bvh.bodyBuffer!==this.bodyBuffer)&&(this.bvh?.destroy(),this.bvh=new no(this.device,this,this.bvhOptions)),this.dispatchIsolation||this.smallGroupPipeline||this.bvh||this.detailCallback||this.sleeping||this.restitution?.active.size||this.bodyCommands?.pending.size||this.propertyEdits?.pending||this.externalBeforeStep?Hl(this):super.step()}encodeStepPrelude(e){this.flushPropertyEdits(e),this.sleeping?.before(e),this.bodyCommands?.flush(e),this.externalBeforeStep?.(e),this.restitution?.before(e)}encodeStepPostlude(e){this.restitution?.after(e),this.sleeping?.after(e),this.externalAfterStep?.(e)}setRestitution(e,t){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.bodyCount||!Number.isFinite(t)||t<0||t>1)throw Error("Restitution requires a live body index and a value between 0 and 1");t>0&&!this.restitution&&(this.restitution=new wr(this)),this.restitution?.set(e,t),this.wakeAll()}setSolverMode(e){return Ar({...this.solverPolicy,requested:e,bodyCount:this.bodyCount}),this.solverPolicy.requested=e,this.selectSolver(),this.solverDecision}solveSource(e,t=this.solverDecision.selected){return e=mc(e,t),this.springFracture&&(e=oo(e)),this.angularConstraints&&(e=mn(e)),this.sensorsEnabled&&(e=fn(e)),e=sn(on(e)),this.scalarPrimal&&(e=Bn(e)),this.portableContactMath&&(e=Cn(e)),t==="points"&&!this.scalarPrimal&&!this.portableContactMath&&!this.dispatchIsolation&&(e=xn(e)),e}setAngularConstraint(e,t){if(!Number.isInteger(e)||e<0||e>=this.jointCount)throw Error("Angular constraint needs a live slot");let i=kt(t);this.flushPropertyEdits(),this.angularConstraints||(this.angularConstraints=!0,this.rebuildSolvePipelines());let r=new Float32Array(32);r[0]=r[1]=1e3,r[3]=3e38,r.set(i.axisA,24),r.set(i.axisB,28),r[27]=i.type==="motor"?i.speed:i.minAngle,r[31]=i.type==="motor"?i.maxTorque:i.maxAngle,this.device.queue.writeBuffer(this.jointBuffer,e*128,r),this.info[e*4]=i.type==="motor"?3:4,this.device.queue.writeBuffer(this.infoBuffer,e*16,this.info.subarray(e*4,e*4+4)),this.captureAngularFrames([e]),this.wakeAll()}captureAngularFrames(e){if(!e.length)return;this.flushPropertyEdits();let t=this.device;this.angularFramePipeline??=t.createComputePipeline({layout:"auto",compute:{module:t.createShaderModule({code:`const DISPATCH_STRIDE = ${t.limits.maxComputeWorkgroupsPerDimension*64}u;
3698
- ${Zl.replaceAll("id.x","(id.x+id.y*DISPATCH_STRIDE)")}`}),entryPoint:"capture"}}),this.runCapture("angular",this.angularFramePipeline,Uint32Array.from(e),e.length)}setMotor(e,{speed:t,maxTorque:i}={}){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(this.info[e*4]!==3)throw Error("Motor needs an active motor slot");if(t!==void 0&&!Number.isFinite(t))throw Error("Motor speed must be finite");if(i!==void 0&&(!Number.isFinite(i)||i<0))throw Error("maxTorque must be nonnegative");t!==void 0&&oe(this).float(this.jointBuffer,e*32+27,t),i!==void 0&&oe(this).float(this.jointBuffer,e*32+31,i),this.wakeAll()}rebuildSolvePipelines(){this.solvePipelineCache.clear(),this.smallGroupPipelines?.clear(),this.smallGroupPipeline=null;let e=this.solverDecision.selected,t=e==="custom"?this.customSolveSource:e==="optimized"?us:e==="points"?so:Ge,i=this.device.createShaderModule({code:this.solveSource(t)}),r=this.device.createPipelineLayout({bindGroupLayouts:[this.layouts.solve,this.layouts.pass]}),o=Object.fromEntries(["warmStartJoints","warmStartBodies","primal","dual","updateVelocities"].map(a=>[a,this.device.createComputePipeline({layout:r,compute:{module:i,entryPoint:a}})]));Object.assign(this.pipes,o),this.solvePipelineCache.set(e,o)}setSensor(e,t){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.bodyCount||typeof t!="boolean")throw Error("Sensor requires a live body index and boolean flag");if(t&&!this.sensorsEnabled){this.sensorsEnabled=!0,hn(this),this.rebuildSolvePipelines(),this.contactShaders.make(uo(vr(this.hullShaders??!1)));let i=this.contactShaders.make;this.contactShaders.make=a=>i(uo(a));let r=this.device.createShaderModule({code:dn()}),o=this.device.createPipelineLayout({bindGroupLayouts:[this.layouts.topo]});for(let a of["degreeContacts","fillContacts"])this.pipes[a]=this.device.createComputePipeline({layout:o,compute:{module:r,entryPoint:a}})}this.sensorsEnabled&&oe(this).float(this.bodyBuffer,e*40+11,t?1:0),this.wakeAll()}selectSolver(){let e=this.jointCount-this.freeSlots.length;this.adaptiveScheduling&&this.schedulingDecision?.dense&&(this.bodyCount<25e4||e>0)&&(this.primalLanes=[...this.defaultPrimalLanes],this.schedulingDecision={...this.schedulingDecision,dense:!1,reason:"Threads per body follow solve-group size"});let t=this.solverDecision;if(t.requested===this.solverPolicy.requested&&t.bodyCount===this.bodyCount&&t.constraintCount===e)return;let i=Ar({...this.solverPolicy,bodyCount:this.bodyCount,constraintCount:e});if(i.selected!==t.selected){let r=this.solvePipelineCache.get(i.selected);if(!r){let o=i.selected==="optimized"?us:i.selected==="points"?so:void 0,a=this.device.createShaderModule({code:this.solveSource(o??Ge,i.selected)}),n=this.device.createPipelineLayout({bindGroupLayouts:[this.layouts.solve,this.layouts.pass]});r=Object.fromEntries(["warmStartJoints","warmStartBodies","primal","dual","updateVelocities"].map(l=>[l,this.device.createComputePipeline({label:`${i.selected} ${l}`,layout:n,compute:{module:a,entryPoint:l}})])),this.solvePipelineCache.set(i.selected,r)}Object.assign(this.pipes,r)}this.solverDecision=i,An(this,i.selected==="points"||i.selected==="optimized")}profileDetailedNextStep(e){if(!this.device.features.has("timestamp-query")||this.timingBusy||this.timingCallback||this.detailCallback)return!1;let t=2*(9+2*this.params.iterations);return(!this.detailTiming||this.detailTiming.count<t)&&(this.releaseAppTiming(),this.detailTiming={count:t,querySet:this.device.createQuerySet({type:"timestamp",count:t}),resolve:this.device.createBuffer({size:t*8,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),read:this.device.createBuffer({size:t*8,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})}),this.detailCallback=e,!0}captureConstraintFrames(e){if(e.length){this.flushPropertyEdits(),this.framePipeline||(this.framePipeline=this.device.createComputePipeline({layout:"auto",compute:{module:this.device.createShaderModule({code:`const DISPATCH_STRIDE = ${this.device.limits.maxComputeWorkgroupsPerDimension*64}u;
3699
- ${Dl.replaceAll("id.x","(id.x+id.y*DISPATCH_STRIDE)")}`}),entryPoint:"capture"}})),(!this.frameData||this.frameData.length<e.length*4)&&(this.frameData=new Uint32Array(Math.max(e.length*4,(this.frameData?.length??0)*2,64)));for(let t=0;t<e.length;t++)this.frameData[t*4]=e[t].slot,this.frameData[t*4+1]=e[t].spring?1:0;this.runCapture("frame",this.framePipeline,this.frameData.subarray(0,e.length*4),e.length)}}runCapture(e,t,i,r){this.flushEdits?.();let o=this.device,a=(this.captureUploads??={})[e]??={};(!a.buffer||a.buffer.size<i.byteLength)&&(a.buffer?.destroy(),a.buffer=o.createBuffer({size:i.byteLength*2,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),a.buffers=null),o.queue.writeBuffer(a.buffer,0,i);let n=[this.bodyBuffer,this.jointBuffer,this.infoBuffer,a.buffer];(!a.buffers||n.some((d,p)=>d!==a.buffers[p])||a.bytes!==i.byteLength)&&(a.group=o.createBindGroup({layout:t.getBindGroupLayout(0),entries:n.map((d,p)=>({binding:p,resource:{buffer:d,...p===3?{size:i.byteLength}:{}}}))}),a.buffers=n,a.bytes=i.byteLength);let l=o.createCommandEncoder(),c=l.beginComputePass();c.setPipeline(t),c.setBindGroup(0,a.group);let u=Math.ceil(r/64),f=o.limits.maxComputeWorkgroupsPerDimension;c.dispatchWorkgroups(Math.min(u,f),Math.ceil(u/f)),c.end(),o.queue.submit([l.finish()])}setSpringMaterial(e,t={}){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.jointCount||this.info[e*4]!==br)throw Error("Spring material requires an active spring slot");let i=It(t);!this.springFracture&&(Number.isFinite(i.breakStrain)||Number.isFinite(i.breakForce))&&(this.springFracture=!0,this.rebuildSolvePipelines());for(let[r,o]of[["breakStrain",11],["breakForce",15]])oe(this).float(this.jointBuffer,e*32+o,i[r]===1/0?0:i[r]);this.wakeAll()}appendConstraints(...e){return this.flushPropertyEdits(),super.appendConstraints(...e)}appendJoint(e,t,i,r,o,a){let n=c=>c===1/0?3e38:c,[l]=this.appendConstraints(1,(c,u)=>{u[3]=n(o),u[7]=n(a),u[11]=3e38,u.set(i,24),u.set(r,28);let f=e>=0?this.bodies[e].size:[0,0,0],d=this.bodies[t].size;return u[15]=f.reduce((p,m,h)=>p+(m+d[h])**2,0),[1,e,t]});return this.wakeConstraint(l),l}appendJoints(...e){let t=super.appendJoints(...e);for(let i of t)this.wakeConstraint(i);return t}appendSprings(...e){let t=super.appendSprings(...e);for(let i of t)this.wakeConstraint(i);return t}enableSleeping(e,t={}){this.sleeping||(this.sleeping=new Fi({device:this.device,gpu:this,capacity:this.bodyCapacity,aggregates:e.bodies.map((i,r)=>({rigid:i,index:r}))},t),this.sleeping.initializing&&this.step())}wakeAll(){this.sleeping&&(this.sleeping.wakeRequested=!0)}async readSleepStats(){return this.sleeping?this.sleeping.readStats():{sleeping:0,wakeRequested:!1}}addBodies(e){this.flushPropertyEdits();let t=super.addBodies(e);if(t>=0)for(let i=0;i<Math.min(e.length,this.bodyCount-t);i++)Fe(e[i])&&this.installCapsule(t+i);if(t>=0&&this.sleeping)for(let i=0;i<Math.min(e.length,this.bodyCount-t);i++)this.sleeping.register(t+i,e[i].mass,e[i].allowSleep!==!1);return t}rewriteBodies(e,t){this.flushPropertyEdits(),super.rewriteBodies(e,t);for(let i=0;i<e.length;i++)Fe(t[i])&&this.installCapsule(e[i]);if(this.sleeping)for(let i=0;i<e.length;i++)this.sleeping.register(e[i],t[i].mass,t[i].allowSleep!==!1)}releaseJoints(e){this.flushPropertyEdits();let t=Array.from(e);for(let i of t)this.wakeConstraint(i);super.releaseJoints(t)}setWorldAnchor(e,t){if(!Number.isInteger(e)||e<0||e>=this.jointCount||this.info[e*4+1]!==-1||t?.length!==3||!Array.from(t).every(Number.isFinite))throw Error("A world joint and finite xyz anchor are required");for(let i=0;i<3;i++)oe(this).float(this.jointBuffer,e*32+24+i,t[i]);this.sleeping?.wakeBody(this.info[e*4+2])}disableConstraint(e){this.flushPropertyEdits(),this.wakeConstraint(e),super.disableConstraint(e)}wakeConstraint(e){if(!(!this.sleeping||e<0||e>=this.jointCount||!this.info[e*4]))for(let t of this.info.subarray(e*4+1,e*4+3))t>=0&&this.sleeping.wakeBody(t)}setFilters(e,t,i){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(e.length!==t.length||e.length!==i.length)throw Error("Each body index needs a group and collision mask");for(let o=0;o<e.length;o++){if(!Number.isInteger(e[o])||e[o]<0||e[o]>=this.bodyCount)throw Error("Collision filters require live body indices");for(let a of[t[o],i[o]])if(!Number.isInteger(a)||a<0||a>4294967295)throw Error("Collision masks must be unsigned 32-bit integers")}let r=oe(this);for(let o=0;o<e.length;o++)r.uint(this.filterBuffer,e[o]*2,t[o]),r.uint(this.filterBuffer,e[o]*2+1,i[o]);this.wakeAll()}profileNextStep(e){return this.detailCallback?!1:super.profileNextStep(t=>e({...t,broadphase:this.broadphase,bvhRebuilt:this.bvh?.lastRebuilt??!1}))}flushPropertyEdits(e){this.propertyEdits?.flush(e)}readJoints(){return this.flushPropertyEdits(),super.readJoints()}releaseAppTiming(){if(this.detailTiming){for(let e of["querySet","resolve","read"])this.detailTiming[e].destroy();this.detailTiming=null}}destroy(){this.passConstantCache=null;for(let e of Object.values(this.captureUploads??{}))e.buffer.destroy();this.captureUploads=null,this.frameData=null,this.propertyEdits?.destroy(),this.shapeQueries?.destroy(),this.restitution?.destroy(),this.sleeping?.dispose(),this.bvh?.destroy(),this.bvh=null,this.timingBusy||this.releaseAppTiming(),super.destroy(),this.solvePipelineCache.clear(),this.adjacencyPipelines={}}adapt(e){if(super.adapt(e),this.colorCap=Math.max(this.minimumColors,this.colorCap),this.colorRounds=Math.max(this.minimumColorRounds,this.colorRounds),this.adaptiveScheduling){let t=this.bodyCount>=25e4&&this.jointCount-this.freeSlots.length===0&&e.manifolds>=1.75*this.bodyCount&&!e.overflow&&!e.clashes;this.primalLanes=t?[2**31,2**31,2**31]:[...this.defaultPrimalLanes],this.schedulingDecision={bodyCount:this.bodyCount,manifolds:e.manifolds,dense:t,cachedAdjacency:this.adjacencyCached,reason:t?"Eight threads share each dense body solve":"Threads per body follow solve-group size"}}}selectAdjacencyPipeline(){let e=this.cacheAdjacencyKeys??this.bodyCount>=25e4;this.adjacencyCached!==e&&(e&&!this.adjacencyPipelines.cached&&(this.adjacencyPipelines.cached=this.device.createComputePipeline({label:"Cached adjacency keys",layout:this.device.createPipelineLayout({bindGroupLayouts:[this.layouts.topo]}),compute:{module:this.device.createShaderModule({code:Xl}),entryPoint:"sortAdjacency"}})),this.pipes.sortAdjacency=e?this.adjacencyPipelines.cached:this.adjacencyPipelines.original,this.adjacencyCached=e)}};var Sn=new WeakMap,gc=[{name:"batched-grid",broadphase:"grid",dispatchIsolation:!1},{name:"isolated-grid",broadphase:"grid",dispatchIsolation:!0},{name:"batched-hploc",broadphase:"hploc",dispatchIsolation:!1},{name:"isolated-hploc",broadphase:"hploc",dispatchIsolation:!0},{name:"scalar-grid",broadphase:"grid",dispatchIsolation:!1,scalarPrimal:!0},{name:"scalar-isolated-grid",broadphase:"grid",dispatchIsolation:!0,scalarPrimal:!0},{name:"portable-contact-grid",broadphase:"grid",dispatchIsolation:!1,portableContactMath:!0},{name:"portable-contact-isolated-grid",broadphase:"grid",dispatchIsolation:!0,scalarPrimal:!0,portableContactMath:!0}];function vc(s){return Sn.has(s)||Sn.set(s,qf(s,void 0,{diagnostics:!1})),Sn.get(s)}async function qf(s,e,{diagnostics:t=!0}={}){let i=[];for(let r of gc){let o=await yc(s,r,e,t);if(!t&&!o.passed&&(o=await yc(s,r,e,!0)),i.push(o),!!o.passed)return dc(s,{dispatchIsolation:r.dispatchIsolation,scalarPrimal:r.scalarPrimal??!1,portableContactMath:r.portableContactMath??!1,broadphase:r.broadphase==="hploc"?"hploc":void 0}),{...o,selected:r.name,compatibility:r.name!==gc[0].name,attempts:i}}return{...i[0],selected:null,compatibility:!1,attempts:i}}function bc(s){let e=new ni;return e.iterations=5,s||(e.gravity=0),new Ze(e,[16,.25,16],0,.6,[0,-.125,0]),new Ze(e,[1,1,1],1,.6,[-2,s?2:.45,0]),nr(e,.5,1,.6,[0,s?2.3:.45,0]),Cr(e,.25,1.6,1,.6,[2,s?2.5:.75,0]),e}async function bi(s,e,t=e.size){let i=s.createBuffer({size:t,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST});try{let r=s.createCommandEncoder();return r.copyBufferToBuffer(e,0,i,0,t),s.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ),i.getMappedRange().slice(0)}finally{i.destroy()}}async function Vf(s){s.step();let e=await s.readCounters(),t=new Uint32Array(await bi(s.device,s.argsBuffer)),i=await Hf(s),r=new Uint32Array(i),o=new Float32Array(i),a=new Uint32Array(await bi(s.device,s.adjBuffer)),n=new Uint32Array(await bi(s.device,s.colorBuffer)),{manifolds:l,contacts:c}=s.contactStorage,u=await bi(s.device,l,Math.max(32,e.manifolds*32)),f=new Uint32Array(u),d=new Float32Array(u),p=new Float32Array(await bi(s.device,c,Math.max(64,e.contacts*64))),m=await s.readBodies(),h=e.manifolds>=3?await Wf(s):[],g=h.some(({contactEvaluation:b})=>b.returnedForce===0&&b.independentForce<-1e-5);return{expectedFloorPairs:3,counters:e,pairs:e.pairs?Array.from(await s.readPairs()):[],narrowphaseWorkgroups:Array.from(t.subarray(0,3)),solver:{scalarPrimal:s.scalarPrimal,portableContactMath:s.portableContactMath,lanes:[...s.primalLanes],contactWorkgroups:Array.from(t.subarray(3,6)),dualWorkgroups:Array.from(t.subarray(9,12)),colorWorkgroups:Array.from(t.subarray(12,12+3*s.colorCap)),adjacencyStarts:Array.from(a.subarray(0,5)),adjacencyEntries:Array.from(a.subarray(2*s.bodyCapacity+1,2*s.bodyCapacity+1+a[4])),colorStarts:Array.from(n.subarray(2*s.bodyCapacity,2*s.bodyCapacity+s.colorCap+1)),colorBodies:Array.from(n.subarray(2*s.bodyCapacity+65,2*s.bodyCapacity+68)),positionsAfterOverlap:[1,2,3].map(b=>Array.from(m.subarray(b*40,b*40+3))),manifolds:Array.from({length:e.manifolds},(b,y)=>({ids:Array.from(f.subarray(y*8,y*8+4)),normalAndFriction:Array.from(d.subarray(y*8+4,y*8+8))})),contacts:Array.from({length:e.contacts},(b,y)=>({anchorA:Array.from(p.subarray(y*16,y*16+3)),anchorB:Array.from(p.subarray(y*16+4,y*16+7)),gap:p[y*16+7],penalty:Array.from(p.subarray(y*16+8,y*16+11)),force:Array.from(p.subarray(y*16+12,y*16+15))})),serialSystems:h,failure:g?"contact-evaluation":null},filters:Array.from(new Uint32Array(await bi(s.device,s.filterBuffer))),params:{bodyCount:r[0],largeCount:r[1],noCollideCount:r[2],pairCapacity:r[3],contactCapacity:r[4],dt:o[5],cellSize:o[6],maxSmallRadius:o[7],up:Array.from(o.subarray(8,11)),alpha:o[11]},stage:e.pairs<3?"collision-pairs":e.manifolds<3?"contact-generation":"contacts-created"}}async function Wf(s){let e=s.portableContactMath?"bitcast<f32>(pc.data.y)":"pc.alpha",t=s.portableContactMath?"k.anchorB.w":"k.c0x",i=s.portableContactMath?"k.penalty.x":"k.pen.x",r=s.portableContactMath?"k.force.x":"k.lam.x",o=s.device.createShaderModule({code:s.solveSource(Ge)+`
3740
+ `}function mc(s,e){return e==="points"&&(s=uc(s)),(e==="points"||e==="optimized")&&(s=fc(s)),s}var gi=class extends ro{writeParams(){cc.call(this)}writePassConstants(e,t){fo.call(this,e,t)}constructor(e,t,i={}){if(i.smallGroups!==void 0&&typeof i.smallGroups!="boolean")throw Error("smallGroups must be a boolean");let r=ho(e),o=i.scalarPrimal??r?.scalarPrimal??!1,a=i.portableContactMath??r?.portableContactMath??!1,n=t.forces.some(v=>fs(v)),l=t.forces.some(v=>{let x=Ui(v);return x&&(Number.isFinite(x.breakStrain)||Number.isFinite(x.breakForce))}),c={requested:i.solverMode??"auto",contactScheduling:i.contactScheduling??"manifolds",custom:!!i.shaders?.solve},u=Ar({...c,bodyCount:t.bodies.length,constraintCount:t.forces.filter(v=>v instanceof ke||v instanceof dt).length}),f=u.selected==="custom"?i.shaders.solve:u.selected==="optimized"?us:u.selected==="points"?so:void 0,d=r?.broadphase??i.broadphase??"auto";if(!["grid","hploc","auto"].includes(d))throw Error("broadphase must be 'grid', 'hploc' or 'auto'");let h=i.bvh?.rebuildInterval??64;if(!Number.isInteger(h)||h<1)throw Error("BVH rebuildInterval must be a positive integer");for(let[v,x]of[["minimumColors",64],["minimumColorRounds",32]]){let w=i[v]??0;if(!Number.isInteger(w)||w<0||w>x)throw Error(`${v} must be an integer between 0 and ${x}`);if(v==="minimumColorRounds"&&w%2)throw Error("minimumColorRounds must be even")}let m=mc(f??Ge,u.selected),p=sn(on(n?mn(l?oo(m):m):l?oo(m):m));o&&(p=Bn(p)),a&&(p=Cn(p)),u.selected==="points"&&!o&&!a&&!r?.dispatchIsolation&&(p=xn(p));let g=!i.shaders?.contacts&&i.hulls!==!1&&e.limits.maxStorageBuffersPerShaderStage>=9&&t.bodies.some(v=>Ct(v)),b=!i.shaders?.contacts&&t.bodies.some(v=>Ue(v)),y=!i.shaders?.contacts&&t.bodies.some(v=>v.isTrigger);y&&(p=fn(p));let A=v=>(b&&(v=gn(v)),y&&(v=uo(v)),v=Ql(v),a?hc(v):v);if(super(e,t,{...i,shaders:{...i.shaders,contacts:i.shaders?.contacts??A(vr(g)),solve:p,refs:i.shaders?.refs??(i.shaders?.contacts?void 0:Yl(eo)),topology:i.shaders?.topology??(y?dn():void 0)}}),this.solverPolicy=c,this.scalarPrimal=o,this.portableContactMath=a,y&&(this.sensorsEnabled=!0,pn(this)),o&&(this.primalLanes=[1,1,1]),this.dispatchIsolation=r?.dispatchIsolation??!1,!i.shaders?.contacts){this.contactShaders.custom=!1,this.hullShaders=g,this.capsulesEnabled=b;let v=this.contactShaders.make;this.contactShaders.make=x=>v(A(x))}this.springFracture=l,this.angularConstraints=n,this.customSolveSource=i.shaders?.solve,t.forces.forEach((v,x)=>{let w=Ui(v);w&&this.setSpringMaterial(x,w)}),this.adaptiveScheduling=o?!1:i.adaptiveScheduling??!0,this.defaultPrimalLanes=[...this.primalLanes],this.cacheAdjacencyKeys=i.cacheAdjacencyKeys,this.smallGroups=i.smallGroups,this.adjacencyPipelines={original:this.pipes.sortAdjacency},this.selectAdjacencyPipeline(),this.solverDecision=u,this.solvePipelineCache=new Map([[u.selected,Object.fromEntries(["warmStartJoints","warmStartBodies","primal","dual","updateVelocities"].map(v=>[v,this.pipes[v]]))]]),An(this,u.selected==="points"||u.selected==="optimized"),this.minimumColors=i.minimumColors??0,this.minimumColorRounds=i.minimumColorRounds??4,this.colorCap=Math.max(this.minimumColors,this.colorCap),this.colorRounds=Math.max(this.minimumColorRounds,this.colorRounds),this.broadphaseRequested=d,this.broadphase=d==="hploc"?"hploc":"grid",this.bvhOptions=i.bvh??{},this.bvh=null,this.detailCallback=null,this.detailTiming=null,this.profileErrors=[],this.selectBroadphase(),t.forces.forEach((v,x)=>{let w=fs(v);w&&this.setAngularConstraint(x,w)}),t.bodies.forEach((v,x)=>{Ue(v)&&this.installCapsule(this.gpuIndex(x))})}installCapsule(e){if(!this.capsulesEnabled){if(this.contactShaders.custom)throw Error("Analytic capsules require the built-in contact kernel");this.capsulesEnabled=!0;let t=this.contactShaders.make;this.contactShaders.make=i=>t(gn(i)),this.contactShaders.make(vr(this.hullShaders??!1))}this.device.queue.writeBuffer(this.bodyBuffer,e*160+156,new Float32Array([-1]))}async raycast(e,t,i={}){let[r]=await this.raycastAll([{origin:e,direction:t,maxDistance:i.maxDistance}],i);return r}raycastAll(e,t={}){return this.flushPropertyEdits(),this.shapeQueries??=new hi(this),this.shapeQueries.cast(e.map(i=>({...i,radius:0})),t)}async sphereCast(e,t,i,r={}){let[o]=await this.sphereCastAll([{origin:e,radius:t,direction:i,maxDistance:r.maxDistance}],r);return o}sphereCastAll(e,t={}){return this.flushPropertyEdits(),this.shapeQueries??=new hi(this),this.shapeQueries.cast(e,t)}selectBroadphase(){if(this.broadphaseRequested!=="auto"){this.broadphaseDecision={requested:this.broadphaseRequested,selected:this.broadphase,reason:"Explicit selection"};return}let e=new Float64Array(this.bodyCount),t=0,i=0,r=0;for(let d=0;d<this.bodyCount;d++){let h=this.bodies[d];if(h.radius>0&&(e[t++]=h.radius),h.dynamic){i++;let[m,p,g]=h.size,b=Math.min(m,p,g),y=Math.max(m,p,g),A=m+p+g-b-y;!h.sphere&&!h.hull&&b<=.4*A&&A>=.5*y&&r++}}let o=t?to(e.subarray(0,t),t>>1):1,a=this.cellSize/(2*o),n=this.jointCount-this.freeSlots.length,l=i?r/i:0,c=this.bodyCapacity<=16*this.device.limits.maxComputeWorkgroupsPerDimension&&(2*this.bodyCapacity+16*Math.ceil(Math.log2(Math.max(2,this.bodyCapacity)))+32)*32<=this.device.limits.maxStorageBufferBindingSize,u=n>=this.bodyCount&&l>=.25,f=c&&this.bodyCount>=1e4&&(a>=4||u);this.broadphase=f?"hploc":"grid",this.broadphaseDecision={requested:"auto",selected:this.broadphase,bodyCount:this.bodyCount,cellRatio:a,constraintCount:n,thinPlateFraction:l,reason:c?f?u?"Many linked thin plates; the tree avoids empty grid-cell space":"Large grid cells contain many smaller objects":"Grid retained for this body count and size distribution":"The GPU tree exceeds this adapter's limits; the grid is used"}}step(){co(this,Jl),this.selectAdjacencyPipeline(),this.selectSolver(),Nl(this),this.radiiDirty&&(this.uploadStatics(),this.selectBroadphase()),this.broadphaseRequested==="auto"&&this.broadphaseDecision.constraintCount!==this.jointCount-this.freeSlots.length&&this.selectBroadphase(),this.broadphase==="grid"&&this.bvh&&(this.bvh.destroy(),this.bvh=null),this.broadphase==="hploc"&&(!this.bvh||this.bvh.bodyBuffer!==this.bodyBuffer)&&(this.bvh?.destroy(),this.bvh=new no(this.device,this,this.bvhOptions)),this.dispatchIsolation||this.smallGroupPipeline||this.bvh||this.detailCallback||this.sleeping||this.restitution?.active.size||this.bodyCommands?.pending.size||this.propertyEdits?.pending||this.externalBeforeStep?Hl(this):super.step()}encodeStepPrelude(e){this.flushPropertyEdits(e),this.sleeping?.before(e),this.bodyCommands?.flush(e),this.externalBeforeStep?.(e),this.restitution?.before(e)}encodeStepPostlude(e){this.restitution?.after(e),this.sleeping?.after(e),this.externalAfterStep?.(e)}setRestitution(e,t){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.bodyCount||!Number.isFinite(t)||t<0||t>1)throw Error("Restitution requires a live body index and a value between 0 and 1");t>0&&!this.restitution&&(this.restitution=new wr(this)),this.restitution?.set(e,t),this.wakeAll()}setSolverMode(e){return Ar({...this.solverPolicy,requested:e,bodyCount:this.bodyCount}),this.solverPolicy.requested=e,this.selectSolver(),this.solverDecision}solveSource(e,t=this.solverDecision.selected){return e=mc(e,t),this.springFracture&&(e=oo(e)),this.angularConstraints&&(e=mn(e)),this.sensorsEnabled&&(e=fn(e)),e=sn(on(e)),this.scalarPrimal&&(e=Bn(e)),this.portableContactMath&&(e=Cn(e)),t==="points"&&!this.scalarPrimal&&!this.portableContactMath&&!this.dispatchIsolation&&(e=xn(e)),e}setAngularConstraint(e,t){if(!Number.isInteger(e)||e<0||e>=this.jointCount)throw Error("Angular constraint needs a live slot");let i=kt(t);this.flushPropertyEdits(),this.angularConstraints||(this.angularConstraints=!0,this.rebuildSolvePipelines());let r=new Float32Array(32);r[0]=r[1]=1e3,r[3]=3e38,r.set(i.axisA,24),r.set(i.axisB,28),r[27]=i.type==="motor"?i.speed:i.minAngle,r[31]=i.type==="motor"?i.maxTorque:i.maxAngle,this.device.queue.writeBuffer(this.jointBuffer,e*128,r),this.info[e*4]=i.type==="motor"?3:4,this.device.queue.writeBuffer(this.infoBuffer,e*16,this.info.subarray(e*4,e*4+4)),this.captureAngularFrames([e]),this.wakeAll()}captureAngularFrames(e){if(!e.length)return;this.flushPropertyEdits();let t=this.device;this.angularFramePipeline??=t.createComputePipeline({layout:"auto",compute:{module:t.createShaderModule({code:`const DISPATCH_STRIDE = ${t.limits.maxComputeWorkgroupsPerDimension*64}u;
3741
+ ${Zl.replaceAll("id.x","(id.x+id.y*DISPATCH_STRIDE)")}`}),entryPoint:"capture"}}),this.runCapture("angular",this.angularFramePipeline,Uint32Array.from(e),e.length)}setMotor(e,{speed:t,maxTorque:i}={}){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(this.info[e*4]!==3)throw Error("Motor needs an active motor slot");if(t!==void 0&&!Number.isFinite(t))throw Error("Motor speed must be finite");if(i!==void 0&&(!Number.isFinite(i)||i<0))throw Error("maxTorque must be nonnegative");t!==void 0&&oe(this).float(this.jointBuffer,e*32+27,t),i!==void 0&&oe(this).float(this.jointBuffer,e*32+31,i),this.wakeAll()}rebuildSolvePipelines(){this.solvePipelineCache.clear(),this.smallGroupPipelines?.clear(),this.smallGroupPipeline=null;let e=this.solverDecision.selected,t=e==="custom"?this.customSolveSource:e==="optimized"?us:e==="points"?so:Ge,i=this.device.createShaderModule({code:this.solveSource(t)}),r=this.device.createPipelineLayout({bindGroupLayouts:[this.layouts.solve,this.layouts.pass]}),o=Object.fromEntries(["warmStartJoints","warmStartBodies","primal","dual","updateVelocities"].map(a=>[a,this.device.createComputePipeline({layout:r,compute:{module:i,entryPoint:a}})]));Object.assign(this.pipes,o),this.solvePipelineCache.set(e,o)}setSensor(e,t){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.bodyCount||typeof t!="boolean")throw Error("Sensor requires a live body index and boolean flag");if(t&&!this.sensorsEnabled){this.sensorsEnabled=!0,pn(this),this.rebuildSolvePipelines(),this.contactShaders.make(uo(vr(this.hullShaders??!1)));let i=this.contactShaders.make;this.contactShaders.make=a=>i(uo(a));let r=this.device.createShaderModule({code:dn()}),o=this.device.createPipelineLayout({bindGroupLayouts:[this.layouts.topo]});for(let a of["degreeContacts","fillContacts"])this.pipes[a]=this.device.createComputePipeline({layout:o,compute:{module:r,entryPoint:a}})}this.sensorsEnabled&&oe(this).float(this.bodyBuffer,e*40+11,t?1:0),this.wakeAll()}selectSolver(){let e=this.jointCount-this.freeSlots.length;this.adaptiveScheduling&&this.schedulingDecision?.dense&&(this.bodyCount<25e4||e>0)&&(this.primalLanes=[...this.defaultPrimalLanes],this.schedulingDecision={...this.schedulingDecision,dense:!1,reason:"Threads per body follow solve-group size"});let t=this.solverDecision;if(t.requested===this.solverPolicy.requested&&t.bodyCount===this.bodyCount&&t.constraintCount===e)return;let i=Ar({...this.solverPolicy,bodyCount:this.bodyCount,constraintCount:e});if(i.selected!==t.selected){let r=this.solvePipelineCache.get(i.selected);if(!r){let o=i.selected==="optimized"?us:i.selected==="points"?so:void 0,a=this.device.createShaderModule({code:this.solveSource(o??Ge,i.selected)}),n=this.device.createPipelineLayout({bindGroupLayouts:[this.layouts.solve,this.layouts.pass]});r=Object.fromEntries(["warmStartJoints","warmStartBodies","primal","dual","updateVelocities"].map(l=>[l,this.device.createComputePipeline({label:`${i.selected} ${l}`,layout:n,compute:{module:a,entryPoint:l}})])),this.solvePipelineCache.set(i.selected,r)}Object.assign(this.pipes,r)}this.solverDecision=i,An(this,i.selected==="points"||i.selected==="optimized")}profileDetailedNextStep(e){if(!this.device.features.has("timestamp-query")||this.timingBusy||this.timingCallback||this.detailCallback)return!1;let t=2*(9+2*this.params.iterations);return(!this.detailTiming||this.detailTiming.count<t)&&(this.releaseAppTiming(),this.detailTiming={count:t,querySet:this.device.createQuerySet({type:"timestamp",count:t}),resolve:this.device.createBuffer({size:t*8,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),read:this.device.createBuffer({size:t*8,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})}),this.detailCallback=e,!0}captureConstraintFrames(e){if(e.length){this.flushPropertyEdits(),this.framePipeline||(this.framePipeline=this.device.createComputePipeline({layout:"auto",compute:{module:this.device.createShaderModule({code:`const DISPATCH_STRIDE = ${this.device.limits.maxComputeWorkgroupsPerDimension*64}u;
3742
+ ${Dl.replaceAll("id.x","(id.x+id.y*DISPATCH_STRIDE)")}`}),entryPoint:"capture"}})),(!this.frameData||this.frameData.length<e.length*4)&&(this.frameData=new Uint32Array(Math.max(e.length*4,(this.frameData?.length??0)*2,64)));for(let t=0;t<e.length;t++)this.frameData[t*4]=e[t].slot,this.frameData[t*4+1]=e[t].spring?1:0;this.runCapture("frame",this.framePipeline,this.frameData.subarray(0,e.length*4),e.length)}}runCapture(e,t,i,r){this.flushEdits?.();let o=this.device,a=(this.captureUploads??={})[e]??={};(!a.buffer||a.buffer.size<i.byteLength)&&(a.buffer?.destroy(),a.buffer=o.createBuffer({size:i.byteLength*2,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),a.buffers=null),o.queue.writeBuffer(a.buffer,0,i);let n=[this.bodyBuffer,this.jointBuffer,this.infoBuffer,a.buffer];(!a.buffers||n.some((d,h)=>d!==a.buffers[h])||a.bytes!==i.byteLength)&&(a.group=o.createBindGroup({layout:t.getBindGroupLayout(0),entries:n.map((d,h)=>({binding:h,resource:{buffer:d,...h===3?{size:i.byteLength}:{}}}))}),a.buffers=n,a.bytes=i.byteLength);let l=o.createCommandEncoder(),c=l.beginComputePass();c.setPipeline(t),c.setBindGroup(0,a.group);let u=Math.ceil(r/64),f=o.limits.maxComputeWorkgroupsPerDimension;c.dispatchWorkgroups(Math.min(u,f),Math.ceil(u/f)),c.end(),o.queue.submit([l.finish()])}setSpringMaterial(e,t={}){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.jointCount||this.info[e*4]!==br)throw Error("Spring material requires an active spring slot");let i=It(t);!this.springFracture&&(Number.isFinite(i.breakStrain)||Number.isFinite(i.breakForce))&&(this.springFracture=!0,this.rebuildSolvePipelines());for(let[r,o]of[["breakStrain",11],["breakForce",15]])oe(this).float(this.jointBuffer,e*32+o,i[r]===1/0?0:i[r]);this.wakeAll()}appendConstraints(...e){return this.flushPropertyEdits(),super.appendConstraints(...e)}appendJoint(e,t,i,r,o,a){let n=c=>c===1/0?3e38:c,[l]=this.appendConstraints(1,(c,u)=>{u[3]=n(o),u[7]=n(a),u[11]=3e38,u.set(i,24),u.set(r,28);let f=e>=0?this.bodies[e].size:[0,0,0],d=this.bodies[t].size;return u[15]=f.reduce((h,m,p)=>h+(m+d[p])**2,0),[1,e,t]});return this.wakeConstraint(l),l}appendJoints(...e){let t=super.appendJoints(...e);for(let i of t)this.wakeConstraint(i);return t}appendSprings(...e){let t=super.appendSprings(...e);for(let i of t)this.wakeConstraint(i);return t}enableSleeping(e,t={}){this.sleeping||(this.sleeping=new Fi({device:this.device,gpu:this,capacity:this.bodyCapacity,aggregates:e.bodies.map((i,r)=>({rigid:i,index:r}))},t),this.sleeping.initializing&&this.step())}wakeAll(){this.sleeping&&(this.sleeping.wakeRequested=!0)}async readSleepStats(){return this.sleeping?this.sleeping.readStats():{sleeping:0,wakeRequested:!1}}addBodies(e){this.flushPropertyEdits();let t=super.addBodies(e);if(t>=0)for(let i=0;i<Math.min(e.length,this.bodyCount-t);i++)Ue(e[i])&&this.installCapsule(t+i);if(t>=0&&this.sleeping)for(let i=0;i<Math.min(e.length,this.bodyCount-t);i++)this.sleeping.register(t+i,e[i].mass,e[i].allowSleep!==!1);return t}rewriteBodies(e,t){this.flushPropertyEdits(),super.rewriteBodies(e,t);for(let i=0;i<e.length;i++)Ue(t[i])&&this.installCapsule(e[i]);if(this.sleeping)for(let i=0;i<e.length;i++)this.sleeping.register(e[i],t[i].mass,t[i].allowSleep!==!1)}releaseJoints(e){this.flushPropertyEdits();let t=Array.from(e);for(let i of t)this.wakeConstraint(i);super.releaseJoints(t)}setWorldAnchor(e,t){if(!Number.isInteger(e)||e<0||e>=this.jointCount||this.info[e*4+1]!==-1||t?.length!==3||!Array.from(t).every(Number.isFinite))throw Error("A world joint and finite xyz anchor are required");for(let i=0;i<3;i++)oe(this).float(this.jointBuffer,e*32+24+i,t[i]);this.sleeping?.wakeBody(this.info[e*4+2])}disableConstraint(e){this.flushPropertyEdits(),this.wakeConstraint(e),super.disableConstraint(e)}wakeConstraint(e){if(!(!this.sleeping||e<0||e>=this.jointCount||!this.info[e*4]))for(let t of this.info.subarray(e*4+1,e*4+3))t>=0&&this.sleeping.wakeBody(t)}setFilters(e,t,i){if(this.destroyed)throw Error("The 3D solver has been destroyed");if(e.length!==t.length||e.length!==i.length)throw Error("Each body index needs a group and collision mask");for(let o=0;o<e.length;o++){if(!Number.isInteger(e[o])||e[o]<0||e[o]>=this.bodyCount)throw Error("Collision filters require live body indices");for(let a of[t[o],i[o]])if(!Number.isInteger(a)||a<0||a>4294967295)throw Error("Collision masks must be unsigned 32-bit integers")}let r=oe(this);for(let o=0;o<e.length;o++)r.uint(this.filterBuffer,e[o]*2,t[o]),r.uint(this.filterBuffer,e[o]*2+1,i[o]);this.wakeAll()}profileNextStep(e){return this.detailCallback?!1:super.profileNextStep(t=>e({...t,broadphase:this.broadphase,bvhRebuilt:this.bvh?.lastRebuilt??!1}))}flushPropertyEdits(e){this.propertyEdits?.flush(e)}readJoints(){return this.flushPropertyEdits(),super.readJoints()}releaseAppTiming(){if(this.detailTiming){for(let e of["querySet","resolve","read"])this.detailTiming[e].destroy();this.detailTiming=null}}destroy(){this.passConstantCache=null;for(let e of Object.values(this.captureUploads??{}))e.buffer.destroy();this.captureUploads=null,this.frameData=null,this.propertyEdits?.destroy(),this.shapeQueries?.destroy(),this.restitution?.destroy(),this.sleeping?.dispose(),this.bvh?.destroy(),this.bvh=null,this.timingBusy||this.releaseAppTiming(),super.destroy(),this.solvePipelineCache.clear(),this.adjacencyPipelines={}}adapt(e){if(super.adapt(e),this.colorCap=Math.max(this.minimumColors,this.colorCap),this.colorRounds=Math.max(this.minimumColorRounds,this.colorRounds),this.adaptiveScheduling){let t=this.bodyCount>=25e4&&this.jointCount-this.freeSlots.length===0&&e.manifolds>=1.75*this.bodyCount&&!e.overflow&&!e.clashes;this.primalLanes=t?[2**31,2**31,2**31]:[...this.defaultPrimalLanes],this.schedulingDecision={bodyCount:this.bodyCount,manifolds:e.manifolds,dense:t,cachedAdjacency:this.adjacencyCached,reason:t?"Eight threads share each dense body solve":"Threads per body follow solve-group size"}}}selectAdjacencyPipeline(){let e=this.cacheAdjacencyKeys??this.bodyCount>=25e4;this.adjacencyCached!==e&&(e&&!this.adjacencyPipelines.cached&&(this.adjacencyPipelines.cached=this.device.createComputePipeline({label:"Cached adjacency keys",layout:this.device.createPipelineLayout({bindGroupLayouts:[this.layouts.topo]}),compute:{module:this.device.createShaderModule({code:Xl}),entryPoint:"sortAdjacency"}})),this.pipes.sortAdjacency=e?this.adjacencyPipelines.cached:this.adjacencyPipelines.original,this.adjacencyCached=e)}};var Sn=new WeakMap,gc=[{name:"batched-grid",broadphase:"grid",dispatchIsolation:!1},{name:"isolated-grid",broadphase:"grid",dispatchIsolation:!0},{name:"batched-hploc",broadphase:"hploc",dispatchIsolation:!1},{name:"isolated-hploc",broadphase:"hploc",dispatchIsolation:!0},{name:"scalar-grid",broadphase:"grid",dispatchIsolation:!1,scalarPrimal:!0},{name:"scalar-isolated-grid",broadphase:"grid",dispatchIsolation:!0,scalarPrimal:!0},{name:"portable-contact-grid",broadphase:"grid",dispatchIsolation:!1,portableContactMath:!0},{name:"portable-contact-isolated-grid",broadphase:"grid",dispatchIsolation:!0,scalarPrimal:!0,portableContactMath:!0}];function vc(s){return Sn.has(s)||Sn.set(s,qf(s,void 0,{diagnostics:!1})),Sn.get(s)}async function qf(s,e,{diagnostics:t=!0}={}){let i=[];for(let r of gc){let o=await yc(s,r,e,t);if(!t&&!o.passed&&(o=await yc(s,r,e,!0)),i.push(o),!!o.passed)return dc(s,{dispatchIsolation:r.dispatchIsolation,scalarPrimal:r.scalarPrimal??!1,portableContactMath:r.portableContactMath??!1,broadphase:r.broadphase==="hploc"?"hploc":void 0}),{...o,selected:r.name,compatibility:r.name!==gc[0].name,attempts:i}}return{...i[0],selected:null,compatibility:!1,attempts:i}}function bc(s){let e=new ni;return e.iterations=5,s||(e.gravity=0),new Ze(e,[16,.25,16],0,.6,[0,-.125,0]),new Ze(e,[1,1,1],1,.6,[-2,s?2:.45,0]),nr(e,.5,1,.6,[0,s?2.3:.45,0]),Cr(e,.25,1.6,1,.6,[2,s?2.5:.75,0]),e}async function bi(s,e,t=e.size){let i=s.createBuffer({size:t,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST});try{let r=s.createCommandEncoder();return r.copyBufferToBuffer(e,0,i,0,t),s.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ),i.getMappedRange().slice(0)}finally{i.destroy()}}async function Vf(s){s.step();let e=await s.readCounters(),t=new Uint32Array(await bi(s.device,s.argsBuffer)),i=await Hf(s),r=new Uint32Array(i),o=new Float32Array(i),a=new Uint32Array(await bi(s.device,s.adjBuffer)),n=new Uint32Array(await bi(s.device,s.colorBuffer)),{manifolds:l,contacts:c}=s.contactStorage,u=await bi(s.device,l,Math.max(32,e.manifolds*32)),f=new Uint32Array(u),d=new Float32Array(u),h=new Float32Array(await bi(s.device,c,Math.max(64,e.contacts*64))),m=await s.readBodies(),p=e.manifolds>=3?await Wf(s):[],g=p.some(({contactEvaluation:b})=>b.returnedForce===0&&b.independentForce<-1e-5);return{expectedFloorPairs:3,counters:e,pairs:e.pairs?Array.from(await s.readPairs()):[],narrowphaseWorkgroups:Array.from(t.subarray(0,3)),solver:{scalarPrimal:s.scalarPrimal,portableContactMath:s.portableContactMath,lanes:[...s.primalLanes],contactWorkgroups:Array.from(t.subarray(3,6)),dualWorkgroups:Array.from(t.subarray(9,12)),colorWorkgroups:Array.from(t.subarray(12,12+3*s.colorCap)),adjacencyStarts:Array.from(a.subarray(0,5)),adjacencyEntries:Array.from(a.subarray(2*s.bodyCapacity+1,2*s.bodyCapacity+1+a[4])),colorStarts:Array.from(n.subarray(2*s.bodyCapacity,2*s.bodyCapacity+s.colorCap+1)),colorBodies:Array.from(n.subarray(2*s.bodyCapacity+65,2*s.bodyCapacity+68)),positionsAfterOverlap:[1,2,3].map(b=>Array.from(m.subarray(b*40,b*40+3))),manifolds:Array.from({length:e.manifolds},(b,y)=>({ids:Array.from(f.subarray(y*8,y*8+4)),normalAndFriction:Array.from(d.subarray(y*8+4,y*8+8))})),contacts:Array.from({length:e.contacts},(b,y)=>({anchorA:Array.from(h.subarray(y*16,y*16+3)),anchorB:Array.from(h.subarray(y*16+4,y*16+7)),gap:h[y*16+7],penalty:Array.from(h.subarray(y*16+8,y*16+11)),force:Array.from(h.subarray(y*16+12,y*16+15))})),serialSystems:p,failure:g?"contact-evaluation":null},filters:Array.from(new Uint32Array(await bi(s.device,s.filterBuffer))),params:{bodyCount:r[0],largeCount:r[1],noCollideCount:r[2],pairCapacity:r[3],contactCapacity:r[4],dt:o[5],cellSize:o[6],maxSmallRadius:o[7],up:Array.from(o.subarray(8,11)),alpha:o[11]},stage:e.pairs<3?"collision-pairs":e.manifolds<3?"contact-generation":"contacts-created"}}async function Wf(s){let e=s.portableContactMath?"bitcast<f32>(pc.data.y)":"pc.alpha",t=s.portableContactMath?"k.anchorB.w":"k.c0x",i=s.portableContactMath?"k.penalty.x":"k.pen.x",r=s.portableContactMath?"k.force.x":"k.lam.x",o=s.device.createShaderModule({code:s.solveSource(Ge)+`
3700
3743
  @compute @workgroup_size(1) fn inspectSystems(@builtin(global_invocation_id) gid: vec3u) {
3701
3744
  let acc = accumulate(gid.x + 1u, 0u, 1u);
3702
3745
  joints[gid.x].penLin = vec4f(acc.lin[0][0], acc.lin[1][1], acc.lin[2][2], 0.0);
@@ -3729,7 +3772,7 @@ ${Dl.replaceAll("id.x","(id.x+id.y*DISPATCH_STRIDE)")}`}),entryPoint:"capture"}}
3729
3772
  out[5]=bitcast<u32>(p.dt); out[6]=bitcast<u32>(p.cellSize); out[7]=bitcast<u32>(p.maxSmallRadius);
3730
3773
  out[8]=bitcast<u32>(p.up.x); out[9]=bitcast<u32>(p.up.y); out[10]=bitcast<u32>(p.up.z);
3731
3774
  out[11]=bitcast<u32>(p.alpha);
3732
- }`}),entryPoint:"inspectParams"}}),r=e.createBindGroup({layout:i.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:s.paramsBuffer}},{binding:1,resource:{buffer:t}}]}),o=e.createCommandEncoder(),a=o.beginComputePass();return a.setPipeline(i),a.setBindGroup(0,r),a.dispatchWorkgroups(1),a.end(),e.queue.submit([o.finish()]),await bi(e,t)}finally{t.destroy()}}async function yc(s,e,t,i){let r={mode:e.name,passed:!1,steps:i?180:90,cases:[],errors:[],contactCache:"normal-float-generations-v1",diagnosticVersion:5,detailed:i,limits:{storageBindings:s.limits.maxStorageBuffersPerShaderStage,workgroupStorageBytes:s.limits.maxComputeWorkgroupStorageSize,workgroupInvocations:s.limits.maxComputeInvocationsPerWorkgroup,storageBindingBytes:s.limits.maxStorageBufferBindingSize}},o,a=n=>{let l=new gi(s,bc(n),{spatialSort:!1,bodyCapacity:4,smallGroups:!1,broadphase:e.broadphase,scalarPrimal:e.scalarPrimal??!1,portableContactMath:e.portableContactMath??!1,capacity:{pairs:32,manifolds:32,contacts:256,colors:8}});return l.params.up=[0,1,0],l.dispatchIsolation=e.dispatchIsolation,t?.(l,e,n),l};s.pushErrorScope("validation");try{if(o=a(!1),i)r.pipeline=await Vf(o);else{o.step();let n=await o.readCounters();r.pipeline={expectedFloorPairs:3,counters:n,solver:{scalarPrimal:o.scalarPrimal,portableContactMath:o.portableContactMath,lanes:[...o.primalLanes]},stage:n.pairs<3?"collision-pairs":n.manifolds<3?"contact-generation":"contacts-created"}}if(r.pipeline.stage!=="contacts-created")r.reason=r.pipeline.stage==="collision-pairs"?"The GPU did not find the three known overlapping floor pairs.":"The GPU found overlapping pairs but did not create all floor contacts.";else{if(i)o.destroy(),o=a(!0);else{let c=bc(!0);o.rewriteBodies([0,1,2,3],c.bodies),o.params.gravity=c.gravity}let n=0;r.samples=[];for(let c=0;c<r.steps;c++){if(o.step(),(c+1)%30&&c!==39)continue;let u=await o.readCounters();if(r.samples.push({step:c+1,...u}),u.manifolds&&n++,u.overflow||u.clashes)throw Error("Incomplete GPU contact graph")}let l=await o.readBodies();for(let c=1;c<4;c++){let u=c*40,[f,d,p,m]=l.subarray(u+4,u+8),h=c===1?.5*(Math.abs(2*(f*d+m*p))+Math.abs(1-2*(f*f+p*p))+Math.abs(2*(d*p-m*f))):c===2?.5:.25+.55*Math.abs(1-2*(f*f+p*p)),g=l[u+1]-h,b=l.subarray(u,u+40).every(Number.isFinite);r.cases.push({shape:["floor","box","sphere","capsule"][c],passed:b&&g>=-.06&&g<.12,floorGap:g,position:Array.from(l.subarray(u,u+3))})}r.contactSteps=n,r.passed=n>0&&r.cases.every(c=>c.passed),r.passed||(r.reason=r.pipeline.solver?.failure==="contact-evaluation"?"The GPU created floor contacts but returned zero force where a push was required.":"The GPU did not keep all three falling shapes on the floor.")}}catch(n){r.errors.push(n.message)}finally{try{let n=await s.popErrorScope();n&&r.errors.push(n.message)}catch(n){r.errors.push(n.message)}o?.destroy()}return r.passed=r.passed&&!r.errors.length,r}async function Sr(s={}){if(!globalThis.navigator?.gpu)throw Error("WebGPU needs a supported browser on localhost or HTTPS");let e=await navigator.gpu.requestAdapter({powerPreference:s.powerPreference??"high-performance"});if(!e)throw Error("No WebGPU adapter is available");let t={};for(let[r,o]of Object.entries(s.preferredLimits??{})){if(!r.startsWith("max")||e.limits[r]===void 0||!Number.isSafeInteger(o)||o<0)throw Error(`Invalid preferred GPU limit: ${r}`);t[r]=Math.min(o,e.limits[r])}for(let[r,o]of Object.entries(s.requiredLimits??{})){if(e.limits[r]===void 0||!Number.isSafeInteger(o)||o<0)throw Error(`Invalid required GPU limit: ${r}`);let a=e.limits[r];if(r.startsWith("min")&&o<a||!r.startsWith("min")&&o>a)throw Error(`GPU limit ${r} requires ${o}; this adapter supports ${a}`);t[r]=o}let i=await e.requestDevice({requiredLimits:t,requiredFeatures:e.features.has("timestamp-query")?["timestamp-query"]:[]});if(s.validate3D)try{await Ni(i)}catch(r){throw i.destroy(),r}return{adapter:e,device:i}}async function Ni(s){if(po(s))return s;let e=await vc(s);if(!e.passed)throw Error(`GPU 3D contact check failed: ${e.reason??e.errors.join("; ")}`);return s}var xc=`struct Body { pos:vec4f,rot:vec4f,initialPos:vec4f,initialRot:vec4f,size:vec4f,moment:vec4f,inertialPos:vec4f,inertialRot:vec4f,velocity:vec4f,angular:vec4f }
3775
+ }`}),entryPoint:"inspectParams"}}),r=e.createBindGroup({layout:i.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:s.paramsBuffer}},{binding:1,resource:{buffer:t}}]}),o=e.createCommandEncoder(),a=o.beginComputePass();return a.setPipeline(i),a.setBindGroup(0,r),a.dispatchWorkgroups(1),a.end(),e.queue.submit([o.finish()]),await bi(e,t)}finally{t.destroy()}}async function yc(s,e,t,i){let r={mode:e.name,passed:!1,steps:i?180:90,cases:[],errors:[],contactCache:"normal-float-generations-v1",diagnosticVersion:5,detailed:i,limits:{storageBindings:s.limits.maxStorageBuffersPerShaderStage,workgroupStorageBytes:s.limits.maxComputeWorkgroupStorageSize,workgroupInvocations:s.limits.maxComputeInvocationsPerWorkgroup,storageBindingBytes:s.limits.maxStorageBufferBindingSize}},o,a=n=>{let l=new gi(s,bc(n),{spatialSort:!1,bodyCapacity:4,smallGroups:!1,broadphase:e.broadphase,scalarPrimal:e.scalarPrimal??!1,portableContactMath:e.portableContactMath??!1,capacity:{pairs:32,manifolds:32,contacts:256,colors:8}});return l.params.up=[0,1,0],l.dispatchIsolation=e.dispatchIsolation,t?.(l,e,n),l};s.pushErrorScope("validation");try{if(o=a(!1),i)r.pipeline=await Vf(o);else{o.step();let n=await o.readCounters();r.pipeline={expectedFloorPairs:3,counters:n,solver:{scalarPrimal:o.scalarPrimal,portableContactMath:o.portableContactMath,lanes:[...o.primalLanes]},stage:n.pairs<3?"collision-pairs":n.manifolds<3?"contact-generation":"contacts-created"}}if(r.pipeline.stage!=="contacts-created")r.reason=r.pipeline.stage==="collision-pairs"?"The GPU did not find the three known overlapping floor pairs.":"The GPU found overlapping pairs but did not create all floor contacts.";else{if(i)o.destroy(),o=a(!0);else{let c=bc(!0);o.rewriteBodies([0,1,2,3],c.bodies),o.params.gravity=c.gravity}let n=0;r.samples=[];for(let c=0;c<r.steps;c++){if(o.step(),(c+1)%30&&c!==39)continue;let u=await o.readCounters();if(r.samples.push({step:c+1,...u}),u.manifolds&&n++,u.overflow||u.clashes)throw Error("Incomplete GPU contact graph")}let l=await o.readBodies();for(let c=1;c<4;c++){let u=c*40,[f,d,h,m]=l.subarray(u+4,u+8),p=c===1?.5*(Math.abs(2*(f*d+m*h))+Math.abs(1-2*(f*f+h*h))+Math.abs(2*(d*h-m*f))):c===2?.5:.25+.55*Math.abs(1-2*(f*f+h*h)),g=l[u+1]-p,b=l.subarray(u,u+40).every(Number.isFinite);r.cases.push({shape:["floor","box","sphere","capsule"][c],passed:b&&g>=-.06&&g<.12,floorGap:g,position:Array.from(l.subarray(u,u+3))})}r.contactSteps=n,r.passed=n>0&&r.cases.every(c=>c.passed),r.passed||(r.reason=r.pipeline.solver?.failure==="contact-evaluation"?"The GPU created floor contacts but returned zero force where a push was required.":"The GPU did not keep all three falling shapes on the floor.")}}catch(n){r.errors.push(n.message)}finally{try{let n=await s.popErrorScope();n&&r.errors.push(n.message)}catch(n){r.errors.push(n.message)}o?.destroy()}return r.passed=r.passed&&!r.errors.length,r}async function Sr(s={}){if(!globalThis.navigator?.gpu)throw Error("WebGPU needs a supported browser on localhost or HTTPS");let e=await navigator.gpu.requestAdapter({powerPreference:s.powerPreference??"high-performance"});if(!e)throw Error("No WebGPU adapter is available");let t={};for(let[r,o]of Object.entries(s.preferredLimits??{})){if(!r.startsWith("max")||e.limits[r]===void 0||!Number.isSafeInteger(o)||o<0)throw Error(`Invalid preferred GPU limit: ${r}`);t[r]=Math.min(o,e.limits[r])}for(let[r,o]of Object.entries(s.requiredLimits??{})){if(e.limits[r]===void 0||!Number.isSafeInteger(o)||o<0)throw Error(`Invalid required GPU limit: ${r}`);let a=e.limits[r];if(r.startsWith("min")&&o<a||!r.startsWith("min")&&o>a)throw Error(`GPU limit ${r} requires ${o}; this adapter supports ${a}`);t[r]=o}let i=await e.requestDevice({requiredLimits:t,requiredFeatures:e.features.has("timestamp-query")?["timestamp-query"]:[]});if(s.validate3D)try{await Ni(i)}catch(r){throw i.destroy(),r}return{adapter:e,device:i}}async function Ni(s){if(ho(s))return s;let e=await vc(s);if(!e.passed)throw Error(`GPU 3D contact check failed: ${e.reason??e.errors.join("; ")}`);return s}var xc=`struct Body { pos:vec4f,rot:vec4f,initialPos:vec4f,initialRot:vec4f,size:vec4f,moment:vec4f,inertialPos:vec4f,inertialRot:vec4f,velocity:vec4f,angular:vec4f }
3733
3776
  struct Command { index:u32,mask:u32,pad0:u32,pad1:u32,velocity:vec4f,angular:vec4f,impulse:vec4f,torque:vec4f,position:vec4f,rotation:vec4f,pointImpulse:vec4f }
3734
3777
  @group(0) @binding(0) var<storage,read_write> bodies:array<Body>;
3735
3778
  @group(0) @binding(1) var<storage,read> commands:array<Command>;
@@ -3768,7 +3811,7 @@ fn rotate(q:vec4f,v:vec3f)->vec3f {let t=2.*cross(q.xyz,v);return v+q.w*t+cross(
3768
3811
  var v=bodies[base];
3769
3812
  ${this.components===1?"v.z=velocities[i];":`v.x=velocities[i*${t}u];v.y=velocities[i*${t}u+1u];${t===3?"v.z=velocities[i*3u+2u];":""}`}
3770
3813
  bodies[base]=v;
3771
- }`})}})}set(e,t){let i=this.solver,r=i.device,o=e instanceof Uint32Array?e:Uint32Array.from(e),a=t instanceof Float32Array?t:Float32Array.from(t);if(a.length!==o.length*this.components)throw Error(`Provide ${this.components} velocity components per body`);let n=-1;for(let c=0;c<e.length;c++){if(i.liveIndex(e[c]),e[c]<=n)throw Error("Velocity batch indices must be unique and ascending GPU slots");n=e[c]}for(let c of a)if(!Number.isFinite(c))throw Error("Velocities must be finite Float32 values");let l=Math.min(r.limits.maxStorageBufferBindingSize,r.limits.maxBufferSize);if(o.byteLength>l||a.byteLength>l)throw Error("Velocity batch exceeds GPU buffer limits");o.length&&(i.wakeAll(),i.flushEdits(),this.submitValidated(o,a))}submitValidated(e,t,i){if(!e.length)return;let r=this.solver,o=r.device,a=Math.min(o.limits.maxStorageBufferBindingSize,o.limits.maxBufferSize);if(e.byteLength>a||t.byteLength>a)throw Error("Velocity batch exceeds GPU buffer limits");for(let[f,d]of[["indices",e],["values",t]])(!this[f]||this[f].size<d.byteLength)&&(this[f]?.destroy(),this[f]=o.createBuffer({size:Math.min(a,d.byteLength*2),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),o.queue.writeBuffer(this[f],0,d);let n=i??o.createCommandEncoder(),l=n.beginComputePass();l.setPipeline(this.pipeline),(!this.binding||this.boundBody!==r.bodyBuffer||this.boundIndices!==this.indices||this.boundValues!==this.values||this.boundBytes!==t.byteLength)&&(this.binding=o.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.bodyBuffer}},{binding:1,resource:{buffer:this.indices,size:e.byteLength}},{binding:2,resource:{buffer:this.values,size:t.byteLength}}]}),this.boundBody=r.bodyBuffer,this.boundIndices=this.indices,this.boundValues=this.values,this.boundBytes=t.byteLength),l.setBindGroup(0,this.binding);let c=Math.ceil(e.length/64),u=o.limits.maxComputeWorkgroupsPerDimension;l.dispatchWorkgroups(Math.min(c,u),Math.ceil(c/u)),l.end(),i||o.queue.submit([n.finish()]),this.lastBatch={bodies:e.length,uploadedBytes:e.byteLength+t.byteLength}}destroy(){this.indices?.destroy(),this.values?.destroy()}},yi=class{constructor(e,t){this.solver=e,this.dimension=t,this.wordsPerBody=t===3?8:5}set(e,{linear:t,angular:i}={}){let r=this.solver,o=this.dimension,a=o===3?3:1,n=e instanceof Uint32Array?e:Uint32Array.from(e),l=t===void 0?null:t instanceof Float32Array?t:Float32Array.from(t),c=i===void 0?null:i instanceof Float32Array?i:Float32Array.from(i);if(!l&&!c)throw Error("Provide linear and/or angular velocities");if(l&&l.length!==n.length*o)throw Error(`Provide ${o} linear components per body`);if(c&&c.length!==n.length*a)throw Error(`Provide ${a} angular components per body`);let u=-1;for(let p=0;p<e.length;p++){if(r.liveIndex(e[p]),e[p]<=u)throw Error("Velocity batch indices must be unique and ascending GPU slots");u=e[p]}for(let p of[l,c])if(p){for(let m of p)if(!Number.isFinite(m))throw Error("Velocities must be finite Float32 values")}let f=n.length*this.wordsPerBody,d=Math.min(r.device.limits.maxStorageBufferBindingSize,r.device.limits.maxBufferSize);if(f*4>d)throw Error("Motion batch exceeds GPU buffer limits");if(f){(!this.data||this.data.length<f)&&(this.data=new Uint32Array(Math.max(f,(this.data?.length??0)*2)),this.floats=new Float32Array(this.data.buffer));for(let p=0;p<n.length;p++){let m=p*this.wordsPerBody;if(this.data[m]=n[p],this.data[m+1]=(l?1:0)|(c?2:0),l)for(let h=0;h<o;h++)this.floats[m+2+h]=l[p*o+h];if(c)for(let h=0;h<a;h++)this.floats[m+2+o+h]=c[p*a+h]}r.wakeAll(),r.flushEdits(),this.submitValidated(this.data.subarray(0,f))}}submitValidated(e,t){if(!e.length)return;let i=this.solver,r=i.device,o=this.wordsPerBody,a=Math.min(r.limits.maxStorageBufferBindingSize,r.limits.maxBufferSize);if(e.byteLength>a)throw Error("Motion batch exceeds GPU buffer limits");(!this.buffer||this.buffer.size<e.byteLength)&&(this.buffer?.destroy(),this.buffer=r.createBuffer({size:Math.min(a,e.byteLength*2),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),r.queue.writeBuffer(this.buffer,0,e),this.pipeline??=r.createComputePipeline({layout:"auto",compute:{entryPoint:"edit",module:r.createShaderModule({code:`
3814
+ }`})}})}set(e,t){let i=this.solver,r=i.device,o=e instanceof Uint32Array?e:Uint32Array.from(e),a=t instanceof Float32Array?t:Float32Array.from(t);if(a.length!==o.length*this.components)throw Error(`Provide ${this.components} velocity components per body`);let n=-1;for(let c=0;c<e.length;c++){if(i.liveIndex(e[c]),e[c]<=n)throw Error("Velocity batch indices must be unique and ascending GPU slots");n=e[c]}for(let c of a)if(!Number.isFinite(c))throw Error("Velocities must be finite Float32 values");let l=Math.min(r.limits.maxStorageBufferBindingSize,r.limits.maxBufferSize);if(o.byteLength>l||a.byteLength>l)throw Error("Velocity batch exceeds GPU buffer limits");o.length&&(i.wakeAll(),i.flushEdits(),this.submitValidated(o,a))}submitValidated(e,t,i){if(!e.length)return;let r=this.solver,o=r.device,a=Math.min(o.limits.maxStorageBufferBindingSize,o.limits.maxBufferSize);if(e.byteLength>a||t.byteLength>a)throw Error("Velocity batch exceeds GPU buffer limits");for(let[f,d]of[["indices",e],["values",t]])(!this[f]||this[f].size<d.byteLength)&&(this[f]?.destroy(),this[f]=o.createBuffer({size:Math.min(a,d.byteLength*2),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),o.queue.writeBuffer(this[f],0,d);let n=i??o.createCommandEncoder(),l=n.beginComputePass();l.setPipeline(this.pipeline),(!this.binding||this.boundBody!==r.bodyBuffer||this.boundIndices!==this.indices||this.boundValues!==this.values||this.boundBytes!==t.byteLength)&&(this.binding=o.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:r.bodyBuffer}},{binding:1,resource:{buffer:this.indices,size:e.byteLength}},{binding:2,resource:{buffer:this.values,size:t.byteLength}}]}),this.boundBody=r.bodyBuffer,this.boundIndices=this.indices,this.boundValues=this.values,this.boundBytes=t.byteLength),l.setBindGroup(0,this.binding);let c=Math.ceil(e.length/64),u=o.limits.maxComputeWorkgroupsPerDimension;l.dispatchWorkgroups(Math.min(c,u),Math.ceil(c/u)),l.end(),i||o.queue.submit([n.finish()]),this.lastBatch={bodies:e.length,uploadedBytes:e.byteLength+t.byteLength}}destroy(){this.indices?.destroy(),this.values?.destroy()}},yi=class{constructor(e,t){this.solver=e,this.dimension=t,this.wordsPerBody=t===3?8:5}set(e,{linear:t,angular:i}={}){let r=this.solver,o=this.dimension,a=o===3?3:1,n=e instanceof Uint32Array?e:Uint32Array.from(e),l=t===void 0?null:t instanceof Float32Array?t:Float32Array.from(t),c=i===void 0?null:i instanceof Float32Array?i:Float32Array.from(i);if(!l&&!c)throw Error("Provide linear and/or angular velocities");if(l&&l.length!==n.length*o)throw Error(`Provide ${o} linear components per body`);if(c&&c.length!==n.length*a)throw Error(`Provide ${a} angular components per body`);let u=-1;for(let h=0;h<e.length;h++){if(r.liveIndex(e[h]),e[h]<=u)throw Error("Velocity batch indices must be unique and ascending GPU slots");u=e[h]}for(let h of[l,c])if(h){for(let m of h)if(!Number.isFinite(m))throw Error("Velocities must be finite Float32 values")}let f=n.length*this.wordsPerBody,d=Math.min(r.device.limits.maxStorageBufferBindingSize,r.device.limits.maxBufferSize);if(f*4>d)throw Error("Motion batch exceeds GPU buffer limits");if(f){(!this.data||this.data.length<f)&&(this.data=new Uint32Array(Math.max(f,(this.data?.length??0)*2)),this.floats=new Float32Array(this.data.buffer));for(let h=0;h<n.length;h++){let m=h*this.wordsPerBody;if(this.data[m]=n[h],this.data[m+1]=(l?1:0)|(c?2:0),l)for(let p=0;p<o;p++)this.floats[m+2+p]=l[h*o+p];if(c)for(let p=0;p<a;p++)this.floats[m+2+o+p]=c[h*a+p]}r.wakeAll(),r.flushEdits(),this.submitValidated(this.data.subarray(0,f))}}submitValidated(e,t){if(!e.length)return;let i=this.solver,r=i.device,o=this.wordsPerBody,a=Math.min(r.limits.maxStorageBufferBindingSize,r.limits.maxBufferSize);if(e.byteLength>a)throw Error("Motion batch exceeds GPU buffer limits");(!this.buffer||this.buffer.size<e.byteLength)&&(this.buffer?.destroy(),this.buffer=r.createBuffer({size:Math.min(a,e.byteLength*2),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),r.queue.writeBuffer(this.buffer,0,e),this.pipeline??=r.createComputePipeline({layout:"auto",compute:{entryPoint:"edit",module:r.createShaderModule({code:`
3772
3815
  @group(0) @binding(0) var<storage,read_write> bodies:array<vec4f>;
3773
3816
  @group(0) @binding(1) var<storage,read> commands:array<u32>;
3774
3817
  @compute @workgroup_size(64) fn edit(@builtin(global_invocation_id) id:vec3u) {
@@ -3787,7 +3830,7 @@ fn rotate(q:vec4f,v:vec3f)->vec3f {let t=2.*cross(q.xyz,v);return v+q.w*t+cross(
3787
3830
  @compute @workgroup_size(64) fn gather(@builtin(global_invocation_id) id:vec3u) {
3788
3831
  let i=id.x+id.y*${n*64}u; if(i>=arrayLength(&selected)){return;}
3789
3832
  selected[i]=bodies[indices[i/${o}u]*${r}u+i%${o}u];
3790
- }`})}}),this.pipelines.set(l,c));let u=t.length*o*16,f=this.acquire(t.length*4,u),{selection:d,selected:p,staging:m}=f;try{a.queue.writeBuffer(d,0,t instanceof Uint32Array?t:Uint32Array.from(t)),(!f.group||f.body!==e||f.pipeline!==c||f.boundSelection!==d||f.boundSelected!==p||f.indexBytes!==t.length*4||f.bytes!==u)&&(f.group=a.createBindGroup({layout:c.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e}},{binding:1,resource:{buffer:d,size:t.length*4}},{binding:2,resource:{buffer:p,size:u}}]}),f.body=e,f.pipeline=c,f.boundSelection=d,f.boundSelected=p,f.indexBytes=t.length*4,f.bytes=u);let h=a.createCommandEncoder(),g=h.beginComputePass();g.setPipeline(c),g.setBindGroup(0,f.group);let b=Math.ceil(t.length*o/64);return g.dispatchWorkgroups(Math.min(b,n),Math.ceil(b/n)),g.end(),h.copyBufferToBuffer(p,0,m,0,u),a.queue.submit([h.finish()]),await m.mapAsync(GPUMapMode.READ,0,u),new Float32Array(m.getMappedRange(0,u).slice(0))}finally{this.release(f)}}};var kn=4,_r=3,Ai=1,Jf=2,ds=`
3833
+ }`})}}),this.pipelines.set(l,c));let u=t.length*o*16,f=this.acquire(t.length*4,u),{selection:d,selected:h,staging:m}=f;try{a.queue.writeBuffer(d,0,t instanceof Uint32Array?t:Uint32Array.from(t)),(!f.group||f.body!==e||f.pipeline!==c||f.boundSelection!==d||f.boundSelected!==h||f.indexBytes!==t.length*4||f.bytes!==u)&&(f.group=a.createBindGroup({layout:c.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:e}},{binding:1,resource:{buffer:d,size:t.length*4}},{binding:2,resource:{buffer:h,size:u}}]}),f.body=e,f.pipeline=c,f.boundSelection=d,f.boundSelected=h,f.indexBytes=t.length*4,f.bytes=u);let p=a.createCommandEncoder(),g=p.beginComputePass();g.setPipeline(c),g.setBindGroup(0,f.group);let b=Math.ceil(t.length*o/64);return g.dispatchWorkgroups(Math.min(b,n),Math.ceil(b/n)),g.end(),p.copyBufferToBuffer(h,0,m,0,u),a.queue.submit([p.finish()]),await m.mapAsync(GPUMapMode.READ,0,u),new Float32Array(m.getMappedRange(0,u).slice(0))}finally{this.release(f)}}};var kn=4,_r=3,Ai=1,Jf=2,ds=`
3791
3834
  struct Manifold { ids: vec4u, geo: vec4f } // a, b (a > b), first contact, count (low 4 bits); normal (b to a)
3792
3835
  struct Contact { rA: vec3f, key: u32, rB: vec3f, c0x: f32, pen: vec3f, c0y: f32, lam: vec3f, c0z: f32 }
3793
3836
  struct Params { prev: u32, now: u32, mask: u32, capacity: u32, pairs: u32, step: u32, dt: f32, pad: u32 }
@@ -3801,7 +3844,7 @@ struct Params { prev: u32, now: u32, mask: u32, capacity: u32, pairs: u32, step:
3801
3844
  @group(0) @binding(6) var<storage, read_write> events: array<vec4f>;
3802
3845
  @group(0) @binding(7) var<uniform> params: Params;
3803
3846
 
3804
- const STRIDE = ${We/4}u;
3847
+ const STRIDE = ${He/4}u;
3805
3848
 
3806
3849
  fn hash32(x0: u32) -> u32 {
3807
3850
  var x = x0;
@@ -3889,7 +3932,7 @@ fn ended(@builtin(global_invocation_id) id: vec3u) {
3889
3932
  let b = atomicLoad(&table[s + 1u]);
3890
3933
  if (!has(params.now, k - 1u, b)) { emit(${Jf}u, k - 1u, b, vec3f(0.0), 0.0, vec3f(0.0)); }
3891
3934
  }
3892
- `,Xf=ds.replace("struct Manifold { ids: vec4u, geo: vec4f }","struct Manifold { ids:vec4u, pl:vec4f, anchors:vec4f, geo:vec4f, misc:vec4f }").replace(`const STRIDE = ${We/4}u;`,"const STRIDE = 6u;").replace(ds.slice(ds.indexOf(`@compute @workgroup_size(64)
3935
+ `,Xf=ds.replace("struct Manifold { ids: vec4u, geo: vec4f }","struct Manifold { ids:vec4u, pl:vec4f, anchors:vec4f, geo:vec4f, misc:vec4f }").replace(`const STRIDE = ${He/4}u;`,"const STRIDE = 6u;").replace(ds.slice(ds.indexOf(`@compute @workgroup_size(64)
3893
3936
  fn touching`),ds.indexOf("/** Per slot of last step")),`
3894
3937
  @compute @workgroup_size(64) fn touching(@builtin(global_invocation_id) id:vec3u){
3895
3938
  let m=id.x;let count=min(counters[1u],params.pairs);if(m>=count){return;}
@@ -3902,8 +3945,8 @@ fn touching`),ds.indexOf("/** Per slot of last step")),`
3902
3945
  emit(${Ai}u,a,b,vec3f(point,0.),abs(c.pl.z)*params.dt,vec3f(c.geo.zw,0.));
3903
3946
  }
3904
3947
 
3905
- `),xi=class{device;pipelines;layout;watch;table;events;params;setSlots;capacity;group=null;bound=[];flip=0;bodies;constructor(e,t,i,r,o,a=3){this.device=e,this.bodies=t,this.capacity=o,this.setSlots=2**Math.ceil(Math.log2(Math.max(64,2*r)));let n=e.createShaderModule({label:"contact events",code:a===2?Xf:ds}),l=["read-only-storage","read-only-storage","read-only-storage","read-only-storage","read-only-storage","storage","storage","uniform"];this.layout=e.createBindGroupLayout({label:"contact events",entries:l.map((d,p)=>({binding:p,visibility:GPUShaderStage.COMPUTE,buffer:{type:d}}))});let c=e.createPipelineLayout({bindGroupLayouts:[this.layout]}),u=d=>e.createComputePipeline({label:`contact events ${d}`,layout:c,compute:{module:n,entryPoint:d}});this.pipelines={touching:u("touching"),ended:u("ended")};let f=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC;this.watch=e.createBuffer({label:"contact watch",size:Math.max(16,i*4),usage:f}),this.table=e.createBuffer({label:"contact sets",size:(kn+4*this.setSlots)*4,usage:f}),this.events=e.createBuffer({label:"contact events",size:o*_r*16,usage:f}),this.params=e.createBuffer({label:"contact params",size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST})}setWatched(e,t){let i=e.map((r,o)=>[r,t[o]?1:0]).sort((r,o)=>r[0]-o[0]);for(let r=0;r<i.length;){let o=r+1;for(;o<i.length&&i[o][0]===i[o-1][0]+1;)o++;this.device.queue.writeBuffer(this.watch,i[r][0]*4,Uint32Array.from(i.slice(r,o),a=>a[1])),r=o}}run(e,t,i,r){let o=this.device,a=[this.bodies,e.manifolds,e.contacts,e.counters,this.watch,this.table,this.events,this.params];(!this.group||a.some((d,p)=>d!==this.bound[p]))&&(this.bound=a,this.group=o.createBindGroup({layout:this.layout,entries:a.map((d,p)=>({binding:p,resource:{buffer:d}}))})),this.flip=1-this.flip;let[n,l]=this.flip?[0,this.setSlots]:[this.setSlots,0],c=new Uint32Array([n,l,this.setSlots-1,this.capacity,t,i,0,0]);new Float32Array(c.buffer)[6]=r,o.queue.writeBuffer(this.params,0,c);let u=o.createCommandEncoder({label:"contact events"});u.clearBuffer(this.table,(kn+2*l)*4,2*this.setSlots*4);let f=u.beginComputePass({label:"contact events"});f.setBindGroup(0,this.group),f.setPipeline(this.pipelines.touching),f.dispatchWorkgroups(Math.max(1,Math.ceil(t/64))),f.setPipeline(this.pipelines.ended),f.dispatchWorkgroups(Math.ceil(this.setSlots/64)),f.end(),o.queue.submit([u.finish()])}async read(){let e=this.device,t=16+this.capacity*_r*16,i=e.createBuffer({size:t,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),r=e.createCommandEncoder({label:"read contact events"});r.copyBufferToBuffer(this.table,0,i,0,16),r.copyBufferToBuffer(this.events,0,i,16,t-16),r.clearBuffer(this.table,0,16),e.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ);let o=i.getMappedRange().slice(0);i.unmap(),i.destroy();let a=new Uint32Array(o),n=new Float32Array(o),l=Math.min(a[0],this.capacity),c=[];for(let u=0;u<l;u++){let f=4+u*_r*4;c.push({kind:a[f],a:a[f+1],b:a[f+2],step:a[f+3],point:[n[f+4],n[f+5],n[f+6]],impulse:n[f+7],normal:[n[f+8],n[f+9],n[f+10]]})}return c.sort((u,f)=>u.step-f.step),{events:c,dropped:a[0]-l,full:a[1]!==0}}destroy(){for(let e of[this.watch,this.table,this.events,this.params])e.destroy()}};var wc=[0,1,2,3,5,4,0,3,4,0,4,1,1,4,5,1,5,2,2,5,3,2,3,0],Er=wc.slice();for(let s=0;s<Er.length;s+=3)[Er[s+1],Er[s+2]]=[Er[s+2],Er[s+1]];var yo=(s,e,t)=>{let i=Array.from(s??[]);if(i.length!==e||!i.every(Number.isFinite))throw Error(`${t} requires ${e} finite values`);return i},Bc=(s,e)=>{if(!Number.isFinite(s)||s<=0)throw Error(`${e} must be positive and finite`);return s};function Cc(s){let e=[0,1,2].map(u=>s.reduce((f,d)=>f+d[u],0)/s.length),[t,i,r,o]=s,a=i.map((u,f)=>u-t[f]),n=r.map((u,f)=>u-t[f]),l=(a[1]*n[2]-a[2]*n[1])*(t[0]-o[0])+(a[2]*n[0]-a[0]*n[2])*(t[1]-o[1])+(a[0]*n[1]-a[1]*n[0])*(t[2]-o[2]),c=ja(s.flatMap(u=>u.map((f,d)=>f-e[d])),l>0?wc:Er);if(!c)throw Error("Terrain contains a degenerate collision piece");return{shape:c,position:c.center.map((u,f)=>u+e[f]),rotation:c.rotation}}function Mr({heights:s,columns:e,rows:t,spacing:i=1,origin:r=[0,0,0],upAxis:o=1,baseHeight:a,holes:n}={}){for(let[g,b]of Object.entries({columns:e,rows:t}))if(!Number.isInteger(b)||b<2)throw Error(`${g} must be an integer >= 2`);let l=yo(s,e*t,"heights"),c=yo(r,3,"origin");if(![0,1,2].includes(o))throw Error("upAxis must be 0, 1 or 2");let u=typeof i=="number"?[i,i]:yo(i,2,"spacing");u.forEach(g=>Bc(g,"spacing"));let f=a??l.reduce((g,b)=>Math.min(g,b),1/0)-2;if(!Number.isFinite(f)||l.some(g=>g<=f))throw Error("baseHeight must be below every terrain height");let d=(e-1)*(t-1);if(n&&n.length!==d)throw Error("holes requires one value per terrain cell");let p=[0,1,2].filter(g=>g!==o),m=[],h=(g,b)=>{let y=[...c];return y[p[0]]+=g*u[0],y[p[1]]+=b*u[1],y[o]+=l[b*e+g],y};for(let g=0;g<t-1;g++)for(let b=0;b<e-1;b++){if(n?.[g*(e-1)+b])continue;let y=h(b,g),A=h(b+1,g),v=h(b,g+1),x=h(b+1,g+1);for(let w of[[y,A,v],[A,x,v]])m.push(Cc([...w,...w.map(B=>{let L=[...B];return L[o]=c[o]+f,L})]))}return{kind:"heightfield",pieces:m,triangleCount:m.length}}function zr({positions:s,indices:e,thickness:t=.1}={}){if(!s||s.length%3)throw Error("positions requires xyz triples");let i=yo(s,s.length,"positions"),r=i.length/3;if(e===void 0&&r%3)throw Error("Nonindexed positions require three vertices per triangle");let o=e===void 0?Array.from({length:r},(n,l)=>l):Array.from(e);if(!o.length||o.length%3||!o.every(n=>Number.isInteger(n)&&n>=0&&n<r))throw Error("indices requires valid triangle vertex indices");Bc(t,"thickness");let a=[];for(let n=0;n<o.length;n+=3){let l=o.slice(n,n+3).map(g=>i.slice(g*3,g*3+3)),[c,u,f]=l,d=u.map((g,b)=>g-c[b]),p=f.map((g,b)=>g-c[b]),m=[d[1]*p[2]-d[2]*p[1],d[2]*p[0]-d[0]*p[2],d[0]*p[1]-d[1]*p[0]],h=Math.hypot(...m);h!==0&&a.push(Cc([...l,...l.map(g=>g.map((b,y)=>b-m[y]*t/h))]))}if(!a.length)throw Error("Static mesh requires at least one nondegenerate triangle");return{kind:"static-mesh",pieces:a,triangleCount:a.length}}function vo(s,e,t={}){if(t.mass!==void 0&&t.mass!==0)throw Error("Terrain is static and requires zero mass");let i=t.friction??.6,r=t.restitution??0;if(!Number.isFinite(i)||i<0)throw Error("friction must be nonnegative and finite");if(!Number.isFinite(r)||r<0||r>1)throw Error("restitution must be between 0 and 1");for(let o of["group","collidesWith"]){let a=t[o]??4294967295;if(!Number.isInteger(a)||a<0||a>4294967295)throw Error(`${o} must be an unsigned 32-bit integer`)}if(!e?.pieces?.length)throw Error("Terrain requires collision pieces");return e.pieces.map(o=>{let a=lr(s,o.shape,0,i,o.position,o.rotation);return Object.assign(a,{allowSleep:!1,isTrigger:!1,restitution:r,group:t.group??4294967295,collidesWith:t.collidesWith??4294967295}),a})}var rt=Object.freeze({BOX:"box",SPHERE:"sphere",CAPSULE:"capsule",CYLINDER:"cylinder",CONVEX_HULL:"convex-hull"}),Le=s=>s&&typeof s.x=="number"?[s.x,s.y,s.z,...typeof s.w=="number"?[s.w]:[]]:Array.from(s),hs=new WeakMap,Ir=s=>{if(!Number.isInteger(s)||s<0||s>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");return s},xo=(s,e,t=!1)=>{if(!Number.isFinite(s)||(t?s<0:s<=0))throw Error(`${e} must be ${t?"nonnegative":"positive"} and finite`);return s},ps=class s{static async create({device:e,...t}={}){if(t.scene&&hs.has(t.scene))throw Error("This scene already has an AVBD world");let i=!e;e||({device:e}=await Sr({preferredLimits:{maxStorageBuffersPerShaderStage:9,maxStorageBufferBindingSize:512*1024*1024,maxBufferSize:1024*1024*1024}}));let r;try{return await Ni(e),r=new s(e,t),r.ownsDevice=i,r.scene&&r.autoAttach&&r.attachToScene(),r}catch(o){throw r?r.dispose():i&&e.destroy(),o}}constructor(e,{scene:t,gravity:i=[0,-10,0],timeStep:r=1/60,iterations:o=10,capacity:a=4096,syncMeshes:n=!0,maxSyncedBodies:l=2048,broadphase:c="auto",solverMode:u="auto",smallGroups:f,bvh:d={},autoAttach:p=!0,maxContactPairs:m=8192,maxContactEvents:h=4096,sleeping:g=!1}={}){if(this.device=e,this.scene=t,this.autoAttach=p,this.syncEnabled=n,this.maxSyncedBodies=l,!Number.isInteger(a)||a<1||!Number.isInteger(l)||l<0)throw Error("capacity and maxSyncedBodies must be valid integer counts");if(this.capacity=a,this.collisionOptions={broadphase:c,bvh:d,solverMode:u,smallGroups:f},this.ref=new ni,this.ref.dt=xo(r,"timeStep"),!Number.isInteger(o)||o<1)throw Error("iterations must be a positive integer");this.ref.iterations=o,this.aggregates=[],this.constraints=new Set,this.contactListeners=new Set;for(let[y,A]of Object.entries({maxContactPairs:m,maxContactEvents:h}))if(!Number.isInteger(A)||A<1)throw Error(`${y} must be a positive integer`);if(this.contactOptions={maxContactPairs:m,maxContactEvents:h},this.bodyReadback=new vi(e),this.sleepOptions=g,g!==!1&&g!==!0&&(typeof g!="object"||g===null))throw Error("sleeping must be a boolean or options object");this.commands=new Map,this.steps=0,this.errors=[],this.deviceLost=null;let b=new WeakRef(this);e.lost.then(y=>{let A=b.deref();!A||A.disposed||(A.deviceLost={reason:y.reason,message:y.message},A.errors.push(`WebGPU device lost: ${y.message||y.reason}`),A.dispose())}),this.setGravity(i),this.errorListener=y=>this.errors.push(y.error.message),e.addEventListener("uncapturederror",this.errorListener),t&&hs.set(t,this)}setGravity(e){let t=Le(e);if(t.length!==3||!t.every(Number.isFinite))throw Error("gravity requires three finite components");let i=Math.hypot(...t);this.gravity=-i,this.up=i?t.map(r=>-r/i):[0,1,0],this.gpu&&(this.gpu.params.gravity=this.gravity,this.gpu.params.up=this.up),this.wakeAll()}get solverDecision(){return this.initialize(),{...this.gpu.solverDecision}}setSolverMode(e){this.initialize();let t=this.gpu.setSolverMode(e);return this.collisionOptions.solverMode=e,{...t}}initialize(){if(this.assertAlive(),this.gpu)return;if(this.syncEnabled&&this.aggregates.filter(r=>r.sync).length>this.maxSyncedBodies)throw Error("For large scenes use syncMeshes:false and draw the GPU body buffer directly");if(this.aggregates.length>this.capacity)throw Error(`Body capacity ${this.capacity} exceeded; size the world before initialization`);this.gpu=new gi(this.device,this.ref,go(this.ref,{bodyCapacity:Math.max(1,this.capacity),spatialSort:!0,...this.collisionOptions})),Object.assign(this.gpu.params,{gravity:this.gravity,up:this.up}),this.gpu.externalBeforeStep=r=>{this.sleepManager?.before(r),this.flushCommands(r)},this.gpu.externalAfterStep=r=>this.sleepManager?.after(r);let e=new Map([...this.constraints].map(r=>[r.force,r])),t=[],i=0;for(let r of this.ref.forces){let o=e.get(r);o&&(o.attach(i++,!1),(o.type==="fixed"||o.type==="spring"&&o.rest===void 0)&&t.push({slot:o.slot,spring:o.type==="spring"}))}this.gpu.captureConstraintFrames(t),this.byGpuIndex=new Map(this.aggregates.map(r=>[this.gpu.gpuIndex(r.index),r.body]));for(let r of this.aggregates)(r.disposed||r.group!==4294967295||r.collidesWith!==4294967295)&&this.gpu.setFilters([this.gpu.gpuIndex(r.index)],[r.disposed?0:r.group],[r.disposed?0:r.collidesWith]);for(let r of this.aggregates)r.isTrigger&&this.gpu.setSensor(r.body.gpuIndex,!0);for(let r of this.aggregates)r.restitution>0&&this.gpu.setRestitution(r.body.gpuIndex,r.restitution);this.contactListeners.size&&this.initializeContacts(),this.sleepOptions&&(this.sleepManager=new Fi(this,this.sleepOptions===!0?{}:this.sleepOptions))}addAggregate(e,t,i={}){return new ms(e,t,i,this)}addAggregates(e){return e.map(({mesh:t,type:i,options:r})=>this.addAggregate(t,i,r))}addHeightfield(e){return this.addTerrain(Mr(e),e)}addStaticMesh(e,t={}){e.computeWorldMatrix(!0);let i=e.getVerticesData("position"),r=e.getWorldMatrix().m;if(!i)throw Error("Static mesh requires vertex positions");let o=new Float64Array(i.length);for(let u=0;u<i.length;u+=3){let f=i[u],d=i[u+1],p=i[u+2];for(let m=0;m<3;m++)o[u+m]=r[m]*f+r[4+m]*d+r[8+m]*p+r[12+m]}let a=e.getIndices(),n=a?.length?Uint32Array.from(a):Uint32Array.from({length:i.length/3},(u,f)=>f),l=e.getVerticesData("normal"),c=e.getWorldMatrix().determinant()<0;for(let u=0;u<n.length;u+=3){let f=n[u]*3,d=n[u+1]*3,p=n[u+2]*3,m=[0,1,2].map(b=>i[d+b]-i[f+b]),h=[0,1,2].map(b=>i[p+b]-i[f+b]),g=!1;l?.length===i.length&&(g=[m[1]*h[2]-m[2]*h[1],m[2]*h[0]-m[0]*h[2],m[0]*h[1]-m[1]*h[0]].reduce((y,A,v)=>y+A*(l[f+v]+l[d+v]+l[p+v]),0)<0),g!==c&&([n[u+1],n[u+2]]=[n[u+2],n[u+1]])}return this.addTerrain(zr({positions:o,indices:n,thickness:t.thickness}),t)}addTerrain(e,t={}){if(this.assertAlive(),this.gpu)throw Error("Add static terrain before initializing the physics world");if(this.device.limits.maxStorageBuffersPerShaderStage<9)throw Error("Terrain collisions require nine storage buffer bindings");if(this.aggregates.length+(e?.pieces?.length??0)>this.capacity)throw Error("AVBD terrain exceeds body capacity; reserve space for its collision pieces");let r=vo(this.ref,e,t).map(a=>new Pn(this,a)),o=!1;return{bodies:r.map(a=>a.body),triangleCount:e.triangleCount,kind:e.kind,dispose:()=>{if(o)return;o=!0;let a=new Set(r.map(n=>n.body));for(let n of[...this.constraints])(a.has(n.bodyA)||a.has(n.bodyB))&&n.dispose();if(this.gpu&&!this.disposed){let n=r.map(c=>c.body.gpuIndex),l=new Uint32Array(n.length);this.gpu.setFilters(n,l,l)}for(let n of r)n.disposed=n.body.disposed=!0,n.group=n.collidesWith=0,this.commands.delete(n.body);this.wakeAll()}}}addConstraint(e,t,i={}){return new Pr(this,e,t,i)}addJoint(e,t,i={}){return this.addConstraint(e,t,{...i,type:i.type??"ball"})}addWeld(e,t,i={}){return this.addConstraint(e,t,{...i,type:"fixed"})}addSpring(e,t,i={}){return this.addConstraint(e,t,{...i,type:"spring"})}enableSleeping(e={}){return this.assertAlive(),this.sleepOptions=e,this.gpu&&!this.sleepManager&&(this.sleepManager=new Fi(this,e)),this}disableSleeping(){return this.assertAlive(),this.sleepOptions=!1,this.gpu?(this.flushCommands(),this.sleepManager&&(this.sleepManager.wakeRequested=!0,this.sleepManager.before(),this.sleepManager.dispose(),this.sleepManager=null),this):this}addMotor(e,t,i={}){return this.addConstraint(e,t,{...i,type:"motor"})}addHinge(e,t,i={}){return new Lr(this,e,t,i)}initializeContacts(){if(this.contactWatch)return;let{maxContactPairs:e,maxContactEvents:t}=this.contactOptions;this.contactWatch=new xi(this.device,this.gpu.bodyBuffer,this.capacity,e,t);let i=this.aggregates.filter(r=>!r.disposed);this.contactWatch.setWatched(i.map(r=>r.body.gpuIndex),i.map(()=>!0))}onContact(e){if(this.assertAlive(),typeof e!="function")throw Error("A contact callback is required");return this.contactListeners.add(e),this.gpu&&this.initializeContacts(),()=>this.contactListeners.delete(e)}async readContactEvents(){return this.initialize(),this.initializeContacts(),this.contactPending?this.contactPending:(this.contactPending=this.contactWatch.read().then(e=>({...e,events:e.events.map(t=>({...t,type:t.kind===Ai?"begin":"end",isTrigger:!!(this.byGpuIndex.get(t.a)?.aggregate.isTrigger||this.byGpuIndex.get(t.b)?.aggregate.isTrigger),a:this.byGpuIndex.get(t.a),b:this.byGpuIndex.get(t.b)}))})).finally(()=>this.contactPending=null),this.contactPending)}async raycast(e,t,i={}){let[r]=await this.raycastAll([{origin:e,direction:t,maxDistance:i.maxDistance}],i);return r}async sphereCast(e,t,i,r={}){let[o]=await this.sphereCastAll([{origin:e,radius:t,direction:i,maxDistance:r.maxDistance}],r);return o}async sphereCastAll(e,{ignore:t=[],collidesWith:i=4294967295,includeTriggers:r=!0}={}){this.assertAlive(),Ir(i),this.initialize(),this.flushCommands();for(let a of t)if(a.aggregate.world!==this||a.disposed)throw Error("Ignored cast bodies must belong to this world and be alive");return(await this.gpu.sphereCastAll(e.map(a=>({...a,origin:Le(a.origin),direction:Le(a.direction)})),{ignore:t.map(a=>a.gpuIndex),collidesWith:i,includeTriggers:r})).map(a=>a?{...a,body:this.byGpuIndex.get(a.index)??null}:null)}async raycastAll(e,{ignore:t=[],collidesWith:i=4294967295,includeTriggers:r=!0}={}){Ir(i),this.initialize(),this.flushCommands();let o=e.map(n=>{let l=Le(n.origin),c=Le(n.direction);if(l.length!==3||c.length!==3||![...l,...c].every(Number.isFinite)||!Math.hypot(...c))throw Error("A ray requires a finite origin and nonzero direction");return n.maxDistance!==void 0&&xo(n.maxDistance,"maxDistance",!0),{...n,origin:l,direction:c}});for(let n of t)if(n.aggregate.world!==this)throw Error("Ignored ray bodies must belong to this world");return(await this.gpu.raycastAll(o,{ignore:t.map(n=>n.gpuIndex),collidesWith:i,includeTriggers:r})).map(n=>n?{...n,body:this.byGpuIndex.get(n.index)??null}:null)}getRenderBinding(e=this.device){if(this.initialize(),e!==this.device)throw Error("Direct GPU rendering must share the physics GPUDevice");return{device:e,buffer:this.bodyBuffer,stride:160,positionOffset:0,rotationOffset:16,sizeOffset:64,count:this.gpu.bodyCount}}wakeAll(){this.sleepManager&&(this.sleepManager.wakeRequested=!0)}async readSleepStats(){return this.initialize(),this.sleepManager?this.sleepManager.readStats():{sleeping:0,wakeRequested:!1}}assertAlive(){if(this.disposed)throw Error("AVBD world is disposed")}queue(e,t,i,r){this.assertAlive(),e.assertAlive();let o=Le(r);if(o.length!==(i==="rotation"?4:3)||!o.every(Number.isFinite))throw Error(`${i} requires ${i==="rotation"?4:3} finite components`);let a=this.commands.get(e);return a||this.commands.set(e,a={mask:0}),a.mask|=t,a[i]=o,this.wakeAll(),a}flushCommands(e){if(this.initialize(),this.gpu.flushPropertyEdits(e),!this.commands.size)return;this.sleepManager?.wakeRequested&&this.sleepManager.before(e);let t=this.commands.size,i=0;for(let h of this.commands.values())i|=h.mask;if(i===1||i===2){if(!this.velocityIndices||this.velocityIndices.length<t){let y=Math.max(t,(this.velocityIndices?.length??0)*2,64);this.velocityIndices=new Uint32Array(y),this.velocityValues=new Float32Array(y*3)}let h=0;for(let[y,A]of this.commands)this.velocityIndices[h]=y.aggregate.gpuSlot??this.gpu.gpuIndex(y.aggregate.index),this.velocityValues.set(i===2?A.angular:A.velocity,h++*3);let g=i===2?"angularVelocityBatch":"velocityBatch",b=this[g]??=new Kt(this.gpu,3,i===2?"angular":"linear");b.solver=this.gpu,b.submitValidated(this.velocityIndices.subarray(0,t),this.velocityValues.subarray(0,t*3),e),this.lastCommandBatch={bodies:t,path:i===2?"packed-angular-velocities":"packed-velocities",uploadedBytes:t*16},this.commands.clear();return}let r=!0;for(let h of this.commands.values())if((h.mask&-4)!==0){r=!1;break}if(r){(!this.motionData||this.motionData.length<t*8)&&(this.motionData=new Uint32Array(Math.max(t*8,(this.motionData?.length??0)*2,512)),this.motionFloats=new Float32Array(this.motionData.buffer));let h=0;for(let[g,b]of this.commands){let y=h++*8;this.motionData[y]=g.aggregate.gpuSlot??this.gpu.gpuIndex(g.aggregate.index),this.motionData[y+1]=b.mask,b.velocity&&this.motionFloats.set(b.velocity,y+2),b.angular&&this.motionFloats.set(b.angular,y+5)}this.motionBatch??=new yi(this.gpu,3),this.motionBatch.submitValidated(this.motionData.subarray(0,t*8),e),this.lastCommandBatch={bodies:t,path:"packed-motion",uploadedBytes:t*32},this.commands.clear();return}let o=t*128,a=Math.min(this.device.limits.maxStorageBufferBindingSize,this.device.limits.maxBufferSize);if(o>a)throw Error("Body command batch exceeds GPU buffer limits");(!this.commandData||this.commandData.byteLength<o)&&(this.commandData=new ArrayBuffer(Math.min(a,Math.max(o,(this.commandData?.byteLength??0)*2,128))));let n=this.commandData,l=new Float32Array(n),c=new Uint32Array(n);l.fill(0,0,t*32);let u=0;for(let[h,g]of this.commands){let b=u++*32;c[b]=h.aggregate.gpuSlot??this.gpu.gpuIndex(h.aggregate.index),c[b+1]=g.mask;for(let[y,A]of[["velocity",4],["angular",8],["impulse",12],["torque",16],["position",20],["rotation",24],["pointImpulse",28]])g[y]&&l.set(g[y],b+A)}this.commands.clear(),(!this.commandBuffer||this.commandBuffer.size<o)&&(this.commandBuffer?.destroy(),this.commandBuffer=this.device.createBuffer({size:Math.min(a,Math.max(o*2,128)),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),this.device.queue.writeBuffer(this.commandBuffer,0,n,0,o),this.commandPipeline??=this.device.createComputePipeline({layout:"auto",compute:{module:this.device.createShaderModule({code:`const DISPATCH_STRIDE = ${this.device.limits.maxComputeWorkgroupsPerDimension*64}u;
3906
- ${xc}`,label:"AVBD body commands"}),entryPoint:"applyCommands"}}),(!this.commandBinding||this.boundCommandBody!==this.gpu.bodyBuffer||this.boundCommandBuffer!==this.commandBuffer||this.boundCommandBytes!==o)&&(this.commandBinding=this.device.createBindGroup({layout:this.commandPipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:this.gpu.bodyBuffer}},{binding:1,resource:{buffer:this.commandBuffer,size:o}}]}),this.boundCommandBody=this.gpu.bodyBuffer,this.boundCommandBuffer=this.commandBuffer,this.boundCommandBytes=o);let f=e??this.device.createCommandEncoder(),d=f.beginComputePass();d.setPipeline(this.commandPipeline),d.setBindGroup(0,this.commandBinding);let p=Math.ceil(u/64),m=this.device.limits.maxComputeWorkgroupsPerDimension;d.dispatchWorkgroups(Math.min(p,m),Math.ceil(p/m)),d.end(),e||this.device.queue.submit([f.finish()]),this.lastCommandBatch={bodies:t,path:"aggregate-commands",uploadedBytes:o}}step(){this.initialize(),this.gpu.step(),this.steps++,this.contactWatch&&(this.contactWatch.run(this.gpu.contactStorage,this.gpu.manifoldCapacity,this.steps,this.ref.dt),this.contactListeners.size&&!this.contactPending&&this.readContactEvents().then(({events:e,dropped:t,full:i})=>{if(!this.disposed){(t||i)&&this.errors.push(`Contact event storage full: ${t} events dropped; increase maxContactEvents/maxContactPairs`);for(let r of e)for(let o of this.contactListeners)o(r)}}).catch(e=>{this.disposed||this.errors.push(e.message)})),this.syncEnabled&&!this.syncPending&&this.syncMeshes().catch(e=>this.errors.push(e.message)),this.steps%20===0&&!this.counterPending&&(this.counterPending=!0,this.gpu.readCounters().then(e=>{this.disposed||(this.counters=e,this.gpu.adapt(e),(e.overflow||e.clashes)&&this.errors.push(`Collision capacity/color conflict: ${JSON.stringify(e)}`))}).catch(e=>{this.disposed||this.errors.push(e.message)}).finally(()=>this.counterPending=!1))}async syncMeshes(){if(this.initialize(),this.flushCommands(),this.syncPending)return this.syncPending;let e=this.aggregates.filter(t=>t.sync&&!t.disposed);return this.syncPending=this.bodyReadback.read(this.bodyBuffer,e.map(t=>t.body.gpuIndex),!0).then(t=>{if(!this.disposed){for(let i=0;i<e.length;i++)e[i].disposed||e[i].syncPose(t,i*8);this.lastSyncBytes=t.byteLength}}).finally(()=>this.syncPending=null),this.syncPending}get bodyBuffer(){return this.initialize(),this.gpu.bodyBuffer}async readBodies(e){if(this.initialize(),this.flushCommands(),e){for(let t of e)if(t.aggregate.world!==this)throw Error("Selected bodies must belong to this world");return this.bodyReadback.read(this.bodyBuffer,e.map(t=>t.gpuIndex))}return this.gpu.readBodies()}dispose(){if(!this.disposed){this.disposed=!0,this.observer&&this.scene?.onBeforeRenderObservable.remove(this.observer),this.disposeObserver&&this.scene?.onDisposeObservable.remove(this.disposeObserver),this.scene&&hs.get(this.scene)===this&&hs.delete(this.scene),this.device.removeEventListener("uncapturederror",this.errorListener),this.gpu?.destroy(),this.contactWatch?.destroy(),this.sleepManager?.dispose(),this.commandBuffer?.destroy(),this.velocityBatch?.destroy(),this.angularVelocityBatch?.destroy(),this.motionBatch?.destroy(),this.bodyReadback.destroy(),this.commandData=this.velocityIndices=this.velocityValues=null,this.commandBinding=null;for(let e of this.aggregates)e.disposed=!0,e.body.disposed=!0;this.commands.clear(),this.contactListeners.clear();for(let e of this.constraints)e.disposed=!0;this.constraints.clear(),this.ownsDevice&&this.device.destroy()}}attachToScene(e=this.scene){if(this.assertAlive(),!e)throw Error("A Babylon scene is required");if(this.observer&&e===this.scene)return this;if(this.observer)throw Error("AVBD world is already attached to another scene");this.scene=e,this.disposeObserver=e.onDisposeObservable.addOnce(()=>this.dispose());let t=0;return this.observer=e.onBeforeRenderObservable.add(()=>{t+=Math.min(.05,e.getEngine().getDeltaTime()/1e3);for(let i=0;t>=this.ref.dt&&i<3;i++)this.step(),t-=this.ref.dt}),this}},ms=class{constructor(e,t,{mass:i=1,friction:r=.6,restitution:o=0,allowSleep:a,isTrigger:n=!1,sync:l=!0,group:c=4294967295,collidesWith:u=4294967295}={},f){if(f=f instanceof ps?f:hs.get(f??e.getScene()),!f)throw Error("Create an AVBD world for this scene before adding aggregates");if(f.assertAlive(),typeof t=="number"&&(t=[rt.SPHERE,rt.CAPSULE,rt.CYLINDER,rt.BOX,rt.CONVEX_HULL][t]),xo(i,"mass",!0),xo(r,"friction",!0),!Number.isFinite(o)||o<0||o>1)throw Error("restitution must be between 0 and 1");if(e.parent)throw Error("AVBD aggregate meshes must have no parent; bake the parent transform first");if(!Object.values(rt).includes(t))throw Error(`Unsupported AVBD shape: ${t}`);if(f.aggregates.length>=f.capacity)throw Error("AVBD body capacity exceeded");if(this.world=f,this.mesh=e,this.sync=l,this.type=t,a!==void 0&&typeof a!="boolean")throw Error("allowSleep must be a boolean");if(this.allowSleep=a??!0,typeof n!="boolean")throw Error("isTrigger must be a boolean");if(this.isTrigger=n,this.restitution=o,a===!0&&!f.sleepOptions&&f.enableSleeping(),this.group=Ir(c),this.collidesWith=Ir(u),f.gpu&&f.syncEnabled&&l&&f.aggregates.filter(v=>v.sync&&!v.disposed).length>=f.maxSyncedBodies)throw Error("For large scenes use syncMeshes:false and draw the GPU body buffer directly");if(![rt.BOX,rt.SPHERE,rt.CAPSULE].includes(t)&&f.device.limits.maxStorageBuffersPerShaderStage<9)throw Error("Convex hull collisions require nine storage buffer bindings");e.computeWorldMatrix(!0),e.refreshBoundingInfo();let d=e.getBoundingInfo().boundingBox,p=e.scaling;if([p.x,p.y,p.z].some(v=>v<=0))throw Error("Bake negative or zero mesh scaling before creating an aggregate");let m=d.maximum.subtract(d.minimum).multiply(p),h=d.center.multiply(p),g=e.rotationQuaternion?.clone()||e.rotation.toQuaternion();this.localCenter=h,this.localRotation=g.constructor.Identity();let b;if(t===rt.BOX)b=new Ze(f.ref,Le(m),1,r,[0,0,0]);else if(t===rt.SPHERE){if(Math.max(m.x,m.y,m.z)-Math.min(m.x,m.y,m.z)>1e-4)throw Error("Sphere aggregate requires uniform dimensions");b=nr(f.ref,m.x/2,1,r,[0,0,0])}else if(t===rt.CAPSULE){if(Math.abs(m.x-m.z)>1e-4)throw Error("Capsule aggregate requires equal X and Z diameters; bake an upright Y-axis capsule mesh");b=Cr(f.ref,m.x/2,m.y,1,r,[0,0,0])}else{let v=e.getVerticesData("position");if(!v)throw Error("Hull aggregate requires mesh positions");let x=Float32Array.from(v,(B,L)=>B*[p.x,p.y,p.z][L%3]),w=Xr(x);if(!w)throw Error("Hull aggregate requires a closed shape with nonzero volume");this.localCenter=new e.position.constructor(...w.center),this.localRotation=g.constructor.FromArray(w.rotation),b=lr(f.ref,w,1,r,[0,0,0])}let y=i/b.mass;b.mass=i,b.moment.forEach((v,x)=>b.moment[x]=v*y);let A=e.position.add(this.localCenter.applyRotationQuaternion(g));if(b.positionLin.set(Le(A)),b.positionAng.set(g.multiply(this.localRotation).asArray()),this.rigid=b,this.index=f.aggregates.length,this.body=new Rr(this),f.aggregates.push(this),e.rotationQuaternion=g,f.gpu){if(this.gpuSlot=f.gpu.addBody(b),this.gpuSlot<0)throw Error("AVBD body capacity exceeded");f.byGpuIndex.set(this.gpuSlot,this.body),f.gpu.setFilters([this.gpuSlot],[this.group],[this.collidesWith]),(this.isTrigger||f.gpu.sensorsEnabled)&&f.gpu.setSensor(this.gpuSlot,this.isTrigger),this.restitution>0&&f.gpu.setRestitution(this.gpuSlot,this.restitution),f.contactWatch?.setWatched([this.gpuSlot],[!0]),f.sleepManager?.register(this.gpuSlot,b.mass,this.allowSleep),f.wakeAll?.()}}syncPose(e,t){let i=t??this.body.gpuIndex*40,r=this.localRotation.constructor.FromArray(e,i+4).multiply(this.localRotation.conjugate());this.mesh.rotationQuaternion.copyFrom(r),this.mesh.position.copyFrom(new this.mesh.position.constructor(...e.subarray(i,i+3)).subtract(this.localCenter.applyRotationQuaternion(r)))}dispose(){Sc(this)}},Pn=class{constructor(e,t){Object.assign(this,{world:e,rigid:t,index:e.aggregates.length,sync:!1,allowSleep:!1,isTrigger:!1,restitution:t.restitution,group:t.group,collidesWith:t.collidesWith,staticTerrain:!0}),this.body=new Rr(this),e.aggregates.push(this)}dispose(){Sc(this)}};function Sc(s){if(s.disposed)return;let e=s.world;for(let t of[...e.constraints])(t.bodyA===s.body||t.bodyB===s.body)&&t.dispose();if(e.gpu){let t=s.body.gpuIndex;e.queue(s.body,16,"velocity",[0,0,0]),e.gpu.setFilters([t],[0],[0]),e.gpu.setRestitution(t,0)}s.rigid.mass=0,s.rigid.moment.fill(0),s.sync=!1,s.disposed=s.body.disposed=!0,e.sleepManager?.register(s.gpuSlot??e.gpu?.gpuIndex(s.index)??s.index,0),e.wakeAll?.()}var Rr=class{constructor(e){this.aggregate=e}assertAlive(){if(this.disposed||this.aggregate.disposed)throw Error("AVBD body is disposed")}get gpuIndex(){this.assertAlive();let e=this.aggregate.world;return e.initialize(),this.aggregate.gpuSlot??e.gpu.gpuIndex(this.aggregate.index)}setLinearVelocity(e){return this.aggregate.world.queue(this,1,"velocity",e),this}setAngularVelocity(e){return this.aggregate.world.queue(this,2,"angular",e),this}applyImpulse(e,t){let i=t?Le(t):null;if(i&&(i.length!==3||!i.every(Number.isFinite)))throw Error("Impulse point requires three finite components");let r=this.aggregate.world,o=Le(e),a=r.commands.get(this),n=o.map((c,u)=>c+(a?.impulse?.[u]||0)),l=r.queue(this,4,"impulse",n);if(t){let c=[i[1]*o[2]-i[2]*o[1],i[2]*o[0]-i[0]*o[2],i[0]*o[1]-i[1]*o[0]],u=l.torque||[0,0,0];l.torque=Le(c).map((f,d)=>f+u[d]),l.pointImpulse=o.map((f,d)=>f+(l.pointImpulse?.[d]||0))}return this}applyAngularImpulse(e){let t=this.aggregate.world,i=t.commands.get(this)?.torque||[0,0,0];return t.queue(this,4,"torque",Le(e).map((r,o)=>r+i[o])),this}applyForce(e,t){return this.applyImpulse(Le(e).map(i=>i*this.aggregate.world.ref.dt),t)}applyTorque(e){return this.applyAngularImpulse(Le(e).map(t=>t*this.aggregate.world.ref.dt))}setCollisionGroups(e,t=4294967295){this.assertAlive();let i=this.aggregate,r=Ir(e),o=Ir(t);return i.group=r,i.collidesWith=o,i.world.gpu&&i.world.gpu.setFilters([this.gpuIndex],[i.group],[i.collidesWith]),i.world.wakeAll?.(),this}setTrigger(e){if(this.assertAlive(),typeof e!="boolean")throw Error("isTrigger must be a boolean");let t=this.aggregate;return t.isTrigger=e,t.world.gpu&&t.world.gpu.setSensor(this.gpuIndex,e),t.world.wakeAll(),this}setRestitution(e){if(this.assertAlive(),!Number.isFinite(e)||e<0||e>1)throw Error("restitution must be between 0 and 1");let t=this.aggregate;return t.restitution=e,t.world.gpu&&t.world.gpu.setRestitution(this.gpuIndex,e),t.world.wakeAll(),this}async readState(){let e=await this.aggregate.world.readBodies([this]),t=this.aggregate.rigid.mass;return{position:Array.from(e.subarray(0,3)),rotation:Array.from(e.subarray(4,8)),linearVelocity:Array.from(e.subarray(32,35)),angularVelocity:Array.from(e.subarray(36,39)),mass:t,effectiveMass:e[19],sleeping:t>0&&e[19]===0}}wakeUp(){return this.assertAlive(),this.aggregate.world.wakeAll(),this}setSleepEnabled(e){if(this.assertAlive(),typeof e!="boolean")throw Error("Sleep eligibility must be a boolean");let t=this.aggregate,i=t.world;return t.allowSleep=e,e&&!i.sleepOptions&&i.enableSleeping(),i.gpu&&i.sleepManager?.register(this.gpuIndex,t.rigid.mass,e),i.wakeAll(),this}teleport(e,t){if(this.assertAlive(),this.aggregate.staticTerrain)throw Error("Terrain is static; set its geometry transform before registration");let i=this.aggregate;if(t===void 0){let a=i.world.commands.get(this);if(a&&(a.mask&8)!==0&&(a.mask&32)===0){let n=i.mesh.rotationQuaternion.clone();n.copyFromFloats(...a.rotation);let l=i.localCenter.applyRotationQuaternion(i.localRotation.conjugate());i.world.queue(this,8,"position",Le(e.add(l.applyRotationQuaternion(n))))}else{let n=i.localCenter.applyRotationQuaternion(i.localRotation.conjugate());i.world.queue(this,40,"position",Le(e)),i.world.queue(this,40,"rotation",[...Le(n),0])}return this}let r=t.clone().normalize();i.world.queue(this,8,"position",Le(e.add(i.localCenter.applyRotationQuaternion(r))));let o=i.world.queue(this,8,"rotation",r.multiply(i.localRotation).asArray());return o.mask&=-33,this}};var qi=class{solver;bodyA;bodyB;J=new Float64Array(12);H=new Float64Array(36);C=new Float64Array(4);fmin=new Float64Array(4).fill(-1/0);fmax=new Float64Array(4).fill(1/0);stiffness=new Float64Array(4).fill(1/0);fracture=new Float64Array(4).fill(1/0);penalty=new Float64Array(4);lambda=new Float64Array(4);constructor(e,t,i){this.solver=e,this.bodyA=t,this.bodyB=i,e.forces.push(this),t?.forces.push(this),i.forces.push(this)}destroy(){let e=this.solver.forces,t=e.indexOf(this);t>=0&&e.splice(t,1),this.unlinkFromBodies()}unlinkFromBodies(){for(let e of[this.bodyA,this.bodyB]){if(!e)continue;let t=e.forces.indexOf(this);t>=0&&e.forces.splice(t,1)}}disable(){this.stiffness.fill(0),this.penalty.fill(0),this.lambda.fill(0)}};var kc=s=>s<0?-1:s>0?1:0,Or=(s,e)=>s<e?s:e,Yf=(s,e)=>s>e?s:e,Tr=(s,e,t)=>Yf(e,Or(t,s));function gs(s,e,t){let i=Math.cos(s),r=Math.sin(s);return[i*e-r*t,r*e+i*t]}function Vi(s,e,t){let i=Math.cos(s[2]),r=Math.sin(s[2]);return[i*e-r*t+s[0],r*e+i*t+s[1]]}function Zt(s,e,t,i,r){s[e*3]=t,s[e*3+1]=i,s[e*3+2]=r}var Ao=class extends qi{rA;rB;C0=new Float64Array(3);torqueArm;restAngle;constructor(e,t,i,r,o,a=[1/0,1/0,1/0],n=1/0){super(e,t,i),this.rA=[r[0],r[1]],this.rB=[o[0],o[1]],this.stiffness[0]=a[0],this.stiffness[1]=a[1],this.stiffness[2]=a[2],this.fmax[2]=n,this.fmin[2]=-n,this.fracture[2]=n,this.restAngle=(t?t.position[2]:0)-i.position[2];let l=(t?t.size[0]:0)+i.size[0],c=(t?t.size[1]:0)+i.size[1];this.torqueArm=l*l+c*c}rows(){return 3}evaluate(e){let t=this.bodyA?Vi(this.bodyA.position,this.rA[0],this.rA[1]):this.rA,i=Vi(this.bodyB.position,this.rB[0],this.rB[1]);e[0]=t[0]-i[0],e[1]=t[1]-i[1],e[2]=((this.bodyA?this.bodyA.position[2]:0)-this.bodyB.position[2]-this.restAngle)*this.torqueArm}initialize(){return this.evaluate(this.C0),this.stiffness[0]!==0||this.stiffness[1]!==0||this.stiffness[2]!==0}Cn=new Float64Array(3);computeConstraint(e){this.evaluate(this.Cn);for(let t=0;t<3;t++)this.C[t]=this.stiffness[t]===1/0?this.Cn[t]-this.C0[t]*e:this.Cn[t]}computeDerivatives(e){let{J:t,H:i}=this;if(i.fill(0,0,27),e===this.bodyA){let r=gs(e.position[2],this.rA[0],this.rA[1]);Zt(t,0,1,0,-r[1]),Zt(t,1,0,1,r[0]),Zt(t,2,0,0,this.torqueArm),i[8]=-r[0],i[17]=-r[1]}else{let r=gs(e.position[2],this.rB[0],this.rB[1]);Zt(t,0,-1,0,r[1]),Zt(t,1,0,-1,-r[0]),Zt(t,2,0,0,-this.torqueArm),i[8]=r[0],i[17]=r[1]}}},wo=class extends qi{rA;rB;rest;constructor(e,t,i,r,o,a,n=-1){if(super(e,t,i),this.rA=[r[0],r[1]],this.rB=[o[0],o[1]],this.stiffness[0]=a,this.rest=n,this.rest<0){let l=Vi(t.position,r[0],r[1]),c=Vi(i.position,o[0],o[1]);this.rest=Math.hypot(l[0]-c[0],l[1]-c[1])}}rows(){return 1}initialize(){return!0}delta(){let e=Vi(this.bodyA.position,this.rA[0],this.rA[1]),t=Vi(this.bodyB.position,this.rB[0],this.rB[1]);return[e[0]-t[0],e[1]-t[1]]}computeConstraint(){let e=this.delta();this.C[0]=Math.hypot(e[0],e[1])-this.rest}computeDerivatives(e){let t=this.delta(),i=t[0]*t[0]+t[1]*t[1];if(i===0)return;let r=Math.sqrt(i),o=t[0]/r,a=t[1]/r,n=(1-o*o)/r,l=(0-o*a)/r,c=(0-a*o)/r,u=(1-a*a)/r,f=e===this.bodyA,d=f?this.rA:this.rB,p=gs(e.position[2],-d[1],d[0]),m=gs(e.position[2],d[0],d[1]),h=n*p[0]+l*p[1],g=c*p[0]+u*p[1],b=o*m[0]+a*m[1],y=o*p[0]+a*p[1];f?Zt(this.J,0,o,a,y):Zt(this.J,0,-o,-a,-y);let A=f?-b-b:b+b,v=this.H;v[0]=n,v[1]=l,v[2]=h,v[3]=c,v[4]=u,v[5]=g,v[6]=h,v[7]=g,v[8]=A}},Bo=class extends qi{rows(){return 0}initialize(){return!0}computeConstraint(){}computeDerivatives(){}},Co=class extends qi{speed;constructor(e,t,i,r,o){super(e,t,i),this.speed=r,this.fmax[0]=o,this.fmin[0]=-o}rows(){return 1}initialize(){return!0}computeConstraint(){let e=this.bodyA?this.bodyA.position[2]-this.bodyA.initial[2]:0,t=this.bodyB.position[2]-this.bodyB.initial[2];this.C[0]=e-t-this.speed*this.solver.dt}computeDerivatives(e){Zt(this.J,0,0,0,e===this.bodyA?1:-1),this.H.fill(0,0,9)}};var So=()=>({dt:1/60,gravity:-10,iterations:10,beta:1e5,alpha:.99,gamma:.99,postStabilize:!0,stiffnessRescale:!1,vbd:!1,vbdStiffness:1e6,matchNearest:!1}),ko=()=>({...So(),postStabilize:!1,alpha:.95,matchNearest:!0});var jr=(s,e)=>s>e?s*2097152+e:e*2097152+s;function Qf(s,e,t){let i=0,r=e;for(;i<r;){let o=i+r>>>1;s[o]<t?i=o+1:r=o}return i}function Ln(s,e,t){let i=Qf(s,e,t);return i<e&&s[i]===t}var Po=class{cellSize=1;pairs=new Float64Array(1024);pairCount=0;configuredFor=-1;large=new Int32Array(0);isLarge=new Uint8Array(0);cellX=new Int32Array(0);cellY=new Int32Array(0);tableSize=0;bucketStart=new Int32Array(0);sorted=new Int32Array(0);configure(e,t){this.configuredFor=e;let i=Float64Array.from({length:e},(n,l)=>t[l*4+1]).sort(),r=e>0?i[e>>1]:1,o=0;for(let n=0;n<e;n++)i[n]<=4*r&&(o=Math.max(o,i[n]));this.cellSize=Math.max(2*o,.001),this.isLarge=new Uint8Array(e);let a=[];for(let n=0;n<e;n++)t[n*4+1]>o&&(this.isLarge[n]=1,a.push(n));for(this.large=Int32Array.from(a),this.cellX=new Int32Array(e),this.cellY=new Int32Array(e),this.tableSize=1;this.tableSize<2*e;)this.tableSize<<=1;this.bucketStart=new Int32Array(this.tableSize+1),this.sorted=new Int32Array(e)}hash(e,t){return(Math.imul(e,73856093)^Math.imul(t,19349663))&this.tableSize-1}findPairs(e,t,i,r,o,a){e!==this.configuredFor&&this.configure(e,i),this.pairCount=0;let{cellX:n,cellY:l,isLarge:c,bucketStart:u,sorted:f}=this,d=1/this.cellSize;u.fill(0);for(let h=0;h<e;h++)c[h]||(n[h]=Math.floor(t[h*4]*d),l[h]=Math.floor(t[h*4+1]*d),u[this.hash(n[h],l[h])+1]++);for(let h=0;h<this.tableSize;h++)u[h+1]+=u[h];let p=u.slice(0,this.tableSize);for(let h=0;h<e;h++)c[h]||(f[p[this.hash(n[h],l[h])]++]=h);let m=(h,g)=>{if(!r[h]&&!r[g])return;let b=t[h*4]-t[g*4],y=t[h*4+1]-t[g*4+1],A=i[h*4+1]+i[g*4+1];if(b*b+y*y>A*A)return;let v=jr(h,g);if(!Ln(o,a,v)){if(this.pairCount===this.pairs.length){let x=new Float64Array(this.pairs.length*2);x.set(this.pairs),this.pairs=x}this.pairs[this.pairCount++]=v}};for(let h=0;h<e;h++){if(c[h])continue;let g=n[h],b=l[h];for(let y=-1;y<=1;y++)for(let A=-1;A<=1;A++){let v=this.hash(g+A,b+y);for(let x=u[v];x<u[v+1];x++){let w=f[x];w>=h||n[w]!==g+A||l[w]!==b+y||m(h,w)}}}for(let h of this.large)for(let g=0;g<e;g++)g===h||c[g]&&g>h||m(h,g);this.pairs.subarray(0,this.pairCount).sort()}};var gt=new Float64Array(12),Pc=new Float64Array(12),Wi=new Float64Array(12);function qt(s,e,t,i,r,o,a,n){let l=e*6;s[l]=t,s[l+1]=i,s[l+2]=r,s[l+3]=o,s[l+4]=a,s[l+5]=n}function Lc(s,e,t,i,r,o){let a=0,n=t*e[0]+i*e[1]-r,l=t*e[6]+i*e[7]-r;if(n<=0){for(let c=0;c<6;c++)s[a*6+c]=e[c];a++}if(l<=0){for(let c=0;c<6;c++)s[a*6+c]=e[6+c];a++}if(n*l<0){let c=n/(n-l),u=e[0]+(e[6]-e[0])*c,f=e[1]+(e[7]-e[1])*c;n>0?qt(s,a,u,f,o,e[3],0,e[5]):qt(s,a,u,f,e[8],o,e[10],0),a++}return a}function Lo(s,e,t,i,r,o,a,n){let l=-(r*a+o*n),c=-(-o*a+r*n);Math.abs(l)>Math.abs(c)?l>0?(qt(gt,0,s,-e,0,0,3,4),qt(gt,1,s,e,0,0,4,1)):(qt(gt,0,-s,e,0,0,1,2),qt(gt,1,-s,-e,0,0,2,3)):c>0?(qt(gt,0,s,e,0,0,4,1),qt(gt,1,-s,e,0,0,1,2)):(qt(gt,0,-s,-e,0,0,2,3),qt(gt,1,s,-e,0,0,3,4));for(let u=0;u<2;u++){let f=u*6,d=gt[f],p=gt[f+1];gt[f]=t+r*d-o*p,gt[f+1]=i+o*d+r*p}}function _o(s,e,t,i,r,o,a,n,l,c,u){let f=Math.cos(t),d=Math.sin(t),p=Math.cos(n),m=Math.sin(n),h=o-s,g=a-e,b=f*h+d*g,y=-d*h+f*g,A=p*h+m*g,v=-m*h+p*g,x=Math.abs(f*p+d*m),w=Math.abs(f*-m+d*p),B=Math.abs(-d*p+f*m),L=Math.abs(-d*-m+f*p),M=Math.abs(b)-i-(x*l+w*c),I=Math.abs(y)-r-(B*l+L*c);if(M>0||I>0)return 0;let E=Math.abs(A)-(x*i+B*r)-l,k=Math.abs(v)-(w*i+L*r)-c;if(E>0||k>0)return 0;let P=0,C=M,_=b>0?f:-f,z=b>0?d:-d;I>.95*C+.01*r&&(P=1,C=I,_=y>0?-d:d,z=y>0?f:-f),E>.95*C+.01*l&&(P=2,C=E,_=A>0?p:-p,z=A>0?m:-m),k>.95*C+.01*c&&(P=3,C=k,_=v>0?-m:m,z=v>0?p:-p);let R,G,X,W,U,H,Z,he,we;if(P===0){R=_,G=z,X=s*R+e*G+i,W=-d,U=f;let $=s*W+e*U;H=-$+r,Z=$+r,he=3,we=1,Lo(l,c,o,a,p,m,R,G)}else if(P===1){R=_,G=z,X=s*R+e*G+r,W=f,U=d;let $=s*W+e*U;H=-$+i,Z=$+i,he=2,we=4,Lo(l,c,o,a,p,m,R,G)}else if(P===2){R=-_,G=-z,X=o*R+a*G+l,W=-m,U=p;let $=o*W+a*U;H=-$+c,Z=$+c,he=3,we=1,Lo(i,r,s,e,f,d,R,G)}else{R=-_,G=-z,X=o*R+a*G+c,W=p,U=m;let $=o*W+a*U;H=-$+l,Z=$+l,he=2,we=4,Lo(i,r,s,e,f,d,R,G)}if(Lc(Pc,gt,-W,-U,H,he)<2||Lc(Wi,Pc,W,U,Z,we)<2)return 0;let Oe=0;for(let $=0;$<2;$++){let Je=$*6,Xe=Wi[Je],Be=Wi[Je+1],at=R*Xe+G*Be-X;if(at>0)continue;let ri=Xe-R*at,Ye=Be-G*at,nt=Wi[Je+2],Qe=Wi[Je+3],lt=Wi[Je+4],wt=Wi[Je+5],Ki,Zi,er,tr;P>=2?([nt,Qe,lt,wt]=[lt,wt,nt,Qe],Ki=Xe-s,Zi=Be-e,er=ri-o,tr=Ye-a):(Ki=ri-s,Zi=Ye-e,er=Xe-o,tr=Be-a);let Wt=Oe*7;u[Wt+0]=nt&255|(Qe&255)<<8|(lt&255)<<16|(wt&255)<<24,u[Wt+1]=f*Ki+d*Zi,u[Wt+1+1]=-d*Ki+f*Zi,u[Wt+3]=p*er+m*tr,u[Wt+3+1]=-m*er+p*tr,u[Wt+5]=-_,u[Wt+5+1]=-z,Oe++}return Oe}var _c=s=>31-Math.clz32(s&-s);function Kf(s){let e=s+2654435769;return e^=e>>>16,e=Math.imul(e,2146121005),e^=e>>>15,e=Math.imul(e,2221713035),e^=e>>>16,e>>>0}var _n=(s,e,t,i)=>s>t||s===t&&e>i,Eo=class{colors=new Int32Array(0);colorStart=new Int32Array(65);colorBodies=new Int32Array(0);next=new Int32Array(0);pending=new Uint8Array(0);prio=new Uint32Array(0);resize(e){if(this.colors.length===e)return;let t=new Int32Array(e).fill(-1);t.set(this.colors.subarray(0,Math.min(e,this.colors.length))),this.colors=t,this.next=new Int32Array(e),this.pending=new Uint8Array(e),this.colorBodies=new Int32Array(e),this.prio=Uint32Array.from({length:e},(i,r)=>Kf(r))}run(e,t,i,r,o,a){this.resize(e);let{colors:n,next:l,pending:c,prio:u}=this,f=(v,x)=>{let w=o[v*4+1],B=w===x?o[v*4+2]:w;return B>=0&&t[B]?B:-1},d=(v,x)=>{let w=0,B=0;for(let L=i[v];L<i[v+1];L++){let M=f(r[L],v);if(M<0||x&&c[M])continue;let I=n[M];I<0||(I<32?w|=1<<I:B|=1<<I-32)}return~w!==0?_c(~w):~B!==0?32+_c(~B):63};for(let v=0;v<e;v++){if(l[v]=n[v],!t[v]||n[v]<0)continue;let x=!0;for(let w=i[v];w<i[v+1]&&x;w++){let B=f(r[w],v);B>=0&&!_n(u[v],v,u[B],B)&&(x=!1)}x&&(l[v]=Math.min(n[v],d(v,!1)))}n.set(l);let p=()=>{let v=0;for(let x=0;x<e;x++)if(c[x]=0,!!t[x]){if(n[x]<0)c[x]=1;else for(let w=i[x];w<i[x+1];w++){let B=f(r[w],x);if(B>=0&&n[B]===n[x]&&_n(u[B],B,u[x],x)){c[x]=1;break}}v+=c[x]}return v},m=p(),h=0;for(;m>0&&h<a;){h++;for(let v=0;v<e;v++){if(l[v]=-2,!c[v])continue;let x=!0;for(let w=i[v];w<i[v+1]&&x;w++){let B=f(r[w],v);B>=0&&c[B]&&!_n(u[v],v,u[B],B)&&(x=!1)}x&&(l[v]=d(v,!0))}for(let v=0;v<e;v++)l[v]!==-2&&(n[v]=l[v],c[v]=0,m--)}let g=0;if(m>0){for(let v=0;v<e;v++)c[v]&&n[v]<0&&(n[v]=0);g=p()}let b=this.colorStart;b.fill(0);let y=0;for(let v=0;v<e;v++)t[v]&&(b[n[v]+1]++,y=Math.max(y,n[v]+1));for(let v=0;v<64;v++)b[v+1]+=b[v];let A=b.slice(0,64);for(let v=0;v<e;v++)t[v]&&(this.colorBodies[A[n[v]]++]=v);return{numColors:y,conflicts:g,rounds:h}}};var Ec=0,Bi=1,Mc=2,Ro=3,bs=4,zc=[0,3,1,1,2],Mn=.05,j=4,O=32,se=0,te=3,Q=6,_e=9,Ae=12,Pt=15,fe=18,N=21,Y=23,re=25,be=26,Ue=27,Hi=28,Dr=class{params=So();options;bodyCount=0;pose;initial;inertial;velocity;prevVelocity;shape;props;dynamic=new Uint8Array(0);jointCount=0;contactCount=0;info=new Int32Array(0);data;handles=[];prevCount=0;prevKeys=new Float64Array(0);prevInfo=new Int32Array(0);prevData=new Float64Array(0);ignorePairs=[];noCollide=new Float64Array(0);noCollideCount=0;noCollideDirty=!0;adjStart=new Int32Array(1);adjList=new Int32Array(0);broadphase=new Po;coloring=new Eo;numColors=0;colorConflicts=0;colorRounds=0;profiling=!1;profile={};phaseStart=0;contactOut=new Float64Array(14);dxBuf=new Float64Array(0);constructor(e={}){this.options={precision:"f32",order:"colored",colorRounds:32,...e},this.pose=this.real(0),this.initial=this.real(0),this.inertial=this.real(0),this.velocity=this.real(0),this.prevVelocity=this.real(0),this.shape=this.real(0),this.props=this.real(0),this.data=this.real(0)}real(e){return this.options.precision==="f32"?new Float32Array(e):new Float64Array(e)}grow(e,t){if(e.length>=t)return e;let i=new e.constructor(Math.max(t,e.length*2,16));return i.set(e),i}clear(){this.bodyCount=0,this.jointCount=0,this.contactCount=0,this.prevCount=0,this.handles=[],this.ignorePairs=[],this.noCollideDirty=!0,this.coloring.resize(0)}addBody(e,t,i,r,o=[0,0,0]){let a=this.bodyCount++,n=this.bodyCount*4;this.pose=this.grow(this.pose,n),this.initial=this.grow(this.initial,n),this.inertial=this.grow(this.inertial,n),this.velocity=this.grow(this.velocity,n),this.prevVelocity=this.grow(this.prevVelocity,n),this.shape=this.grow(this.shape,n),this.props=this.grow(this.props,n),this.dynamic=this.grow(this.dynamic,this.bodyCount);let l=e[0]*e[1]*t;return this.pose.set([r[0],r[1],r[2]??0,0],a*4),this.velocity.set([o[0],o[1],o[2]??0,0],a*4),this.prevVelocity.set(this.velocity.subarray(a*4,a*4+4),a*4),this.shape.set([e[0],e[1],l,l*(e[0]*e[0]+e[1]*e[1])/12],a*4),this.props.set([i,Math.hypot(e[0]*.5,e[1]*.5),0,0],a*4),this.dynamic[a]=l>0?1:0,a}allocConstraint(){let e=this.jointCount++,t=this.jointCount+this.contactCount;this.info=this.grow(this.info,t*j),this.data=this.grow(this.data,t*O),this.contactCount>0&&(this.info.copyWithin((e+1)*j,e*j,(t-1)*j),this.data.copyWithin((e+1)*O,e*O,(t-1)*O)),this.data.fill(0,e*O,e*O+O);for(let i=0;i<3;i++)this.data[e*O+Q+i]=1/0,this.data[e*O+_e+i]=-1/0,this.data[e*O+Ae+i]=1/0,this.data[e*O+Pt+i]=1/0;return this.handles[e]=null,this.noCollideDirty=!0,e}setInfo(e,t,i,r){this.info.set([t,i,r,0],e*j)}addJoint(e,t,i,r,o=[1/0,1/0,1/0],a=1/0){let n=this.allocConstraint();this.setInfo(n,Bi,e,t);let l=this.data,c=n*O;l.set(o,c+Q),l[c+Ae+2]=a,l[c+_e+2]=-a,l[c+Pt+2]=a,l.set(i,c+N),l.set(r,c+Y),l[c+re]=(e>=0?this.pose[e*4+2]:0)-this.pose[t*4+2];let u=(e>=0?this.shape[e*4]:0)+this.shape[t*4],f=(e>=0?this.shape[e*4+1]:0)+this.shape[t*4+1];l[c+be]=u*u+f*f;let d={slot:n,alive:!0};return this.handles[n]=d,d}setJointWorldAnchor(e,t,i){e.alive&&(this.data[e.slot*O+N]=t,this.data[e.slot*O+N+1]=i)}removeJoint(e){e.alive&&(this.disable(e.slot),e.alive=!1)}addSpring(e,t,i,r,o,a){let n=this.allocConstraint();this.setInfo(n,Mc,e,t);let l=n*O;this.data[l+Q]=o,this.data.set(i,l+N),this.data.set(r,l+Y),this.data[l+re]=a}addMotor(e,t,i,r){let o=this.allocConstraint();this.setInfo(o,Ro,e,t);let a=o*O;this.data[a+Ae]=r,this.data[a+_e]=-r,this.data[a+re]=i}ignoredPairs(){return this.ignorePairs}addIgnoreCollision(e,t){this.ignorePairs.push(jr(e,t)),this.noCollideDirty=!0}loadFromReference(e){this.clear();let t=Object.keys(So());Object.assign(this.params,Object.fromEntries(t.map(r=>[r,e[r]])));let i=new Map(e.bodies.map((r,o)=>[r,o]));for(let r of e.bodies){let o=this.addBody(r.size,0,r.friction,r.position,r.velocity);this.shape[o*4+2]=r.mass,this.shape[o*4+3]=r.moment,this.dynamic[o]=r.mass>0?1:0}for(let r of e.forces){let o=r.bodyA?i.get(r.bodyA):-1,a=i.get(r.bodyB);if(r instanceof Ao){let n=this.addJoint(o,a,r.rA,r.rB,[r.stiffness[0],r.stiffness[1],r.stiffness[2]],r.fracture[2]);this.data[n.slot*O+re]=r.restAngle,this.data[n.slot*O+be]=r.torqueArm}else r instanceof wo?this.addSpring(o,a,r.rA,r.rB,r.stiffness[0],r.rest):r instanceof Co?this.addMotor(o,a,r.speed,r.fmax[0]):r instanceof Bo&&this.addIgnoreCollision(o,a)}}step(){let e=this.params,t=e.postStabilize&&!e.vbd,i=e.vbd?0:e.alpha;this.phaseStart=this.profiling?performance.now():0,this.saveContacts(),this.findPairs(),this.mark("broadphase"),this.initJoints(),this.narrowphase(),this.mark("narrowphase"),this.warmStartConstraints(t,i),this.buildAdjacency(),this.mark("adjacency"),this.colorBodies(),this.mark("coloring"),this.warmStartBodies();let r=e.iterations+(t?1:0);for(let o=0;o<r;o++){let a=t?o<e.iterations?1:0:i;this.primal(a),this.mark("primal"),o<e.iterations&&this.dual(a),o===e.iterations-1&&this.updateVelocities(),this.mark("dual")}t&&this.refreshStick()}mark(e){if(!this.profiling)return;let t=performance.now();this.profile[e]=(this.profile[e]??0)+t-this.phaseStart,this.phaseStart=t}resetProfile(){for(let e of Object.keys(this.profile))delete this.profile[e]}saveContacts(){let e=this.contactCount,t=this.jointCount;this.prevKeys.length<e&&(this.prevKeys=new Float64Array(e*2),this.prevInfo=new Int32Array(e*2*j),this.prevData=new Float64Array(e*2*O));for(let i=0;i<e;i++){let r=t+i;this.prevKeys[i]=jr(this.info[r*j+1],this.info[r*j+2])}this.prevInfo.set(this.info.subarray(t*j,(t+e)*j)),this.prevData.set(this.data.subarray(t*O,(t+e)*O)),this.prevCount=e,this.contactCount=0}findPairs(){if(this.noCollideDirty){let e=[...this.ignorePairs];for(let t=0;t<this.jointCount;t++){let i=this.info[t*j+1],r=this.info[t*j+2];this.info[t*j]!==Ec&&i>=0&&e.push(jr(i,r))}this.noCollide=Float64Array.from(e).sort(),this.noCollideCount=e.length,this.noCollideDirty=!1}this.broadphase.findPairs(this.bodyCount,this.pose,this.props,this.dynamic,this.noCollide,this.noCollideCount)}initJoints(){let{info:e,data:t,pose:i}=this,r=0;for(let o=0;o<this.jointCount;o++){let a=o*O;if(e[o*j]===Bi){if(t[a+Q]===0&&t[a+Q+1]===0&&t[a+Q+2]===0){let u=this.handles[o];u&&(u.alive=!1);continue}let l=e[o*j+1],c=e[o*j+2];this.jointC(l,c,a,i,t,a+fe)}r!==o&&(e.copyWithin(r*j,o*j,(o+1)*j),t.copyWithin(r*O,a,a+O),this.handles[r]=this.handles[o],this.handles[r]&&(this.handles[r].slot=r)),r++}if(r!==this.jointCount){for(let o=r;o<this.jointCount;o++)this.handles[o]=null;this.jointCount=r,this.noCollideDirty=!0}}jointC(e,t,i,r,o,a,n=o){let l,c,u;if(e>=0){let h=Math.cos(r[e*4+2]),g=Math.sin(r[e*4+2]),b=o[i+N],y=o[i+N+1];l=h*b-g*y+r[e*4],c=g*b+h*y+r[e*4+1],u=r[e*4+2]}else l=o[i+N],c=o[i+N+1],u=0;let f=Math.cos(r[t*4+2]),d=Math.sin(r[t*4+2]),p=o[i+Y],m=o[i+Y+1];n[a]=l-(f*p-d*m+r[t*4]),n[a+1]=c-(d*p+f*m+r[t*4+1]),n[a+2]=(u-r[t*4+2]-o[i+re])*o[i+be]}narrowphase(){let{pose:e,shape:t,props:i}=this,r=this.broadphase.pairs,o=this.contactOut;for(let a=0;a<this.broadphase.pairCount;a++){let n=r[a],l=Math.floor(n/2097152),c=n-l*2097152,u=_o(e[l*4],e[l*4+1],e[l*4+2],t[l*4]*.5,t[l*4+1]*.5,e[c*4],e[c*4+1],e[c*4+2],t[c*4]*.5,t[c*4+1]*.5,o);if(u===0)continue;let f=0,d=this.prevCount;for(;f<d;){let h=f+d>>>1;this.prevKeys[h]<n?f=h+1:d=h}let p=f,m=Math.sqrt(i[l*4]*i[c*4]);for(let h=0;h<u;h++){let g=this.jointCount+this.contactCount++;this.info=this.grow(this.info,(g+1)*j),this.data=this.grow(this.data,(g+1)*O);let b=this.data,y=g*O,A=h*7,v=o[A+0];this.info.set([bs,l,c,v],g*j),b.fill(0,y,y+O),b[y+Q]=b[y+Q+1]=1/0,b[y+_e]=-1/0,b[y+Ae]=0,b[y+Pt]=b[y+Pt+1]=1/0,b[y+N]=o[A+1],b[y+N+1]=o[A+1+1],b[y+Y]=o[A+3],b[y+Y+1]=o[A+3+1],b[y+re]=m,b[y+be]=o[A+5],b[y+Ue]=o[A+5+1];let x=-1;for(let C=p;C<this.prevCount&&this.prevKeys[C]===n;C++)this.prevInfo[C*j+3]===v&&(x=C);if(x<0&&this.params.matchNearest){let C=Mn*Math.min(t[l*4],t[l*4+1],t[c*4],t[c*4+1]);for(let _=p;_<this.prevCount&&this.prevKeys[_]===n;_++){let z=Math.hypot(this.prevData[_*O+N]-b[y+N],this.prevData[_*O+N+1]-b[y+N+1]);z<=C&&(C=z,x=_)}}if(x>=0){let C=x*O;b[y+se]=this.prevData[C+se],b[y+se+1]=this.prevData[C+se+1],b[y+te]=this.prevData[C+te],b[y+te+1]=this.prevData[C+te+1],this.prevData[C+Hi]&&(b[y+N]=this.prevData[C+N],b[y+N+1]=this.prevData[C+N+1],b[y+Y]=this.prevData[C+Y],b[y+Y+1]=this.prevData[C+Y+1])}let[w,B]=wi(e[l*4+2],b[y+N],b[y+N+1]),[L,M]=wi(e[c*4+2],b[y+Y],b[y+Y+1]),I=b[y+be],E=b[y+Ue],k=e[l*4]+w-e[c*4]-L,P=e[l*4+1]+B-e[c*4+1]-M;b[y+fe]=I*k+E*P+5e-4,b[y+fe+1]=E*k-I*P}}}warmStartConstraints(e,t){let i=this.params,r=this.data,o=this.jointCount+this.contactCount;for(let a=0;a<o;a++){let n=zc[this.info[a*j]],l=a*O;for(let c=0;c<n;c++){if(i.vbd){r[l+se+c]=Or(r[l+Q+c],i.vbdStiffness);continue}e||(r[l+te+c]=r[l+te+c]*t*i.gamma),r[l+se+c]=Or(Tr(r[l+se+c]*i.gamma,1,1e9),r[l+Q+c])}}}prepareTopology(){this.buildAdjacency(),this.colorBodies()}buildAdjacency(){let e=this.bodyCount,t=this.jointCount+this.contactCount;this.adjStart=this.grow(this.adjStart,e+1),this.adjList=this.grow(this.adjList,t*2);let i=this.adjStart;i.fill(0,0,e+1);for(let o=0;o<t;o++)for(let a=1;a<=2;a++){let n=this.info[o*j+a];n>=0&&this.dynamic[n]&&i[n+1]++}for(let o=0;o<e;o++)i[o+1]+=i[o];let r=i.slice(0,e);for(let o=0;o<t;o++)for(let a=1;a<=2;a++){let n=this.info[o*j+a];n>=0&&this.dynamic[n]&&(this.adjList[r[n]++]=o)}}colorBodies(){if(this.options.order!=="colored")return;let e=this.coloring.run(this.bodyCount,this.dynamic,this.adjStart,this.adjList,this.info,this.options.colorRounds);this.numColors=e.numColors,this.colorConflicts=e.conflicts,this.colorRounds=e.rounds}warmStartBodies(){let{dt:e,gravity:t}=this.params,{pose:i,velocity:r,initial:o,inertial:a,prevVelocity:n}=this;for(let l=0;l<this.bodyCount;l++){let c=l*4;r[c+2]=Tr(r[c+2],-50,50),a[c]=i[c]+r[c]*e,a[c+1]=i[c+1]+r[c+1]*e,a[c+2]=i[c+2]+r[c+2]*e,this.dynamic[l]&&(a[c+1]+=t*e*e);let u=(r[c+1]-n[c+1])/e*kc(t),f=Tr(u/Math.abs(t),0,1);Number.isFinite(f)||(f=0),o[c]=i[c],o[c+1]=i[c+1],o[c+2]=i[c+2],i[c]=i[c]+r[c]*e,i[c+1]=i[c+1]+r[c+1]*e+t*f*e*e,i[c+2]=i[c+2]+r[c+2]*e}}eC=new Float64Array(3);eMin=new Float64Array(3);eMax=new Float64Array(3);eJ=new Float64Array(9);eG=new Float64Array(9);evalConstraint(e,t,i){let{info:r,data:o,pose:a,initial:n}=this,l=r[e*j],c=r[e*j+1],u=r[e*j+2],f=e*O,{eC:d,eMin:p,eMax:m,eJ:h,eG:g}=this,b=zc[l];for(let A=0;A<b;A++)p[A]=o[f+_e+A],m[A]=o[f+Ae+A];let y=i===c;if(g.fill(0),l===Bi){this.jointC(c,u,f,a,o,0,d);for(let A=0;A<3;A++)o[f+Q+A]===1/0&&(d[A]-=o[f+fe+A]*t);if(i>=0){let A=a[i*4+2],[v,x]=wi(A,o[f+(y?N:Y)],o[f+(y?N:Y)+1]),w=y?1:-1;h[0]=w,h[1]=0,h[2]=-w*x,h[3]=0,h[4]=w,h[5]=w*v,h[6]=0,h[7]=0,h[8]=w*o[f+be],g[2]=Math.abs(v),g[5]=Math.abs(x)}}else if(l===Mc){let[A,v]=Ic(a,c,o[f+N],o[f+N+1]),[x,w]=Ic(a,u,o[f+Y],o[f+Y+1]),B=A-x,L=v-w,M=B*B+L*L,I=Math.sqrt(M);if(d[0]=I-o[f+re],i>=0&&M!==0){let E=B/I,k=L/I,P=(1-E*E)/I,C=-E*k/I,_=(1-k*k)/I,z=a[i*4+2],R=y?N:Y,[G,X]=wi(z,-o[f+R+1],o[f+R]),[W,U]=wi(z,o[f+R],o[f+R+1]),H=P*G+C*X,Z=C*G+_*X,he=E*W+k*U,we=E*G+k*X,Oe=y?1:-1;h[0]=Oe*E,h[1]=Oe*k,h[2]=Oe*we;let $=y?-he-he:he+he;g[0]=Math.hypot(P,C,H),g[1]=Math.hypot(C,_,Z),g[2]=Math.hypot(H,Z,$)}else i>=0&&h.fill(0,0,3)}else if(l===Ro){let A=c>=0?a[c*4+2]-n[c*4+2]:0,v=a[u*4+2]-n[u*4+2];d[0]=A-v-o[f+re]*this.params.dt,i>=0&&(h[0]=0,h[1]=0,h[2]=y?1:-1)}else if(l===bs){let A=o[f+be],v=o[f+Ue],x=v,w=-A,[B,L]=wi(n[c*4+2],o[f+N],o[f+N+1]),[M,I]=wi(n[u*4+2],o[f+Y],o[f+Y+1]),E=B*v-L*A,k=-(M*v-I*A),P=B*w-L*x,C=-(M*w-I*x),_=a[c*4]-n[c*4],z=a[c*4+1]-n[c*4+1],R=a[c*4+2]-n[c*4+2],G=a[u*4]-n[u*4],X=a[u*4+1]-n[u*4+1],W=a[u*4+2]-n[u*4+2];d[0]=o[f+fe]*(1-t)+A*_+v*z+E*R+-A*G+-v*X+k*W,d[1]=o[f+fe+1]*(1-t)+x*_+w*z+P*R+-x*G+-w*X+C*W;let U=Math.abs(o[f+te])*o[f+re];m[1]=U,p[1]=-U,i>=0&&(y?(h[0]=A,h[1]=v,h[2]=E,h[3]=x,h[4]=w,h[5]=P):(h[0]=-A,h[1]=-v,h[2]=k,h[3]=-x,h[4]=-w,h[5]=C))}return b}solveBody(e,t){let i=this.params,{shape:r,pose:o,inertial:a,data:n}=this,l=i.dt*i.dt,c=r[e*4+2]/l,u=r[e*4+3]/l,f=c,d=0,p=c,m=0,h=0,g=u,b=c*(o[e*4]-a[e*4]),y=c*(o[e*4+1]-a[e*4+1]),A=u*(o[e*4+2]-a[e*4+2]),{eC:v,eMin:x,eMax:w,eJ:B,eG:L}=this,M=this.adjStart,I=this.adjList;for(let H=M[e+1]-1;H>=M[e];H--){let Z=I[H],he=this.evalConstraint(Z,t,e),we=Z*O,Oe=!i.vbd;for(let $=0;$<he;$++){let Je=n[we+Q+$],Xe=Oe&&Je===1/0?n[we+te+$]:0,Be=n[we+se+$],at=v[$],ri=Be*at+Xe,Ye=Tr(ri,x[$],w[$]),nt=Math.abs(Ye);i.stiffnessRescale&&at!==0&&(ri<x[$]?Be=Math.abs((x[$]-Xe)/at):ri>w[$]&&(Be=Math.abs((w[$]-Xe)/at)));let Qe=B[$*3],lt=B[$*3+1],wt=B[$*3+2];b+=Qe*Ye,y+=lt*Ye,A+=wt*Ye,f+=Qe*Qe*Be+L[$*3]*nt,d+=lt*Qe*Be,p+=lt*lt*Be+L[$*3+1]*nt,m+=wt*Qe*Be,h+=wt*lt*Be,g+=wt*wt*Be+L[$*3+2]*nt}}let E=f,k=d/f,P=m/f,C=p-k*k*E,_=(h-k*P*E)/C,z=g-(P*P*E+_*_*C),R=y-k*b,X=(A-P*b-_*R)/z,W=R/C-_*X,U=b/E-k*W-P*X;this.dxBuf[e*3]=U,this.dxBuf[e*3+1]=W,this.dxBuf[e*3+2]=X}applyDx(e){this.pose[e*4]-=this.dxBuf[e*3],this.pose[e*4+1]-=this.dxBuf[e*3+1],this.pose[e*4+2]-=this.dxBuf[e*3+2]}primal(e){if(this.dxBuf.length<this.bodyCount*3&&(this.dxBuf=new Float64Array(this.bodyCount*3)),this.options.order==="sequential"){for(let r=this.bodyCount-1;r>=0;r--)this.dynamic[r]&&(this.solveBody(r,e),this.applyDx(r));return}let{colorStart:t,colorBodies:i}=this.coloring;for(let r=0;r<this.numColors;r++){for(let o=t[r];o<t[r+1];o++)this.solveBody(i[o],e);for(let o=t[r];o<t[r+1];o++)this.applyDx(i[o])}}dual(e){let t=this.params,i=this.data,{eC:r,eMin:o,eMax:a}=this,n=this.jointCount+this.contactCount;for(let l=0;l<n;l++){let c=this.info[l*j];if(c===Ec)continue;let u=this.evalConstraint(l,e,-1),f=l*O;c===bs&&(i[f+Hi]=Math.abs(i[f+te+1])<a[1]&&Math.abs(i[f+fe+1])<.01?1:0);for(let d=0;d<u;d++){let p=i[f+Q+d],m=!t.vbd&&p===1/0?i[f+te+d]:0,h=Tr(i[f+se+d]*r[d]+m,o[d],a[d]);i[f+te+d]=h,Math.abs(h)>=i[f+Pt+d]&&this.disable(l),!t.vbd&&h>o[d]&&h<a[d]&&(i[f+se+d]=Or(i[f+se+d]+t.beta*Math.abs(r[d]),Or(1e9,i[f+Q+d])))}}}refreshStick(){let e=this.data;for(let t=0;t<this.contactCount;t++){let i=(this.jointCount+t)*O,r=Math.abs(e[i+te])*e[i+re];e[i+Hi]=Math.abs(e[i+te+1])<r&&Math.abs(e[i+fe+1])<.01?1:0}}disable(e){let t=e*O;this.data.fill(0,t+se,t+se+3),this.data.fill(0,t+te,t+te+3),this.data.fill(0,t+Q,t+Q+3)}updateVelocities(){let{dt:e}=this.params,{pose:t,initial:i,velocity:r,prevVelocity:o}=this;for(let a=0;a<this.bodyCount;a++){let n=a*4;o[n]=r[n],o[n+1]=r[n+1],o[n+2]=r[n+2],this.dynamic[a]&&(r[n]=(t[n]-i[n])/e,r[n+1]=(t[n+1]-i[n+1])/e,r[n+2]=(t[n+2]-i[n+2])/e)}}pick(e,t){for(let i=this.bodyCount-1;i>=0;i--){let[r,o]=wi(-this.pose[i*4+2],e-this.pose[i*4],t-this.pose[i*4+1]);if(Math.abs(r)<=this.shape[i*4]*.5&&Math.abs(o)<=this.shape[i*4+1]*.5)return{body:i,local:[r,o]}}return null}kineticEnergy(){let e=0;for(let t=0;t<this.bodyCount;t++){if(!this.dynamic[t])continue;let i=t*4,r=this.velocity;e+=.5*this.shape[i+2]*(r[i]*r[i]+r[i+1]*r[i+1])+.5*this.shape[i+3]*r[i+2]*r[i+2]}return e}maxJointError(){let e=0,t=new Float64Array(3);for(let i=0;i<this.jointCount;i++){if(this.info[i*j]!==Bi)continue;let r=i*O;this.jointC(this.info[i*j+1],this.info[i*j+2],r,this.pose,this.data,0,t);for(let o=0;o<2;o++)this.data[r+Q+o]===1/0&&(e=Math.max(e,Math.abs(t[o])))}return e}isContactPairIgnored(e,t){return Ln(this.noCollide,this.noCollideCount,jr(e,t))}};function wi(s,e,t){let i=Math.cos(s),r=Math.sin(s);return[i*e-r*t,r*e+i*t]}function Ic(s,e,t,i){let r=Math.cos(s[e*4+2]),o=Math.sin(s[e*4+2]);return[r*t-o*i+s[e*4],o*t+r*i+s[e*4+1]]}var ys=`
3948
+ `),xi=class{device;pipelines;layout;watch;table;events;params;setSlots;capacity;group=null;bound=[];flip=0;bodies;constructor(e,t,i,r,o,a=3){this.device=e,this.bodies=t,this.capacity=o,this.setSlots=2**Math.ceil(Math.log2(Math.max(64,2*r)));let n=e.createShaderModule({label:"contact events",code:a===2?Xf:ds}),l=["read-only-storage","read-only-storage","read-only-storage","read-only-storage","read-only-storage","storage","storage","uniform"];this.layout=e.createBindGroupLayout({label:"contact events",entries:l.map((d,h)=>({binding:h,visibility:GPUShaderStage.COMPUTE,buffer:{type:d}}))});let c=e.createPipelineLayout({bindGroupLayouts:[this.layout]}),u=d=>e.createComputePipeline({label:`contact events ${d}`,layout:c,compute:{module:n,entryPoint:d}});this.pipelines={touching:u("touching"),ended:u("ended")};let f=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC;this.watch=e.createBuffer({label:"contact watch",size:Math.max(16,i*4),usage:f}),this.table=e.createBuffer({label:"contact sets",size:(kn+4*this.setSlots)*4,usage:f}),this.events=e.createBuffer({label:"contact events",size:o*_r*16,usage:f}),this.params=e.createBuffer({label:"contact params",size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST})}setWatched(e,t){let i=e.map((r,o)=>[r,t[o]?1:0]).sort((r,o)=>r[0]-o[0]);for(let r=0;r<i.length;){let o=r+1;for(;o<i.length&&i[o][0]===i[o-1][0]+1;)o++;this.device.queue.writeBuffer(this.watch,i[r][0]*4,Uint32Array.from(i.slice(r,o),a=>a[1])),r=o}}run(e,t,i,r){let o=this.device,a=[this.bodies,e.manifolds,e.contacts,e.counters,this.watch,this.table,this.events,this.params];(!this.group||a.some((d,h)=>d!==this.bound[h]))&&(this.bound=a,this.group=o.createBindGroup({layout:this.layout,entries:a.map((d,h)=>({binding:h,resource:{buffer:d}}))})),this.flip=1-this.flip;let[n,l]=this.flip?[0,this.setSlots]:[this.setSlots,0],c=new Uint32Array([n,l,this.setSlots-1,this.capacity,t,i,0,0]);new Float32Array(c.buffer)[6]=r,o.queue.writeBuffer(this.params,0,c);let u=o.createCommandEncoder({label:"contact events"});u.clearBuffer(this.table,(kn+2*l)*4,2*this.setSlots*4);let f=u.beginComputePass({label:"contact events"});f.setBindGroup(0,this.group),f.setPipeline(this.pipelines.touching),f.dispatchWorkgroups(Math.max(1,Math.ceil(t/64))),f.setPipeline(this.pipelines.ended),f.dispatchWorkgroups(Math.ceil(this.setSlots/64)),f.end(),o.queue.submit([u.finish()])}async read(){let e=this.device,t=16+this.capacity*_r*16,i=e.createBuffer({size:t,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),r=e.createCommandEncoder({label:"read contact events"});r.copyBufferToBuffer(this.table,0,i,0,16),r.copyBufferToBuffer(this.events,0,i,16,t-16),r.clearBuffer(this.table,0,16),e.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ);let o=i.getMappedRange().slice(0);i.unmap(),i.destroy();let a=new Uint32Array(o),n=new Float32Array(o),l=Math.min(a[0],this.capacity),c=[];for(let u=0;u<l;u++){let f=4+u*_r*4;c.push({kind:a[f],a:a[f+1],b:a[f+2],step:a[f+3],point:[n[f+4],n[f+5],n[f+6]],impulse:n[f+7],normal:[n[f+8],n[f+9],n[f+10]]})}return c.sort((u,f)=>u.step-f.step),{events:c,dropped:a[0]-l,full:a[1]!==0}}destroy(){for(let e of[this.watch,this.table,this.events,this.params])e.destroy()}};var wc=[0,1,2,3,5,4,0,3,4,0,4,1,1,4,5,1,5,2,2,5,3,2,3,0],Er=wc.slice();for(let s=0;s<Er.length;s+=3)[Er[s+1],Er[s+2]]=[Er[s+2],Er[s+1]];var yo=(s,e,t)=>{let i=Array.from(s??[]);if(i.length!==e||!i.every(Number.isFinite))throw Error(`${t} requires ${e} finite values`);return i},Bc=(s,e)=>{if(!Number.isFinite(s)||s<=0)throw Error(`${e} must be positive and finite`);return s};function Cc(s){let e=[0,1,2].map(u=>s.reduce((f,d)=>f+d[u],0)/s.length),[t,i,r,o]=s,a=i.map((u,f)=>u-t[f]),n=r.map((u,f)=>u-t[f]),l=(a[1]*n[2]-a[2]*n[1])*(t[0]-o[0])+(a[2]*n[0]-a[0]*n[2])*(t[1]-o[1])+(a[0]*n[1]-a[1]*n[0])*(t[2]-o[2]),c=ja(s.flatMap(u=>u.map((f,d)=>f-e[d])),l>0?wc:Er);if(!c)throw Error("Terrain contains a degenerate collision piece");return{shape:c,position:c.center.map((u,f)=>u+e[f]),rotation:c.rotation}}function Mr({heights:s,columns:e,rows:t,spacing:i=1,origin:r=[0,0,0],upAxis:o=1,baseHeight:a,holes:n}={}){for(let[g,b]of Object.entries({columns:e,rows:t}))if(!Number.isInteger(b)||b<2)throw Error(`${g} must be an integer >= 2`);let l=yo(s,e*t,"heights"),c=yo(r,3,"origin");if(![0,1,2].includes(o))throw Error("upAxis must be 0, 1 or 2");let u=typeof i=="number"?[i,i]:yo(i,2,"spacing");u.forEach(g=>Bc(g,"spacing"));let f=a??l.reduce((g,b)=>Math.min(g,b),1/0)-2;if(!Number.isFinite(f)||l.some(g=>g<=f))throw Error("baseHeight must be below every terrain height");let d=(e-1)*(t-1);if(n&&n.length!==d)throw Error("holes requires one value per terrain cell");let h=[0,1,2].filter(g=>g!==o),m=[],p=(g,b)=>{let y=[...c];return y[h[0]]+=g*u[0],y[h[1]]+=b*u[1],y[o]+=l[b*e+g],y};for(let g=0;g<t-1;g++)for(let b=0;b<e-1;b++){if(n?.[g*(e-1)+b])continue;let y=p(b,g),A=p(b+1,g),v=p(b,g+1),x=p(b+1,g+1);for(let w of[[y,A,v],[A,x,v]])m.push(Cc([...w,...w.map(B=>{let L=[...B];return L[o]=c[o]+f,L})]))}return{kind:"heightfield",pieces:m,triangleCount:m.length}}function zr({positions:s,indices:e,thickness:t=.1}={}){if(!s||s.length%3)throw Error("positions requires xyz triples");let i=yo(s,s.length,"positions"),r=i.length/3;if(e===void 0&&r%3)throw Error("Nonindexed positions require three vertices per triangle");let o=e===void 0?Array.from({length:r},(n,l)=>l):Array.from(e);if(!o.length||o.length%3||!o.every(n=>Number.isInteger(n)&&n>=0&&n<r))throw Error("indices requires valid triangle vertex indices");Bc(t,"thickness");let a=[];for(let n=0;n<o.length;n+=3){let l=o.slice(n,n+3).map(g=>i.slice(g*3,g*3+3)),[c,u,f]=l,d=u.map((g,b)=>g-c[b]),h=f.map((g,b)=>g-c[b]),m=[d[1]*h[2]-d[2]*h[1],d[2]*h[0]-d[0]*h[2],d[0]*h[1]-d[1]*h[0]],p=Math.hypot(...m);p!==0&&a.push(Cc([...l,...l.map(g=>g.map((b,y)=>b-m[y]*t/p))]))}if(!a.length)throw Error("Static mesh requires at least one nondegenerate triangle");return{kind:"static-mesh",pieces:a,triangleCount:a.length}}function vo(s,e,t={}){if(t.mass!==void 0&&t.mass!==0)throw Error("Terrain is static and requires zero mass");let i=t.friction??.6,r=t.restitution??0;if(!Number.isFinite(i)||i<0)throw Error("friction must be nonnegative and finite");if(!Number.isFinite(r)||r<0||r>1)throw Error("restitution must be between 0 and 1");for(let o of["group","collidesWith"]){let a=t[o]??4294967295;if(!Number.isInteger(a)||a<0||a>4294967295)throw Error(`${o} must be an unsigned 32-bit integer`)}if(!e?.pieces?.length)throw Error("Terrain requires collision pieces");return e.pieces.map(o=>{let a=lr(s,o.shape,0,i,o.position,o.rotation);return Object.assign(a,{allowSleep:!1,isTrigger:!1,restitution:r,group:t.group??4294967295,collidesWith:t.collidesWith??4294967295}),a})}var rt=Object.freeze({BOX:"box",SPHERE:"sphere",CAPSULE:"capsule",CYLINDER:"cylinder",CONVEX_HULL:"convex-hull"}),Le=s=>s&&typeof s.x=="number"?[s.x,s.y,s.z,...typeof s.w=="number"?[s.w]:[]]:Array.from(s),ps=new WeakMap,Ir=s=>{if(!Number.isInteger(s)||s<0||s>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");return s},xo=(s,e,t=!1)=>{if(!Number.isFinite(s)||(t?s<0:s<=0))throw Error(`${e} must be ${t?"nonnegative":"positive"} and finite`);return s},hs=class s{static async create({device:e,...t}={}){if(t.scene&&ps.has(t.scene))throw Error("This scene already has an AVBD world");let i=!e;e||({device:e}=await Sr({preferredLimits:{maxStorageBuffersPerShaderStage:9,maxStorageBufferBindingSize:512*1024*1024,maxBufferSize:1024*1024*1024}}));let r;try{return await Ni(e),r=new s(e,t),r.ownsDevice=i,r.scene&&r.autoAttach&&r.attachToScene(),r}catch(o){throw r?r.dispose():i&&e.destroy(),o}}constructor(e,{scene:t,gravity:i=[0,-10,0],timeStep:r=1/60,iterations:o=10,capacity:a=4096,syncMeshes:n=!0,maxSyncedBodies:l=2048,broadphase:c="auto",solverMode:u="auto",smallGroups:f,minimumColors:d,minimumColorRounds:h,bvh:m={},autoAttach:p=!0,maxContactPairs:g=8192,maxContactEvents:b=4096,sleeping:y=!1}={}){if(this.device=e,this.scene=t,this.autoAttach=p,this.syncEnabled=n,this.maxSyncedBodies=l,!Number.isInteger(a)||a<1||!Number.isInteger(l)||l<0)throw Error("capacity and maxSyncedBodies must be valid integer counts");if(this.capacity=a,this.collisionOptions={broadphase:c,bvh:m,solverMode:u,smallGroups:f,minimumColors:d,minimumColorRounds:h},this.ref=new ni,this.ref.dt=xo(r,"timeStep"),!Number.isInteger(o)||o<1)throw Error("iterations must be a positive integer");this.ref.iterations=o,this.aggregates=[],this.constraints=new Set,this.contactListeners=new Set;for(let[v,x]of Object.entries({maxContactPairs:g,maxContactEvents:b}))if(!Number.isInteger(x)||x<1)throw Error(`${v} must be a positive integer`);if(this.contactOptions={maxContactPairs:g,maxContactEvents:b},this.bodyReadback=new vi(e),this.sleepOptions=y,y!==!1&&y!==!0&&(typeof y!="object"||y===null))throw Error("sleeping must be a boolean or options object");this.commands=new Map,this.steps=0,this.errors=[],this.deviceLost=null;let A=new WeakRef(this);e.lost.then(v=>{let x=A.deref();!x||x.disposed||(x.deviceLost={reason:v.reason,message:v.message},x.errors.push(`WebGPU device lost: ${v.message||v.reason}`),x.dispose())}),this.setGravity(i),this.errorListener=v=>this.errors.push(v.error.message),e.addEventListener("uncapturederror",this.errorListener),t&&ps.set(t,this)}setGravity(e){let t=Le(e);if(t.length!==3||!t.every(Number.isFinite))throw Error("gravity requires three finite components");let i=Math.hypot(...t);this.gravity=-i,this.up=i?t.map(r=>-r/i):[0,1,0],this.gpu&&(this.gpu.params.gravity=this.gravity,this.gpu.params.up=this.up),this.wakeAll()}get solverDecision(){return this.initialize(),{...this.gpu.solverDecision}}setSolverMode(e){this.initialize();let t=this.gpu.setSolverMode(e);return this.collisionOptions.solverMode=e,{...t}}initialize(){if(this.assertAlive(),this.gpu)return;if(this.syncEnabled&&this.aggregates.filter(r=>r.sync).length>this.maxSyncedBodies)throw Error("For large scenes use syncMeshes:false and draw the GPU body buffer directly");if(this.aggregates.length>this.capacity)throw Error(`Body capacity ${this.capacity} exceeded; size the world before initialization`);this.gpu=new gi(this.device,this.ref,go(this.ref,{bodyCapacity:Math.max(1,this.capacity),spatialSort:!0,...this.collisionOptions})),Object.assign(this.gpu.params,{gravity:this.gravity,up:this.up}),this.gpu.externalBeforeStep=r=>{this.sleepManager?.before(r),this.flushCommands(r)},this.gpu.externalAfterStep=r=>this.sleepManager?.after(r);let e=new Map([...this.constraints].map(r=>[r.force,r])),t=[],i=0;for(let r of this.ref.forces){let o=e.get(r);o&&(o.attach(i++,!1),(o.type==="fixed"||o.type==="spring"&&o.rest===void 0)&&t.push({slot:o.slot,spring:o.type==="spring"}))}this.gpu.captureConstraintFrames(t),this.byGpuIndex=new Map(this.aggregates.map(r=>[this.gpu.gpuIndex(r.index),r.body]));for(let r of this.aggregates)(r.disposed||r.group!==4294967295||r.collidesWith!==4294967295)&&this.gpu.setFilters([this.gpu.gpuIndex(r.index)],[r.disposed?0:r.group],[r.disposed?0:r.collidesWith]);for(let r of this.aggregates)r.isTrigger&&this.gpu.setSensor(r.body.gpuIndex,!0);for(let r of this.aggregates)r.restitution>0&&this.gpu.setRestitution(r.body.gpuIndex,r.restitution);this.contactListeners.size&&this.initializeContacts(),this.sleepOptions&&(this.sleepManager=new Fi(this,this.sleepOptions===!0?{}:this.sleepOptions))}addAggregate(e,t,i={}){return new ms(e,t,i,this)}addAggregates(e){return e.map(({mesh:t,type:i,options:r})=>this.addAggregate(t,i,r))}addHeightfield(e){return this.addTerrain(Mr(e),e)}addStaticMesh(e,t={}){e.computeWorldMatrix(!0);let i=e.getVerticesData("position"),r=e.getWorldMatrix().m;if(!i)throw Error("Static mesh requires vertex positions");let o=new Float64Array(i.length);for(let u=0;u<i.length;u+=3){let f=i[u],d=i[u+1],h=i[u+2];for(let m=0;m<3;m++)o[u+m]=r[m]*f+r[4+m]*d+r[8+m]*h+r[12+m]}let a=e.getIndices(),n=a?.length?Uint32Array.from(a):Uint32Array.from({length:i.length/3},(u,f)=>f),l=e.getVerticesData("normal"),c=e.getWorldMatrix().determinant()<0;for(let u=0;u<n.length;u+=3){let f=n[u]*3,d=n[u+1]*3,h=n[u+2]*3,m=[0,1,2].map(b=>i[d+b]-i[f+b]),p=[0,1,2].map(b=>i[h+b]-i[f+b]),g=!1;l?.length===i.length&&(g=[m[1]*p[2]-m[2]*p[1],m[2]*p[0]-m[0]*p[2],m[0]*p[1]-m[1]*p[0]].reduce((y,A,v)=>y+A*(l[f+v]+l[d+v]+l[h+v]),0)<0),g!==c&&([n[u+1],n[u+2]]=[n[u+2],n[u+1]])}return this.addTerrain(zr({positions:o,indices:n,thickness:t.thickness}),t)}addTerrain(e,t={}){if(this.assertAlive(),this.gpu)throw Error("Add static terrain before initializing the physics world");if(this.device.limits.maxStorageBuffersPerShaderStage<9)throw Error("Terrain collisions require nine storage buffer bindings");if(this.aggregates.length+(e?.pieces?.length??0)>this.capacity)throw Error("AVBD terrain exceeds body capacity; reserve space for its collision pieces");let r=vo(this.ref,e,t).map(a=>new Pn(this,a)),o=!1;return{bodies:r.map(a=>a.body),triangleCount:e.triangleCount,kind:e.kind,dispose:()=>{if(o)return;o=!0;let a=new Set(r.map(n=>n.body));for(let n of[...this.constraints])(a.has(n.bodyA)||a.has(n.bodyB))&&n.dispose();if(this.gpu&&!this.disposed){let n=r.map(c=>c.body.gpuIndex),l=new Uint32Array(n.length);this.gpu.setFilters(n,l,l)}for(let n of r)n.disposed=n.body.disposed=!0,n.group=n.collidesWith=0,this.commands.delete(n.body);this.wakeAll()}}}addConstraint(e,t,i={}){return new Pr(this,e,t,i)}addJoint(e,t,i={}){return this.addConstraint(e,t,{...i,type:i.type??"ball"})}addWeld(e,t,i={}){return this.addConstraint(e,t,{...i,type:"fixed"})}addSpring(e,t,i={}){return this.addConstraint(e,t,{...i,type:"spring"})}enableSleeping(e={}){return this.assertAlive(),this.sleepOptions=e,this.gpu&&!this.sleepManager&&(this.sleepManager=new Fi(this,e)),this}disableSleeping(){return this.assertAlive(),this.sleepOptions=!1,this.gpu?(this.flushCommands(),this.sleepManager&&(this.sleepManager.wakeRequested=!0,this.sleepManager.before(),this.sleepManager.dispose(),this.sleepManager=null),this):this}addMotor(e,t,i={}){return this.addConstraint(e,t,{...i,type:"motor"})}addHinge(e,t,i={}){return new Lr(this,e,t,i)}initializeContacts(){if(this.contactWatch)return;let{maxContactPairs:e,maxContactEvents:t}=this.contactOptions;this.contactWatch=new xi(this.device,this.gpu.bodyBuffer,this.capacity,e,t);let i=this.aggregates.filter(r=>!r.disposed);this.contactWatch.setWatched(i.map(r=>r.body.gpuIndex),i.map(()=>!0))}onContact(e){if(this.assertAlive(),typeof e!="function")throw Error("A contact callback is required");return this.contactListeners.add(e),this.gpu&&this.initializeContacts(),()=>this.contactListeners.delete(e)}async readContactEvents(){return this.initialize(),this.initializeContacts(),this.contactPending?this.contactPending:(this.contactPending=this.contactWatch.read().then(e=>({...e,events:e.events.map(t=>({...t,type:t.kind===Ai?"begin":"end",isTrigger:!!(this.byGpuIndex.get(t.a)?.aggregate.isTrigger||this.byGpuIndex.get(t.b)?.aggregate.isTrigger),a:this.byGpuIndex.get(t.a),b:this.byGpuIndex.get(t.b)}))})).finally(()=>this.contactPending=null),this.contactPending)}async raycast(e,t,i={}){let[r]=await this.raycastAll([{origin:e,direction:t,maxDistance:i.maxDistance}],i);return r}async sphereCast(e,t,i,r={}){let[o]=await this.sphereCastAll([{origin:e,radius:t,direction:i,maxDistance:r.maxDistance}],r);return o}async sphereCastAll(e,{ignore:t=[],collidesWith:i=4294967295,includeTriggers:r=!0}={}){this.assertAlive(),Ir(i),this.initialize(),this.flushCommands();for(let a of t)if(a.aggregate.world!==this||a.disposed)throw Error("Ignored cast bodies must belong to this world and be alive");return(await this.gpu.sphereCastAll(e.map(a=>({...a,origin:Le(a.origin),direction:Le(a.direction)})),{ignore:t.map(a=>a.gpuIndex),collidesWith:i,includeTriggers:r})).map(a=>a?{...a,body:this.byGpuIndex.get(a.index)??null}:null)}async raycastAll(e,{ignore:t=[],collidesWith:i=4294967295,includeTriggers:r=!0}={}){Ir(i),this.initialize(),this.flushCommands();let o=e.map(n=>{let l=Le(n.origin),c=Le(n.direction);if(l.length!==3||c.length!==3||![...l,...c].every(Number.isFinite)||!Math.hypot(...c))throw Error("A ray requires a finite origin and nonzero direction");return n.maxDistance!==void 0&&xo(n.maxDistance,"maxDistance",!0),{...n,origin:l,direction:c}});for(let n of t)if(n.aggregate.world!==this)throw Error("Ignored ray bodies must belong to this world");return(await this.gpu.raycastAll(o,{ignore:t.map(n=>n.gpuIndex),collidesWith:i,includeTriggers:r})).map(n=>n?{...n,body:this.byGpuIndex.get(n.index)??null}:null)}getRenderBinding(e=this.device){if(this.initialize(),e!==this.device)throw Error("Direct GPU rendering must share the physics GPUDevice");return{device:e,buffer:this.bodyBuffer,stride:160,positionOffset:0,rotationOffset:16,sizeOffset:64,count:this.gpu.bodyCount}}wakeAll(){this.sleepManager&&(this.sleepManager.wakeRequested=!0)}async readSleepStats(){return this.initialize(),this.sleepManager?this.sleepManager.readStats():{sleeping:0,wakeRequested:!1}}assertAlive(){if(this.disposed)throw Error("AVBD world is disposed")}queue(e,t,i,r){this.assertAlive(),e.assertAlive();let o=Le(r);if(o.length!==(i==="rotation"?4:3)||!o.every(Number.isFinite))throw Error(`${i} requires ${i==="rotation"?4:3} finite components`);let a=this.commands.get(e);return a||this.commands.set(e,a={mask:0}),a.mask|=t,a[i]=o,this.wakeAll(),a}flushCommands(e){if(this.initialize(),this.gpu.flushPropertyEdits(e),!this.commands.size)return;this.sleepManager?.wakeRequested&&this.sleepManager.before(e);let t=this.commands.size,i=0;for(let p of this.commands.values())i|=p.mask;if(i===1||i===2){if(!this.velocityIndices||this.velocityIndices.length<t){let y=Math.max(t,(this.velocityIndices?.length??0)*2,64);this.velocityIndices=new Uint32Array(y),this.velocityValues=new Float32Array(y*3)}let p=0;for(let[y,A]of this.commands)this.velocityIndices[p]=y.aggregate.gpuSlot??this.gpu.gpuIndex(y.aggregate.index),this.velocityValues.set(i===2?A.angular:A.velocity,p++*3);let g=i===2?"angularVelocityBatch":"velocityBatch",b=this[g]??=new Kt(this.gpu,3,i===2?"angular":"linear");b.solver=this.gpu,b.submitValidated(this.velocityIndices.subarray(0,t),this.velocityValues.subarray(0,t*3),e),this.lastCommandBatch={bodies:t,path:i===2?"packed-angular-velocities":"packed-velocities",uploadedBytes:t*16},this.commands.clear();return}let r=!0;for(let p of this.commands.values())if((p.mask&-4)!==0){r=!1;break}if(r){(!this.motionData||this.motionData.length<t*8)&&(this.motionData=new Uint32Array(Math.max(t*8,(this.motionData?.length??0)*2,512)),this.motionFloats=new Float32Array(this.motionData.buffer));let p=0;for(let[g,b]of this.commands){let y=p++*8;this.motionData[y]=g.aggregate.gpuSlot??this.gpu.gpuIndex(g.aggregate.index),this.motionData[y+1]=b.mask,b.velocity&&this.motionFloats.set(b.velocity,y+2),b.angular&&this.motionFloats.set(b.angular,y+5)}this.motionBatch??=new yi(this.gpu,3),this.motionBatch.submitValidated(this.motionData.subarray(0,t*8),e),this.lastCommandBatch={bodies:t,path:"packed-motion",uploadedBytes:t*32},this.commands.clear();return}let o=t*128,a=Math.min(this.device.limits.maxStorageBufferBindingSize,this.device.limits.maxBufferSize);if(o>a)throw Error("Body command batch exceeds GPU buffer limits");(!this.commandData||this.commandData.byteLength<o)&&(this.commandData=new ArrayBuffer(Math.min(a,Math.max(o,(this.commandData?.byteLength??0)*2,128))));let n=this.commandData,l=new Float32Array(n),c=new Uint32Array(n);l.fill(0,0,t*32);let u=0;for(let[p,g]of this.commands){let b=u++*32;c[b]=p.aggregate.gpuSlot??this.gpu.gpuIndex(p.aggregate.index),c[b+1]=g.mask;for(let[y,A]of[["velocity",4],["angular",8],["impulse",12],["torque",16],["position",20],["rotation",24],["pointImpulse",28]])g[y]&&l.set(g[y],b+A)}this.commands.clear(),(!this.commandBuffer||this.commandBuffer.size<o)&&(this.commandBuffer?.destroy(),this.commandBuffer=this.device.createBuffer({size:Math.min(a,Math.max(o*2,128)),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),this.device.queue.writeBuffer(this.commandBuffer,0,n,0,o),this.commandPipeline??=this.device.createComputePipeline({layout:"auto",compute:{module:this.device.createShaderModule({code:`const DISPATCH_STRIDE = ${this.device.limits.maxComputeWorkgroupsPerDimension*64}u;
3949
+ ${xc}`,label:"AVBD body commands"}),entryPoint:"applyCommands"}}),(!this.commandBinding||this.boundCommandBody!==this.gpu.bodyBuffer||this.boundCommandBuffer!==this.commandBuffer||this.boundCommandBytes!==o)&&(this.commandBinding=this.device.createBindGroup({layout:this.commandPipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:this.gpu.bodyBuffer}},{binding:1,resource:{buffer:this.commandBuffer,size:o}}]}),this.boundCommandBody=this.gpu.bodyBuffer,this.boundCommandBuffer=this.commandBuffer,this.boundCommandBytes=o);let f=e??this.device.createCommandEncoder(),d=f.beginComputePass();d.setPipeline(this.commandPipeline),d.setBindGroup(0,this.commandBinding);let h=Math.ceil(u/64),m=this.device.limits.maxComputeWorkgroupsPerDimension;d.dispatchWorkgroups(Math.min(h,m),Math.ceil(h/m)),d.end(),e||this.device.queue.submit([f.finish()]),this.lastCommandBatch={bodies:t,path:"aggregate-commands",uploadedBytes:o}}step(){this.initialize(),this.gpu.step(),this.steps++,this.contactWatch&&(this.contactWatch.run(this.gpu.contactStorage,this.gpu.manifoldCapacity,this.steps,this.ref.dt),this.contactListeners.size&&!this.contactPending&&this.readContactEvents().then(({events:e,dropped:t,full:i})=>{if(!this.disposed){(t||i)&&this.errors.push(`Contact event storage full: ${t} events dropped; increase maxContactEvents/maxContactPairs`);for(let r of e)for(let o of this.contactListeners)o(r)}}).catch(e=>{this.disposed||this.errors.push(e.message)})),this.syncEnabled&&!this.syncPending&&this.syncMeshes().catch(e=>this.errors.push(e.message)),this.steps%20===0&&!this.counterPending&&(this.counterPending=!0,this.gpu.readCounters().then(e=>{this.disposed||(this.counters=e,this.gpu.adapt(e),(e.overflow||e.clashes)&&this.errors.push(`Collision capacity/color conflict: ${JSON.stringify(e)}`))}).catch(e=>{this.disposed||this.errors.push(e.message)}).finally(()=>this.counterPending=!1))}async syncMeshes(){if(this.initialize(),this.flushCommands(),this.syncPending)return this.syncPending;let e=this.aggregates.filter(t=>t.sync&&!t.disposed);return this.syncPending=this.bodyReadback.read(this.bodyBuffer,e.map(t=>t.body.gpuIndex),!0).then(t=>{if(!this.disposed){for(let i=0;i<e.length;i++)e[i].disposed||e[i].syncPose(t,i*8);this.lastSyncBytes=t.byteLength}}).finally(()=>this.syncPending=null),this.syncPending}get bodyBuffer(){return this.initialize(),this.gpu.bodyBuffer}async readBodies(e){if(this.initialize(),this.flushCommands(),e){for(let t of e)if(t.aggregate.world!==this)throw Error("Selected bodies must belong to this world");return this.bodyReadback.read(this.bodyBuffer,e.map(t=>t.gpuIndex))}return this.gpu.readBodies()}dispose(){if(!this.disposed){this.disposed=!0,this.observer&&this.scene?.onBeforeRenderObservable.remove(this.observer),this.disposeObserver&&this.scene?.onDisposeObservable.remove(this.disposeObserver),this.scene&&ps.get(this.scene)===this&&ps.delete(this.scene),this.device.removeEventListener("uncapturederror",this.errorListener),this.gpu?.destroy(),this.contactWatch?.destroy(),this.sleepManager?.dispose(),this.commandBuffer?.destroy(),this.velocityBatch?.destroy(),this.angularVelocityBatch?.destroy(),this.motionBatch?.destroy(),this.bodyReadback.destroy(),this.commandData=this.velocityIndices=this.velocityValues=null,this.commandBinding=null;for(let e of this.aggregates)e.disposed=!0,e.body.disposed=!0;this.commands.clear(),this.contactListeners.clear();for(let e of this.constraints)e.disposed=!0;this.constraints.clear(),this.ownsDevice&&this.device.destroy()}}attachToScene(e=this.scene){if(this.assertAlive(),!e)throw Error("A Babylon scene is required");if(this.observer&&e===this.scene)return this;if(this.observer)throw Error("AVBD world is already attached to another scene");this.scene=e,this.disposeObserver=e.onDisposeObservable.addOnce(()=>this.dispose());let t=0;return this.observer=e.onBeforeRenderObservable.add(()=>{t+=Math.min(.05,e.getEngine().getDeltaTime()/1e3);for(let i=0;t>=this.ref.dt&&i<3;i++)this.step(),t-=this.ref.dt}),this}},ms=class{constructor(e,t,{mass:i=1,friction:r=.6,restitution:o=0,allowSleep:a,isTrigger:n=!1,sync:l=!0,group:c=4294967295,collidesWith:u=4294967295}={},f){if(f=f instanceof hs?f:ps.get(f??e.getScene()),!f)throw Error("Create an AVBD world for this scene before adding aggregates");if(f.assertAlive(),typeof t=="number"&&(t=[rt.SPHERE,rt.CAPSULE,rt.CYLINDER,rt.BOX,rt.CONVEX_HULL][t]),xo(i,"mass",!0),xo(r,"friction",!0),!Number.isFinite(o)||o<0||o>1)throw Error("restitution must be between 0 and 1");if(e.parent)throw Error("AVBD aggregate meshes must have no parent; bake the parent transform first");if(!Object.values(rt).includes(t))throw Error(`Unsupported AVBD shape: ${t}`);if(f.aggregates.length>=f.capacity)throw Error("AVBD body capacity exceeded");if(this.world=f,this.mesh=e,this.sync=l,this.type=t,a!==void 0&&typeof a!="boolean")throw Error("allowSleep must be a boolean");if(this.allowSleep=a??!0,typeof n!="boolean")throw Error("isTrigger must be a boolean");if(this.isTrigger=n,this.restitution=o,a===!0&&!f.sleepOptions&&f.enableSleeping(),this.group=Ir(c),this.collidesWith=Ir(u),f.gpu&&f.syncEnabled&&l&&f.aggregates.filter(v=>v.sync&&!v.disposed).length>=f.maxSyncedBodies)throw Error("For large scenes use syncMeshes:false and draw the GPU body buffer directly");if(![rt.BOX,rt.SPHERE,rt.CAPSULE].includes(t)&&f.device.limits.maxStorageBuffersPerShaderStage<9)throw Error("Convex hull collisions require nine storage buffer bindings");e.computeWorldMatrix(!0),e.refreshBoundingInfo();let d=e.getBoundingInfo().boundingBox,h=e.scaling;if([h.x,h.y,h.z].some(v=>v<=0))throw Error("Bake negative or zero mesh scaling before creating an aggregate");let m=d.maximum.subtract(d.minimum).multiply(h),p=d.center.multiply(h),g=e.rotationQuaternion?.clone()||e.rotation.toQuaternion();this.localCenter=p,this.localRotation=g.constructor.Identity();let b;if(t===rt.BOX)b=new Ze(f.ref,Le(m),1,r,[0,0,0]);else if(t===rt.SPHERE){if(Math.max(m.x,m.y,m.z)-Math.min(m.x,m.y,m.z)>1e-4)throw Error("Sphere aggregate requires uniform dimensions");b=nr(f.ref,m.x/2,1,r,[0,0,0])}else if(t===rt.CAPSULE){if(Math.abs(m.x-m.z)>1e-4)throw Error("Capsule aggregate requires equal X and Z diameters; bake an upright Y-axis capsule mesh");b=Cr(f.ref,m.x/2,m.y,1,r,[0,0,0])}else{let v=e.getVerticesData("position");if(!v)throw Error("Hull aggregate requires mesh positions");let x=Float32Array.from(v,(B,L)=>B*[h.x,h.y,h.z][L%3]),w=Xr(x);if(!w)throw Error("Hull aggregate requires a closed shape with nonzero volume");this.localCenter=new e.position.constructor(...w.center),this.localRotation=g.constructor.FromArray(w.rotation),b=lr(f.ref,w,1,r,[0,0,0])}let y=i/b.mass;b.mass=i,b.moment.forEach((v,x)=>b.moment[x]=v*y);let A=e.position.add(this.localCenter.applyRotationQuaternion(g));if(b.positionLin.set(Le(A)),b.positionAng.set(g.multiply(this.localRotation).asArray()),this.rigid=b,this.index=f.aggregates.length,this.body=new Rr(this),f.aggregates.push(this),e.rotationQuaternion=g,f.gpu){if(this.gpuSlot=f.gpu.addBody(b),this.gpuSlot<0)throw Error("AVBD body capacity exceeded");f.byGpuIndex.set(this.gpuSlot,this.body),f.gpu.setFilters([this.gpuSlot],[this.group],[this.collidesWith]),(this.isTrigger||f.gpu.sensorsEnabled)&&f.gpu.setSensor(this.gpuSlot,this.isTrigger),this.restitution>0&&f.gpu.setRestitution(this.gpuSlot,this.restitution),f.contactWatch?.setWatched([this.gpuSlot],[!0]),f.sleepManager?.register(this.gpuSlot,b.mass,this.allowSleep),f.wakeAll?.()}}syncPose(e,t){let i=t??this.body.gpuIndex*40,r=this.localRotation.constructor.FromArray(e,i+4).multiply(this.localRotation.conjugate());this.mesh.rotationQuaternion.copyFrom(r),this.mesh.position.copyFrom(new this.mesh.position.constructor(...e.subarray(i,i+3)).subtract(this.localCenter.applyRotationQuaternion(r)))}dispose(){Sc(this)}},Pn=class{constructor(e,t){Object.assign(this,{world:e,rigid:t,index:e.aggregates.length,sync:!1,allowSleep:!1,isTrigger:!1,restitution:t.restitution,group:t.group,collidesWith:t.collidesWith,staticTerrain:!0}),this.body=new Rr(this),e.aggregates.push(this)}dispose(){Sc(this)}};function Sc(s){if(s.disposed)return;let e=s.world;for(let t of[...e.constraints])(t.bodyA===s.body||t.bodyB===s.body)&&t.dispose();if(e.gpu){let t=s.body.gpuIndex;e.queue(s.body,16,"velocity",[0,0,0]),e.gpu.setFilters([t],[0],[0]),e.gpu.setRestitution(t,0)}s.rigid.mass=0,s.rigid.moment.fill(0),s.sync=!1,s.disposed=s.body.disposed=!0,e.sleepManager?.register(s.gpuSlot??e.gpu?.gpuIndex(s.index)??s.index,0),e.wakeAll?.()}var Rr=class{constructor(e){this.aggregate=e}assertAlive(){if(this.disposed||this.aggregate.disposed)throw Error("AVBD body is disposed")}get gpuIndex(){this.assertAlive();let e=this.aggregate.world;return e.initialize(),this.aggregate.gpuSlot??e.gpu.gpuIndex(this.aggregate.index)}setLinearVelocity(e){return this.aggregate.world.queue(this,1,"velocity",e),this}setAngularVelocity(e){return this.aggregate.world.queue(this,2,"angular",e),this}applyImpulse(e,t){let i=t?Le(t):null;if(i&&(i.length!==3||!i.every(Number.isFinite)))throw Error("Impulse point requires three finite components");let r=this.aggregate.world,o=Le(e),a=r.commands.get(this),n=o.map((c,u)=>c+(a?.impulse?.[u]||0)),l=r.queue(this,4,"impulse",n);if(t){let c=[i[1]*o[2]-i[2]*o[1],i[2]*o[0]-i[0]*o[2],i[0]*o[1]-i[1]*o[0]],u=l.torque||[0,0,0];l.torque=Le(c).map((f,d)=>f+u[d]),l.pointImpulse=o.map((f,d)=>f+(l.pointImpulse?.[d]||0))}return this}applyAngularImpulse(e){let t=this.aggregate.world,i=t.commands.get(this)?.torque||[0,0,0];return t.queue(this,4,"torque",Le(e).map((r,o)=>r+i[o])),this}applyForce(e,t){return this.applyImpulse(Le(e).map(i=>i*this.aggregate.world.ref.dt),t)}applyTorque(e){return this.applyAngularImpulse(Le(e).map(t=>t*this.aggregate.world.ref.dt))}setCollisionGroups(e,t=4294967295){this.assertAlive();let i=this.aggregate,r=Ir(e),o=Ir(t);return i.group=r,i.collidesWith=o,i.world.gpu&&i.world.gpu.setFilters([this.gpuIndex],[i.group],[i.collidesWith]),i.world.wakeAll?.(),this}setTrigger(e){if(this.assertAlive(),typeof e!="boolean")throw Error("isTrigger must be a boolean");let t=this.aggregate;return t.isTrigger=e,t.world.gpu&&t.world.gpu.setSensor(this.gpuIndex,e),t.world.wakeAll(),this}setRestitution(e){if(this.assertAlive(),!Number.isFinite(e)||e<0||e>1)throw Error("restitution must be between 0 and 1");let t=this.aggregate;return t.restitution=e,t.world.gpu&&t.world.gpu.setRestitution(this.gpuIndex,e),t.world.wakeAll(),this}async readState(){let e=await this.aggregate.world.readBodies([this]),t=this.aggregate.rigid.mass;return{position:Array.from(e.subarray(0,3)),rotation:Array.from(e.subarray(4,8)),linearVelocity:Array.from(e.subarray(32,35)),angularVelocity:Array.from(e.subarray(36,39)),mass:t,effectiveMass:e[19],sleeping:t>0&&e[19]===0}}wakeUp(){return this.assertAlive(),this.aggregate.world.wakeAll(),this}setSleepEnabled(e){if(this.assertAlive(),typeof e!="boolean")throw Error("Sleep eligibility must be a boolean");let t=this.aggregate,i=t.world;return t.allowSleep=e,e&&!i.sleepOptions&&i.enableSleeping(),i.gpu&&i.sleepManager?.register(this.gpuIndex,t.rigid.mass,e),i.wakeAll(),this}teleport(e,t){if(this.assertAlive(),this.aggregate.staticTerrain)throw Error("Terrain is static; set its geometry transform before registration");let i=this.aggregate;if(t===void 0){let a=i.world.commands.get(this);if(a&&(a.mask&8)!==0&&(a.mask&32)===0){let n=i.mesh.rotationQuaternion.clone();n.copyFromFloats(...a.rotation);let l=i.localCenter.applyRotationQuaternion(i.localRotation.conjugate());i.world.queue(this,8,"position",Le(e.add(l.applyRotationQuaternion(n))))}else{let n=i.localCenter.applyRotationQuaternion(i.localRotation.conjugate());i.world.queue(this,40,"position",Le(e)),i.world.queue(this,40,"rotation",[...Le(n),0])}return this}let r=t.clone().normalize();i.world.queue(this,8,"position",Le(e.add(i.localCenter.applyRotationQuaternion(r))));let o=i.world.queue(this,8,"rotation",r.multiply(i.localRotation).asArray());return o.mask&=-33,this}};var qi=class{solver;bodyA;bodyB;J=new Float64Array(12);H=new Float64Array(36);C=new Float64Array(4);fmin=new Float64Array(4).fill(-1/0);fmax=new Float64Array(4).fill(1/0);stiffness=new Float64Array(4).fill(1/0);fracture=new Float64Array(4).fill(1/0);penalty=new Float64Array(4);lambda=new Float64Array(4);constructor(e,t,i){this.solver=e,this.bodyA=t,this.bodyB=i,e.forces.push(this),t?.forces.push(this),i.forces.push(this)}destroy(){let e=this.solver.forces,t=e.indexOf(this);t>=0&&e.splice(t,1),this.unlinkFromBodies()}unlinkFromBodies(){for(let e of[this.bodyA,this.bodyB]){if(!e)continue;let t=e.forces.indexOf(this);t>=0&&e.forces.splice(t,1)}}disable(){this.stiffness.fill(0),this.penalty.fill(0),this.lambda.fill(0)}};var kc=s=>s<0?-1:s>0?1:0,Or=(s,e)=>s<e?s:e,Yf=(s,e)=>s>e?s:e,Tr=(s,e,t)=>Yf(e,Or(t,s));function gs(s,e,t){let i=Math.cos(s),r=Math.sin(s);return[i*e-r*t,r*e+i*t]}function Vi(s,e,t){let i=Math.cos(s[2]),r=Math.sin(s[2]);return[i*e-r*t+s[0],r*e+i*t+s[1]]}function Zt(s,e,t,i,r){s[e*3]=t,s[e*3+1]=i,s[e*3+2]=r}var Ao=class extends qi{rA;rB;C0=new Float64Array(3);torqueArm;restAngle;constructor(e,t,i,r,o,a=[1/0,1/0,1/0],n=1/0){super(e,t,i),this.rA=[r[0],r[1]],this.rB=[o[0],o[1]],this.stiffness[0]=a[0],this.stiffness[1]=a[1],this.stiffness[2]=a[2],this.fmax[2]=n,this.fmin[2]=-n,this.fracture[2]=n,this.restAngle=(t?t.position[2]:0)-i.position[2];let l=(t?t.size[0]:0)+i.size[0],c=(t?t.size[1]:0)+i.size[1];this.torqueArm=l*l+c*c}rows(){return 3}evaluate(e){let t=this.bodyA?Vi(this.bodyA.position,this.rA[0],this.rA[1]):this.rA,i=Vi(this.bodyB.position,this.rB[0],this.rB[1]);e[0]=t[0]-i[0],e[1]=t[1]-i[1],e[2]=((this.bodyA?this.bodyA.position[2]:0)-this.bodyB.position[2]-this.restAngle)*this.torqueArm}initialize(){return this.evaluate(this.C0),this.stiffness[0]!==0||this.stiffness[1]!==0||this.stiffness[2]!==0}Cn=new Float64Array(3);computeConstraint(e){this.evaluate(this.Cn);for(let t=0;t<3;t++)this.C[t]=this.stiffness[t]===1/0?this.Cn[t]-this.C0[t]*e:this.Cn[t]}computeDerivatives(e){let{J:t,H:i}=this;if(i.fill(0,0,27),e===this.bodyA){let r=gs(e.position[2],this.rA[0],this.rA[1]);Zt(t,0,1,0,-r[1]),Zt(t,1,0,1,r[0]),Zt(t,2,0,0,this.torqueArm),i[8]=-r[0],i[17]=-r[1]}else{let r=gs(e.position[2],this.rB[0],this.rB[1]);Zt(t,0,-1,0,r[1]),Zt(t,1,0,-1,-r[0]),Zt(t,2,0,0,-this.torqueArm),i[8]=r[0],i[17]=r[1]}}},wo=class extends qi{rA;rB;rest;constructor(e,t,i,r,o,a,n=-1){if(super(e,t,i),this.rA=[r[0],r[1]],this.rB=[o[0],o[1]],this.stiffness[0]=a,this.rest=n,this.rest<0){let l=Vi(t.position,r[0],r[1]),c=Vi(i.position,o[0],o[1]);this.rest=Math.hypot(l[0]-c[0],l[1]-c[1])}}rows(){return 1}initialize(){return!0}delta(){let e=Vi(this.bodyA.position,this.rA[0],this.rA[1]),t=Vi(this.bodyB.position,this.rB[0],this.rB[1]);return[e[0]-t[0],e[1]-t[1]]}computeConstraint(){let e=this.delta();this.C[0]=Math.hypot(e[0],e[1])-this.rest}computeDerivatives(e){let t=this.delta(),i=t[0]*t[0]+t[1]*t[1];if(i===0)return;let r=Math.sqrt(i),o=t[0]/r,a=t[1]/r,n=(1-o*o)/r,l=(0-o*a)/r,c=(0-a*o)/r,u=(1-a*a)/r,f=e===this.bodyA,d=f?this.rA:this.rB,h=gs(e.position[2],-d[1],d[0]),m=gs(e.position[2],d[0],d[1]),p=n*h[0]+l*h[1],g=c*h[0]+u*h[1],b=o*m[0]+a*m[1],y=o*h[0]+a*h[1];f?Zt(this.J,0,o,a,y):Zt(this.J,0,-o,-a,-y);let A=f?-b-b:b+b,v=this.H;v[0]=n,v[1]=l,v[2]=p,v[3]=c,v[4]=u,v[5]=g,v[6]=p,v[7]=g,v[8]=A}},Bo=class extends qi{rows(){return 0}initialize(){return!0}computeConstraint(){}computeDerivatives(){}},Co=class extends qi{speed;constructor(e,t,i,r,o){super(e,t,i),this.speed=r,this.fmax[0]=o,this.fmin[0]=-o}rows(){return 1}initialize(){return!0}computeConstraint(){let e=this.bodyA?this.bodyA.position[2]-this.bodyA.initial[2]:0,t=this.bodyB.position[2]-this.bodyB.initial[2];this.C[0]=e-t-this.speed*this.solver.dt}computeDerivatives(e){Zt(this.J,0,0,0,e===this.bodyA?1:-1),this.H.fill(0,0,9)}};var So=()=>({dt:1/60,gravity:-10,iterations:10,beta:1e5,alpha:.99,gamma:.99,postStabilize:!0,stiffnessRescale:!1,vbd:!1,vbdStiffness:1e6,matchNearest:!1}),ko=()=>({...So(),postStabilize:!1,alpha:.95,matchNearest:!0});var jr=(s,e)=>s>e?s*2097152+e:e*2097152+s;function Qf(s,e,t){let i=0,r=e;for(;i<r;){let o=i+r>>>1;s[o]<t?i=o+1:r=o}return i}function Ln(s,e,t){let i=Qf(s,e,t);return i<e&&s[i]===t}var Po=class{cellSize=1;pairs=new Float64Array(1024);pairCount=0;configuredFor=-1;large=new Int32Array(0);isLarge=new Uint8Array(0);cellX=new Int32Array(0);cellY=new Int32Array(0);tableSize=0;bucketStart=new Int32Array(0);sorted=new Int32Array(0);configure(e,t){this.configuredFor=e;let i=Float64Array.from({length:e},(n,l)=>t[l*4+1]).sort(),r=e>0?i[e>>1]:1,o=0;for(let n=0;n<e;n++)i[n]<=4*r&&(o=Math.max(o,i[n]));this.cellSize=Math.max(2*o,.001),this.isLarge=new Uint8Array(e);let a=[];for(let n=0;n<e;n++)t[n*4+1]>o&&(this.isLarge[n]=1,a.push(n));for(this.large=Int32Array.from(a),this.cellX=new Int32Array(e),this.cellY=new Int32Array(e),this.tableSize=1;this.tableSize<2*e;)this.tableSize<<=1;this.bucketStart=new Int32Array(this.tableSize+1),this.sorted=new Int32Array(e)}hash(e,t){return(Math.imul(e,73856093)^Math.imul(t,19349663))&this.tableSize-1}findPairs(e,t,i,r,o,a){e!==this.configuredFor&&this.configure(e,i),this.pairCount=0;let{cellX:n,cellY:l,isLarge:c,bucketStart:u,sorted:f}=this,d=1/this.cellSize;u.fill(0);for(let p=0;p<e;p++)c[p]||(n[p]=Math.floor(t[p*4]*d),l[p]=Math.floor(t[p*4+1]*d),u[this.hash(n[p],l[p])+1]++);for(let p=0;p<this.tableSize;p++)u[p+1]+=u[p];let h=u.slice(0,this.tableSize);for(let p=0;p<e;p++)c[p]||(f[h[this.hash(n[p],l[p])]++]=p);let m=(p,g)=>{if(!r[p]&&!r[g])return;let b=t[p*4]-t[g*4],y=t[p*4+1]-t[g*4+1],A=i[p*4+1]+i[g*4+1];if(b*b+y*y>A*A)return;let v=jr(p,g);if(!Ln(o,a,v)){if(this.pairCount===this.pairs.length){let x=new Float64Array(this.pairs.length*2);x.set(this.pairs),this.pairs=x}this.pairs[this.pairCount++]=v}};for(let p=0;p<e;p++){if(c[p])continue;let g=n[p],b=l[p];for(let y=-1;y<=1;y++)for(let A=-1;A<=1;A++){let v=this.hash(g+A,b+y);for(let x=u[v];x<u[v+1];x++){let w=f[x];w>=p||n[w]!==g+A||l[w]!==b+y||m(p,w)}}}for(let p of this.large)for(let g=0;g<e;g++)g===p||c[g]&&g>p||m(p,g);this.pairs.subarray(0,this.pairCount).sort()}};var gt=new Float64Array(12),Pc=new Float64Array(12),Wi=new Float64Array(12);function qt(s,e,t,i,r,o,a,n){let l=e*6;s[l]=t,s[l+1]=i,s[l+2]=r,s[l+3]=o,s[l+4]=a,s[l+5]=n}function Lc(s,e,t,i,r,o){let a=0,n=t*e[0]+i*e[1]-r,l=t*e[6]+i*e[7]-r;if(n<=0){for(let c=0;c<6;c++)s[a*6+c]=e[c];a++}if(l<=0){for(let c=0;c<6;c++)s[a*6+c]=e[6+c];a++}if(n*l<0){let c=n/(n-l),u=e[0]+(e[6]-e[0])*c,f=e[1]+(e[7]-e[1])*c;n>0?qt(s,a,u,f,o,e[3],0,e[5]):qt(s,a,u,f,e[8],o,e[10],0),a++}return a}function Lo(s,e,t,i,r,o,a,n){let l=-(r*a+o*n),c=-(-o*a+r*n);Math.abs(l)>Math.abs(c)?l>0?(qt(gt,0,s,-e,0,0,3,4),qt(gt,1,s,e,0,0,4,1)):(qt(gt,0,-s,e,0,0,1,2),qt(gt,1,-s,-e,0,0,2,3)):c>0?(qt(gt,0,s,e,0,0,4,1),qt(gt,1,-s,e,0,0,1,2)):(qt(gt,0,-s,-e,0,0,2,3),qt(gt,1,s,-e,0,0,3,4));for(let u=0;u<2;u++){let f=u*6,d=gt[f],h=gt[f+1];gt[f]=t+r*d-o*h,gt[f+1]=i+o*d+r*h}}function _o(s,e,t,i,r,o,a,n,l,c,u){let f=Math.cos(t),d=Math.sin(t),h=Math.cos(n),m=Math.sin(n),p=o-s,g=a-e,b=f*p+d*g,y=-d*p+f*g,A=h*p+m*g,v=-m*p+h*g,x=Math.abs(f*h+d*m),w=Math.abs(f*-m+d*h),B=Math.abs(-d*h+f*m),L=Math.abs(-d*-m+f*h),M=Math.abs(b)-i-(x*l+w*c),I=Math.abs(y)-r-(B*l+L*c);if(M>0||I>0)return 0;let E=Math.abs(A)-(x*i+B*r)-l,k=Math.abs(v)-(w*i+L*r)-c;if(E>0||k>0)return 0;let P=0,C=M,_=b>0?f:-f,z=b>0?d:-d;I>.95*C+.01*r&&(P=1,C=I,_=y>0?-d:d,z=y>0?f:-f),E>.95*C+.01*l&&(P=2,C=E,_=A>0?h:-h,z=A>0?m:-m),k>.95*C+.01*c&&(P=3,C=k,_=v>0?-m:m,z=v>0?h:-h);let R,G,X,W,U,H,Z,pe,we;if(P===0){R=_,G=z,X=s*R+e*G+i,W=-d,U=f;let $=s*W+e*U;H=-$+r,Z=$+r,pe=3,we=1,Lo(l,c,o,a,h,m,R,G)}else if(P===1){R=_,G=z,X=s*R+e*G+r,W=f,U=d;let $=s*W+e*U;H=-$+i,Z=$+i,pe=2,we=4,Lo(l,c,o,a,h,m,R,G)}else if(P===2){R=-_,G=-z,X=o*R+a*G+l,W=-m,U=h;let $=o*W+a*U;H=-$+c,Z=$+c,pe=3,we=1,Lo(i,r,s,e,f,d,R,G)}else{R=-_,G=-z,X=o*R+a*G+c,W=h,U=m;let $=o*W+a*U;H=-$+l,Z=$+l,pe=2,we=4,Lo(i,r,s,e,f,d,R,G)}if(Lc(Pc,gt,-W,-U,H,pe)<2||Lc(Wi,Pc,W,U,Z,we)<2)return 0;let Oe=0;for(let $=0;$<2;$++){let Je=$*6,Xe=Wi[Je],Be=Wi[Je+1],at=R*Xe+G*Be-X;if(at>0)continue;let ri=Xe-R*at,Ye=Be-G*at,nt=Wi[Je+2],Qe=Wi[Je+3],lt=Wi[Je+4],wt=Wi[Je+5],Ki,Zi,er,tr;P>=2?([nt,Qe,lt,wt]=[lt,wt,nt,Qe],Ki=Xe-s,Zi=Be-e,er=ri-o,tr=Ye-a):(Ki=ri-s,Zi=Ye-e,er=Xe-o,tr=Be-a);let Wt=Oe*7;u[Wt+0]=nt&255|(Qe&255)<<8|(lt&255)<<16|(wt&255)<<24,u[Wt+1]=f*Ki+d*Zi,u[Wt+1+1]=-d*Ki+f*Zi,u[Wt+3]=h*er+m*tr,u[Wt+3+1]=-m*er+h*tr,u[Wt+5]=-_,u[Wt+5+1]=-z,Oe++}return Oe}var _c=s=>31-Math.clz32(s&-s);function Kf(s){let e=s+2654435769;return e^=e>>>16,e=Math.imul(e,2146121005),e^=e>>>15,e=Math.imul(e,2221713035),e^=e>>>16,e>>>0}var _n=(s,e,t,i)=>s>t||s===t&&e>i,Eo=class{colors=new Int32Array(0);colorStart=new Int32Array(65);colorBodies=new Int32Array(0);next=new Int32Array(0);pending=new Uint8Array(0);prio=new Uint32Array(0);resize(e){if(this.colors.length===e)return;let t=new Int32Array(e).fill(-1);t.set(this.colors.subarray(0,Math.min(e,this.colors.length))),this.colors=t,this.next=new Int32Array(e),this.pending=new Uint8Array(e),this.colorBodies=new Int32Array(e),this.prio=Uint32Array.from({length:e},(i,r)=>Kf(r))}run(e,t,i,r,o,a){this.resize(e);let{colors:n,next:l,pending:c,prio:u}=this,f=(v,x)=>{let w=o[v*4+1],B=w===x?o[v*4+2]:w;return B>=0&&t[B]?B:-1},d=(v,x)=>{let w=0,B=0;for(let L=i[v];L<i[v+1];L++){let M=f(r[L],v);if(M<0||x&&c[M])continue;let I=n[M];I<0||(I<32?w|=1<<I:B|=1<<I-32)}return~w!==0?_c(~w):~B!==0?32+_c(~B):63};for(let v=0;v<e;v++){if(l[v]=n[v],!t[v]||n[v]<0)continue;let x=!0;for(let w=i[v];w<i[v+1]&&x;w++){let B=f(r[w],v);B>=0&&!_n(u[v],v,u[B],B)&&(x=!1)}x&&(l[v]=Math.min(n[v],d(v,!1)))}n.set(l);let h=()=>{let v=0;for(let x=0;x<e;x++)if(c[x]=0,!!t[x]){if(n[x]<0)c[x]=1;else for(let w=i[x];w<i[x+1];w++){let B=f(r[w],x);if(B>=0&&n[B]===n[x]&&_n(u[B],B,u[x],x)){c[x]=1;break}}v+=c[x]}return v},m=h(),p=0;for(;m>0&&p<a;){p++;for(let v=0;v<e;v++){if(l[v]=-2,!c[v])continue;let x=!0;for(let w=i[v];w<i[v+1]&&x;w++){let B=f(r[w],v);B>=0&&c[B]&&!_n(u[v],v,u[B],B)&&(x=!1)}x&&(l[v]=d(v,!0))}for(let v=0;v<e;v++)l[v]!==-2&&(n[v]=l[v],c[v]=0,m--)}let g=0;if(m>0){for(let v=0;v<e;v++)c[v]&&n[v]<0&&(n[v]=0);g=h()}let b=this.colorStart;b.fill(0);let y=0;for(let v=0;v<e;v++)t[v]&&(b[n[v]+1]++,y=Math.max(y,n[v]+1));for(let v=0;v<64;v++)b[v+1]+=b[v];let A=b.slice(0,64);for(let v=0;v<e;v++)t[v]&&(this.colorBodies[A[n[v]]++]=v);return{numColors:y,conflicts:g,rounds:p}}};var Ec=0,Bi=1,Mc=2,Ro=3,bs=4,zc=[0,3,1,1,2],Mn=.05,j=4,O=32,se=0,te=3,Q=6,_e=9,Ae=12,Pt=15,fe=18,N=21,Y=23,re=25,be=26,Ne=27,Hi=28,Dr=class{params=So();options;bodyCount=0;pose;initial;inertial;velocity;prevVelocity;shape;props;dynamic=new Uint8Array(0);jointCount=0;contactCount=0;info=new Int32Array(0);data;handles=[];prevCount=0;prevKeys=new Float64Array(0);prevInfo=new Int32Array(0);prevData=new Float64Array(0);ignorePairs=[];noCollide=new Float64Array(0);noCollideCount=0;noCollideDirty=!0;adjStart=new Int32Array(1);adjList=new Int32Array(0);broadphase=new Po;coloring=new Eo;numColors=0;colorConflicts=0;colorRounds=0;profiling=!1;profile={};phaseStart=0;contactOut=new Float64Array(14);dxBuf=new Float64Array(0);constructor(e={}){this.options={precision:"f32",order:"colored",colorRounds:32,...e},this.pose=this.real(0),this.initial=this.real(0),this.inertial=this.real(0),this.velocity=this.real(0),this.prevVelocity=this.real(0),this.shape=this.real(0),this.props=this.real(0),this.data=this.real(0)}real(e){return this.options.precision==="f32"?new Float32Array(e):new Float64Array(e)}grow(e,t){if(e.length>=t)return e;let i=new e.constructor(Math.max(t,e.length*2,16));return i.set(e),i}clear(){this.bodyCount=0,this.jointCount=0,this.contactCount=0,this.prevCount=0,this.handles=[],this.ignorePairs=[],this.noCollideDirty=!0,this.coloring.resize(0)}addBody(e,t,i,r,o=[0,0,0]){let a=this.bodyCount++,n=this.bodyCount*4;this.pose=this.grow(this.pose,n),this.initial=this.grow(this.initial,n),this.inertial=this.grow(this.inertial,n),this.velocity=this.grow(this.velocity,n),this.prevVelocity=this.grow(this.prevVelocity,n),this.shape=this.grow(this.shape,n),this.props=this.grow(this.props,n),this.dynamic=this.grow(this.dynamic,this.bodyCount);let l=e[0]*e[1]*t;return this.pose.set([r[0],r[1],r[2]??0,0],a*4),this.velocity.set([o[0],o[1],o[2]??0,0],a*4),this.prevVelocity.set(this.velocity.subarray(a*4,a*4+4),a*4),this.shape.set([e[0],e[1],l,l*(e[0]*e[0]+e[1]*e[1])/12],a*4),this.props.set([i,Math.hypot(e[0]*.5,e[1]*.5),0,0],a*4),this.dynamic[a]=l>0?1:0,a}allocConstraint(){let e=this.jointCount++,t=this.jointCount+this.contactCount;this.info=this.grow(this.info,t*j),this.data=this.grow(this.data,t*O),this.contactCount>0&&(this.info.copyWithin((e+1)*j,e*j,(t-1)*j),this.data.copyWithin((e+1)*O,e*O,(t-1)*O)),this.data.fill(0,e*O,e*O+O);for(let i=0;i<3;i++)this.data[e*O+Q+i]=1/0,this.data[e*O+_e+i]=-1/0,this.data[e*O+Ae+i]=1/0,this.data[e*O+Pt+i]=1/0;return this.handles[e]=null,this.noCollideDirty=!0,e}setInfo(e,t,i,r){this.info.set([t,i,r,0],e*j)}addJoint(e,t,i,r,o=[1/0,1/0,1/0],a=1/0){let n=this.allocConstraint();this.setInfo(n,Bi,e,t);let l=this.data,c=n*O;l.set(o,c+Q),l[c+Ae+2]=a,l[c+_e+2]=-a,l[c+Pt+2]=a,l.set(i,c+N),l.set(r,c+Y),l[c+re]=(e>=0?this.pose[e*4+2]:0)-this.pose[t*4+2];let u=(e>=0?this.shape[e*4]:0)+this.shape[t*4],f=(e>=0?this.shape[e*4+1]:0)+this.shape[t*4+1];l[c+be]=u*u+f*f;let d={slot:n,alive:!0};return this.handles[n]=d,d}setJointWorldAnchor(e,t,i){e.alive&&(this.data[e.slot*O+N]=t,this.data[e.slot*O+N+1]=i)}removeJoint(e){e.alive&&(this.disable(e.slot),e.alive=!1)}addSpring(e,t,i,r,o,a){let n=this.allocConstraint();this.setInfo(n,Mc,e,t);let l=n*O;this.data[l+Q]=o,this.data.set(i,l+N),this.data.set(r,l+Y),this.data[l+re]=a}addMotor(e,t,i,r){let o=this.allocConstraint();this.setInfo(o,Ro,e,t);let a=o*O;this.data[a+Ae]=r,this.data[a+_e]=-r,this.data[a+re]=i}ignoredPairs(){return this.ignorePairs}addIgnoreCollision(e,t){this.ignorePairs.push(jr(e,t)),this.noCollideDirty=!0}loadFromReference(e){this.clear();let t=Object.keys(So());Object.assign(this.params,Object.fromEntries(t.map(r=>[r,e[r]])));let i=new Map(e.bodies.map((r,o)=>[r,o]));for(let r of e.bodies){let o=this.addBody(r.size,0,r.friction,r.position,r.velocity);this.shape[o*4+2]=r.mass,this.shape[o*4+3]=r.moment,this.dynamic[o]=r.mass>0?1:0}for(let r of e.forces){let o=r.bodyA?i.get(r.bodyA):-1,a=i.get(r.bodyB);if(r instanceof Ao){let n=this.addJoint(o,a,r.rA,r.rB,[r.stiffness[0],r.stiffness[1],r.stiffness[2]],r.fracture[2]);this.data[n.slot*O+re]=r.restAngle,this.data[n.slot*O+be]=r.torqueArm}else r instanceof wo?this.addSpring(o,a,r.rA,r.rB,r.stiffness[0],r.rest):r instanceof Co?this.addMotor(o,a,r.speed,r.fmax[0]):r instanceof Bo&&this.addIgnoreCollision(o,a)}}step(){let e=this.params,t=e.postStabilize&&!e.vbd,i=e.vbd?0:e.alpha;this.phaseStart=this.profiling?performance.now():0,this.saveContacts(),this.findPairs(),this.mark("broadphase"),this.initJoints(),this.narrowphase(),this.mark("narrowphase"),this.warmStartConstraints(t,i),this.buildAdjacency(),this.mark("adjacency"),this.colorBodies(),this.mark("coloring"),this.warmStartBodies();let r=e.iterations+(t?1:0);for(let o=0;o<r;o++){let a=t?o<e.iterations?1:0:i;this.primal(a),this.mark("primal"),o<e.iterations&&this.dual(a),o===e.iterations-1&&this.updateVelocities(),this.mark("dual")}t&&this.refreshStick()}mark(e){if(!this.profiling)return;let t=performance.now();this.profile[e]=(this.profile[e]??0)+t-this.phaseStart,this.phaseStart=t}resetProfile(){for(let e of Object.keys(this.profile))delete this.profile[e]}saveContacts(){let e=this.contactCount,t=this.jointCount;this.prevKeys.length<e&&(this.prevKeys=new Float64Array(e*2),this.prevInfo=new Int32Array(e*2*j),this.prevData=new Float64Array(e*2*O));for(let i=0;i<e;i++){let r=t+i;this.prevKeys[i]=jr(this.info[r*j+1],this.info[r*j+2])}this.prevInfo.set(this.info.subarray(t*j,(t+e)*j)),this.prevData.set(this.data.subarray(t*O,(t+e)*O)),this.prevCount=e,this.contactCount=0}findPairs(){if(this.noCollideDirty){let e=[...this.ignorePairs];for(let t=0;t<this.jointCount;t++){let i=this.info[t*j+1],r=this.info[t*j+2];this.info[t*j]!==Ec&&i>=0&&e.push(jr(i,r))}this.noCollide=Float64Array.from(e).sort(),this.noCollideCount=e.length,this.noCollideDirty=!1}this.broadphase.findPairs(this.bodyCount,this.pose,this.props,this.dynamic,this.noCollide,this.noCollideCount)}initJoints(){let{info:e,data:t,pose:i}=this,r=0;for(let o=0;o<this.jointCount;o++){let a=o*O;if(e[o*j]===Bi){if(t[a+Q]===0&&t[a+Q+1]===0&&t[a+Q+2]===0){let u=this.handles[o];u&&(u.alive=!1);continue}let l=e[o*j+1],c=e[o*j+2];this.jointC(l,c,a,i,t,a+fe)}r!==o&&(e.copyWithin(r*j,o*j,(o+1)*j),t.copyWithin(r*O,a,a+O),this.handles[r]=this.handles[o],this.handles[r]&&(this.handles[r].slot=r)),r++}if(r!==this.jointCount){for(let o=r;o<this.jointCount;o++)this.handles[o]=null;this.jointCount=r,this.noCollideDirty=!0}}jointC(e,t,i,r,o,a,n=o){let l,c,u;if(e>=0){let p=Math.cos(r[e*4+2]),g=Math.sin(r[e*4+2]),b=o[i+N],y=o[i+N+1];l=p*b-g*y+r[e*4],c=g*b+p*y+r[e*4+1],u=r[e*4+2]}else l=o[i+N],c=o[i+N+1],u=0;let f=Math.cos(r[t*4+2]),d=Math.sin(r[t*4+2]),h=o[i+Y],m=o[i+Y+1];n[a]=l-(f*h-d*m+r[t*4]),n[a+1]=c-(d*h+f*m+r[t*4+1]),n[a+2]=(u-r[t*4+2]-o[i+re])*o[i+be]}narrowphase(){let{pose:e,shape:t,props:i}=this,r=this.broadphase.pairs,o=this.contactOut;for(let a=0;a<this.broadphase.pairCount;a++){let n=r[a],l=Math.floor(n/2097152),c=n-l*2097152,u=_o(e[l*4],e[l*4+1],e[l*4+2],t[l*4]*.5,t[l*4+1]*.5,e[c*4],e[c*4+1],e[c*4+2],t[c*4]*.5,t[c*4+1]*.5,o);if(u===0)continue;let f=0,d=this.prevCount;for(;f<d;){let p=f+d>>>1;this.prevKeys[p]<n?f=p+1:d=p}let h=f,m=Math.sqrt(i[l*4]*i[c*4]);for(let p=0;p<u;p++){let g=this.jointCount+this.contactCount++;this.info=this.grow(this.info,(g+1)*j),this.data=this.grow(this.data,(g+1)*O);let b=this.data,y=g*O,A=p*7,v=o[A+0];this.info.set([bs,l,c,v],g*j),b.fill(0,y,y+O),b[y+Q]=b[y+Q+1]=1/0,b[y+_e]=-1/0,b[y+Ae]=0,b[y+Pt]=b[y+Pt+1]=1/0,b[y+N]=o[A+1],b[y+N+1]=o[A+1+1],b[y+Y]=o[A+3],b[y+Y+1]=o[A+3+1],b[y+re]=m,b[y+be]=o[A+5],b[y+Ne]=o[A+5+1];let x=-1;for(let C=h;C<this.prevCount&&this.prevKeys[C]===n;C++)this.prevInfo[C*j+3]===v&&(x=C);if(x<0&&this.params.matchNearest){let C=Mn*Math.min(t[l*4],t[l*4+1],t[c*4],t[c*4+1]);for(let _=h;_<this.prevCount&&this.prevKeys[_]===n;_++){let z=Math.hypot(this.prevData[_*O+N]-b[y+N],this.prevData[_*O+N+1]-b[y+N+1]);z<=C&&(C=z,x=_)}}if(x>=0){let C=x*O;b[y+se]=this.prevData[C+se],b[y+se+1]=this.prevData[C+se+1],b[y+te]=this.prevData[C+te],b[y+te+1]=this.prevData[C+te+1],this.prevData[C+Hi]&&(b[y+N]=this.prevData[C+N],b[y+N+1]=this.prevData[C+N+1],b[y+Y]=this.prevData[C+Y],b[y+Y+1]=this.prevData[C+Y+1])}let[w,B]=wi(e[l*4+2],b[y+N],b[y+N+1]),[L,M]=wi(e[c*4+2],b[y+Y],b[y+Y+1]),I=b[y+be],E=b[y+Ne],k=e[l*4]+w-e[c*4]-L,P=e[l*4+1]+B-e[c*4+1]-M;b[y+fe]=I*k+E*P+5e-4,b[y+fe+1]=E*k-I*P}}}warmStartConstraints(e,t){let i=this.params,r=this.data,o=this.jointCount+this.contactCount;for(let a=0;a<o;a++){let n=zc[this.info[a*j]],l=a*O;for(let c=0;c<n;c++){if(i.vbd){r[l+se+c]=Or(r[l+Q+c],i.vbdStiffness);continue}e||(r[l+te+c]=r[l+te+c]*t*i.gamma),r[l+se+c]=Or(Tr(r[l+se+c]*i.gamma,1,1e9),r[l+Q+c])}}}prepareTopology(){this.buildAdjacency(),this.colorBodies()}buildAdjacency(){let e=this.bodyCount,t=this.jointCount+this.contactCount;this.adjStart=this.grow(this.adjStart,e+1),this.adjList=this.grow(this.adjList,t*2);let i=this.adjStart;i.fill(0,0,e+1);for(let o=0;o<t;o++)for(let a=1;a<=2;a++){let n=this.info[o*j+a];n>=0&&this.dynamic[n]&&i[n+1]++}for(let o=0;o<e;o++)i[o+1]+=i[o];let r=i.slice(0,e);for(let o=0;o<t;o++)for(let a=1;a<=2;a++){let n=this.info[o*j+a];n>=0&&this.dynamic[n]&&(this.adjList[r[n]++]=o)}}colorBodies(){if(this.options.order!=="colored")return;let e=this.coloring.run(this.bodyCount,this.dynamic,this.adjStart,this.adjList,this.info,this.options.colorRounds);this.numColors=e.numColors,this.colorConflicts=e.conflicts,this.colorRounds=e.rounds}warmStartBodies(){let{dt:e,gravity:t}=this.params,{pose:i,velocity:r,initial:o,inertial:a,prevVelocity:n}=this;for(let l=0;l<this.bodyCount;l++){let c=l*4;r[c+2]=Tr(r[c+2],-50,50),a[c]=i[c]+r[c]*e,a[c+1]=i[c+1]+r[c+1]*e,a[c+2]=i[c+2]+r[c+2]*e,this.dynamic[l]&&(a[c+1]+=t*e*e);let u=(r[c+1]-n[c+1])/e*kc(t),f=Tr(u/Math.abs(t),0,1);Number.isFinite(f)||(f=0),o[c]=i[c],o[c+1]=i[c+1],o[c+2]=i[c+2],i[c]=i[c]+r[c]*e,i[c+1]=i[c+1]+r[c+1]*e+t*f*e*e,i[c+2]=i[c+2]+r[c+2]*e}}eC=new Float64Array(3);eMin=new Float64Array(3);eMax=new Float64Array(3);eJ=new Float64Array(9);eG=new Float64Array(9);evalConstraint(e,t,i){let{info:r,data:o,pose:a,initial:n}=this,l=r[e*j],c=r[e*j+1],u=r[e*j+2],f=e*O,{eC:d,eMin:h,eMax:m,eJ:p,eG:g}=this,b=zc[l];for(let A=0;A<b;A++)h[A]=o[f+_e+A],m[A]=o[f+Ae+A];let y=i===c;if(g.fill(0),l===Bi){this.jointC(c,u,f,a,o,0,d);for(let A=0;A<3;A++)o[f+Q+A]===1/0&&(d[A]-=o[f+fe+A]*t);if(i>=0){let A=a[i*4+2],[v,x]=wi(A,o[f+(y?N:Y)],o[f+(y?N:Y)+1]),w=y?1:-1;p[0]=w,p[1]=0,p[2]=-w*x,p[3]=0,p[4]=w,p[5]=w*v,p[6]=0,p[7]=0,p[8]=w*o[f+be],g[2]=Math.abs(v),g[5]=Math.abs(x)}}else if(l===Mc){let[A,v]=Ic(a,c,o[f+N],o[f+N+1]),[x,w]=Ic(a,u,o[f+Y],o[f+Y+1]),B=A-x,L=v-w,M=B*B+L*L,I=Math.sqrt(M);if(d[0]=I-o[f+re],i>=0&&M!==0){let E=B/I,k=L/I,P=(1-E*E)/I,C=-E*k/I,_=(1-k*k)/I,z=a[i*4+2],R=y?N:Y,[G,X]=wi(z,-o[f+R+1],o[f+R]),[W,U]=wi(z,o[f+R],o[f+R+1]),H=P*G+C*X,Z=C*G+_*X,pe=E*W+k*U,we=E*G+k*X,Oe=y?1:-1;p[0]=Oe*E,p[1]=Oe*k,p[2]=Oe*we;let $=y?-pe-pe:pe+pe;g[0]=Math.hypot(P,C,H),g[1]=Math.hypot(C,_,Z),g[2]=Math.hypot(H,Z,$)}else i>=0&&p.fill(0,0,3)}else if(l===Ro){let A=c>=0?a[c*4+2]-n[c*4+2]:0,v=a[u*4+2]-n[u*4+2];d[0]=A-v-o[f+re]*this.params.dt,i>=0&&(p[0]=0,p[1]=0,p[2]=y?1:-1)}else if(l===bs){let A=o[f+be],v=o[f+Ne],x=v,w=-A,[B,L]=wi(n[c*4+2],o[f+N],o[f+N+1]),[M,I]=wi(n[u*4+2],o[f+Y],o[f+Y+1]),E=B*v-L*A,k=-(M*v-I*A),P=B*w-L*x,C=-(M*w-I*x),_=a[c*4]-n[c*4],z=a[c*4+1]-n[c*4+1],R=a[c*4+2]-n[c*4+2],G=a[u*4]-n[u*4],X=a[u*4+1]-n[u*4+1],W=a[u*4+2]-n[u*4+2];d[0]=o[f+fe]*(1-t)+A*_+v*z+E*R+-A*G+-v*X+k*W,d[1]=o[f+fe+1]*(1-t)+x*_+w*z+P*R+-x*G+-w*X+C*W;let U=Math.abs(o[f+te])*o[f+re];m[1]=U,h[1]=-U,i>=0&&(y?(p[0]=A,p[1]=v,p[2]=E,p[3]=x,p[4]=w,p[5]=P):(p[0]=-A,p[1]=-v,p[2]=k,p[3]=-x,p[4]=-w,p[5]=C))}return b}solveBody(e,t){let i=this.params,{shape:r,pose:o,inertial:a,data:n}=this,l=i.dt*i.dt,c=r[e*4+2]/l,u=r[e*4+3]/l,f=c,d=0,h=c,m=0,p=0,g=u,b=c*(o[e*4]-a[e*4]),y=c*(o[e*4+1]-a[e*4+1]),A=u*(o[e*4+2]-a[e*4+2]),{eC:v,eMin:x,eMax:w,eJ:B,eG:L}=this,M=this.adjStart,I=this.adjList;for(let H=M[e+1]-1;H>=M[e];H--){let Z=I[H],pe=this.evalConstraint(Z,t,e),we=Z*O,Oe=!i.vbd;for(let $=0;$<pe;$++){let Je=n[we+Q+$],Xe=Oe&&Je===1/0?n[we+te+$]:0,Be=n[we+se+$],at=v[$],ri=Be*at+Xe,Ye=Tr(ri,x[$],w[$]),nt=Math.abs(Ye);i.stiffnessRescale&&at!==0&&(ri<x[$]?Be=Math.abs((x[$]-Xe)/at):ri>w[$]&&(Be=Math.abs((w[$]-Xe)/at)));let Qe=B[$*3],lt=B[$*3+1],wt=B[$*3+2];b+=Qe*Ye,y+=lt*Ye,A+=wt*Ye,f+=Qe*Qe*Be+L[$*3]*nt,d+=lt*Qe*Be,h+=lt*lt*Be+L[$*3+1]*nt,m+=wt*Qe*Be,p+=wt*lt*Be,g+=wt*wt*Be+L[$*3+2]*nt}}let E=f,k=d/f,P=m/f,C=h-k*k*E,_=(p-k*P*E)/C,z=g-(P*P*E+_*_*C),R=y-k*b,X=(A-P*b-_*R)/z,W=R/C-_*X,U=b/E-k*W-P*X;this.dxBuf[e*3]=U,this.dxBuf[e*3+1]=W,this.dxBuf[e*3+2]=X}applyDx(e){this.pose[e*4]-=this.dxBuf[e*3],this.pose[e*4+1]-=this.dxBuf[e*3+1],this.pose[e*4+2]-=this.dxBuf[e*3+2]}primal(e){if(this.dxBuf.length<this.bodyCount*3&&(this.dxBuf=new Float64Array(this.bodyCount*3)),this.options.order==="sequential"){for(let r=this.bodyCount-1;r>=0;r--)this.dynamic[r]&&(this.solveBody(r,e),this.applyDx(r));return}let{colorStart:t,colorBodies:i}=this.coloring;for(let r=0;r<this.numColors;r++){for(let o=t[r];o<t[r+1];o++)this.solveBody(i[o],e);for(let o=t[r];o<t[r+1];o++)this.applyDx(i[o])}}dual(e){let t=this.params,i=this.data,{eC:r,eMin:o,eMax:a}=this,n=this.jointCount+this.contactCount;for(let l=0;l<n;l++){let c=this.info[l*j];if(c===Ec)continue;let u=this.evalConstraint(l,e,-1),f=l*O;c===bs&&(i[f+Hi]=Math.abs(i[f+te+1])<a[1]&&Math.abs(i[f+fe+1])<.01?1:0);for(let d=0;d<u;d++){let h=i[f+Q+d],m=!t.vbd&&h===1/0?i[f+te+d]:0,p=Tr(i[f+se+d]*r[d]+m,o[d],a[d]);i[f+te+d]=p,Math.abs(p)>=i[f+Pt+d]&&this.disable(l),!t.vbd&&p>o[d]&&p<a[d]&&(i[f+se+d]=Or(i[f+se+d]+t.beta*Math.abs(r[d]),Or(1e9,i[f+Q+d])))}}}refreshStick(){let e=this.data;for(let t=0;t<this.contactCount;t++){let i=(this.jointCount+t)*O,r=Math.abs(e[i+te])*e[i+re];e[i+Hi]=Math.abs(e[i+te+1])<r&&Math.abs(e[i+fe+1])<.01?1:0}}disable(e){let t=e*O;this.data.fill(0,t+se,t+se+3),this.data.fill(0,t+te,t+te+3),this.data.fill(0,t+Q,t+Q+3)}updateVelocities(){let{dt:e}=this.params,{pose:t,initial:i,velocity:r,prevVelocity:o}=this;for(let a=0;a<this.bodyCount;a++){let n=a*4;o[n]=r[n],o[n+1]=r[n+1],o[n+2]=r[n+2],this.dynamic[a]&&(r[n]=(t[n]-i[n])/e,r[n+1]=(t[n+1]-i[n+1])/e,r[n+2]=(t[n+2]-i[n+2])/e)}}pick(e,t){for(let i=this.bodyCount-1;i>=0;i--){let[r,o]=wi(-this.pose[i*4+2],e-this.pose[i*4],t-this.pose[i*4+1]);if(Math.abs(r)<=this.shape[i*4]*.5&&Math.abs(o)<=this.shape[i*4+1]*.5)return{body:i,local:[r,o]}}return null}kineticEnergy(){let e=0;for(let t=0;t<this.bodyCount;t++){if(!this.dynamic[t])continue;let i=t*4,r=this.velocity;e+=.5*this.shape[i+2]*(r[i]*r[i]+r[i+1]*r[i+1])+.5*this.shape[i+3]*r[i+2]*r[i+2]}return e}maxJointError(){let e=0,t=new Float64Array(3);for(let i=0;i<this.jointCount;i++){if(this.info[i*j]!==Bi)continue;let r=i*O;this.jointC(this.info[i*j+1],this.info[i*j+2],r,this.pose,this.data,0,t);for(let o=0;o<2;o++)this.data[r+Q+o]===1/0&&(e=Math.max(e,Math.abs(t[o])))}return e}isContactPairIgnored(e,t){return Ln(this.noCollide,this.noCollideCount,jr(e,t))}};function wi(s,e,t){let i=Math.cos(s),r=Math.sin(s);return[i*e-r*t,r*e+i*t]}function Ic(s,e,t,i){let r=Math.cos(s[e*4+2]),o=Math.sin(s[e*4+2]);return[r*t-o*i+s[e*4],o*t+r*i+s[e*4+1]]}var ys=`
3907
3950
  ${Ut}
3908
3951
 
3909
3952
  @group(0) @binding(0) var<uniform> params: Params;
@@ -4743,7 +4786,7 @@ fn updateVelocities(@builtin(global_invocation_id) gid: vec3u) {
4743
4786
  if (b.shape.z > 0.0) { b.vel = vec4f((b.pose.xyz - b.initial.xyz) / params.dt, 0.0); }
4744
4787
  bodies[i] = b;
4745
4788
  }
4746
- `;var Oo=s=>s===1/0?3e38:s===-1/0?-3e38:s,bt=s=>Math.ceil(s/64),Tc=s=>2**Math.ceil(Math.log2(Math.max(s,2))),od=s=>Math.max(s,1)*24*4,ad=4,yt=()=>GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST,To=class{device;params=ko();topology;bodyCount=0;bodyCapacity;jointCount=0;jointCapacity=0;pairCapacity=0;contactCapacity=0;colorCap=12;splitPasses=!1;primalMode="bucket";shrinkVotes=0;get colorHistOffset(){return 3*this.bodyCapacity+65}colorRounds;bodyBuffer;ownsBodyBuffer;jointBuffer;infoBuffer;contactBuffers;pairBuffer;tableBuffer;gridBuffer;staticBuffer=null;counterBuffer;argsBuffer;adjBuffer=null;colorBuffer;paramsBuffer;passBuffer=null;passEntries=0;parity=0;tableSize;hashSize=0;cellSize=1;maxSmallRadius=0;largeCount=0;noCollideCount=0;staticsDirty=!0;layouts;pipes={};groups;passGroup=null;gridScan;colorHistScan;colorGroups;adjScan=null;timing;timingCallback=null;timingBusy=!1;destroyed=!1;constructor(e,t,i={}){if(this.device=e,this.topology=t,Object.assign(this.params,t.params),this.bodyCount=t.bodyCount,this.colorRounds=i.colorRounds??16,this.ownsBodyBuffer=!i.bodyBuffer,this.bodyCapacity=i.bodyBuffer?Math.floor(i.bodyBuffer.size/96):Math.max(i.bodyCapacity??this.bodyCount+1024,this.bodyCount,1),this.bodyCapacity<this.bodyCount)throw new Error("body buffer too small");this.bodyBuffer=i.bodyBuffer??e.createBuffer({label:"bodies",size:od(this.bodyCapacity),usage:yt()});let r=this.bodyCapacity;this.tableSize=Tc(2*r),this.gridBuffer=e.createBuffer({label:"grid",size:(2*this.tableSize+1+3*r)*4,usage:yt()}),this.counterBuffer=e.createBuffer({label:"counters",size:64,usage:yt()}),this.argsBuffer=e.createBuffer({label:"indirect args",size:816,usage:yt()|GPUBufferUsage.INDIRECT}),this.colorGroups=Math.ceil(r/256),this.colorBuffer=e.createBuffer({label:"colours",size:(3*r+65+64*this.colorGroups+1)*4,usage:yt()}),this.paramsBuffer=e.createBuffer({label:"params",size:128,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),e.queue.writeBuffer(this.colorBuffer,0,new Uint32Array(r).fill(255));let o=2*Se.length;this.timing=e.features.has("timestamp-query")?{querySet:e.createQuerySet({type:"timestamp",count:o}),resolve:e.createBuffer({size:o*8,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),read:e.createBuffer({size:o*8,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST})}:null,this.layouts=this.createLayouts(),this.createPipelines(),this.gridScan=new tt(e,this.gridBuffer,0,this.tableSize+1),this.colorHistScan=new tt(e,this.colorBuffer,this.colorHistOffset,64*this.colorGroups+1),this.jointCount=t.jointCount,this.allocateJoints(t.jointCount+256),this.uploadJoints(0,t.jointCount),this.allocateContacts(Math.max(4096,4*r)),this.uploadBodies()}createLayouts(){let e=this.device,t=(a,n)=>e.createBindGroupLayout({label:a,entries:n.map((l,c)=>({binding:c,visibility:GPUShaderStage.COMPUTE,buffer:{type:l}}))}),i="read-only-storage",r="storage",o="uniform";return{broad:t("broadphase",[o,i,r,r,r,i,i]),contacts:t("contacts",[o,i,i,r,i,r,r]),topo:t("topology",[o,i,i,i,i,r,r,r]),solve:t("solve",[o,r,r,i,r,i,i,i]),pass:e.createBindGroupLayout({label:"pass",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform",hasDynamicOffset:!0,minBindingSize:16}}]}),args:t("args",[o,i,i,r])}}createPipelines(){let e=this.device,t=(r,o,a)=>{let n=e.createShaderModule({code:r}),l=e.createPipelineLayout({bindGroupLayouts:o});for(let c of a)this.pipes[c]=e.createComputePipeline({label:c,layout:l,compute:{module:n,entryPoint:c}})},i=this.layouts;t(ys,[i.broad],["beginFrame","gridCount","gridScatter","findPairs"]),t(vs,[i.contacts],["hashInsert","narrowphase"]),t(Qr,[i.topo],["degreeJoints","degreeContacts","fillJoints","fillContacts","sortAdjacency","colorCompact","colorMark","colorRoundAB","colorRoundBA","colorCount","colorStarts","colorScatter"]),t(xs,[i.solve,i.pass],["warmStartJoints","warmStartBodies","primal","primalScan","dual","refreshStick","updateVelocities"]),t(qs,[i.args],["argsPrev","argsPairs","argsContacts","argsColors"])}allocateJoints(e){let t=this.device,i=t.createBuffer({label:"joints",size:Math.max(e,1)*36*4,usage:yt()}),r=t.createBuffer({label:"joint info",size:Math.max(e,1)*16,usage:yt()});if(this.jointBuffer){let o=t.createCommandEncoder();o.copyBufferToBuffer(this.jointBuffer,0,i,0,this.jointCapacity*36*4),o.copyBufferToBuffer(this.infoBuffer,0,r,0,this.jointCapacity*16),t.queue.submit([o.finish()]),this.jointBuffer.destroy(),this.infoBuffer.destroy()}this.jointBuffer=i,this.infoBuffer=r,this.jointCapacity=e,this.contactBuffers&&this.rebuildBindings()}allocateContacts(e,t=2*e){let i=this.device,r=i.limits.maxStorageBufferBindingSize,o=Math.min(e,Math.floor(r/80),Math.floor(r/16)),a=Math.min(t,Math.floor(r/8)),n=this.contactBuffers,l=this.contactCapacity;for(let c of[this.pairBuffer,this.tableBuffer])c?.destroy();if(this.contactCapacity=o,this.pairCapacity=a,this.hashSize=Tc(4*o),this.pairBuffer=i.createBuffer({label:"pairs",size:a*8,usage:yt()}),this.tableBuffer=i.createBuffer({label:"contact hash",size:this.hashSize*4,usage:yt()}),this.contactBuffers=[0,1].map(c=>i.createBuffer({label:`contacts ${c}`,size:o*20*4,usage:yt()})),n){let c=i.createCommandEncoder(),u=Math.min(l,o)*20*4;n.forEach((f,d)=>c.copyBufferToBuffer(f,0,this.contactBuffers[d],0,u)),i.queue.submit([c.finish()]),n.forEach(f=>f.destroy())}this.rebuildBindings()}rebuildBindings(){let e=this.device,t=this.bodyCapacity;this.adjBuffer?.destroy(),this.adjBuffer=e.createBuffer({label:"adjacency",size:(2*t+1+2*(this.jointCapacity+this.contactCapacity))*4,usage:yt()}),this.adjScan?.destroy(),this.adjScan=new tt(e,this.adjBuffer,0,this.bodyCount+1),this.staticBuffer??=e.createBuffer({label:"statics",size:16,usage:yt()});let i=(l,c)=>e.createBindGroup({layout:l,entries:c.map((u,f)=>({binding:f,resource:{buffer:u}}))}),r=this.paramsBuffer,[o,a]=this.contactBuffers,n=this.adjBuffer;this.groups={broad:i(this.layouts.broad,[r,this.bodyBuffer,this.gridBuffer,this.pairBuffer,this.counterBuffer,this.staticBuffer,this.jointBuffer]),contacts:[i(this.layouts.contacts,[r,this.bodyBuffer,this.pairBuffer,o,a,this.tableBuffer,this.counterBuffer]),i(this.layouts.contacts,[r,this.bodyBuffer,this.pairBuffer,a,o,this.tableBuffer,this.counterBuffer])],topo:[o,a].map(l=>i(this.layouts.topo,[r,this.bodyBuffer,this.jointBuffer,this.infoBuffer,l,this.counterBuffer,n,this.colorBuffer])),solve:[o,a].map(l=>i(this.layouts.solve,[r,this.bodyBuffer,this.jointBuffer,this.infoBuffer,l,n,this.colorBuffer,this.counterBuffer])),args:i(this.layouts.args,[r,this.counterBuffer,this.colorBuffer,this.argsBuffer])}}uploadBodies(e=0,t=this.topology.bodyCount-e){let i=this.topology,r=new Float32Array(Math.max(t,1)*24);for(let o=0;o<t;o++){let a=e+o,n=o*24;r.set(i.pose.subarray(a*4,a*4+3),n),r[n+3]=i.props[a*4],r.set(i.initial.subarray(a*4,a*4+4),n+4),r.set(i.inertial.subarray(a*4,a*4+4),n+8),r.set(i.velocity.subarray(a*4,a*4+4),n+12),r.set(i.prevVelocity.subarray(a*4,a*4+4),n+16),r.set(i.shape.subarray(a*4,a*4+4),n+20)}this.device.queue.writeBuffer(this.bodyBuffer,e*24*4,r),this.staticsDirty=!0}uploadJoints(e,t){if(t===0)return;let i=this.topology,r=new Float32Array(t*36);for(let o=0;o<t;o++){let a=(e+o)*O,n=o*36;for(let l=0;l<3;l++)r[n+0+l]=i.data[a+se+l],r[n+4+l]=i.data[a+te+l],r[n+8+l]=Oo(i.data[a+Q+l]),r[n+12+l]=Oo(i.data[a+_e+l]),r[n+16+l]=Oo(i.data[a+Ae+l]),r[n+20+l]=Oo(i.data[a+Pt+l]),r[n+24+l]=i.data[a+fe+l];r[n+28]=i.data[a+N],r[n+28+1]=i.data[a+N+1],r[n+28+2]=i.data[a+Y],r[n+28+3]=i.data[a+Y+1],r[n+32]=i.data[a+re],r[n+32+1]=i.data[a+be]}this.device.queue.writeBuffer(this.jointBuffer,e*36*4,r),this.device.queue.writeBuffer(this.infoBuffer,e*16,i.info,e*j,t*j)}uploadStatics(){let e=this.topology,t=this.bodyCount,i=Float64Array.from({length:t},(f,d)=>e.props[d*4+1]).sort(),r=t>0?i[t>>1]:1,o=0;for(let f=0;f<t;f++)i[f]<=ad*r&&(o=Math.max(o,i[f]));let a=1/0;for(let f=0;f<t;f++)i[f]>o&&(a=Math.min(a,i[f]));let n=a===1/0?o*1.5:(o+a)/2;this.maxSmallRadius=n,this.cellSize=Math.max(2*o*(1+1e-4),.001);let l=[];for(let f=0;f<t;f++)e.props[f*4+1]>n&&l.push(f);let c=[];for(let f=0;f<e.jointCount;f++){let d=e.info[f*j+1],p=e.info[f*j+2];d>=0&&c.push([Math.max(d,p),Math.min(d,p),f])}for(let f of e.ignoredPairs()){let d=Math.floor(f/2097152);c.push([d,f-d*2097152,4294967295])}c.sort((f,d)=>f[0]-d[0]||f[1]-d[1]),this.largeCount=l.length,this.noCollideCount=c.length;let u=new Uint32Array(Math.max(l.length+3*c.length,4));u.set(l,0),c.forEach((f,d)=>u.set(f,l.length+3*d)),this.staticBuffer.size<u.byteLength&&(this.staticBuffer.destroy(),this.staticBuffer=this.device.createBuffer({label:"statics",size:u.byteLength,usage:yt()}),this.rebuildBindings()),this.device.queue.writeBuffer(this.staticBuffer,0,u),this.staticsDirty=!1}seedContactsFrom(e){let t=e.contactCount;if(t>this.contactCapacity)throw new Error("seedContactsFrom: too many contacts");let i=new ArrayBuffer(Math.max(t,1)*20*4),r=new Uint32Array(i),o=new Float32Array(i);for(let l=0;l<t;l++){let c=e.jointCount+l,u=c*O,f=l*20;r[f]=e.info[c*j+1],r[f+1]=e.info[c*j+2],r[f+2]=e.info[c*j+3],r[f+3]=e.data[u+Hi]?1:0,o.set([e.data[u+se],e.data[u+se+1],e.data[u+te],e.data[u+te+1]],f+4),o.set([e.data[u+N],e.data[u+N+1],e.data[u+Y],e.data[u+Y+1]],f+8),o.set([e.data[u+fe],e.data[u+fe+1],e.data[u+be],e.data[u+Ue]],f+12),o[f+16]=e.data[u+re]}this.device.queue.writeBuffer(this.contactBuffers[1-this.parity],0,i);let a=new Uint32Array(16);a[1]=t,this.device.queue.writeBuffer(this.counterBuffer,0,a);let n=Uint32Array.from({length:this.bodyCount},(l,c)=>(e.coloring.colors[c]??-1)<0?255:e.coloring.colors[c]);this.device.queue.writeBuffer(this.colorBuffer,0,n)}addBody(e,t,i,r,o){if(this.bodyCount>=this.bodyCapacity)return-1;let a=this.topology.addBody(e,t,i,r,o);return this.bodyCount=this.topology.bodyCount,this.uploadBodies(a,1),this.device.queue.writeBuffer(this.colorBuffer,a*4,new Uint32Array([255])),this.adjScan.destroy(),this.adjScan=new tt(this.device,this.adjBuffer,0,this.bodyCount+1),a}appendJoint(e,t,i,r,o,a=1/0){let n=this.topology;if(n.contactCount>0)throw new Error("appendJoint: the CPU mirror must not hold contacts");let l=n.addJoint(e,t,i,r,o,a).slot;return l>=this.jointCapacity&&this.allocateJoints(Math.max(l+1,this.jointCapacity*2)),this.jointCount=l+1,this.uploadJoints(l,1),e>=0&&(this.staticsDirty=!0),l}setWorldAnchor(e,t,i){this.device.queue.writeBuffer(this.jointBuffer,(e*36+28)*4,new Float32Array([t,i]))}disableConstraint(e){this.device.queue.writeBuffer(this.jointBuffer,(e*36+0)*4,new Float32Array(12)),this.topology.data.fill(0,e*O+Q,e*O+Q+3)}profileNextStep(e){this.timing&&!this.timingBusy&&(this.timingCallback=e)}writeParams(e,t){let i=this.params,r=this.bodyCapacity,o=new ArrayBuffer(128),a=new Float32Array(o),n=new Uint32Array(o);a[0]=i.dt,a[1]=i.gravity,a[2]=i.beta,a[3]=i.gamma,a[4]=e,a[5]=i.vbdStiffness,n[6]=(i.vbd?1:0)|(i.stiffnessRescale?2:0)|(t?4:0)|(i.matchNearest?8:0),n[7]=this.bodyCount,n[8]=this.jointCount,n[9]=this.colorCap,a[10]=this.cellSize,n[11]=this.tableSize-1,a[12]=this.maxSmallRadius,n[13]=this.largeCount,n[14]=this.noCollideCount,n[15]=this.pairCapacity,n[16]=this.contactCapacity,n[17]=this.hashSize-1,n[18]=r+1,n[19]=2*r+1,n[20]=this.tableSize+1,n[21]=2*this.tableSize+1,n[22]=2*this.tableSize+1+r,n[23]=r,n[24]=this.colorHistOffset,n[25]=2*r,n[26]=this.colorGroups,n[27]=2*r+65,n[28]=this.colorRounds,this.device.queue.writeBuffer(this.paramsBuffer,0,o)}writePassConstants(e,t){let i=this.colorCap+1,r=e*i;(r>this.passEntries||!this.passGroup)&&(this.passBuffer?.destroy(),this.passBuffer=this.device.createBuffer({label:"pass constants",size:r*256,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.passEntries=r,this.passGroup=this.device.createBindGroup({layout:this.layouts.pass,entries:[{binding:0,resource:{buffer:this.passBuffer,size:16}}]}));let o=new ArrayBuffer(r*256),a=new Uint32Array(o),n=new Float32Array(o);for(let l=0;l<e;l++)for(let c=0;c<=this.colorCap;c++){let u=(l*i+c)*256/4;a[u]=c,n[u+1]=t(l)}this.device.queue.writeBuffer(this.passBuffer,0,o)}step(){this.staticsDirty&&this.uploadStatics();let e=this.params,t=e.postStabilize&&!e.vbd,i=e.vbd?0:e.alpha,r=e.iterations+(t?1:0);this.writeParams(i,t),this.writePassConstants(r,x=>t?x<e.iterations?1:0:i);let o=this.parity,a=this.bodyCapacity,n=this.bodyCount,l=this.jointCount,c=this.device.createCommandEncoder({label:"avbd2d step"});c.clearBuffer(this.gridBuffer,0,(2*this.tableSize+1)*4),c.clearBuffer(this.tableBuffer),c.clearBuffer(this.adjBuffer,0,(2*a+1)*4);let u=this.timingCallback!==null&&this.timing!==null,f,d=0,p=u||this.splitPasses,m=()=>{f&&!p||(f?.end(),f=c.beginComputePass({label:p?Se[d]:"avbd2d step",timestampWrites:u?{querySet:this.timing.querySet,beginningOfPassWriteIndex:2*d,endOfPassWriteIndex:2*d+1}:void 0}),d++)},h=this.groups,g=(x,w,B)=>{B<=0||(f.setPipeline(this.pipes[x]),f.setBindGroup(0,w),f.dispatchWorkgroups(B))},b=(x,w,B)=>{f.setPipeline(this.pipes[x]),f.setBindGroup(0,w),f.dispatchWorkgroupsIndirect(this.argsBuffer,B*4)};m(),g("beginFrame",h.broad,1),g("argsPrev",h.args,1),b("hashInsert",h.contacts[o],6),g("gridCount",h.broad,bt(n)),this.gridScan.encode(f),g("gridScatter",h.broad,bt(n)),g("findPairs",h.broad,bt(n)),g("argsPairs",h.args,1),b("narrowphase",h.contacts[o],0),g("argsContacts",h.args,1),m(),g("degreeJoints",h.topo[o],bt(l)),b("degreeContacts",h.topo[o],3),this.adjScan.encode(f),g("fillJoints",h.topo[o],bt(l)),b("fillContacts",h.topo[o],3),g("sortAdjacency",h.topo[o],bt(n)),m(),g("colorCompact",h.topo[o],bt(n)),g("colorMark",h.topo[o],bt(n));for(let x=0;x<this.colorRounds;x++)g(x%2===0?"colorRoundAB":"colorRoundBA",h.topo[o],bt(n));g("colorCount",h.topo[o],this.colorGroups),this.colorHistScan.encode(f),g("colorStarts",h.topo[o],1),g("argsColors",h.args,1),g("colorScatter",h.topo[o],this.colorGroups),m();let y=this.colorCap+1,A=x=>f.setBindGroup(1,this.passGroup,[x*256]);f.setBindGroup(0,h.solve[o]),A(0),l>0&&(f.setPipeline(this.pipes.warmStartJoints),f.dispatchWorkgroups(bt(l))),f.setPipeline(this.pipes.warmStartBodies),f.dispatchWorkgroups(bt(n));for(let x=0;x<r;x++){let w=this.primalMode==="scan";f.setPipeline(w?this.pipes.primalScan:this.pipes.primal);for(let B=0;B<this.colorCap;B++)A(x*y+B),w?f.dispatchWorkgroups(bt(n)):f.dispatchWorkgroupsIndirect(this.argsBuffer,(12+3*B)*4);x<e.iterations&&(A(x*y+this.colorCap),f.setPipeline(this.pipes.dual),f.dispatchWorkgroupsIndirect(this.argsBuffer,36)),x===e.iterations-1&&(f.setPipeline(this.pipes.updateVelocities),f.dispatchWorkgroups(bt(n)))}t&&(f.setPipeline(this.pipes.refreshStick),f.dispatchWorkgroupsIndirect(this.argsBuffer,12)),f.end();let v=2*Se.length;if(u){let{querySet:x,resolve:w,read:B}=this.timing;c.resolveQuerySet(x,0,v,w,0),c.copyBufferToBuffer(w,0,B,0,v*8)}if(this.device.queue.submit([c.finish()]),this.parity=1-o,u){let x=this.timingCallback;this.timingCallback=null,this.timingBusy=!0;let w=this.timing.read;w.mapAsync(GPUMapMode.READ).then(()=>{let B=new BigUint64Array(w.getMappedRange()).slice();if(w.unmap(),this.timingBusy=!1,this.destroyed)return this.releaseTiming();let L=(I,E)=>Number(B[E]-B[I])/1e6,M={total:L(0,v-1)};Se.forEach((I,E)=>M[I]=L(2*E,2*E+1)),x(M)},()=>{this.timingBusy=!1,this.destroyed&&this.releaseTiming()})}}async readBodies(){return new Float32Array(await this.read(this.bodyBuffer,this.bodyCount*24*4))}async readJoints(){return new Float32Array(await this.read(this.jointBuffer,this.jointCount*36*4))}async readCounters(){let e=new Uint32Array(await this.read(this.counterBuffer,64));return{pairs:e[0],contacts:e[1],overflow:e[3],clashes:e[4],colors:e[5]}}async readContacts(){let{contacts:e}=await this.readCounters(),t=Math.min(e,this.contactCapacity);return this.read(this.contactBuffers[1-this.parity],t*20*4)}async readPairs(){let{pairs:e}=await this.readCounters();return new Uint32Array(await this.read(this.pairBuffer,Math.min(e,this.pairCapacity)*8))}async readColors(){return new Uint32Array(await this.read(this.colorBuffer,this.bodyCount*4))}async readAdjacency(){let e=new Uint32Array(await this.read(this.adjBuffer,this.adjBuffer.size)),t=e.slice(0,this.bodyCount+1),i=2*this.bodyCapacity+1;return{start:t,list:e.slice(i,i+t[this.bodyCount])}}adapt(e){let t=e.colors;e.clashes>0||t>=this.colorCap-1?(this.colorCap=Math.min(64,Math.max(t+4,this.colorCap+4)),this.shrinkVotes=0):t+2<this.colorCap?++this.shrinkVotes>=3&&(this.colorCap=Math.min(64,Math.max(4,t+2)),this.shrinkVotes=0):this.shrinkVotes=0;let i=(e.overflow&2)!==0||e.contacts>.8*this.contactCapacity,r=(e.overflow&1)!==0||e.pairs>.8*this.pairCapacity,o=this.contactCapacity*(i?2:1),a=this.pairCapacity*(r?2:1);(i||r)&&this.capacityCanGrow(o,a)&&this.allocateContacts(o,a)}capacityCanGrow(e,t){let i=this.device.limits.maxStorageBufferBindingSize,r=Math.min(Math.floor(i/80),Math.floor(i/16));return Math.min(e,r)>this.contactCapacity||Math.min(t,Math.floor(i/8))>this.pairCapacity}async readStats(e){let[t,i]=await Promise.all([e??this.readBodies(),this.readJoints()]),r=0;for(let c=0;c<this.bodyCount;c++){let u=c*24,f=t[u+22],d=t[u+12],p=t[u+13],m=t[u+14];f>0&&(r+=.5*f*(d*d+p*p)+.5*t[u+23]*m*m)}let o=0,a=0,n=this.topology.info,l=(c,u,f)=>{let d=c*24,p=Math.cos(t[d+2]),m=Math.sin(t[d+2]);return[p*u-m*f+t[d],m*u+p*f+t[d+1]]};for(let c=0;c<this.jointCount;c++){if(n[c*j]!==Bi)continue;let u=c*36;if(i[u+8]===0&&i[u+8+1]===0&&i[u+8+2]===0)continue;a++;let f=n[c*j+1],d=n[c*j+2],p=f>=0?l(f,i[u+28],i[u+28+1]):[i[u+28],i[u+28+1]],m=l(d,i[u+28+2],i[u+28+3]);for(let h=0;h<2;h++)i[u+8+h]>=1e30&&(o=Math.max(o,Math.abs(p[h]-m[h])))}return{kineticEnergy:r,maxJointError:o,joints:a}}async read(e,t){if(t===0)return new ArrayBuffer(0);let i=this.device.createBuffer({size:t,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),r=this.device.createCommandEncoder();r.copyBufferToBuffer(e,0,i,0,t),this.device.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ);let o=i.getMappedRange().slice(0);return i.unmap(),i.destroy(),o}releaseTiming(){this.timing?.resolve.destroy(),this.timing?.read.destroy(),this.timing?.querySet.destroy()}destroy(){this.ownsBodyBuffer&&this.bodyBuffer.destroy();let e=[this.jointBuffer,this.infoBuffer,...this.contactBuffers,this.pairBuffer,this.tableBuffer,this.gridBuffer,this.staticBuffer,this.counterBuffer,this.argsBuffer,this.adjBuffer,this.colorBuffer,this.paramsBuffer,this.passBuffer];for(let t of e)t?.destroy();this.destroyed=!0,this.timingBusy||this.releaseTiming(),this.gridScan.destroy(),this.colorHistScan.destroy(),this.adjScan?.destroy()}};var nd=`${Ut}
4789
+ `;var Oo=s=>s===1/0?3e38:s===-1/0?-3e38:s,bt=s=>Math.ceil(s/64),Tc=s=>2**Math.ceil(Math.log2(Math.max(s,2))),od=s=>Math.max(s,1)*24*4,ad=4,yt=()=>GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST,To=class{device;params=ko();topology;bodyCount=0;bodyCapacity;jointCount=0;jointCapacity=0;pairCapacity=0;contactCapacity=0;colorCap=12;splitPasses=!1;primalMode="bucket";shrinkVotes=0;get colorHistOffset(){return 3*this.bodyCapacity+65}colorRounds;bodyBuffer;ownsBodyBuffer;jointBuffer;infoBuffer;contactBuffers;pairBuffer;tableBuffer;gridBuffer;staticBuffer=null;counterBuffer;argsBuffer;adjBuffer=null;colorBuffer;paramsBuffer;passBuffer=null;passEntries=0;parity=0;tableSize;hashSize=0;cellSize=1;maxSmallRadius=0;largeCount=0;noCollideCount=0;staticsDirty=!0;layouts;pipes={};groups;passGroup=null;gridScan;colorHistScan;colorGroups;adjScan=null;timing;timingCallback=null;timingBusy=!1;destroyed=!1;constructor(e,t,i={}){if(this.device=e,this.topology=t,Object.assign(this.params,t.params),this.bodyCount=t.bodyCount,this.colorRounds=i.colorRounds??16,this.ownsBodyBuffer=!i.bodyBuffer,this.bodyCapacity=i.bodyBuffer?Math.floor(i.bodyBuffer.size/96):Math.max(i.bodyCapacity??this.bodyCount+1024,this.bodyCount,1),this.bodyCapacity<this.bodyCount)throw new Error("body buffer too small");this.bodyBuffer=i.bodyBuffer??e.createBuffer({label:"bodies",size:od(this.bodyCapacity),usage:yt()});let r=this.bodyCapacity;this.tableSize=Tc(2*r),this.gridBuffer=e.createBuffer({label:"grid",size:(2*this.tableSize+1+3*r)*4,usage:yt()}),this.counterBuffer=e.createBuffer({label:"counters",size:64,usage:yt()}),this.argsBuffer=e.createBuffer({label:"indirect args",size:816,usage:yt()|GPUBufferUsage.INDIRECT}),this.colorGroups=Math.ceil(r/256),this.colorBuffer=e.createBuffer({label:"colours",size:(3*r+65+64*this.colorGroups+1)*4,usage:yt()}),this.paramsBuffer=e.createBuffer({label:"params",size:128,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),e.queue.writeBuffer(this.colorBuffer,0,new Uint32Array(r).fill(255));let o=2*Se.length;this.timing=e.features.has("timestamp-query")?{querySet:e.createQuerySet({type:"timestamp",count:o}),resolve:e.createBuffer({size:o*8,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),read:e.createBuffer({size:o*8,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST})}:null,this.layouts=this.createLayouts(),this.createPipelines(),this.gridScan=new tt(e,this.gridBuffer,0,this.tableSize+1),this.colorHistScan=new tt(e,this.colorBuffer,this.colorHistOffset,64*this.colorGroups+1),this.jointCount=t.jointCount,this.allocateJoints(t.jointCount+256),this.uploadJoints(0,t.jointCount),this.allocateContacts(Math.max(4096,4*r)),this.uploadBodies()}createLayouts(){let e=this.device,t=(a,n)=>e.createBindGroupLayout({label:a,entries:n.map((l,c)=>({binding:c,visibility:GPUShaderStage.COMPUTE,buffer:{type:l}}))}),i="read-only-storage",r="storage",o="uniform";return{broad:t("broadphase",[o,i,r,r,r,i,i]),contacts:t("contacts",[o,i,i,r,i,r,r]),topo:t("topology",[o,i,i,i,i,r,r,r]),solve:t("solve",[o,r,r,i,r,i,i,i]),pass:e.createBindGroupLayout({label:"pass",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform",hasDynamicOffset:!0,minBindingSize:16}}]}),args:t("args",[o,i,i,r])}}createPipelines(){let e=this.device,t=(r,o,a)=>{let n=e.createShaderModule({code:r}),l=e.createPipelineLayout({bindGroupLayouts:o});for(let c of a)this.pipes[c]=e.createComputePipeline({label:c,layout:l,compute:{module:n,entryPoint:c}})},i=this.layouts;t(ys,[i.broad],["beginFrame","gridCount","gridScatter","findPairs"]),t(vs,[i.contacts],["hashInsert","narrowphase"]),t(Qr,[i.topo],["degreeJoints","degreeContacts","fillJoints","fillContacts","sortAdjacency","colorCompact","colorMark","colorRoundAB","colorRoundBA","colorCount","colorStarts","colorScatter"]),t(xs,[i.solve,i.pass],["warmStartJoints","warmStartBodies","primal","primalScan","dual","refreshStick","updateVelocities"]),t(qs,[i.args],["argsPrev","argsPairs","argsContacts","argsColors"])}allocateJoints(e){let t=this.device,i=t.createBuffer({label:"joints",size:Math.max(e,1)*36*4,usage:yt()}),r=t.createBuffer({label:"joint info",size:Math.max(e,1)*16,usage:yt()});if(this.jointBuffer){let o=t.createCommandEncoder();o.copyBufferToBuffer(this.jointBuffer,0,i,0,this.jointCapacity*36*4),o.copyBufferToBuffer(this.infoBuffer,0,r,0,this.jointCapacity*16),t.queue.submit([o.finish()]),this.jointBuffer.destroy(),this.infoBuffer.destroy()}this.jointBuffer=i,this.infoBuffer=r,this.jointCapacity=e,this.contactBuffers&&this.rebuildBindings()}allocateContacts(e,t=2*e){let i=this.device,r=i.limits.maxStorageBufferBindingSize,o=Math.min(e,Math.floor(r/80),Math.floor(r/16)),a=Math.min(t,Math.floor(r/8)),n=this.contactBuffers,l=this.contactCapacity;for(let c of[this.pairBuffer,this.tableBuffer])c?.destroy();if(this.contactCapacity=o,this.pairCapacity=a,this.hashSize=Tc(4*o),this.pairBuffer=i.createBuffer({label:"pairs",size:a*8,usage:yt()}),this.tableBuffer=i.createBuffer({label:"contact hash",size:this.hashSize*4,usage:yt()}),this.contactBuffers=[0,1].map(c=>i.createBuffer({label:`contacts ${c}`,size:o*20*4,usage:yt()})),n){let c=i.createCommandEncoder(),u=Math.min(l,o)*20*4;n.forEach((f,d)=>c.copyBufferToBuffer(f,0,this.contactBuffers[d],0,u)),i.queue.submit([c.finish()]),n.forEach(f=>f.destroy())}this.rebuildBindings()}rebuildBindings(){let e=this.device,t=this.bodyCapacity;this.adjBuffer?.destroy(),this.adjBuffer=e.createBuffer({label:"adjacency",size:(2*t+1+2*(this.jointCapacity+this.contactCapacity))*4,usage:yt()}),this.adjScan?.destroy(),this.adjScan=new tt(e,this.adjBuffer,0,this.bodyCount+1),this.staticBuffer??=e.createBuffer({label:"statics",size:16,usage:yt()});let i=(l,c)=>e.createBindGroup({layout:l,entries:c.map((u,f)=>({binding:f,resource:{buffer:u}}))}),r=this.paramsBuffer,[o,a]=this.contactBuffers,n=this.adjBuffer;this.groups={broad:i(this.layouts.broad,[r,this.bodyBuffer,this.gridBuffer,this.pairBuffer,this.counterBuffer,this.staticBuffer,this.jointBuffer]),contacts:[i(this.layouts.contacts,[r,this.bodyBuffer,this.pairBuffer,o,a,this.tableBuffer,this.counterBuffer]),i(this.layouts.contacts,[r,this.bodyBuffer,this.pairBuffer,a,o,this.tableBuffer,this.counterBuffer])],topo:[o,a].map(l=>i(this.layouts.topo,[r,this.bodyBuffer,this.jointBuffer,this.infoBuffer,l,this.counterBuffer,n,this.colorBuffer])),solve:[o,a].map(l=>i(this.layouts.solve,[r,this.bodyBuffer,this.jointBuffer,this.infoBuffer,l,n,this.colorBuffer,this.counterBuffer])),args:i(this.layouts.args,[r,this.counterBuffer,this.colorBuffer,this.argsBuffer])}}uploadBodies(e=0,t=this.topology.bodyCount-e){let i=this.topology,r=new Float32Array(Math.max(t,1)*24);for(let o=0;o<t;o++){let a=e+o,n=o*24;r.set(i.pose.subarray(a*4,a*4+3),n),r[n+3]=i.props[a*4],r.set(i.initial.subarray(a*4,a*4+4),n+4),r.set(i.inertial.subarray(a*4,a*4+4),n+8),r.set(i.velocity.subarray(a*4,a*4+4),n+12),r.set(i.prevVelocity.subarray(a*4,a*4+4),n+16),r.set(i.shape.subarray(a*4,a*4+4),n+20)}this.device.queue.writeBuffer(this.bodyBuffer,e*24*4,r),this.staticsDirty=!0}uploadJoints(e,t){if(t===0)return;let i=this.topology,r=new Float32Array(t*36);for(let o=0;o<t;o++){let a=(e+o)*O,n=o*36;for(let l=0;l<3;l++)r[n+0+l]=i.data[a+se+l],r[n+4+l]=i.data[a+te+l],r[n+8+l]=Oo(i.data[a+Q+l]),r[n+12+l]=Oo(i.data[a+_e+l]),r[n+16+l]=Oo(i.data[a+Ae+l]),r[n+20+l]=Oo(i.data[a+Pt+l]),r[n+24+l]=i.data[a+fe+l];r[n+28]=i.data[a+N],r[n+28+1]=i.data[a+N+1],r[n+28+2]=i.data[a+Y],r[n+28+3]=i.data[a+Y+1],r[n+32]=i.data[a+re],r[n+32+1]=i.data[a+be]}this.device.queue.writeBuffer(this.jointBuffer,e*36*4,r),this.device.queue.writeBuffer(this.infoBuffer,e*16,i.info,e*j,t*j)}uploadStatics(){let e=this.topology,t=this.bodyCount,i=Float64Array.from({length:t},(f,d)=>e.props[d*4+1]).sort(),r=t>0?i[t>>1]:1,o=0;for(let f=0;f<t;f++)i[f]<=ad*r&&(o=Math.max(o,i[f]));let a=1/0;for(let f=0;f<t;f++)i[f]>o&&(a=Math.min(a,i[f]));let n=a===1/0?o*1.5:(o+a)/2;this.maxSmallRadius=n,this.cellSize=Math.max(2*o*(1+1e-4),.001);let l=[];for(let f=0;f<t;f++)e.props[f*4+1]>n&&l.push(f);let c=[];for(let f=0;f<e.jointCount;f++){let d=e.info[f*j+1],h=e.info[f*j+2];d>=0&&c.push([Math.max(d,h),Math.min(d,h),f])}for(let f of e.ignoredPairs()){let d=Math.floor(f/2097152);c.push([d,f-d*2097152,4294967295])}c.sort((f,d)=>f[0]-d[0]||f[1]-d[1]),this.largeCount=l.length,this.noCollideCount=c.length;let u=new Uint32Array(Math.max(l.length+3*c.length,4));u.set(l,0),c.forEach((f,d)=>u.set(f,l.length+3*d)),this.staticBuffer.size<u.byteLength&&(this.staticBuffer.destroy(),this.staticBuffer=this.device.createBuffer({label:"statics",size:u.byteLength,usage:yt()}),this.rebuildBindings()),this.device.queue.writeBuffer(this.staticBuffer,0,u),this.staticsDirty=!1}seedContactsFrom(e){let t=e.contactCount;if(t>this.contactCapacity)throw new Error("seedContactsFrom: too many contacts");let i=new ArrayBuffer(Math.max(t,1)*20*4),r=new Uint32Array(i),o=new Float32Array(i);for(let l=0;l<t;l++){let c=e.jointCount+l,u=c*O,f=l*20;r[f]=e.info[c*j+1],r[f+1]=e.info[c*j+2],r[f+2]=e.info[c*j+3],r[f+3]=e.data[u+Hi]?1:0,o.set([e.data[u+se],e.data[u+se+1],e.data[u+te],e.data[u+te+1]],f+4),o.set([e.data[u+N],e.data[u+N+1],e.data[u+Y],e.data[u+Y+1]],f+8),o.set([e.data[u+fe],e.data[u+fe+1],e.data[u+be],e.data[u+Ne]],f+12),o[f+16]=e.data[u+re]}this.device.queue.writeBuffer(this.contactBuffers[1-this.parity],0,i);let a=new Uint32Array(16);a[1]=t,this.device.queue.writeBuffer(this.counterBuffer,0,a);let n=Uint32Array.from({length:this.bodyCount},(l,c)=>(e.coloring.colors[c]??-1)<0?255:e.coloring.colors[c]);this.device.queue.writeBuffer(this.colorBuffer,0,n)}addBody(e,t,i,r,o){if(this.bodyCount>=this.bodyCapacity)return-1;let a=this.topology.addBody(e,t,i,r,o);return this.bodyCount=this.topology.bodyCount,this.uploadBodies(a,1),this.device.queue.writeBuffer(this.colorBuffer,a*4,new Uint32Array([255])),this.adjScan.destroy(),this.adjScan=new tt(this.device,this.adjBuffer,0,this.bodyCount+1),a}appendJoint(e,t,i,r,o,a=1/0){let n=this.topology;if(n.contactCount>0)throw new Error("appendJoint: the CPU mirror must not hold contacts");let l=n.addJoint(e,t,i,r,o,a).slot;return l>=this.jointCapacity&&this.allocateJoints(Math.max(l+1,this.jointCapacity*2)),this.jointCount=l+1,this.uploadJoints(l,1),e>=0&&(this.staticsDirty=!0),l}setWorldAnchor(e,t,i){this.device.queue.writeBuffer(this.jointBuffer,(e*36+28)*4,new Float32Array([t,i]))}disableConstraint(e){this.device.queue.writeBuffer(this.jointBuffer,(e*36+0)*4,new Float32Array(12)),this.topology.data.fill(0,e*O+Q,e*O+Q+3)}profileNextStep(e){this.timing&&!this.timingBusy&&(this.timingCallback=e)}writeParams(e,t){let i=this.params,r=this.bodyCapacity,o=new ArrayBuffer(128),a=new Float32Array(o),n=new Uint32Array(o);a[0]=i.dt,a[1]=i.gravity,a[2]=i.beta,a[3]=i.gamma,a[4]=e,a[5]=i.vbdStiffness,n[6]=(i.vbd?1:0)|(i.stiffnessRescale?2:0)|(t?4:0)|(i.matchNearest?8:0),n[7]=this.bodyCount,n[8]=this.jointCount,n[9]=this.colorCap,a[10]=this.cellSize,n[11]=this.tableSize-1,a[12]=this.maxSmallRadius,n[13]=this.largeCount,n[14]=this.noCollideCount,n[15]=this.pairCapacity,n[16]=this.contactCapacity,n[17]=this.hashSize-1,n[18]=r+1,n[19]=2*r+1,n[20]=this.tableSize+1,n[21]=2*this.tableSize+1,n[22]=2*this.tableSize+1+r,n[23]=r,n[24]=this.colorHistOffset,n[25]=2*r,n[26]=this.colorGroups,n[27]=2*r+65,n[28]=this.colorRounds,this.device.queue.writeBuffer(this.paramsBuffer,0,o)}writePassConstants(e,t){let i=this.colorCap+1,r=e*i;(r>this.passEntries||!this.passGroup)&&(this.passBuffer?.destroy(),this.passBuffer=this.device.createBuffer({label:"pass constants",size:r*256,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.passEntries=r,this.passGroup=this.device.createBindGroup({layout:this.layouts.pass,entries:[{binding:0,resource:{buffer:this.passBuffer,size:16}}]}));let o=new ArrayBuffer(r*256),a=new Uint32Array(o),n=new Float32Array(o);for(let l=0;l<e;l++)for(let c=0;c<=this.colorCap;c++){let u=(l*i+c)*256/4;a[u]=c,n[u+1]=t(l)}this.device.queue.writeBuffer(this.passBuffer,0,o)}step(){this.staticsDirty&&this.uploadStatics();let e=this.params,t=e.postStabilize&&!e.vbd,i=e.vbd?0:e.alpha,r=e.iterations+(t?1:0);this.writeParams(i,t),this.writePassConstants(r,x=>t?x<e.iterations?1:0:i);let o=this.parity,a=this.bodyCapacity,n=this.bodyCount,l=this.jointCount,c=this.device.createCommandEncoder({label:"avbd2d step"});c.clearBuffer(this.gridBuffer,0,(2*this.tableSize+1)*4),c.clearBuffer(this.tableBuffer),c.clearBuffer(this.adjBuffer,0,(2*a+1)*4);let u=this.timingCallback!==null&&this.timing!==null,f,d=0,h=u||this.splitPasses,m=()=>{f&&!h||(f?.end(),f=c.beginComputePass({label:h?Se[d]:"avbd2d step",timestampWrites:u?{querySet:this.timing.querySet,beginningOfPassWriteIndex:2*d,endOfPassWriteIndex:2*d+1}:void 0}),d++)},p=this.groups,g=(x,w,B)=>{B<=0||(f.setPipeline(this.pipes[x]),f.setBindGroup(0,w),f.dispatchWorkgroups(B))},b=(x,w,B)=>{f.setPipeline(this.pipes[x]),f.setBindGroup(0,w),f.dispatchWorkgroupsIndirect(this.argsBuffer,B*4)};m(),g("beginFrame",p.broad,1),g("argsPrev",p.args,1),b("hashInsert",p.contacts[o],6),g("gridCount",p.broad,bt(n)),this.gridScan.encode(f),g("gridScatter",p.broad,bt(n)),g("findPairs",p.broad,bt(n)),g("argsPairs",p.args,1),b("narrowphase",p.contacts[o],0),g("argsContacts",p.args,1),m(),g("degreeJoints",p.topo[o],bt(l)),b("degreeContacts",p.topo[o],3),this.adjScan.encode(f),g("fillJoints",p.topo[o],bt(l)),b("fillContacts",p.topo[o],3),g("sortAdjacency",p.topo[o],bt(n)),m(),g("colorCompact",p.topo[o],bt(n)),g("colorMark",p.topo[o],bt(n));for(let x=0;x<this.colorRounds;x++)g(x%2===0?"colorRoundAB":"colorRoundBA",p.topo[o],bt(n));g("colorCount",p.topo[o],this.colorGroups),this.colorHistScan.encode(f),g("colorStarts",p.topo[o],1),g("argsColors",p.args,1),g("colorScatter",p.topo[o],this.colorGroups),m();let y=this.colorCap+1,A=x=>f.setBindGroup(1,this.passGroup,[x*256]);f.setBindGroup(0,p.solve[o]),A(0),l>0&&(f.setPipeline(this.pipes.warmStartJoints),f.dispatchWorkgroups(bt(l))),f.setPipeline(this.pipes.warmStartBodies),f.dispatchWorkgroups(bt(n));for(let x=0;x<r;x++){let w=this.primalMode==="scan";f.setPipeline(w?this.pipes.primalScan:this.pipes.primal);for(let B=0;B<this.colorCap;B++)A(x*y+B),w?f.dispatchWorkgroups(bt(n)):f.dispatchWorkgroupsIndirect(this.argsBuffer,(12+3*B)*4);x<e.iterations&&(A(x*y+this.colorCap),f.setPipeline(this.pipes.dual),f.dispatchWorkgroupsIndirect(this.argsBuffer,36)),x===e.iterations-1&&(f.setPipeline(this.pipes.updateVelocities),f.dispatchWorkgroups(bt(n)))}t&&(f.setPipeline(this.pipes.refreshStick),f.dispatchWorkgroupsIndirect(this.argsBuffer,12)),f.end();let v=2*Se.length;if(u){let{querySet:x,resolve:w,read:B}=this.timing;c.resolveQuerySet(x,0,v,w,0),c.copyBufferToBuffer(w,0,B,0,v*8)}if(this.device.queue.submit([c.finish()]),this.parity=1-o,u){let x=this.timingCallback;this.timingCallback=null,this.timingBusy=!0;let w=this.timing.read;w.mapAsync(GPUMapMode.READ).then(()=>{let B=new BigUint64Array(w.getMappedRange()).slice();if(w.unmap(),this.timingBusy=!1,this.destroyed)return this.releaseTiming();let L=(I,E)=>Number(B[E]-B[I])/1e6,M={total:L(0,v-1)};Se.forEach((I,E)=>M[I]=L(2*E,2*E+1)),x(M)},()=>{this.timingBusy=!1,this.destroyed&&this.releaseTiming()})}}async readBodies(){return new Float32Array(await this.read(this.bodyBuffer,this.bodyCount*24*4))}async readJoints(){return new Float32Array(await this.read(this.jointBuffer,this.jointCount*36*4))}async readCounters(){let e=new Uint32Array(await this.read(this.counterBuffer,64));return{pairs:e[0],contacts:e[1],overflow:e[3],clashes:e[4],colors:e[5]}}async readContacts(){let{contacts:e}=await this.readCounters(),t=Math.min(e,this.contactCapacity);return this.read(this.contactBuffers[1-this.parity],t*20*4)}async readPairs(){let{pairs:e}=await this.readCounters();return new Uint32Array(await this.read(this.pairBuffer,Math.min(e,this.pairCapacity)*8))}async readColors(){return new Uint32Array(await this.read(this.colorBuffer,this.bodyCount*4))}async readAdjacency(){let e=new Uint32Array(await this.read(this.adjBuffer,this.adjBuffer.size)),t=e.slice(0,this.bodyCount+1),i=2*this.bodyCapacity+1;return{start:t,list:e.slice(i,i+t[this.bodyCount])}}adapt(e){let t=e.colors;e.clashes>0||t>=this.colorCap-1?(this.colorCap=Math.min(64,Math.max(t+4,this.colorCap+4)),this.shrinkVotes=0):t+2<this.colorCap?++this.shrinkVotes>=3&&(this.colorCap=Math.min(64,Math.max(4,t+2)),this.shrinkVotes=0):this.shrinkVotes=0;let i=(e.overflow&2)!==0||e.contacts>.8*this.contactCapacity,r=(e.overflow&1)!==0||e.pairs>.8*this.pairCapacity,o=this.contactCapacity*(i?2:1),a=this.pairCapacity*(r?2:1);(i||r)&&this.capacityCanGrow(o,a)&&this.allocateContacts(o,a)}capacityCanGrow(e,t){let i=this.device.limits.maxStorageBufferBindingSize,r=Math.min(Math.floor(i/80),Math.floor(i/16));return Math.min(e,r)>this.contactCapacity||Math.min(t,Math.floor(i/8))>this.pairCapacity}async readStats(e){let[t,i]=await Promise.all([e??this.readBodies(),this.readJoints()]),r=0;for(let c=0;c<this.bodyCount;c++){let u=c*24,f=t[u+22],d=t[u+12],h=t[u+13],m=t[u+14];f>0&&(r+=.5*f*(d*d+h*h)+.5*t[u+23]*m*m)}let o=0,a=0,n=this.topology.info,l=(c,u,f)=>{let d=c*24,h=Math.cos(t[d+2]),m=Math.sin(t[d+2]);return[h*u-m*f+t[d],m*u+h*f+t[d+1]]};for(let c=0;c<this.jointCount;c++){if(n[c*j]!==Bi)continue;let u=c*36;if(i[u+8]===0&&i[u+8+1]===0&&i[u+8+2]===0)continue;a++;let f=n[c*j+1],d=n[c*j+2],h=f>=0?l(f,i[u+28],i[u+28+1]):[i[u+28],i[u+28+1]],m=l(d,i[u+28+2],i[u+28+3]);for(let p=0;p<2;p++)i[u+8+p]>=1e30&&(o=Math.max(o,Math.abs(h[p]-m[p])))}return{kineticEnergy:r,maxJointError:o,joints:a}}async read(e,t){if(t===0)return new ArrayBuffer(0);let i=this.device.createBuffer({size:t,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),r=this.device.createCommandEncoder();r.copyBufferToBuffer(e,0,i,0,t),this.device.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ);let o=i.getMappedRange().slice(0);return i.unmap(),i.destroy(),o}releaseTiming(){this.timing?.resolve.destroy(),this.timing?.read.destroy(),this.timing?.querySet.destroy()}destroy(){this.ownsBodyBuffer&&this.bodyBuffer.destroy();let e=[this.jointBuffer,this.infoBuffer,...this.contactBuffers,this.pairBuffer,this.tableBuffer,this.gridBuffer,this.staticBuffer,this.counterBuffer,this.argsBuffer,this.adjBuffer,this.colorBuffer,this.paramsBuffer,this.passBuffer];for(let t of e)t?.destroy();this.destroyed=!0,this.timingBusy||this.releaseTiming(),this.gridScan.destroy(),this.colorHistScan.destroy(),this.adjScan?.destroy()}};var nd=`${Ut}
4747
4790
  struct Config { count:u32,joints:u32,capacity:u32,list:u32,threshold:f32,dt:f32,pad0:u32,pad1:u32 }
4748
4791
  struct Velocity { incoming:vec4f, incomingAngular:vec4f, linear:vec4f, angular:vec4f }
4749
4792
  struct Bounce { impulse:f32,delta:f32,reboundSpeed:f32,inverseMass:f32,rA:vec4f,rB:vec4f }
@@ -4864,7 +4907,7 @@ fn rotate(angle:f32,p:vec2f)->vec2f{let c=cos(angle);let s=sin(angle);return vec
4864
4907
  }
4865
4908
  `;function Go(s={}){if(s!==!0&&(typeof s!="object"||s===null))throw Error("sleeping must be a boolean or options object");let e=s.speedThreshold??.03,t=s.timeThreshold??.5;if(![e,t].every(i=>Number.isFinite(i)&&i>0))throw Error("Sleep thresholds must be positive and finite");return{speedThreshold:e,timeThreshold:t}}function Gc(s){for(let e of["warmStartBodies","updateVelocities"])s=s.replace(`fn ${e}(@builtin(global_invocation_id) gid: vec3u) {`,`fn ${e}(@builtin(global_invocation_id) gid: vec3u) {
4866
4909
  if(gid.x<params.bodyCount && bodies[gid.x].vel.w!=0.){return;}`);return s.replace("fn solveBody(i: u32) {",`fn solveBody(i: u32) {
4867
- if(bodies[i].vel.w!=0.){return;}`)}function Fc(s){return s.replace("return i >= 0 && bodies[i].shape.z > 0.0;","return i >= 0 && bodies[i].shape.z > 0.0 && bodies[i].vel.w==0.;")}var Do=class{constructor(e,t){this.gpu=e,this.device=e.device,this.options=Go(t);let i=this.device,r=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC;this.state=i.createBuffer({size:e.bodyCapacity*16,usage:r}),this.globals=i.createBuffer({size:8,usage:r}),this.params=i.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=i.createShaderModule({code:Dc});this.layout=i.createBindGroupLayout({entries:["storage","storage","read-only-storage","read-only-storage","read-only-storage","read-only-storage","storage","uniform"].map((l,c)=>({binding:c,visibility:GPUShaderStage.COMPUTE,buffer:{type:l}}))});let a=i.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipes=Object.fromEntries(["clear","before","contactsWake","jointsWake","decide","applyWake","rest"].map(l=>[l,i.createComputePipeline({layout:a,compute:{module:o,entryPoint:l}})]));let n=new Uint32Array(e.bodyCapacity*4);for(let l=0;l<e.bodyCount;l++)n[l*4+1]=e.sleepEligible?.get(l)===!1?0:1;i.queue.writeBuffer(this.state,0,n),this.wakeRequested=!1}register(e,t=!0){let i=oe(this.gpu);for(let r=0;r<4;r++)i.uint(this.state,e*4+r,r===1?Number(t):0);this.wakeRequested=!0}group(e){let t=this.gpu,i=[t.bodyBuffer,this.state,t.infoBuffer,t.jointBuffer,t.contactBuffers[e],t.counterBuffer,this.globals,this.params],r=this.groups?.find(o=>o.buffers.every((a,n)=>a===i[n]));return r||(r={buffers:i,group:this.device.createBindGroup({layout:this.layout,entries:i.map((o,a)=>({binding:a,resource:{buffer:o}}))})},this.groups=[...(this.groups??[]).slice(-1),r]),r.group}dispatch(e,t,i){e.setBindGroup(0,this.group(t));for(let[r,o]of i)o&&(e.setPipeline(this.pipes[r]),e.dispatchWorkgroups(Math.ceil(o/64)))}run(e,t){let i=t??this.device.createCommandEncoder(),r=i.beginComputePass();this.dispatch(r,1-this.gpu.parity,e),r.end(),t||this.device.queue.submit([i.finish()])}before(e){this.gpu.flushPropertyEdits(e);let t=this.gpu,i=this.paramData??=hi(8),{u:r,f:o}=i;r[0]=t.bodyCount,r[1]=t.jointCount,r[2]=t.contactCapacity,r[3]=Number(this.wakeRequested),o[4]=this.options.speedThreshold,o[5]=this.options.timeThreshold,o[6]=t.params.dt,o[7]=t.params.gravity,Qt(this.device,this.params,i),this.wakeRequested=!1,this.run([["clear",1],["before",t.bodyCount]],e)}encodeWake(e,t){let i=this.gpu;this.dispatch(e,t,[["contactsWake",i.contactCapacity],["jointsWake",i.jointCount],["decide",i.bodyCount],["applyWake",i.bodyCount]])}after(e){this.run([["rest",this.gpu.bodyCount]],e)}async readStats(){let e=new Uint32Array(await this.gpu.read(this.globals,8));return{sleeping:e[1],wakeRequested:this.wakeRequested||!!e[0]}}destroy(){this.gpu.propertyEdits?.forget(this.state),this.state.destroy(),this.globals.destroy(),this.params.destroy()}};var vt=s=>Math.ceil(s/64);function Uc(){this.staticsDirty&&this.uploadStatics();let s=this.params,e=s.postStabilize&&!s.vbd,t=s.vbd?0:s.alpha,i=s.iterations+(e?1:0);this.writeParams(t,e),this.writePassConstants(i,L=>e?L<s.iterations?1:0:t);let r=this.parity,o=this.bodyCapacity,a=this.bodyCount,n=this.jointCount,l=this.device.createCommandEncoder({label:"avbd2d step"});this.encodeStepPrelude?.(l),l.clearBuffer(this.gridBuffer,0,(2*this.tableSize+1)*4),l.clearBuffer(this.tableBuffer),l.clearBuffer(this.adjBuffer,0,(2*o+1)*4);let c=this.timingCallback!==null&&this.timing!==null,u,f,d=0,p=c||this.splitPasses,m=()=>{u&&!p||(u?.end(),u=l.beginComputePass({label:p?Se[d]:"avbd2d step",timestampWrites:c?{querySet:this.timing.querySet,beginningOfPassWriteIndex:2*d,endOfPassWriteIndex:2*d+1}:void 0}),f=void 0,d++)},h=this.groups,g=L=>{f!==L&&(u.setBindGroup(0,L),f=L)},b=(L,M,I)=>{I<=0||(u.setPipeline(this.pipes[L]),g(M),u.dispatchWorkgroups(I))},y=(L,M,I)=>{u.setPipeline(this.pipes[L]),g(M),u.dispatchWorkgroupsIndirect(this.argsBuffer,I*4)};m(),b("beginFrame",h.broad,1),b("argsPrev",h.args,1),y("hashInsert",h.contacts[r],6),b("gridCount",h.broad,vt(a)),this.gridScan.encode(u),f=void 0,b("gridScatter",h.broad,vt(a)),b("findPairs",h.broad,vt(a)),b("argsPairs",h.args,1),y("narrowphase",h.contacts[r],0),b("argsContacts",h.args,1),this.sleeping?.encodeWake(u,r),f=void 0,m(),b("degreeJoints",h.topo[r],vt(n)),y("degreeContacts",h.topo[r],3),this.adjScan.encode(u),f=void 0,b("fillJoints",h.topo[r],vt(n)),y("fillContacts",h.topo[r],3),b("sortAdjacency",h.topo[r],vt(a)),m(),b("colorCompact",h.topo[r],vt(a)),b("colorMark",h.topo[r],vt(a));for(let L=0;L<this.colorRounds;L++)b(L%2===0?"colorRoundAB":"colorRoundBA",h.topo[r],vt(a));b("colorCount",h.topo[r],this.colorGroups),this.colorHistScan.encode(u),f=void 0,b("colorStarts",h.topo[r],1),b("argsColors",h.args,1),b("colorScatter",h.topo[r],this.colorGroups),m();let A=this.colorCap+1,v=this.passOffsets??=[0],x=-1,w=L=>{L!==x&&(v[0]=L*256,u.setBindGroup(1,this.passGroup,v),x=L)};u.setBindGroup(0,h.solve[r]),w(0),n>0&&(u.setPipeline(this.pipes.warmStartJoints),u.dispatchWorkgroups(vt(n))),u.setPipeline(this.pipes.warmStartBodies),u.dispatchWorkgroups(vt(a));for(let L=0;L<i;L++){let M=this.primalMode==="scan";u.setPipeline(M?this.pipes.primalScan:this.pipes.primal);for(let I=0;I<this.colorCap;I++)w(L*A+I),M?u.dispatchWorkgroups(vt(a)):u.dispatchWorkgroupsIndirect(this.argsBuffer,(12+3*I)*4);L<s.iterations&&(w(L*A+this.colorCap),u.setPipeline(this.pipes.dual),u.dispatchWorkgroupsIndirect(this.argsBuffer,36)),L===s.iterations-1&&(u.setPipeline(this.pipes.updateVelocities),u.dispatchWorkgroups(vt(a)))}e&&(u.setPipeline(this.pipes.refreshStick),u.dispatchWorkgroupsIndirect(this.argsBuffer,12)),u.end();let B=2*Se.length;if(c){let{querySet:L,resolve:M,read:I}=this.timing;l.resolveQuerySet(L,0,B,M,0),l.copyBufferToBuffer(M,0,I,0,B*8)}if(this.parity=1-r,this.encodeStepPostlude?.(l),this.device.queue.submit([l.finish()]),c){let L=this.timingCallback;this.timingCallback=null,this.timingBusy=!0;let M=this.timing.read;M.mapAsync(GPUMapMode.READ).then(()=>{let I=new BigUint64Array(M.getMappedRange()).slice();if(M.unmap(),this.timingBusy=!1,this.destroyed)return this.releaseTiming();let E=(P,C)=>Number(I[C]-I[P])/1e6,k={total:E(0,B-1)};Se.forEach((P,C)=>k[P]=E(2*C,2*C+1)),L(k)},()=>{this.timingBusy=!1,this.destroyed&&this.releaseTiming()})}}var Fo=5;function ki({minAngle:s=-Math.PI,maxAngle:e=Math.PI}={}){if(!Number.isFinite(s)||!Number.isFinite(e)||s>e)throw Error("Angle limits require finite minAngle <= maxAngle, in radians");return{minAngle:s,maxAngle:e}}function Bs(s,e,t){let i=e*O;s.info[e*j]=Fo,s.data.set([1/0,1/0,0],i+Q),s.data.set([-1/0,0,0],i+_e),s.data.set([0,1/0,0],i+Ae),s.data[i+be]=t.minAngle,s.data[i+Ue]=t.maxAngle}function Nc(s){let e=s.topology;for(let t=0;t<e.jointCount;t++)e.info[t*j]===Fo&&s.device.queue.writeBuffer(s.jointBuffer,(t*36+32)*4,new Float32Array([e.data[t*O+re],e.data[t*O+be],e.data[t*O+Ue],0]))}var ws=(s,e,t)=>{if(s.split(e).length!==2)throw Error("Pinned 2D angular layout changed");return s.replace(e,t)};function qc(s){return s=ws(s,"case T_JOINT: { return 3u; }",`case T_JOINT: { return 3u; }
4910
+ if(bodies[i].vel.w!=0.){return;}`)}function Fc(s){return s.replace("return i >= 0 && bodies[i].shape.z > 0.0;","return i >= 0 && bodies[i].shape.z > 0.0 && bodies[i].vel.w==0.;")}var Do=class{constructor(e,t){this.gpu=e,this.device=e.device,this.options=Go(t);let i=this.device,r=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC;this.state=i.createBuffer({size:e.bodyCapacity*16,usage:r}),this.globals=i.createBuffer({size:8,usage:r}),this.params=i.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let o=i.createShaderModule({code:Dc});this.layout=i.createBindGroupLayout({entries:["storage","storage","read-only-storage","read-only-storage","read-only-storage","read-only-storage","storage","uniform"].map((l,c)=>({binding:c,visibility:GPUShaderStage.COMPUTE,buffer:{type:l}}))});let a=i.createPipelineLayout({bindGroupLayouts:[this.layout]});this.pipes=Object.fromEntries(["clear","before","contactsWake","jointsWake","decide","applyWake","rest"].map(l=>[l,i.createComputePipeline({layout:a,compute:{module:o,entryPoint:l}})]));let n=new Uint32Array(e.bodyCapacity*4);for(let l=0;l<e.bodyCount;l++)n[l*4+1]=e.sleepEligible?.get(l)===!1?0:1;i.queue.writeBuffer(this.state,0,n),this.wakeRequested=!1}register(e,t=!0){let i=oe(this.gpu);for(let r=0;r<4;r++)i.uint(this.state,e*4+r,r===1?Number(t):0);this.wakeRequested=!0}group(e){let t=this.gpu,i=[t.bodyBuffer,this.state,t.infoBuffer,t.jointBuffer,t.contactBuffers[e],t.counterBuffer,this.globals,this.params],r=this.groups?.find(o=>o.buffers.every((a,n)=>a===i[n]));return r||(r={buffers:i,group:this.device.createBindGroup({layout:this.layout,entries:i.map((o,a)=>({binding:a,resource:{buffer:o}}))})},this.groups=[...(this.groups??[]).slice(-1),r]),r.group}dispatch(e,t,i){e.setBindGroup(0,this.group(t));for(let[r,o]of i)o&&(e.setPipeline(this.pipes[r]),e.dispatchWorkgroups(Math.ceil(o/64)))}run(e,t){let i=t??this.device.createCommandEncoder(),r=i.beginComputePass();this.dispatch(r,1-this.gpu.parity,e),r.end(),t||this.device.queue.submit([i.finish()])}before(e){this.gpu.flushPropertyEdits(e);let t=this.gpu,i=this.paramData??=pi(8),{u:r,f:o}=i;r[0]=t.bodyCount,r[1]=t.jointCount,r[2]=t.contactCapacity,r[3]=Number(this.wakeRequested),o[4]=this.options.speedThreshold,o[5]=this.options.timeThreshold,o[6]=t.params.dt,o[7]=t.params.gravity,Qt(this.device,this.params,i),this.wakeRequested=!1,this.run([["clear",1],["before",t.bodyCount]],e)}encodeWake(e,t){let i=this.gpu;this.dispatch(e,t,[["contactsWake",i.contactCapacity],["jointsWake",i.jointCount],["decide",i.bodyCount],["applyWake",i.bodyCount]])}after(e){this.run([["rest",this.gpu.bodyCount]],e)}async readStats(){let e=new Uint32Array(await this.gpu.read(this.globals,8));return{sleeping:e[1],wakeRequested:this.wakeRequested||!!e[0]}}destroy(){this.gpu.propertyEdits?.forget(this.state),this.state.destroy(),this.globals.destroy(),this.params.destroy()}};var vt=s=>Math.ceil(s/64);function Uc(){this.staticsDirty&&this.uploadStatics();let s=this.params,e=s.postStabilize&&!s.vbd,t=s.vbd?0:s.alpha,i=s.iterations+(e?1:0);this.writeParams(t,e),this.writePassConstants(i,L=>e?L<s.iterations?1:0:t);let r=this.parity,o=this.bodyCapacity,a=this.bodyCount,n=this.jointCount,l=this.device.createCommandEncoder({label:"avbd2d step"});this.encodeStepPrelude?.(l),l.clearBuffer(this.gridBuffer,0,(2*this.tableSize+1)*4),l.clearBuffer(this.tableBuffer),l.clearBuffer(this.adjBuffer,0,(2*o+1)*4);let c=this.timingCallback!==null&&this.timing!==null,u,f,d=0,h=c||this.splitPasses,m=()=>{u&&!h||(u?.end(),u=l.beginComputePass({label:h?Se[d]:"avbd2d step",timestampWrites:c?{querySet:this.timing.querySet,beginningOfPassWriteIndex:2*d,endOfPassWriteIndex:2*d+1}:void 0}),f=void 0,d++)},p=this.groups,g=L=>{f!==L&&(u.setBindGroup(0,L),f=L)},b=(L,M,I)=>{I<=0||(u.setPipeline(this.pipes[L]),g(M),u.dispatchWorkgroups(I))},y=(L,M,I)=>{u.setPipeline(this.pipes[L]),g(M),u.dispatchWorkgroupsIndirect(this.argsBuffer,I*4)};m(),b("beginFrame",p.broad,1),b("argsPrev",p.args,1),y("hashInsert",p.contacts[r],6),b("gridCount",p.broad,vt(a)),this.gridScan.encode(u),f=void 0,b("gridScatter",p.broad,vt(a)),b("findPairs",p.broad,vt(a)),b("argsPairs",p.args,1),y("narrowphase",p.contacts[r],0),b("argsContacts",p.args,1),this.sleeping?.encodeWake(u,r),f=void 0,m(),b("degreeJoints",p.topo[r],vt(n)),y("degreeContacts",p.topo[r],3),this.adjScan.encode(u),f=void 0,b("fillJoints",p.topo[r],vt(n)),y("fillContacts",p.topo[r],3),b("sortAdjacency",p.topo[r],vt(a)),m(),b("colorCompact",p.topo[r],vt(a)),b("colorMark",p.topo[r],vt(a));for(let L=0;L<this.colorRounds;L++)b(L%2===0?"colorRoundAB":"colorRoundBA",p.topo[r],vt(a));b("colorCount",p.topo[r],this.colorGroups),this.colorHistScan.encode(u),f=void 0,b("colorStarts",p.topo[r],1),b("argsColors",p.args,1),b("colorScatter",p.topo[r],this.colorGroups),m();let A=this.colorCap+1,v=this.passOffsets??=[0],x=-1,w=L=>{L!==x&&(v[0]=L*256,u.setBindGroup(1,this.passGroup,v),x=L)};u.setBindGroup(0,p.solve[r]),w(0),n>0&&(u.setPipeline(this.pipes.warmStartJoints),u.dispatchWorkgroups(vt(n))),u.setPipeline(this.pipes.warmStartBodies),u.dispatchWorkgroups(vt(a));for(let L=0;L<i;L++){let M=this.primalMode==="scan";u.setPipeline(M?this.pipes.primalScan:this.pipes.primal);for(let I=0;I<this.colorCap;I++)w(L*A+I),M?u.dispatchWorkgroups(vt(a)):u.dispatchWorkgroupsIndirect(this.argsBuffer,(12+3*I)*4);L<s.iterations&&(w(L*A+this.colorCap),u.setPipeline(this.pipes.dual),u.dispatchWorkgroupsIndirect(this.argsBuffer,36)),L===s.iterations-1&&(u.setPipeline(this.pipes.updateVelocities),u.dispatchWorkgroups(vt(a)))}e&&(u.setPipeline(this.pipes.refreshStick),u.dispatchWorkgroupsIndirect(this.argsBuffer,12)),u.end();let B=2*Se.length;if(c){let{querySet:L,resolve:M,read:I}=this.timing;l.resolveQuerySet(L,0,B,M,0),l.copyBufferToBuffer(M,0,I,0,B*8)}if(this.parity=1-r,this.encodeStepPostlude?.(l),this.device.queue.submit([l.finish()]),c){let L=this.timingCallback;this.timingCallback=null,this.timingBusy=!0;let M=this.timing.read;M.mapAsync(GPUMapMode.READ).then(()=>{let I=new BigUint64Array(M.getMappedRange()).slice();if(M.unmap(),this.timingBusy=!1,this.destroyed)return this.releaseTiming();let E=(P,C)=>Number(I[C]-I[P])/1e6,k={total:E(0,B-1)};Se.forEach((P,C)=>k[P]=E(2*C,2*C+1)),L(k)},()=>{this.timingBusy=!1,this.destroyed&&this.releaseTiming()})}}var Fo=5;function ki({minAngle:s=-Math.PI,maxAngle:e=Math.PI}={}){if(!Number.isFinite(s)||!Number.isFinite(e)||s>e)throw Error("Angle limits require finite minAngle <= maxAngle, in radians");return{minAngle:s,maxAngle:e}}function Bs(s,e,t){let i=e*O;s.info[e*j]=Fo,s.data.set([1/0,1/0,0],i+Q),s.data.set([-1/0,0,0],i+_e),s.data.set([0,1/0,0],i+Ae),s.data[i+be]=t.minAngle,s.data[i+Ne]=t.maxAngle}function Nc(s){let e=s.topology;for(let t=0;t<e.jointCount;t++)e.info[t*j]===Fo&&s.device.queue.writeBuffer(s.jointBuffer,(t*36+32)*4,new Float32Array([e.data[t*O+re],e.data[t*O+be],e.data[t*O+Ne],0]))}var ws=(s,e,t)=>{if(s.split(e).length!==2)throw Error("Pinned 2D angular layout changed");return s.replace(e,t)};function qc(s){return s=ws(s,"case T_JOINT: { return 3u; }",`case T_JOINT: { return 3u; }
4868
4911
  case 5: { return 2u; }`),s=ws(s,"fn jointRowsC(j: u32, alpha: f32) -> vec3f {",`
4869
4912
  fn limitAngle2D(k:Joint,a:i32,b:i32)->f32 {
4870
4913
  var angleA=0.;if(a>=0){angleA=bodies[a].pose.z;}
@@ -5040,7 +5083,7 @@ fn collideShapes2D(a:u32,b:u32)->Collision {
5040
5083
  }
5041
5084
  out.count=count;return out;
5042
5085
  }
5043
- `;var On=new WeakMap,Gr=(s,e,t=!1)=>{if(!Number.isFinite(s)||(t?s<0:s<=0))throw Error(`${e} must be ${t?"nonnegative":"positive"} and finite`);return s},Uo=(s,e)=>{if(!s||s.length!==2||!Array.from(s).every(Number.isFinite))throw Error(`${e} requires two finite components`);return Array.from(s)},ei=s=>On.get(s);function No(s){let e=Array.from(s??[]),t=typeof e[0]=="number"?e:e.flatMap(w=>Uo(w,"Hull point"));if(t.length<6||t.length%2||!t.every(Number.isFinite))throw Error("A 2D hull requires finite xy pairs spanning an area");let i=[];for(let w=0;w<t.length;w+=2)i.push([t[w],t[w+1]]);i.sort((w,B)=>w[0]-B[0]||w[1]-B[1]);let r=i.filter((w,B)=>!B||w[0]!==i[B-1][0]||w[1]!==i[B-1][1]),o=(w,B,L)=>(B[0]-w[0])*(L[1]-w[1])-(B[1]-w[1])*(L[0]-w[0]),a=w=>{let B=[];for(let L of w){for(;B.length>1&&o(B.at(-2),B.at(-1),L)<=0;)B.pop();B.push(L)}return B.slice(0,-1)},n=[...a(r),...a([...r].reverse())];if(n.length<3||n.length>32)throw Error("A 2D hull needs 3\u201332 boundary vertices spanning an area");let l=n[0],c=n.map(w=>[w[0]-l[0],w[1]-l[1]]),u=0,f=0,d=0;for(let w=0;w<c.length;w++){let B=c[w],L=c[(w+1)%c.length],M=B[0]*L[1]-L[0]*B[1];u+=M,f+=(B[0]+L[0])*M,d+=(B[1]+L[1])*M}if(!(u>0)||!Number.isFinite(u))throw Error("Hull area must be positive and finite");f/=3*u,d/=3*u;let p=c.map(w=>[w[0]-f,w[1]-d]),m=0,h=0,g=0,b=0,y=[];for(let w=0;w<p.length;w++){let B=p[w],L=p[(w+1)%p.length],M=B[0]*L[1]-L[0]*B[1];m+=M*(B[0]*B[0]+B[0]*L[0]+L[0]*L[0]+B[1]*B[1]+B[1]*L[1]+L[1]*L[1])/12;let I=L[0]-B[0],E=L[1]-B[1],k=Math.hypot(I,E);y.push(B[0],B[1],E/k,-I/k),h=Math.max(h,Math.hypot(...B)),g=Math.max(g,Math.abs(B[0])),b=Math.max(b,Math.abs(B[1]))}let A=u/2,v=m/A;if(![A,v,h,g,b,...y].every(w=>Number.isFinite(Math.fround(w)))||Math.fround(A)<=0||Math.fround(v)<=0)throw Error("Hull geometry exceeds GPU floating-point range");let x=[4,h,0,p.length];return x.vertices=y,{geometry:x,size:[2*g,2*b],area:A,momentPerMass:v,radius:h}}function qo(s){let e=Gr(s,"radius");return{geometry:[1,e,0,0],size:[2*e,2*e],area:Math.PI*e*e,momentPerMass:e*e/2,radius:e}}function Vo(s,e){let t=Gr(s,"radius");if(Gr(e,"length"),e<2*t)throw Error("Capsule length must be at least twice its radius");return Wc((e-2*t)/2,t)}function Wc(s,e){let t=2*s,i=2*e*t,r=Math.PI*e*e,o=i+r,a=i*(t*t+4*e*e)/12+r*(t*t/4+e*e/2+4*t*e/(3*Math.PI));return{geometry:[2,e,s,0],size:[t+2*e,Math.max(2*e,1e-6)],area:o,momentPerMass:o?a/o:0,radius:s+e}}function Wo(s,e,t={}){let i=Uo(s,"start"),r=Uo(e,"end"),o=r[0]-i[0],a=r[1]-i[1],n=Math.hypot(o,a),l=Gr(t.radius??0,"radius",!0);if(Gr(n,"segment length"),t.position!==void 0||t.angle!==void 0)throw Error("Segment position and angle come from its endpoints");if(l===0&&(t.density??0)!==0)throw Error("A zero-thickness segment must be static; give it a radius for a dynamic capsule");return{...Wc(n/2,l),options:{...t,density:t.density??0,position:[(i[0]+r[0])/2,(i[1]+r[1])/2],angle:Math.atan2(a,o)}}}function Ho(s,e=0,t={}){let i=Uo(s,"normal"),r=Gr(Math.hypot(...i),"normal length");if(!Number.isFinite(e))throw Error("Plane offset must be finite");if((t.density??0)!==0)throw Error("An infinite plane must be static");if(t.position!==void 0||t.angle!==void 0)throw Error("Plane position and angle come from its normal and offset");let o=i[0]/r,a=i[1]/r;return{geometry:[3,0,0,0],size:[1,1],area:0,momentPerMass:0,radius:0,options:{...t,density:0,position:[o*e,a*e],angle:Math.atan2(-o,a)}}}function Fr(s,e,t,i){let r=On.get(s);r||On.set(s,r=new Map),r.set(e,t.geometry);let o=t.area*i,a=e*4;s.shape[a+2]=o,s.shape[a+3]=o*t.momentPerMass,s.props[a+1]=t.radius,s.dynamic[e]=+(o>0)}var Hc=`struct Body {pose:vec4f,initial:vec4f,inertial:vec4f,velocity:vec4f,previous:vec4f,shape:vec4f}
5086
+ `;var On=new WeakMap,Gr=(s,e,t=!1)=>{if(!Number.isFinite(s)||(t?s<0:s<=0))throw Error(`${e} must be ${t?"nonnegative":"positive"} and finite`);return s},Uo=(s,e)=>{if(!s||s.length!==2||!Array.from(s).every(Number.isFinite))throw Error(`${e} requires two finite components`);return Array.from(s)},ei=s=>On.get(s);function No(s){let e=Array.from(s??[]),t=typeof e[0]=="number"?e:e.flatMap(w=>Uo(w,"Hull point"));if(t.length<6||t.length%2||!t.every(Number.isFinite))throw Error("A 2D hull requires finite xy pairs spanning an area");let i=[];for(let w=0;w<t.length;w+=2)i.push([t[w],t[w+1]]);i.sort((w,B)=>w[0]-B[0]||w[1]-B[1]);let r=i.filter((w,B)=>!B||w[0]!==i[B-1][0]||w[1]!==i[B-1][1]),o=(w,B,L)=>(B[0]-w[0])*(L[1]-w[1])-(B[1]-w[1])*(L[0]-w[0]),a=w=>{let B=[];for(let L of w){for(;B.length>1&&o(B.at(-2),B.at(-1),L)<=0;)B.pop();B.push(L)}return B.slice(0,-1)},n=[...a(r),...a([...r].reverse())];if(n.length<3||n.length>32)throw Error("A 2D hull needs 3\u201332 boundary vertices spanning an area");let l=n[0],c=n.map(w=>[w[0]-l[0],w[1]-l[1]]),u=0,f=0,d=0;for(let w=0;w<c.length;w++){let B=c[w],L=c[(w+1)%c.length],M=B[0]*L[1]-L[0]*B[1];u+=M,f+=(B[0]+L[0])*M,d+=(B[1]+L[1])*M}if(!(u>0)||!Number.isFinite(u))throw Error("Hull area must be positive and finite");f/=3*u,d/=3*u;let h=c.map(w=>[w[0]-f,w[1]-d]),m=0,p=0,g=0,b=0,y=[];for(let w=0;w<h.length;w++){let B=h[w],L=h[(w+1)%h.length],M=B[0]*L[1]-L[0]*B[1];m+=M*(B[0]*B[0]+B[0]*L[0]+L[0]*L[0]+B[1]*B[1]+B[1]*L[1]+L[1]*L[1])/12;let I=L[0]-B[0],E=L[1]-B[1],k=Math.hypot(I,E);y.push(B[0],B[1],E/k,-I/k),p=Math.max(p,Math.hypot(...B)),g=Math.max(g,Math.abs(B[0])),b=Math.max(b,Math.abs(B[1]))}let A=u/2,v=m/A;if(![A,v,p,g,b,...y].every(w=>Number.isFinite(Math.fround(w)))||Math.fround(A)<=0||Math.fround(v)<=0)throw Error("Hull geometry exceeds GPU floating-point range");let x=[4,p,0,h.length];return x.vertices=y,{geometry:x,size:[2*g,2*b],area:A,momentPerMass:v,radius:p}}function qo(s){let e=Gr(s,"radius");return{geometry:[1,e,0,0],size:[2*e,2*e],area:Math.PI*e*e,momentPerMass:e*e/2,radius:e}}function Vo(s,e){let t=Gr(s,"radius");if(Gr(e,"length"),e<2*t)throw Error("Capsule length must be at least twice its radius");return Wc((e-2*t)/2,t)}function Wc(s,e){let t=2*s,i=2*e*t,r=Math.PI*e*e,o=i+r,a=i*(t*t+4*e*e)/12+r*(t*t/4+e*e/2+4*t*e/(3*Math.PI));return{geometry:[2,e,s,0],size:[t+2*e,Math.max(2*e,1e-6)],area:o,momentPerMass:o?a/o:0,radius:s+e}}function Wo(s,e,t={}){let i=Uo(s,"start"),r=Uo(e,"end"),o=r[0]-i[0],a=r[1]-i[1],n=Math.hypot(o,a),l=Gr(t.radius??0,"radius",!0);if(Gr(n,"segment length"),t.position!==void 0||t.angle!==void 0)throw Error("Segment position and angle come from its endpoints");if(l===0&&(t.density??0)!==0)throw Error("A zero-thickness segment must be static; give it a radius for a dynamic capsule");return{...Wc(n/2,l),options:{...t,density:t.density??0,position:[(i[0]+r[0])/2,(i[1]+r[1])/2],angle:Math.atan2(a,o)}}}function Ho(s,e=0,t={}){let i=Uo(s,"normal"),r=Gr(Math.hypot(...i),"normal length");if(!Number.isFinite(e))throw Error("Plane offset must be finite");if((t.density??0)!==0)throw Error("An infinite plane must be static");if(t.position!==void 0||t.angle!==void 0)throw Error("Plane position and angle come from its normal and offset");let o=i[0]/r,a=i[1]/r;return{geometry:[3,0,0,0],size:[1,1],area:0,momentPerMass:0,radius:0,options:{...t,density:0,position:[o*e,a*e],angle:Math.atan2(-o,a)}}}function Fr(s,e,t,i){let r=On.get(s);r||On.set(s,r=new Map),r.set(e,t.geometry);let o=t.area*i,a=e*4;s.shape[a+2]=o,s.shape[a+3]=o*t.momentPerMass,s.props[a+1]=t.radius,s.dynamic[e]=+(o>0)}var Hc=`struct Body {pose:vec4f,initial:vec4f,inertial:vec4f,velocity:vec4f,previous:vec4f,shape:vec4f}
5044
5087
  struct Command { header:vec4u, value:vec4f, point:vec4f }
5045
5088
  @group(0) @binding(0) var<storage,read_write> bodies:array<Body>;
5046
5089
  @group(0) @binding(1) var<storage,read> commands:array<Command>;
@@ -5076,7 +5119,7 @@ fn edit(@builtin(global_invocation_id) id:vec3u) {
5076
5119
  bodies[index]=b;
5077
5120
  }
5078
5121
  \r
5079
- `;function Vt(s,e){let t=s&&typeof s.x=="number"?[s.x,s.y]:Array.isArray(s)||ArrayBuffer.isView(s)&&!(s instanceof DataView)?s:Array.from(s??[]);if(t.length!==2||!t.every(Number.isFinite))throw Error(`${e} requires two finite components`);return t}var ti=class{constructor(){this.count=0,this.capacity=0}reserve(e){if(e<=this.capacity)return;let t=Math.max(e,this.capacity*2,64),i=new ArrayBuffer(t*48),r=new Float32Array(i),o=new Uint32Array(i);this.u32&&o.set(this.u32.subarray(0,this.count*12)),this.words=r,this.u32=o,this.capacity=t}append(e,t,i,r,o=!1){this.reserve(this.count+1),$c(this.words,this.u32,this.count++*12,e,t,i,r,o)}};function $c(s,e,t,i,r,o,a,n){e[t]=i,e[t+1]=r,e[t+2]=Number(n),e[t+3]=0;for(let l=0;l<4;l++)s[t+4+l]=o[l]??0,s[t+8+l]=a?.[l]??0}var Ur=class{constructor(e,t=Hc,i=2){this.solver=e,this.shader=t,this.dimension=i,this.pending=new Map,this.queue=new ti,this.requested=0,this.linearOnly=!0,this.angularOnly=!0,this.hasTeleports=!1,this.motionOnly=!0,this.freeRanges=[]}slot(e,t){this.requested++,this.linearOnly&&=t===0,this.angularOnly&&=t===1,this.motionOnly&&=t===0||t===1,this.hasTeleports||=t===4;let i=this.pending.get(e);if(i&&(t===0||t===1)&&this.queue.u32[i.tail*12+1]===t)return i.tail;if(this.queue.reserve(this.queue.count+1),!this.next||this.next.length<this.queue.capacity){let o=new Int32Array(this.queue.capacity);this.next&&o.set(this.next),this.next=o}let r=this.queue.count++;return this.next[r]=-1,i?(this.next[i.tail]=r,i.tail=r,i.length++):(i=this.freeRanges.pop()??{},i.head=i.tail=r,i.length=1,this.pending.set(e,i)),r}enqueue(e,t,i,r,o=!1){let a=this.slot(e,t);$c(this.queue.words,this.queue.u32,a*12,e,t,i,r,o)}enqueueValidated(e){for(let t=0;t<e.count;t++){let i=t*12,r=this.slot(e.u32[i],e.u32[i+1])*12;for(let o=0;o<12;o++)this.queue.u32[r+o]=e.u32[i+o]}}flush(e){if(!this.pending.size)return;let t=this.solver.device,i=this.pending.size;if(this.linearOnly||this.angularOnly){let r=this.angularOnly&&this.dimension===2?1:this.dimension;if(!this.linearIndices||this.linearIndices.length<i){let l=Math.max(i,(this.linearIndices?.length??0)*2,64);this.linearIndices=new Uint32Array(l),this.linearValues=new Float32Array(l*this.dimension)}let o=0;for(let[l,c]of this.pending){this.linearIndices[o]=l;for(let u=0;u<r;u++)this.linearValues[o*r+u]=this.queue.words[c.tail*12+4+u];o++}let a=this.angularOnly?"angularVelocityBatch":"velocityBatch",n=this.solver[a]??=new Kt(this.solver,this.dimension,this.angularOnly?"angular":"linear");n.submitValidated(this.linearIndices.subarray(0,i),this.linearValues.subarray(0,i*r),e),this.lastBatch={bodies:i,commands:this.queue.count,requestedCommands:this.requested,uploadedBytes:n.lastBatch.uploadedBytes,path:this.angularOnly?"packed-angular-velocities":"packed-velocities",submissions:e?0:1}}else if(this.motionOnly){let r=this.motionBatch??=new yi(this.solver,this.dimension),o=r.wordsPerBody;(!this.motionData||this.motionData.length<i*o)&&(this.motionData=new Uint32Array(Math.max(i*o,(this.motionData?.length??0)*2,64*o)),this.motionFloats=new Float32Array(this.motionData.buffer));let a=0;for(let[n,l]of this.pending){let c=a++*o;this.motionData[c]=n;let u=0;for(let f=l.head;f!==-1;f=this.next[f]){let d=this.queue.u32[f*12+1];u|=1<<d;let p=c+(d===0?2:2+this.dimension),m=d===0||this.dimension===3?this.dimension:1;for(let h=0;h<m;h++)this.motionFloats[p+h]=this.queue.words[f*12+4+h]}this.motionData[c+1]=u}r.submitValidated(this.motionData.subarray(0,i*o),e),this.lastBatch={bodies:i,commands:this.queue.count,requestedCommands:this.requested,uploadedBytes:r.lastBatch.uploadedBytes,path:"packed-motion",submissions:e?0:1}}else{this.upload??=new ti,this.upload.count=0,this.upload.reserve(this.queue.count),(!this.rangeData||this.rangeData.length<i*2)&&(this.rangeData=new Uint32Array(Math.max(i*2,(this.rangeData?.length??0)*2,128)));let r=0,o=0;for(let p of this.pending.values()){this.rangeData[o++]=r,this.rangeData[o++]=p.length;for(let m=p.head;m!==-1;m=this.next[m]){for(let h=0;h<12;h++)this.upload.u32[r*12+h]=this.queue.u32[m*12+h];r++}}let a=r*48,n=i*8,l=Math.min(t.limits.maxStorageBufferBindingSize,t.limits.maxBufferSize);if(a>l||n>l)throw Error("Body command batch exceeds GPU buffer limits");for(let[p,m]of[["commands",a],["ranges",n]])(!this[p]||this[p].size<m)&&(this[p]?.destroy(),this[p]=t.createBuffer({size:Math.min(l,Math.max(m*2,16)),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}));t.queue.writeBuffer(this.commands,0,this.upload.words.buffer,0,a),t.queue.writeBuffer(this.ranges,0,this.rangeData.buffer,0,n),this.pipeline??=t.createComputePipeline({layout:"auto",compute:{entryPoint:"edit",module:t.createShaderModule({code:"const DISPATCH_STRIDE = "+t.limits.maxComputeWorkgroupsPerDimension*64+`u;
5122
+ `;function Vt(s,e){let t=s&&typeof s.x=="number"?[s.x,s.y]:Array.isArray(s)||ArrayBuffer.isView(s)&&!(s instanceof DataView)?s:Array.from(s??[]);if(t.length!==2||!t.every(Number.isFinite))throw Error(`${e} requires two finite components`);return t}var ti=class{constructor(){this.count=0,this.capacity=0}reserve(e){if(e<=this.capacity)return;let t=Math.max(e,this.capacity*2,64),i=new ArrayBuffer(t*48),r=new Float32Array(i),o=new Uint32Array(i);this.u32&&o.set(this.u32.subarray(0,this.count*12)),this.words=r,this.u32=o,this.capacity=t}append(e,t,i,r,o=!1){this.reserve(this.count+1),$c(this.words,this.u32,this.count++*12,e,t,i,r,o)}};function $c(s,e,t,i,r,o,a,n){e[t]=i,e[t+1]=r,e[t+2]=Number(n),e[t+3]=0;for(let l=0;l<4;l++)s[t+4+l]=o[l]??0,s[t+8+l]=a?.[l]??0}var Ur=class{constructor(e,t=Hc,i=2){this.solver=e,this.shader=t,this.dimension=i,this.pending=new Map,this.queue=new ti,this.requested=0,this.linearOnly=!0,this.angularOnly=!0,this.hasTeleports=!1,this.motionOnly=!0,this.freeRanges=[]}slot(e,t){this.requested++,this.linearOnly&&=t===0,this.angularOnly&&=t===1,this.motionOnly&&=t===0||t===1,this.hasTeleports||=t===4;let i=this.pending.get(e);if(i&&(t===0||t===1)&&this.queue.u32[i.tail*12+1]===t)return i.tail;if(this.queue.reserve(this.queue.count+1),!this.next||this.next.length<this.queue.capacity){let o=new Int32Array(this.queue.capacity);this.next&&o.set(this.next),this.next=o}let r=this.queue.count++;return this.next[r]=-1,i?(this.next[i.tail]=r,i.tail=r,i.length++):(i=this.freeRanges.pop()??{},i.head=i.tail=r,i.length=1,this.pending.set(e,i)),r}enqueue(e,t,i,r,o=!1){let a=this.slot(e,t);$c(this.queue.words,this.queue.u32,a*12,e,t,i,r,o)}enqueueValidated(e){for(let t=0;t<e.count;t++){let i=t*12,r=this.slot(e.u32[i],e.u32[i+1])*12;for(let o=0;o<12;o++)this.queue.u32[r+o]=e.u32[i+o]}}flush(e){if(!this.pending.size)return;let t=this.solver.device,i=this.pending.size;if(this.linearOnly||this.angularOnly){let r=this.angularOnly&&this.dimension===2?1:this.dimension;if(!this.linearIndices||this.linearIndices.length<i){let l=Math.max(i,(this.linearIndices?.length??0)*2,64);this.linearIndices=new Uint32Array(l),this.linearValues=new Float32Array(l*this.dimension)}let o=0;for(let[l,c]of this.pending){this.linearIndices[o]=l;for(let u=0;u<r;u++)this.linearValues[o*r+u]=this.queue.words[c.tail*12+4+u];o++}let a=this.angularOnly?"angularVelocityBatch":"velocityBatch",n=this.solver[a]??=new Kt(this.solver,this.dimension,this.angularOnly?"angular":"linear");n.submitValidated(this.linearIndices.subarray(0,i),this.linearValues.subarray(0,i*r),e),this.lastBatch={bodies:i,commands:this.queue.count,requestedCommands:this.requested,uploadedBytes:n.lastBatch.uploadedBytes,path:this.angularOnly?"packed-angular-velocities":"packed-velocities",submissions:e?0:1}}else if(this.motionOnly){let r=this.motionBatch??=new yi(this.solver,this.dimension),o=r.wordsPerBody;(!this.motionData||this.motionData.length<i*o)&&(this.motionData=new Uint32Array(Math.max(i*o,(this.motionData?.length??0)*2,64*o)),this.motionFloats=new Float32Array(this.motionData.buffer));let a=0;for(let[n,l]of this.pending){let c=a++*o;this.motionData[c]=n;let u=0;for(let f=l.head;f!==-1;f=this.next[f]){let d=this.queue.u32[f*12+1];u|=1<<d;let h=c+(d===0?2:2+this.dimension),m=d===0||this.dimension===3?this.dimension:1;for(let p=0;p<m;p++)this.motionFloats[h+p]=this.queue.words[f*12+4+p]}this.motionData[c+1]=u}r.submitValidated(this.motionData.subarray(0,i*o),e),this.lastBatch={bodies:i,commands:this.queue.count,requestedCommands:this.requested,uploadedBytes:r.lastBatch.uploadedBytes,path:"packed-motion",submissions:e?0:1}}else{this.upload??=new ti,this.upload.count=0,this.upload.reserve(this.queue.count),(!this.rangeData||this.rangeData.length<i*2)&&(this.rangeData=new Uint32Array(Math.max(i*2,(this.rangeData?.length??0)*2,128)));let r=0,o=0;for(let h of this.pending.values()){this.rangeData[o++]=r,this.rangeData[o++]=h.length;for(let m=h.head;m!==-1;m=this.next[m]){for(let p=0;p<12;p++)this.upload.u32[r*12+p]=this.queue.u32[m*12+p];r++}}let a=r*48,n=i*8,l=Math.min(t.limits.maxStorageBufferBindingSize,t.limits.maxBufferSize);if(a>l||n>l)throw Error("Body command batch exceeds GPU buffer limits");for(let[h,m]of[["commands",a],["ranges",n]])(!this[h]||this[h].size<m)&&(this[h]?.destroy(),this[h]=t.createBuffer({size:Math.min(l,Math.max(m*2,16)),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}));t.queue.writeBuffer(this.commands,0,this.upload.words.buffer,0,a),t.queue.writeBuffer(this.ranges,0,this.rangeData.buffer,0,n),this.pipeline??=t.createComputePipeline({layout:"auto",compute:{entryPoint:"edit",module:t.createShaderModule({code:"const DISPATCH_STRIDE = "+t.limits.maxComputeWorkgroupsPerDimension*64+`u;
5080
5123
  `+this.shader})}}),(!this.group||this.boundBody!==this.solver.bodyBuffer||this.boundCommands!==this.commands||this.boundRanges!==this.ranges||this.boundRangeBytes!==n)&&(this.group=t.createBindGroup({layout:this.pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:this.solver.bodyBuffer}},{binding:1,resource:{buffer:this.commands}},{binding:2,resource:{buffer:this.ranges,size:n}}]}),this.boundBody=this.solver.bodyBuffer,this.boundCommands=this.commands,this.boundRanges=this.ranges,this.boundRangeBytes=n);let c=e??t.createCommandEncoder(),u=c.beginComputePass();u.setPipeline(this.pipeline),u.setBindGroup(0,this.group);let f=Math.ceil(i/64),d=t.limits.maxComputeWorkgroupsPerDimension;u.dispatchWorkgroups(Math.min(f,d),Math.ceil(f/d)),u.end(),this.encodeAfterEdits(c,i),e||t.queue.submit([c.finish()]),this.lastBatch={bodies:i,commands:r,requestedCommands:this.requested,uploadedBytes:a+n,path:"ordered-commands",submissions:e?0:1}}for(let r of this.pending.values())this.freeRanges.push(r);this.pending.clear(),this.queue.count=0,this.requested=0,this.linearOnly=!0,this.angularOnly=!0,this.motionOnly=!0,this.hasTeleports=!1}encodeAfterEdits(){}destroy(){this.commands?.destroy(),this.ranges?.destroy(),this.solver.velocityBatch?.destroy(),this.solver.angularVelocityBatch?.destroy(),this.motionBatch?.destroy(),this.freeRanges.length=0,this.pending.clear(),this.queue=this.upload=this.next=this.linearIndices=this.linearValues=this.rangeData=this.motionData=this.motionFloats=null,this.group=null}};var $o=class extends To{writeParams(e,t){lc.call(this,e,t)}writePassConstants(e,t){fo.call(this,e,t)}createPipelines(){let e=this.layouts;this.compile(ys,[e.broad],["beginFrame","gridCount","gridScatter","findPairs"]),this.compile(vs,[e.contacts],["hashInsert","narrowphase"]),this.compile(Qr,[e.topo],["degreeJoints","degreeContacts","fillJoints","fillContacts","sortAdjacency","colorCompact","colorMark","colorRoundAB","colorRoundBA","colorCount","colorStarts","colorScatter"]),this.compile(xs,[e.solve,e.pass],["warmStartJoints","warmStartBodies","primal","primalScan","dual","refreshStick","updateVelocities"]),this.compile(qs,[e.args],["argsPrev","argsPairs","argsContacts","argsColors"])}constructor(e,t,i={}){if(i.minimumColors!==void 0&&(!Number.isInteger(i.minimumColors)||i.minimumColors<4||i.minimumColors>64))throw Error("minimumColors must be an integer from 4 to 64");i.sleeping!==void 0&&i.sleeping!==!1&&Go(i.sleeping),super(e,t,i),this.minimumColors=i.minimumColors??4,this.colorCap=Math.max(this.colorCap,this.minimumColors),this.sleepEligible=new Map(t.avbdSleepEligible??[]),Nc(this),ei(t)?.size&&this.enableShapes(),(i.sleeping||[...this.sleepEligible.values()].some(r=>r===!0))&&this.enableSleeping(i.sleeping||{})}enableShapes(){this.shapeBuffer||(this.syncShapeGeometry(),this.shapeContactLayout=this.makeLayout(["uniform","read-only-storage","read-only-storage","storage","read-only-storage","storage","storage","read-only-storage"]),this.compileBroadphase(),this.compileContacts(),this.bindContacts(),this.staticsDirty=!0)}geometryBytes(e=0){let t=(this.geometryRecords??this.bodyCapacity)*4+e;if(this.geometryRecords===void 0)for(let r of ei(this.topology)?.values()??[])t+=r.vertices?.length??0;let i=t*4;if(i>Math.min(this.device.limits.maxStorageBufferBindingSize,this.device.limits.maxBufferSize,16777216*16))throw Error("2D hull geometry exceeds this GPU's storage capacity");return i}syncShapeGeometry(){let e=this.geometryBytes(),t=new Float32Array(e/4);this.packedShapes=new Map;let i=this.bodyCapacity;for(let[r,o]of ei(this.topology)??[]){let a=Array.from(o);o.vertices&&(a[2]=i,t.set(o.vertices,i*4),i+=o.vertices.length/4),t.set(a,r*4),this.packedShapes.set(r,a)}this.geometryRecords=i,this.shapeBuffer=this.createShapeBuffer(e),this.device.queue.writeBuffer(this.shapeBuffer,0,t)}createShapeBuffer(e){let t=Math.min(this.device.limits.maxStorageBufferBindingSize,this.device.limits.maxBufferSize,268435456);return this.device.createBuffer({label:"2D collider geometry",size:Math.min(t,Math.max(e,Math.ceil(e*1.5/16)*16)),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC})}appendShapeGeometry(e,t){let i=this.geometryBytes(t.vertices?.length??0);if(this.shapeBuffer.size<i){let o=this.shapeBuffer;this.shapeBuffer=this.createShapeBuffer(i);let a=this.device.createCommandEncoder();a.copyBufferToBuffer(o,0,this.shapeBuffer,0,this.geometryRecords*16),this.device.queue.submit([a.finish()]),o.destroy(),this.bindFilters(),this.bindContacts()}let r=Array.from(t);t.vertices&&(r[2]=this.geometryRecords,this.device.queue.writeBuffer(this.shapeBuffer,this.geometryRecords*16,new Float32Array(t.vertices)),this.geometryRecords+=t.vertices.length/4),this.packedShapes.set(e,r),this.device.queue.writeBuffer(this.shapeBuffer,e*16,new Float32Array(r))}makeLayout(e){return this.device.createBindGroupLayout({entries:e.map((t,i)=>({binding:i,visibility:GPUShaderStage.COMPUTE,buffer:{type:t}}))})}contactSource(){let e=vs;return this.shapeBuffer&&(e=e.replace(`@compute @workgroup_size(64)
5081
5124
  fn narrowphase`,Vc+`
5082
5125
  @compute @workgroup_size(64)
@@ -5088,13 +5131,13 @@ let plane=select(b,a,geometry[a].x==3.);let other=select(a,b,geometry[a].x==3.);
5088
5131
  if(dot(bodies[other].pose.xy-bodies[plane].pose.xy,normal)>radius(other)){return;}
5089
5132
  } else if(dot(d,d)>r*r){return;}`)),this.filters){let i=e.length;e.push("read-only-storage"),t=t.replace("fn ignored(hi: u32, lo: u32) -> bool {",`@group(0) @binding(${i}) var<storage,read> filters:array<vec2u>;
5090
5133
  fn ignored(hi:u32,lo:u32)->bool{
5091
- if((filters[hi].x&filters[lo].y)==0u || (filters[lo].x&filters[hi].y)==0u){return true;}`)}this.filterLayout=this.makeLayout(e),this.compile(t,[this.filterLayout],["beginFrame","gridCount","gridScatter","findPairs"]),this.bindFilters()}uploadBodies(e=0,t=this.topology.bodyCount-e){this.flushPropertyEdits(),super.uploadBodies(e,t);for(let o=e;o<e+t;o++)this.sleeping?.register(o,this.sleepEligible?.get(o)!==!1);if(!this.shapeBuffer&&!this.triggers?.size)return;let i=this.shapeBuffer&&t>0?new Float32Array(t*4):null,r=this.packedShapes;for(let o=e;o<e+t;o++){let a=r?.get(o);i&&a&&i.set(a,(o-e)*4),this.triggers?.has(o)&&this.device.queue.writeBuffer(this.bodyBuffer,o*96+28,new Float32Array([1]))}i&&this.device.queue.writeBuffer(this.shapeBuffer,e*16,i)}uploadStatics(){if(!this.shapeBuffer)return super.uploadStatics();let e=this.topology,t=ei(e),i=[];for(let f=0;f<this.bodyCount;f++)t?.get(f)?.[0]!==3&&i.push(e.props[f*4+1]);i.sort((f,d)=>f-d);let r=i[i.length>>1]??1,o=0,a=1/0;for(let f of i)f<=4*r&&(o=Math.max(o,f));for(let f of i)f>o&&(a=Math.min(a,f));let n=a===1/0?o*1.5:(o+a)/2;this.maxSmallRadius=n,this.cellSize=Math.max(2*o*(1+1e-4),.001);let l=[],c=[];for(let f=0;f<this.bodyCount;f++)(t?.get(f)?.[0]===3||e.props[f*4+1]>n)&&l.push(f);for(let f=0;f<e.jointCount;f++){let d=e.info[f*4+1],p=e.info[f*4+2];d>=0&&c.push([Math.max(d,p),Math.min(d,p),f])}for(let f of e.ignoredPairs()){let d=Math.floor(f/2097152);c.push([d,f-d*2097152,4294967295])}c.sort((f,d)=>f[0]-d[0]||f[1]-d[1]),this.largeCount=l.length,this.noCollideCount=c.length;let u=new Uint32Array(Math.max(l.length+3*c.length,4));u.set(l),c.forEach((f,d)=>u.set(f,l.length+3*d)),this.staticBuffer.size<u.byteLength&&(this.staticBuffer.destroy(),this.staticBuffer=this.device.createBuffer({label:"2D boundaries",size:u.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.rebuildBindings()),this.device.queue.writeBuffer(this.staticBuffer,0,u),this.staticsDirty=!1}async raycast(e,t,i={}){let[r]=await this.raycastAll([{origin:e,direction:t,maxDistance:i.maxDistance}],i);return r}raycastAll(e,t={}){return this.flushEdits(),this.shapeQueries??=new pi(this,2),this.shapeQueries.cast(e.map(i=>({...i,radius:0})),t)}async circleCast(e,t,i,r={}){let[o]=await this.circleCastAll([{origin:e,radius:t,direction:i,maxDistance:r.maxDistance}],r);return o}circleCastAll(e,t={}){return this.flushEdits(),this.shapeQueries??=new pi(this,2),this.shapeQueries.cast(e,t)}liveIndex(e){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.bodyCount)throw Error("A live 2D body index is required")}queueBodyCommand(e,t,i,r,o=!1){return this.liveIndex(e),this.prepareBodyCommands().enqueue(e,t,i,r,o),this}prepareBodyCommands(){return this.wakeAll(),this.bodyCommands||(this.bodyCommands=new Ur(this),this.compileContacts()),this.bodyCommands}setLinearVelocity(e,t){return this.queueBodyCommand(e,0,Vt(t,"velocity"))}setAngularVelocity(e,t){if(!Number.isFinite(t))throw Error("Angular velocity must be finite");return this.queueBodyCommand(e,1,[t,0,0,0])}applyImpulse(e,t,i){return this.queueBodyCommand(e,2,Vt(t,"impulse"),i===void 0?void 0:Vt(i,"point"),i!==void 0)}applyForce(e,t,i){return this.queueBodyCommand(e,3,[...Vt(t,"force"),0,this.params.dt],i===void 0?void 0:Vt(i,"point"),i!==void 0)}applyAngularImpulse(e,t){if(!Number.isFinite(t))throw Error("Angular impulse must be finite");return this.queueBodyCommand(e,5,[t,0,0,0])}applyTorque(e,t){if(!Number.isFinite(t))throw Error("Torque must be finite");return this.queueBodyCommand(e,6,[t,0,0,this.params.dt])}teleport(e,t,i){if(i!==void 0&&!Number.isFinite(i))throw Error("Angle must be finite");return this.queueBodyCommand(e,4,[...Vt(t,"position"),i??0,0],void 0,i!==void 0)}readBodies(){return this.flushEdits(),super.readBodies()}async readBodyState(e){this.liveIndex(e),this.flushEdits();let t=this.device,i=t.createBuffer({size:96,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});try{let r=t.createCommandEncoder();r.copyBufferToBuffer(this.bodyBuffer,e*96,i,0,96),t.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ);let o=new Float32Array(i.getMappedRange());return{position:[o[0],o[1]],angle:o[2],linearVelocity:[o[12],o[13]],angularVelocity:o[14],mass:o[22],moment:o[23],sleeping:o[15]!==0}}finally{i.destroy()}}addBox(e,t={}){return this.addShape({size:Array.from(e)},t)}addCircle(e,t={}){return this.addShape(qo(e),t)}addHull(e,t={}){return this.addShape(No(e),t)}addCapsule(e,t,i={}){return this.addShape(Vo(e,t),i)}addSegment(e,t,i={}){return this.addShape(Wo(e,t,i))}addPlane(e=[0,1],t=0,i={}){return this.addShape(Ho(e,t,i))}addShape(e,t={}){t=e.options??t;let{density:i=1,friction:r=.6,position:o=[0,0],angle:a=0,velocity:n=[0,0,0],restitution:l=0,isTrigger:c=!1,group:u=4294967295,collidesWith:f=4294967295,allowSleep:d}=t;if(this.destroyed)throw Error("The 2D solver has been destroyed");if(d!==void 0&&typeof d!="boolean")throw Error("allowSleep must be boolean");if(this.bodyCount>=this.bodyCapacity)throw Error("2D body capacity reached; reserve bodyCapacity when creating the solver");if(e.size.length!==2||!e.size.every(h=>Number.isFinite(h)&&h>0)||!Number.isFinite(i)||i<0||!Number.isFinite(r)||r<0||!Number.isFinite(a))throw Error("Body dimensions must be positive, density and friction nonnegative, and angle finite");if(n.length!==3||!Array.from(n).every(Number.isFinite))throw Error("Velocity requires [x, y, angular] finite components");if(typeof c!="boolean"||!Number.isFinite(l)||l<0||l>1)throw Error("isTrigger must be boolean and restitution between zero and one");if([u,f].some(h=>!Number.isInteger(h)||h<0||h>4294967295))throw Error("Collision masks must be unsigned 32-bit integers");let p=Vt(o,"position");e.geometry&&this.geometryBytes(e.geometry.vertices?.length??0);let m=super.addBody(e.size,i,r,[...p,a],Array.from(n));return e.geometry&&(Fr(this.topology,m,e,i),this.shapeBuffer?this.appendShapeGeometry(m,e.geometry):this.enableShapes(),this.uploadBodies(m,1)),l&&this.setRestitution(m,l),c&&this.setSensor(m,!0),(u!==4294967295||f!==4294967295)&&this.setFilters([m],[u],[f]),this.contactWatch?.setWatched([m],[!this.watchedIndices||this.watchedIndices.has(m)]),this.sleepEligible.set(m,d??!0),d===!0&&!this.sleeping&&this.enableSleeping(),this.sleeping?.register(m,d!==!1),this.wakeAll(),m}setRestitution(e,t){if(this.liveIndex(e),!Number.isInteger(e)||e<0||e>=this.bodyCount||!Number.isFinite(t)||t<0||t>1)throw Error("Restitution requires a live body index and a coefficient in 0..1");t>0&&!this.restitution&&(this.restitution=new jo(this)),this.restitution?.set(e,t),this.wakeAll()}constraintSlot(e,t){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.jointCount||this.topology.handles[e]?.disposed)throw Error("A live 2D constraint slot is required");if(t!==void 0&&this.topology.info[e*j]!==t)throw Error("The constraint has a different type");return e}setMotor(e,{speed:t,maxTorque:i}={}){if(this.constraintSlot(e,Ro),t!==void 0&&!Number.isFinite(t)||i!==void 0&&(!Number.isFinite(i)||i<0))throw Error("Motor speed must be finite and maximum torque nonnegative");let r=e*O,o=e*36;t!==void 0&&(this.topology.data[r+re]=t,oe(this).float(this.jointBuffer,o+32,t)),i!==void 0&&(this.topology.data[r+_e]=-i,this.topology.data[r+Ae]=i,oe(this).float(this.jointBuffer,o+12,-i),oe(this).float(this.jointBuffer,o+16,i)),this.wakeAll()}setAngleLimits(e,t){this.constraintSlot(e,Fo);let i=ki(t);this.topology.data[e*O+be]=i.minAngle,this.topology.data[e*O+Ue]=i.maxAngle,oe(this).float(this.jointBuffer,e*36+32+1,i.minAngle),oe(this).float(this.jointBuffer,e*36+32+2,i.maxAngle);for(let r=4;r<8;r++)oe(this).float(this.jointBuffer,e*36+r,0);this.wakeAll()}setWorldAnchor(e,t,i){if(this.constraintSlot(e,Bi),this.topology.info[e*j+1]!==-1||!Number.isFinite(t)||!Number.isFinite(i))throw Error("A world joint and finite xy anchor are required");oe(this).float(this.jointBuffer,e*36+28,t),oe(this).float(this.jointBuffer,e*36+28+1,i),this.wakeAll()}disableConstraint(e){if(this.topology.handles[e]?.disposed)return;this.constraintSlot(e),this.flushPropertyEdits(),super.disableConstraint(e),this.wakeAll();let t=this.topology.handles[e];t&&(t.alive=!1,t.disposed=!0)}appendJoint(e,t,i,r,o,a=1/0){if(e!==-1&&this.liveIndex(e),this.liveIndex(t),e===t)throw Error("Constraint endpoints must differ");let n=Vt(i,"anchorA"),l=Vt(r,"anchorB");if(!o||o.length!==3||Array.from(o).some(u=>u!==1/0&&(!Number.isFinite(u)||u<0))||a!==1/0&&(!Number.isFinite(a)||a<0))throw Error("Joint stiffness and break force must be nonnegative or Infinity");this.flushPropertyEdits();let c=super.appendJoint(e,t,n,l,Array.from(o),a);return this.wakeAll(),c}setFilters(e,t,i){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(e.length!==t.length||e.length!==i.length)throw Error("Each body index needs a group and collision mask");let r=n=>{if(!Number.isInteger(n)||n<0||n>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");return n},o=Array.from(e,(n,l)=>(this.liveIndex(n),[n,r(t[l]),r(i[l])]));if(this.wakeAll(),!this.filters){let n=this.device;this.filters=n.createBuffer({size:this.bodyCapacity*8,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),n.queue.writeBuffer(this.filters,0,new Uint32Array(this.bodyCapacity*2).fill(4294967295)),this.compileBroadphase()}let a=oe(this);for(let[n,l,c]of o)a.uint(this.filters,n*2,l),a.uint(this.filters,n*2+1,c)}bindFilters(){this.filterLayout&&(this.groups.broad=this.device.createBindGroup({layout:this.filterLayout,entries:[this.paramsBuffer,this.bodyBuffer,this.gridBuffer,this.pairBuffer,this.counterBuffer,this.staticBuffer,this.jointBuffer,...this.shapeBuffer?[this.shapeBuffer]:[],...this.filters?[this.filters]:[]].map((e,t)=>({binding:t,resource:{buffer:e}}))}))}rebuildBindings(){super.rebuildBindings(),this.bindFilters(),this.bindContacts()}setSensor(e,t){if(this.liveIndex(e),typeof t!="boolean")throw Error("Sensor flag must be boolean");if(this.wakeAll(),t&&!this.sensorsEnabled){this.sensorsEnabled=!0;let i=this.device,r=i.createComputePipeline({layout:"auto",compute:{module:i.createShaderModule({code:"@group(0) @binding(0) var<storage,read_write> data:array<vec4f>; @compute @workgroup_size(64) fn clear(@builtin(global_invocation_id) id:vec3u){if(id.x*6u+1u<arrayLength(&data)){data[id.x*6u+1u].w=0.;}}"}),entryPoint:"clear"}}),o=i.createBindGroup({layout:r.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:this.bodyBuffer}}]}),a=i.createCommandEncoder(),n=a.beginComputePass();n.setPipeline(r),n.setBindGroup(0,o),n.dispatchWorkgroups(Math.ceil(this.bodyCount/64)),n.end(),i.queue.submit([a.finish()]),this.compileContacts();let l=xs.replace("b.initial = b.pose;","b.initial = vec4f(b.pose.xyz,b.initial.w);").replace("fn addContact(acc: ptr<function, Acc>, c: u32, alpha: f32, i: u32) {",`fn addContact(acc: ptr<function, Acc>, c: u32, alpha: f32, i: u32) {
5134
+ if((filters[hi].x&filters[lo].y)==0u || (filters[lo].x&filters[hi].y)==0u){return true;}`)}this.filterLayout=this.makeLayout(e),this.compile(t,[this.filterLayout],["beginFrame","gridCount","gridScatter","findPairs"]),this.bindFilters()}uploadBodies(e=0,t=this.topology.bodyCount-e){this.flushPropertyEdits(),super.uploadBodies(e,t);for(let o=e;o<e+t;o++)this.sleeping?.register(o,this.sleepEligible?.get(o)!==!1);if(!this.shapeBuffer&&!this.triggers?.size)return;let i=this.shapeBuffer&&t>0?new Float32Array(t*4):null,r=this.packedShapes;for(let o=e;o<e+t;o++){let a=r?.get(o);i&&a&&i.set(a,(o-e)*4),this.triggers?.has(o)&&this.device.queue.writeBuffer(this.bodyBuffer,o*96+28,new Float32Array([1]))}i&&this.device.queue.writeBuffer(this.shapeBuffer,e*16,i)}uploadStatics(){if(!this.shapeBuffer)return super.uploadStatics();let e=this.topology,t=ei(e),i=[];for(let f=0;f<this.bodyCount;f++)t?.get(f)?.[0]!==3&&i.push(e.props[f*4+1]);i.sort((f,d)=>f-d);let r=i[i.length>>1]??1,o=0,a=1/0;for(let f of i)f<=4*r&&(o=Math.max(o,f));for(let f of i)f>o&&(a=Math.min(a,f));let n=a===1/0?o*1.5:(o+a)/2;this.maxSmallRadius=n,this.cellSize=Math.max(2*o*(1+1e-4),.001);let l=[],c=[];for(let f=0;f<this.bodyCount;f++)(t?.get(f)?.[0]===3||e.props[f*4+1]>n)&&l.push(f);for(let f=0;f<e.jointCount;f++){let d=e.info[f*4+1],h=e.info[f*4+2];d>=0&&c.push([Math.max(d,h),Math.min(d,h),f])}for(let f of e.ignoredPairs()){let d=Math.floor(f/2097152);c.push([d,f-d*2097152,4294967295])}c.sort((f,d)=>f[0]-d[0]||f[1]-d[1]),this.largeCount=l.length,this.noCollideCount=c.length;let u=new Uint32Array(Math.max(l.length+3*c.length,4));u.set(l),c.forEach((f,d)=>u.set(f,l.length+3*d)),this.staticBuffer.size<u.byteLength&&(this.staticBuffer.destroy(),this.staticBuffer=this.device.createBuffer({label:"2D boundaries",size:u.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.rebuildBindings()),this.device.queue.writeBuffer(this.staticBuffer,0,u),this.staticsDirty=!1}async raycast(e,t,i={}){let[r]=await this.raycastAll([{origin:e,direction:t,maxDistance:i.maxDistance}],i);return r}raycastAll(e,t={}){return this.flushEdits(),this.shapeQueries??=new hi(this,2),this.shapeQueries.cast(e.map(i=>({...i,radius:0})),t)}async circleCast(e,t,i,r={}){let[o]=await this.circleCastAll([{origin:e,radius:t,direction:i,maxDistance:r.maxDistance}],r);return o}circleCastAll(e,t={}){return this.flushEdits(),this.shapeQueries??=new hi(this,2),this.shapeQueries.cast(e,t)}liveIndex(e){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.bodyCount)throw Error("A live 2D body index is required")}queueBodyCommand(e,t,i,r,o=!1){return this.liveIndex(e),this.prepareBodyCommands().enqueue(e,t,i,r,o),this}prepareBodyCommands(){return this.wakeAll(),this.bodyCommands||(this.bodyCommands=new Ur(this),this.compileContacts()),this.bodyCommands}setLinearVelocity(e,t){return this.queueBodyCommand(e,0,Vt(t,"velocity"))}setAngularVelocity(e,t){if(!Number.isFinite(t))throw Error("Angular velocity must be finite");return this.queueBodyCommand(e,1,[t,0,0,0])}applyImpulse(e,t,i){return this.queueBodyCommand(e,2,Vt(t,"impulse"),i===void 0?void 0:Vt(i,"point"),i!==void 0)}applyForce(e,t,i){return this.queueBodyCommand(e,3,[...Vt(t,"force"),0,this.params.dt],i===void 0?void 0:Vt(i,"point"),i!==void 0)}applyAngularImpulse(e,t){if(!Number.isFinite(t))throw Error("Angular impulse must be finite");return this.queueBodyCommand(e,5,[t,0,0,0])}applyTorque(e,t){if(!Number.isFinite(t))throw Error("Torque must be finite");return this.queueBodyCommand(e,6,[t,0,0,this.params.dt])}teleport(e,t,i){if(i!==void 0&&!Number.isFinite(i))throw Error("Angle must be finite");return this.queueBodyCommand(e,4,[...Vt(t,"position"),i??0,0],void 0,i!==void 0)}readBodies(){return this.flushEdits(),super.readBodies()}async readBodyState(e){this.liveIndex(e),this.flushEdits();let t=this.device,i=t.createBuffer({size:96,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});try{let r=t.createCommandEncoder();r.copyBufferToBuffer(this.bodyBuffer,e*96,i,0,96),t.queue.submit([r.finish()]),await i.mapAsync(GPUMapMode.READ);let o=new Float32Array(i.getMappedRange());return{position:[o[0],o[1]],angle:o[2],linearVelocity:[o[12],o[13]],angularVelocity:o[14],mass:o[22],moment:o[23],sleeping:o[15]!==0}}finally{i.destroy()}}addBox(e,t={}){return this.addShape({size:Array.from(e)},t)}addCircle(e,t={}){return this.addShape(qo(e),t)}addHull(e,t={}){return this.addShape(No(e),t)}addCapsule(e,t,i={}){return this.addShape(Vo(e,t),i)}addSegment(e,t,i={}){return this.addShape(Wo(e,t,i))}addPlane(e=[0,1],t=0,i={}){return this.addShape(Ho(e,t,i))}addShape(e,t={}){t=e.options??t;let{density:i=1,friction:r=.6,position:o=[0,0],angle:a=0,velocity:n=[0,0,0],restitution:l=0,isTrigger:c=!1,group:u=4294967295,collidesWith:f=4294967295,allowSleep:d}=t;if(this.destroyed)throw Error("The 2D solver has been destroyed");if(d!==void 0&&typeof d!="boolean")throw Error("allowSleep must be boolean");if(this.bodyCount>=this.bodyCapacity)throw Error("2D body capacity reached; reserve bodyCapacity when creating the solver");if(e.size.length!==2||!e.size.every(p=>Number.isFinite(p)&&p>0)||!Number.isFinite(i)||i<0||!Number.isFinite(r)||r<0||!Number.isFinite(a))throw Error("Body dimensions must be positive, density and friction nonnegative, and angle finite");if(n.length!==3||!Array.from(n).every(Number.isFinite))throw Error("Velocity requires [x, y, angular] finite components");if(typeof c!="boolean"||!Number.isFinite(l)||l<0||l>1)throw Error("isTrigger must be boolean and restitution between zero and one");if([u,f].some(p=>!Number.isInteger(p)||p<0||p>4294967295))throw Error("Collision masks must be unsigned 32-bit integers");let h=Vt(o,"position");e.geometry&&this.geometryBytes(e.geometry.vertices?.length??0);let m=super.addBody(e.size,i,r,[...h,a],Array.from(n));return e.geometry&&(Fr(this.topology,m,e,i),this.shapeBuffer?this.appendShapeGeometry(m,e.geometry):this.enableShapes(),this.uploadBodies(m,1)),l&&this.setRestitution(m,l),c&&this.setSensor(m,!0),(u!==4294967295||f!==4294967295)&&this.setFilters([m],[u],[f]),this.contactWatch?.setWatched([m],[!this.watchedIndices||this.watchedIndices.has(m)]),this.sleepEligible.set(m,d??!0),d===!0&&!this.sleeping&&this.enableSleeping(),this.sleeping?.register(m,d!==!1),this.wakeAll(),m}setRestitution(e,t){if(this.liveIndex(e),!Number.isInteger(e)||e<0||e>=this.bodyCount||!Number.isFinite(t)||t<0||t>1)throw Error("Restitution requires a live body index and a coefficient in 0..1");t>0&&!this.restitution&&(this.restitution=new jo(this)),this.restitution?.set(e,t),this.wakeAll()}constraintSlot(e,t){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(!Number.isInteger(e)||e<0||e>=this.jointCount||this.topology.handles[e]?.disposed)throw Error("A live 2D constraint slot is required");if(t!==void 0&&this.topology.info[e*j]!==t)throw Error("The constraint has a different type");return e}setMotor(e,{speed:t,maxTorque:i}={}){if(this.constraintSlot(e,Ro),t!==void 0&&!Number.isFinite(t)||i!==void 0&&(!Number.isFinite(i)||i<0))throw Error("Motor speed must be finite and maximum torque nonnegative");let r=e*O,o=e*36;t!==void 0&&(this.topology.data[r+re]=t,oe(this).float(this.jointBuffer,o+32,t)),i!==void 0&&(this.topology.data[r+_e]=-i,this.topology.data[r+Ae]=i,oe(this).float(this.jointBuffer,o+12,-i),oe(this).float(this.jointBuffer,o+16,i)),this.wakeAll()}setAngleLimits(e,t){this.constraintSlot(e,Fo);let i=ki(t);this.topology.data[e*O+be]=i.minAngle,this.topology.data[e*O+Ne]=i.maxAngle,oe(this).float(this.jointBuffer,e*36+32+1,i.minAngle),oe(this).float(this.jointBuffer,e*36+32+2,i.maxAngle);for(let r=4;r<8;r++)oe(this).float(this.jointBuffer,e*36+r,0);this.wakeAll()}setWorldAnchor(e,t,i){if(this.constraintSlot(e,Bi),this.topology.info[e*j+1]!==-1||!Number.isFinite(t)||!Number.isFinite(i))throw Error("A world joint and finite xy anchor are required");oe(this).float(this.jointBuffer,e*36+28,t),oe(this).float(this.jointBuffer,e*36+28+1,i),this.wakeAll()}disableConstraint(e){if(this.topology.handles[e]?.disposed)return;this.constraintSlot(e),this.flushPropertyEdits(),super.disableConstraint(e),this.wakeAll();let t=this.topology.handles[e];t&&(t.alive=!1,t.disposed=!0)}appendJoint(e,t,i,r,o,a=1/0){if(e!==-1&&this.liveIndex(e),this.liveIndex(t),e===t)throw Error("Constraint endpoints must differ");let n=Vt(i,"anchorA"),l=Vt(r,"anchorB");if(!o||o.length!==3||Array.from(o).some(u=>u!==1/0&&(!Number.isFinite(u)||u<0))||a!==1/0&&(!Number.isFinite(a)||a<0))throw Error("Joint stiffness and break force must be nonnegative or Infinity");this.flushPropertyEdits();let c=super.appendJoint(e,t,n,l,Array.from(o),a);return this.wakeAll(),c}setFilters(e,t,i){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(e.length!==t.length||e.length!==i.length)throw Error("Each body index needs a group and collision mask");let r=n=>{if(!Number.isInteger(n)||n<0||n>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");return n},o=Array.from(e,(n,l)=>(this.liveIndex(n),[n,r(t[l]),r(i[l])]));if(this.wakeAll(),!this.filters){let n=this.device;this.filters=n.createBuffer({size:this.bodyCapacity*8,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),n.queue.writeBuffer(this.filters,0,new Uint32Array(this.bodyCapacity*2).fill(4294967295)),this.compileBroadphase()}let a=oe(this);for(let[n,l,c]of o)a.uint(this.filters,n*2,l),a.uint(this.filters,n*2+1,c)}bindFilters(){this.filterLayout&&(this.groups.broad=this.device.createBindGroup({layout:this.filterLayout,entries:[this.paramsBuffer,this.bodyBuffer,this.gridBuffer,this.pairBuffer,this.counterBuffer,this.staticBuffer,this.jointBuffer,...this.shapeBuffer?[this.shapeBuffer]:[],...this.filters?[this.filters]:[]].map((e,t)=>({binding:t,resource:{buffer:e}}))}))}rebuildBindings(){super.rebuildBindings(),this.bindFilters(),this.bindContacts()}setSensor(e,t){if(this.liveIndex(e),typeof t!="boolean")throw Error("Sensor flag must be boolean");if(this.wakeAll(),t&&!this.sensorsEnabled){this.sensorsEnabled=!0;let i=this.device,r=i.createComputePipeline({layout:"auto",compute:{module:i.createShaderModule({code:"@group(0) @binding(0) var<storage,read_write> data:array<vec4f>; @compute @workgroup_size(64) fn clear(@builtin(global_invocation_id) id:vec3u){if(id.x*6u+1u<arrayLength(&data)){data[id.x*6u+1u].w=0.;}}"}),entryPoint:"clear"}}),o=i.createBindGroup({layout:r.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:this.bodyBuffer}}]}),a=i.createCommandEncoder(),n=a.beginComputePass();n.setPipeline(r),n.setBindGroup(0,o),n.dispatchWorkgroups(Math.ceil(this.bodyCount/64)),n.end(),i.queue.submit([a.finish()]),this.compileContacts();let l=xs.replace("b.initial = b.pose;","b.initial = vec4f(b.pose.xyz,b.initial.w);").replace("fn addContact(acc: ptr<function, Acc>, c: u32, alpha: f32, i: u32) {",`fn addContact(acc: ptr<function, Acc>, c: u32, alpha: f32, i: u32) {
5092
5135
  if((contacts[c].ids.w&0x80000000u)!=0u){return;}`).replace("fn dualContact(c: u32) {",`fn dualContact(c: u32) {
5093
5136
  if((contacts[c].ids.w&0x80000000u)!=0u){return;}`).replace(` let k = contacts[c];
5094
5137
  let bound`,` let k = contacts[c];
5095
5138
  if((k.ids.w&0x80000000u)!=0u){return;}
5096
5139
  let bound`);this.compile(l,[this.layouts.solve,this.layouts.pass],["warmStartJoints","warmStartBodies","primal","primalScan","dual","refreshStick","updateVelocities"]);let c=Qr.replaceAll("if (gid.x >= topoCount()) { return; }",`if (gid.x >= topoCount()) { return; }
5097
- if((contacts[gid.x].ids.w&0x80000000u)!=0u){return;}`);this.compile(c,[this.layouts.topo],["degreeContacts","fillContacts"])}this.sensorsEnabled&&oe(this).float(this.bodyBuffer,e*24+7,t?1:0),this.triggers??=new Set,t?this.triggers.add(e):this.triggers.delete(e)}compile(e,t,i){e.includes("fn warmStartBodies(")&&(e=jc(Gc(qc(e)))),e.includes("fn dynamicBody(")&&(e=Fc(e));let r=e.includes("fn colorCount(");r&&(this.colorBucketSource=Rn(lo(e)),e=Rn(e));let o=this.device,a=o.createShaderModule({code:e}),n=o.createPipelineLayout({bindGroupLayouts:t});for(let l of i)this.pipes[l]=o.createComputePipeline({layout:n,compute:{module:a,entryPoint:l}});r&&i.includes("colorCount")&&(this.colorBucketPipelines={scan:this.pipes.colorCount},this.bitsetColorBuckets=void 0)}watchContacts({maxPairs:e=8192,maxEvents:t=4096,indices:i}={}){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(i!==void 0){if(!Array.isArray(i))throw Error("Watched indices must be an array of live body indices");for(let r of i)this.liveIndex(r)}for(let r of[e,t])if(!Number.isInteger(r)||r<1)throw Error("Contact capacities must be positive integers");return this.contactWatch||(this.contactWatch=new xi(this.device,this.bodyBuffer,this.bodyCapacity,e,t,2),i===void 0&&this.contactWatch.setWatched(Array.from({length:this.bodyCount},(r,o)=>o),Array(this.bodyCount).fill(!0))),i!==void 0&&(this.watchedIndices=new Set(i),this.contactWatch.setWatched(Array.from({length:this.bodyCount},(r,o)=>o),Array.from({length:this.bodyCount},(r,o)=>this.watchedIndices.has(o)))),this}async readContactEvents(){this.watchContacts();let e=await this.contactWatch.read();return{...e,events:e.events.map(t=>({...t,type:t.kind===Ai?"begin":"end",isTrigger:!!(this.triggers?.has(t.a)||this.triggers?.has(t.b))}))}}step(){if(this.destroyed)throw Error("The 2D solver has been destroyed");co(this,this.colorBucketSource),this.sleeping||this.restitution?.active.size||this.bodyCommands?.pending.size||this.propertyEdits?.pending||this.externalBeforeStep||this.externalAfterStep?Uc.call(this):super.step(),this.contactWatch&&this.contactWatch.run({manifolds:this.contactBuffers[1-this.parity],contacts:this.contactBuffers[1-this.parity],counters:this.counterBuffer},this.contactCapacity,this.eventStep=(this.eventStep??0)+1,this.params.dt)}adapt(e){super.adapt(e),this.colorCap=Math.max(this.colorCap,this.minimumColors)}encodeStepPrelude(e){this.flushPropertyEdits(e),this.sleeping?.before(e),this.bodyCommands?.flush(e),this.restitution?.before(e),this.externalBeforeStep?.(e)}encodeStepPostlude(e){this.restitution?.after(e),this.sleeping?.after(e),this.externalAfterStep?.(e)}destroy(){this.passConstantCache=null,this.propertyEdits?.destroy(),!this.destroyed&&(this.detachFromScene(),this.shapeQueries?.destroy(),this.restitution?.destroy(),this.filters?.destroy(),this.shapeBuffer?.destroy(),this.bodyCommands?.destroy(),this.contactWatch?.destroy(),this.sleeping?.destroy(),super.destroy())}enableSleeping(e={}){if(this.destroyed)throw Error("The 2D solver has been destroyed");return this.sleeping?this.sleeping.options=Go(e):this.sleeping=new Do(this,e),this}disableSleeping(){if(this.destroyed)throw Error("The 2D solver has been destroyed");return this.sleeping&&(this.sleeping.wakeRequested=!0,this.sleeping.before(),this.sleeping.destroy(),this.sleeping=null),this}setSleepEnabled(e,t){if(this.liveIndex(e),typeof t!="boolean")throw Error("Sleep flag must be boolean");return this.sleepEligible.set(e,t),t&&!this.sleeping&&this.enableSleeping(),this.sleeping?.register(e,t),this.wakeAll(),this}wakeAll(){return this.sleeping&&(this.sleeping.wakeRequested=!0),this}wakeUp(e){return this.liveIndex(e),this.wakeAll()}async readSleepStats(){return this.sleeping?this.sleeping.readStats():{sleeping:0,wakeRequested:!1}}flushEdits(){this.flushPropertyEdits(),this.sleeping?.wakeRequested&&this.sleeping.before(),this.bodyCommands?.flush()}flushPropertyEdits(e){this.propertyEdits?.flush(e)}readJoints(){return this.flushPropertyEdits(),super.readJoints()}attachToScene(e,{maxSubSteps:t=6,maxFrameTime:i=.05,afterStep:r}={}){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(!e?.onBeforeRenderObservable?.add||!e?.onDisposeObservable?.addOnce||!e?.getEngine)throw Error("A Babylon scene is required");if(!Number.isInteger(t)||t<1||!Number.isFinite(i)||i<=0||r!==void 0&&typeof r!="function")throw Error("Scene stepping requires positive frame limits and an optional afterStep function");if(this.sceneBinding){if(this.sceneBinding.scene===e)return this;throw Error("The 2D solver is already attached to another scene")}let o=0,a=e.onBeforeRenderObservable.add(()=>{let l=this.params.dt;if(!(l>0)||!Number.isFinite(l))throw Error("Simulation timestep must be positive and finite");let c=e.getEngine().getDeltaTime()/1e3;o=Math.min(t*l,o+Math.min(i,Math.max(0,c)));for(let u=0;o+1e-12>=l&&u<t&&(this.step(),o=Math.max(0,o-l),r?.(this),!(!this.sceneBinding||this.destroyed));u++);}),n=e.onDisposeObservable.addOnce(()=>this.destroy());return this.sceneBinding={scene:e,before:a,dispose:n},this}detachFromScene(){let e=this.sceneBinding;return e&&(e.scene.onBeforeRenderObservable.remove(e.before),e.scene.onDisposeObservable.remove(e.dispose),this.sceneBinding=null),this}};var Jo=s=>{if(!Number.isInteger(s)||s<0||s>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");return s};function me(s,e,t){let i=s&&typeof s.x=="number"?[s.x,s.y,...e>=3?[s.z]:[],...e===4?[s.w]:[]]:Array.isArray(s)||ArrayBuffer.isView(s)&&!(s instanceof DataView)?s:Array.from(s??[]);if(i.length!==e||!i.every(Number.isFinite))throw Error(`${t} requires ${e} finite components`);return i}var Jc=["linearVelocity","angularVelocity","impulse","force","","angularImpulse","torque"];function fd(s,e){if(this.destroyed)throw Error("The solver has been destroyed");let t=this.editInProgress,i=t?new ti:this.editStaging??=new ti;this.editInProgress=!0;try{return dd.call(this,s,e,i)}finally{this.editInProgress=t}}function dd(s,e,t){t.count=0;let i,r=(o,a)=>{if(e===3)return me(o,3,a);if(!Number.isFinite(o))throw Error(`${a} must be finite`);return[o,0,0]};for(let o of s){let a=this.bodyIndex(o.body),{isTrigger:n,restitution:l,group:c,collidesWith:u,allowSleep:f}=o;if(n!==void 0||l!==void 0||c!==void 0||u!==void 0||f!==void 0){if(n!==void 0&&typeof n!="boolean")throw Error("isTrigger must be a boolean");if(f!==void 0&&typeof f!="boolean")throw Error("allowSleep must be a boolean");if(l!==void 0&&(!Number.isFinite(l)||l<0||l>1))throw Error("restitution must be between 0 and 1");if(u!==void 0&&c===void 0)throw Error("A collision-mask edit requires group as well");c!==void 0&&Jo(c),u!==void 0&&Jo(u),(i??=[]).push({index:a,isTrigger:n,restitution:l,group:c,collidesWith:u??4294967295,allowSleep:f})}let d=o.worldPoint===void 0?void 0:me(o.worldPoint,e,"worldPoint");if(o.position!==void 0){let p=me(o.position,e,"position"),m;if(o.rotation!==void 0){if(m=e===3?me(o.rotation,4,"rotation"):[o.rotation],e===3){let h=Math.hypot(...m);if(!h)throw Error("rotation must be nonzero");m=m.map(g=>g/h)}else if(!Number.isFinite(o.rotation))throw Error("angle must be finite")}t.append(a,4,p,e===3?m:void 0,m!==void 0),e===2&&(t.words[(t.count-1)*12+6]=m?.[0]??0)}else if(o.rotation!==void 0)throw Error("A rotation edit requires position; use teleport for a full pose");for(let p=0;p<Jc.length;p++){if(p===4)continue;let m=Jc[p];if(o[m]===void 0)continue;let g=p===1||p>=5?r(o[m],m):me(o[m],e,m);t.append(a,p,g,p===2||p===3?d:void 0,(p===2||p===3)&&d!==void 0),(p===3||p===6)&&(t.words[(t.count-1)*12+7]=this.params.dt)}}if(this.destroyed)throw Error("The solver was destroyed while reading body edits");t.count&&this.prepareBodyCommands().enqueueValidated(t);for(let o of i??[])o.isTrigger!==void 0&&this.setSensor(o.index,o.isTrigger),o.restitution!==void 0&&this.setRestitution(o.index,o.restitution),o.group!==void 0&&this.setFilters([o.index],[o.group],[o.collidesWith]),o.allowSleep!==void 0&&this.setSleepEnabled(o.index,o.allowSleep);return this}var Xo=class{constructor(e,t){this.solver=e,this.index=t}get gpuIndex(){return this.solver.liveIndex(this.index),this.index}setLinearVelocity(e){return this.solver.setLinearVelocity(this.gpuIndex,e),this}setAngularVelocity(e){return this.solver.setAngularVelocity(this.gpuIndex,e),this}applyImpulse(e,t){return this.solver.applyImpulse(this.gpuIndex,e,t),this}applyForce(e,t){return this.solver.applyForce(this.gpuIndex,e,t),this}applyAngularImpulse(e){return this.solver.applyAngularImpulse(this.gpuIndex,e),this}applyTorque(e){return this.solver.applyTorque(this.gpuIndex,e),this}teleport(e,t){return this.solver.teleport(this.gpuIndex,e,t),this}setTrigger(e){return this.solver.setSensor(this.gpuIndex,e),this.solver.wakeAll(),this}setRestitution(e){return this.solver.setRestitution(this.gpuIndex,e),this.solver.wakeAll(),this}setCollisionGroups(e,t=4294967295){return this.solver.setFilters([this.gpuIndex],[Jo(e)],[Jo(t)]),this.solver.wakeAll(),this}setSleepEnabled(e){return this.solver.setSleepEnabled(this.gpuIndex,e),this}wakeUp(){return this.solver.liveIndex(this.index),this.solver.wakeAll(),this}readState(){return this.solver.readBodyState(this.gpuIndex)}};function Xc(s,{maxSubSteps:e=6,maxFrameTime:t=.05}={}){if(!Number.isInteger(e)||e<1||!Number.isFinite(t)||t<=0)throw Error("Stepping limits must be positive");let i=s.params.dt;if(!Number.isFinite(i)||i<=0)throw Error("Simulation timestep must be positive and finite");return{dt:i,maxSubSteps:e,maxFrameTime:t}}function Yc(s,e,t,i){if(s.destroyed)throw Error("The solver has been destroyed");if(!Number.isFinite(e)||e<0)throw Error("elapsed must be finite nonnegative seconds");let{dt:r,maxSubSteps:o,maxFrameTime:a}=Xc(s,t);s.timeAccumulator=Math.min(o*r,(s.timeAccumulator??0)+Math.min(a,e));let n=0;for(;s.timeAccumulator+1e-12>=r&&n<o;)s.step(),s.timeAccumulator=Math.max(0,s.timeAccumulator-r),n++,i?.(s);return n}function hd(s,e){return Yc(this,s,e)}function Yo(s,{afterStep:e,...t}={}){if(this.destroyed)throw Error("The solver has been destroyed");if(!s?.onBeforeRenderObservable?.add||!s?.onDisposeObservable?.addOnce||!s?.getEngine)throw Error("A Babylon scene is required");if(e!==void 0&&typeof e!="function")throw Error("afterStep must be a function");if(Xc(this,t),this.sceneBinding){if(this.sceneBinding.scene===s)return this;throw Error("The solver is already attached to another scene")}let i=s.onBeforeRenderObservable.add(()=>{Yc(this,Math.max(0,s.getEngine().getDeltaTime()/1e3),t,e)}),r=s.onDisposeObservable.addOnce(()=>this.destroy());return this.sceneBinding={scene:s,before:i,dispose:r},this}function Qo(){let s=this.sceneBinding;return s&&(s.scene.onBeforeRenderObservable.remove(s.before),s.scene.onDisposeObservable.remove(s.dispose),this.sceneBinding=null,this.timeAccumulator=0),this}function Nr(s,e,t,i={}){s.advance=hd;let r,o;s.bodyIndex=function(n){if(this.destroyed)throw Error("The solver has been destroyed");let l=n;if(n instanceof Xo){if(n.solver!==this)throw Error("Body belongs to another solver");return n.gpuIndex}return typeof l!="number"&&t===3&&(o||(o=new WeakMap,e.bodies.forEach((c,u)=>o.set(c,this.gpuIndex(u)))),l=o.get(n)),this.liveIndex(l),l},s.body=function(n){let l=this.bodyIndex(n);return r??=new Map,r.has(l)||r.set(l,new Xo(this,l)),r.get(l)},s.editBodies=function(n){return fd.call(this,n,t)},s.setLinearVelocities=function(n,l){if(this.destroyed)throw Error("The solver has been destroyed");return i.setVelocities?i.setVelocities.call(this,n,{linear:l}):(this.velocityBatch??=new Kt(this,t),this.velocityBatch.set(n,l),this)},s.setVelocities=function(n,l){if(this.destroyed)throw Error("The solver has been destroyed");return i.setVelocities?i.setVelocities.call(this,n,l):l?.angular===void 0&&l?.linear!==void 0?this.setLinearVelocities(n,l.linear):l?.linear===void 0&&l?.angular!==void 0?this.setAngularVelocities(n,l.angular):(this.motionBatch??=new yi(this,t),this.motionBatch.set(n,l),this)},s.setAngularVelocities=function(n,l){if(this.destroyed)throw Error("The solver has been destroyed");return i.setVelocities?i.setVelocities.call(this,n,{angular:l}):(this.angularVelocityBatch??=new Kt(this,t,"angular"),this.angularVelocityBatch.set(n,l),this)};let a=s.destroy;return s.destroy=function(){this.destroyed||(this.velocityBatch?.destroy(),this.angularVelocityBatch?.destroy(),this.motionBatch?.destroy(),this.bodyReadback?.destroy(),this.editStaging=null,a.call(this),r?.clear(),o=null,e=null)},i.readSelectedBodies?s.readSelectedBodies=i.readSelectedBodies:t===2&&(s.readSelectedBodies=function(n,{posesOnly:l=!1}={}){let c=n instanceof Uint32Array?n:Array.from(n);return c.forEach(u=>this.liveIndex(u)),this.flushEdits(),this.bodyReadback??=new vi(this.device),this.bodyReadback.read(this.bodyBuffer,c,l,6)}),s}var Ko=class extends $o{constructor(e,t,i){super(e,t,i),Nr(this,null,2)}};var Tn=`struct Body { pos:vec4f, rot:vec4f, initialPos:vec4f, initialRot:vec4f, size:vec4f, moment:vec4f, inertialPos:vec4f, inertialRot:vec4f, velocity:vec4f, angular:vec4f }
5140
+ if((contacts[gid.x].ids.w&0x80000000u)!=0u){return;}`);this.compile(c,[this.layouts.topo],["degreeContacts","fillContacts"])}this.sensorsEnabled&&oe(this).float(this.bodyBuffer,e*24+7,t?1:0),this.triggers??=new Set,t?this.triggers.add(e):this.triggers.delete(e)}compile(e,t,i){e.includes("fn warmStartBodies(")&&(e=jc(Gc(qc(e)))),e.includes("fn dynamicBody(")&&(e=Fc(e));let r=e.includes("fn colorCount(");r&&(this.colorBucketSource=Rn(lo(e)),e=Rn(e));let o=this.device,a=o.createShaderModule({code:e}),n=o.createPipelineLayout({bindGroupLayouts:t});for(let l of i)this.pipes[l]=o.createComputePipeline({layout:n,compute:{module:a,entryPoint:l}});r&&i.includes("colorCount")&&(this.colorBucketPipelines={scan:this.pipes.colorCount},this.bitsetColorBuckets=void 0)}watchContacts({maxPairs:e=8192,maxEvents:t=4096,indices:i}={}){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(i!==void 0){if(!Array.isArray(i))throw Error("Watched indices must be an array of live body indices");for(let r of i)this.liveIndex(r)}for(let r of[e,t])if(!Number.isInteger(r)||r<1)throw Error("Contact capacities must be positive integers");return this.contactWatch||(this.contactWatch=new xi(this.device,this.bodyBuffer,this.bodyCapacity,e,t,2),i===void 0&&this.contactWatch.setWatched(Array.from({length:this.bodyCount},(r,o)=>o),Array(this.bodyCount).fill(!0))),i!==void 0&&(this.watchedIndices=new Set(i),this.contactWatch.setWatched(Array.from({length:this.bodyCount},(r,o)=>o),Array.from({length:this.bodyCount},(r,o)=>this.watchedIndices.has(o)))),this}async readContactEvents(){this.watchContacts();let e=await this.contactWatch.read();return{...e,events:e.events.map(t=>({...t,type:t.kind===Ai?"begin":"end",isTrigger:!!(this.triggers?.has(t.a)||this.triggers?.has(t.b))}))}}step(){if(this.destroyed)throw Error("The 2D solver has been destroyed");co(this,this.colorBucketSource),this.sleeping||this.restitution?.active.size||this.bodyCommands?.pending.size||this.propertyEdits?.pending||this.externalBeforeStep||this.externalAfterStep?Uc.call(this):super.step(),this.contactWatch&&this.contactWatch.run({manifolds:this.contactBuffers[1-this.parity],contacts:this.contactBuffers[1-this.parity],counters:this.counterBuffer},this.contactCapacity,this.eventStep=(this.eventStep??0)+1,this.params.dt)}adapt(e){super.adapt(e),this.colorCap=Math.max(this.colorCap,this.minimumColors)}encodeStepPrelude(e){this.flushPropertyEdits(e),this.sleeping?.before(e),this.bodyCommands?.flush(e),this.restitution?.before(e),this.externalBeforeStep?.(e)}encodeStepPostlude(e){this.restitution?.after(e),this.sleeping?.after(e),this.externalAfterStep?.(e)}destroy(){this.passConstantCache=null,this.propertyEdits?.destroy(),!this.destroyed&&(this.detachFromScene(),this.shapeQueries?.destroy(),this.restitution?.destroy(),this.filters?.destroy(),this.shapeBuffer?.destroy(),this.bodyCommands?.destroy(),this.contactWatch?.destroy(),this.sleeping?.destroy(),super.destroy())}enableSleeping(e={}){if(this.destroyed)throw Error("The 2D solver has been destroyed");return this.sleeping?this.sleeping.options=Go(e):this.sleeping=new Do(this,e),this}disableSleeping(){if(this.destroyed)throw Error("The 2D solver has been destroyed");return this.sleeping&&(this.sleeping.wakeRequested=!0,this.sleeping.before(),this.sleeping.destroy(),this.sleeping=null),this}setSleepEnabled(e,t){if(this.liveIndex(e),typeof t!="boolean")throw Error("Sleep flag must be boolean");return this.sleepEligible.set(e,t),t&&!this.sleeping&&this.enableSleeping(),this.sleeping?.register(e,t),this.wakeAll(),this}wakeAll(){return this.sleeping&&(this.sleeping.wakeRequested=!0),this}wakeUp(e){return this.liveIndex(e),this.wakeAll()}async readSleepStats(){return this.sleeping?this.sleeping.readStats():{sleeping:0,wakeRequested:!1}}flushEdits(){this.flushPropertyEdits(),this.sleeping?.wakeRequested&&this.sleeping.before(),this.bodyCommands?.flush()}flushPropertyEdits(e){this.propertyEdits?.flush(e)}readJoints(){return this.flushPropertyEdits(),super.readJoints()}attachToScene(e,{maxSubSteps:t=6,maxFrameTime:i=.05,afterStep:r}={}){if(this.destroyed)throw Error("The 2D solver has been destroyed");if(!e?.onBeforeRenderObservable?.add||!e?.onDisposeObservable?.addOnce||!e?.getEngine)throw Error("A Babylon scene is required");if(!Number.isInteger(t)||t<1||!Number.isFinite(i)||i<=0||r!==void 0&&typeof r!="function")throw Error("Scene stepping requires positive frame limits and an optional afterStep function");if(this.sceneBinding){if(this.sceneBinding.scene===e)return this;throw Error("The 2D solver is already attached to another scene")}let o=0,a=e.onBeforeRenderObservable.add(()=>{let l=this.params.dt;if(!(l>0)||!Number.isFinite(l))throw Error("Simulation timestep must be positive and finite");let c=e.getEngine().getDeltaTime()/1e3;o=Math.min(t*l,o+Math.min(i,Math.max(0,c)));for(let u=0;o+1e-12>=l&&u<t&&(this.step(),o=Math.max(0,o-l),r?.(this),!(!this.sceneBinding||this.destroyed));u++);}),n=e.onDisposeObservable.addOnce(()=>this.destroy());return this.sceneBinding={scene:e,before:a,dispose:n},this}detachFromScene(){let e=this.sceneBinding;return e&&(e.scene.onBeforeRenderObservable.remove(e.before),e.scene.onDisposeObservable.remove(e.dispose),this.sceneBinding=null),this}};var Jo=s=>{if(!Number.isInteger(s)||s<0||s>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");return s};function me(s,e,t){let i=s&&typeof s.x=="number"?[s.x,s.y,...e>=3?[s.z]:[],...e===4?[s.w]:[]]:Array.isArray(s)||ArrayBuffer.isView(s)&&!(s instanceof DataView)?s:Array.from(s??[]);if(i.length!==e||!i.every(Number.isFinite))throw Error(`${t} requires ${e} finite components`);return i}var Jc=["linearVelocity","angularVelocity","impulse","force","","angularImpulse","torque"];function fd(s,e){if(this.destroyed)throw Error("The solver has been destroyed");let t=this.editInProgress,i=t?new ti:this.editStaging??=new ti;this.editInProgress=!0;try{return dd.call(this,s,e,i)}finally{this.editInProgress=t}}function dd(s,e,t){t.count=0;let i,r=(o,a)=>{if(e===3)return me(o,3,a);if(!Number.isFinite(o))throw Error(`${a} must be finite`);return[o,0,0]};for(let o of s){let a=this.bodyIndex(o.body),{isTrigger:n,restitution:l,group:c,collidesWith:u,allowSleep:f}=o;if(n!==void 0||l!==void 0||c!==void 0||u!==void 0||f!==void 0){if(n!==void 0&&typeof n!="boolean")throw Error("isTrigger must be a boolean");if(f!==void 0&&typeof f!="boolean")throw Error("allowSleep must be a boolean");if(l!==void 0&&(!Number.isFinite(l)||l<0||l>1))throw Error("restitution must be between 0 and 1");if(u!==void 0&&c===void 0)throw Error("A collision-mask edit requires group as well");c!==void 0&&Jo(c),u!==void 0&&Jo(u),(i??=[]).push({index:a,isTrigger:n,restitution:l,group:c,collidesWith:u??4294967295,allowSleep:f})}let d=o.worldPoint===void 0?void 0:me(o.worldPoint,e,"worldPoint");if(o.position!==void 0){let h=me(o.position,e,"position"),m;if(o.rotation!==void 0){if(m=e===3?me(o.rotation,4,"rotation"):[o.rotation],e===3){let p=Math.hypot(...m);if(!p)throw Error("rotation must be nonzero");m=m.map(g=>g/p)}else if(!Number.isFinite(o.rotation))throw Error("angle must be finite")}t.append(a,4,h,e===3?m:void 0,m!==void 0),e===2&&(t.words[(t.count-1)*12+6]=m?.[0]??0)}else if(o.rotation!==void 0)throw Error("A rotation edit requires position; use teleport for a full pose");for(let h=0;h<Jc.length;h++){if(h===4)continue;let m=Jc[h];if(o[m]===void 0)continue;let g=h===1||h>=5?r(o[m],m):me(o[m],e,m);t.append(a,h,g,h===2||h===3?d:void 0,(h===2||h===3)&&d!==void 0),(h===3||h===6)&&(t.words[(t.count-1)*12+7]=this.params.dt)}}if(this.destroyed)throw Error("The solver was destroyed while reading body edits");t.count&&this.prepareBodyCommands().enqueueValidated(t);for(let o of i??[])o.isTrigger!==void 0&&this.setSensor(o.index,o.isTrigger),o.restitution!==void 0&&this.setRestitution(o.index,o.restitution),o.group!==void 0&&this.setFilters([o.index],[o.group],[o.collidesWith]),o.allowSleep!==void 0&&this.setSleepEnabled(o.index,o.allowSleep);return this}var Xo=class{constructor(e,t){this.solver=e,this.index=t}get gpuIndex(){return this.solver.liveIndex(this.index),this.index}setLinearVelocity(e){return this.solver.setLinearVelocity(this.gpuIndex,e),this}setAngularVelocity(e){return this.solver.setAngularVelocity(this.gpuIndex,e),this}applyImpulse(e,t){return this.solver.applyImpulse(this.gpuIndex,e,t),this}applyForce(e,t){return this.solver.applyForce(this.gpuIndex,e,t),this}applyAngularImpulse(e){return this.solver.applyAngularImpulse(this.gpuIndex,e),this}applyTorque(e){return this.solver.applyTorque(this.gpuIndex,e),this}teleport(e,t){return this.solver.teleport(this.gpuIndex,e,t),this}setTrigger(e){return this.solver.setSensor(this.gpuIndex,e),this.solver.wakeAll(),this}setRestitution(e){return this.solver.setRestitution(this.gpuIndex,e),this.solver.wakeAll(),this}setCollisionGroups(e,t=4294967295){return this.solver.setFilters([this.gpuIndex],[Jo(e)],[Jo(t)]),this.solver.wakeAll(),this}setSleepEnabled(e){return this.solver.setSleepEnabled(this.gpuIndex,e),this}wakeUp(){return this.solver.liveIndex(this.index),this.solver.wakeAll(),this}readState(){return this.solver.readBodyState(this.gpuIndex)}};function Xc(s,{maxSubSteps:e=6,maxFrameTime:t=.05}={}){if(!Number.isInteger(e)||e<1||!Number.isFinite(t)||t<=0)throw Error("Stepping limits must be positive");let i=s.params.dt;if(!Number.isFinite(i)||i<=0)throw Error("Simulation timestep must be positive and finite");return{dt:i,maxSubSteps:e,maxFrameTime:t}}function Yc(s,e,t,i){if(s.destroyed)throw Error("The solver has been destroyed");if(!Number.isFinite(e)||e<0)throw Error("elapsed must be finite nonnegative seconds");let{dt:r,maxSubSteps:o,maxFrameTime:a}=Xc(s,t);s.timeAccumulator=Math.min(o*r,(s.timeAccumulator??0)+Math.min(a,e));let n=0;for(;s.timeAccumulator+1e-12>=r&&n<o;)s.step(),s.timeAccumulator=Math.max(0,s.timeAccumulator-r),n++,i?.(s);return n}function pd(s,e){return Yc(this,s,e)}function Yo(s,{afterStep:e,...t}={}){if(this.destroyed)throw Error("The solver has been destroyed");if(!s?.onBeforeRenderObservable?.add||!s?.onDisposeObservable?.addOnce||!s?.getEngine)throw Error("A Babylon scene is required");if(e!==void 0&&typeof e!="function")throw Error("afterStep must be a function");if(Xc(this,t),this.sceneBinding){if(this.sceneBinding.scene===s)return this;throw Error("The solver is already attached to another scene")}let i=s.onBeforeRenderObservable.add(()=>{Yc(this,Math.max(0,s.getEngine().getDeltaTime()/1e3),t,e)}),r=s.onDisposeObservable.addOnce(()=>this.destroy());return this.sceneBinding={scene:s,before:i,dispose:r},this}function Qo(){let s=this.sceneBinding;return s&&(s.scene.onBeforeRenderObservable.remove(s.before),s.scene.onDisposeObservable.remove(s.dispose),this.sceneBinding=null,this.timeAccumulator=0),this}function Nr(s,e,t,i={}){s.advance=pd;let r,o;s.bodyIndex=function(n){if(this.destroyed)throw Error("The solver has been destroyed");let l=n;if(n instanceof Xo){if(n.solver!==this)throw Error("Body belongs to another solver");return n.gpuIndex}return typeof l!="number"&&t===3&&(o||(o=new WeakMap,e.bodies.forEach((c,u)=>o.set(c,this.gpuIndex(u)))),l=o.get(n)),this.liveIndex(l),l},s.body=function(n){let l=this.bodyIndex(n);return r??=new Map,r.has(l)||r.set(l,new Xo(this,l)),r.get(l)},s.editBodies=function(n){return fd.call(this,n,t)},s.setLinearVelocities=function(n,l){if(this.destroyed)throw Error("The solver has been destroyed");return i.setVelocities?i.setVelocities.call(this,n,{linear:l}):(this.velocityBatch??=new Kt(this,t),this.velocityBatch.set(n,l),this)},s.setVelocities=function(n,l){if(this.destroyed)throw Error("The solver has been destroyed");return i.setVelocities?i.setVelocities.call(this,n,l):l?.angular===void 0&&l?.linear!==void 0?this.setLinearVelocities(n,l.linear):l?.linear===void 0&&l?.angular!==void 0?this.setAngularVelocities(n,l.angular):(this.motionBatch??=new yi(this,t),this.motionBatch.set(n,l),this)},s.setAngularVelocities=function(n,l){if(this.destroyed)throw Error("The solver has been destroyed");return i.setVelocities?i.setVelocities.call(this,n,{angular:l}):(this.angularVelocityBatch??=new Kt(this,t,"angular"),this.angularVelocityBatch.set(n,l),this)};let a=s.destroy;return s.destroy=function(){this.destroyed||(this.velocityBatch?.destroy(),this.angularVelocityBatch?.destroy(),this.motionBatch?.destroy(),this.bodyReadback?.destroy(),this.editStaging=null,a.call(this),r?.clear(),o=null,e=null)},i.readSelectedBodies?s.readSelectedBodies=i.readSelectedBodies:t===2&&(s.readSelectedBodies=function(n,{posesOnly:l=!1}={}){let c=n instanceof Uint32Array?n:Array.from(n);return c.forEach(u=>this.liveIndex(u)),this.flushEdits(),this.bodyReadback??=new vi(this.device),this.bodyReadback.read(this.bodyBuffer,c,l,6)}),s}var Ko=class extends $o{constructor(e,t,i){super(e,t,i),Nr(this,null,2)}};var Tn=`struct Body { pos:vec4f, rot:vec4f, initialPos:vec4f, initialRot:vec4f, size:vec4f, moment:vec4f, inertialPos:vec4f, inertialRot:vec4f, velocity:vec4f, angular:vec4f }
5098
5141
  struct Command { header:vec4u, value:vec4f, point:vec4f }
5099
5142
  struct Manifold { ids:vec4u, geo:vec4f }
5100
5143
  @group(0) @binding(0) var<storage,read_write> bodies:array<Body>;
@@ -5184,7 +5227,7 @@ ${Tn}`});this.invalidate=r.createComputePipeline({layout:"auto",compute:{module:
5184
5227
  let v1 = y1/d1 - l21*v2 - l31*v3;
5185
5228
  bodies[i].pos = vec4f(bodies[i].pos.xyz - vec3f(v1,v2,v3), bodies[i].pos.w);
5186
5229
  return;
5187
- }`);var Qc=ii;var iu=8,Kc=16,Yi=1e-6,Gn=1e-5,md=1e-6,Fn=34028234663852886e22,ea=0,ru=1,ta=2;function Zc(s){let e=s.positionAng;return{center:s.positionLin,half:ne(S(),s.size,.5),axis:[le(S(),e,[1,0,0]),le(S(),e,[0,1,0]),le(S(),e,[0,0,1])]}}var Xi=(s,e)=>Math.abs(V(s,e));function ia(s,e){let t=V(e,s.axis[0])>=0?1:-1,i=V(e,s.axis[1])>=0?1:-1,r=V(e,s.axis[2])>=0?1:-1,o=D(S(),s.center,s.axis[0],s.half[0]*t);return D(o,o,s.axis[1],s.half[1]*i),D(o,o,s.axis[2],s.half[2]*r)}function su(s,e){return e===0?{u:s.axis[1],v:s.axis[2],extentU:s.half[1],extentV:s.half[2]}:e===1?{u:s.axis[0],v:s.axis[2],extentU:s.half[0],extentV:s.half[2]}:{u:s.axis[0],v:s.axis[1],extentU:s.half[0],extentV:s.half[1]}}function gd(s,e,t){let i=V(t,s.axis[e])>=0?1:-1,r=ne(S(),s.axis[e],i),o=D(S(),s.center,r,s.half[e]);return{normal:r,center:o,...su(s,e)}}function bd(s,e){let t=0,i=-Fn;for(let r=0;r<3;r++){let o=Xi(s.axis[r],e);o>i&&(i=o,t=r)}return t}function yd(s,e,t){let i=V(s.axis[e],t)>0?-1:1,r=ne(S(),s.axis[e],i),o=D(S(),s.center,r,s.half[e]),{u:a,v:n,extentU:l,extentV:c}=su(s,e),u=(f,d)=>{let p=D(S(),o,a,f*l);return D(p,p,n,d*c)};return[u(1,1),u(-1,1),u(-1,-1),u(1,-1)]}function vd(s,e,t){let i=[];if(s.length===0)return i;let r=s[s.length-1],o=V(e,r)-t;for(let a of s){let n=V(e,a)-t,l=o<=Gn,c=n<=Gn;if(l!==c){let u=0,f=o-n;Math.abs(f)>Yi&&(u=ce(o/f,0,1)),i.length<Kc&&i.push(D(S(),r,J(S(),a,r),u))}c&&i.length<Kc&&i.push(a),r=a,o=n}return i}var ra=class{contacts=[];midpoints=[];bodyA;bodyB;constructor(e,t){this.bodyA=e,this.bodyB=t}add(e,t,i){let r=ne(S(),Li(S(),e,t),.5);for(let n of this.midpoints)if(Ne(J(S(),r,n))<md)return;if(this.contacts.length>=iu)return;let{bodyA:o,bodyB:a}=this;this.contacts.push({feature:i,rA:Te(S(),o.positionAng,J(S(),e,o.positionLin)),rB:Te(S(),a.positionAng,J(S(),t,a.positionLin))}),this.midpoints.push(r)}};function Dn(s,e,t,i,r,o,a,n){let l=Ne(i);if(l<Yi)return!0;let c=1/Math.sqrt(l),u=ne(S(),i,c);V(u,t)<0&&ee(u,u);let f=Math.abs(V(t,u)),d=s.half[0]*Xi(u,s.axis[0])+s.half[1]*Xi(u,s.axis[1])+s.half[2]*Xi(u,s.axis[2]),p=e.half[0]*Xi(u,e.axis[0])+e.half[1]*Xi(u,e.axis[1])+e.half[2]*Xi(u,e.axis[2]),m=f-(d+p);return m>0?!1:((!n.valid||m>n.separation)&&(n.valid=!0,n.type=r,n.indexA=o,n.indexB=a,n.separation=m,n.normalAB=u),!0)}function eu(s,e,t){let i=(e+1)%3,r=(e+2)%3,o=V(t,s.axis[i])>=0?1:-1,a=V(t,s.axis[r])>=0?1:-1,n=D(S(),s.center,s.axis[i],s.half[i]*o);D(n,n,s.axis[r],s.half[r]*a);let l=ne(S(),s.axis[e],s.half[e]);return[J(S(),n,l),Li(S(),n,l)]}function xd(s,e,t,i){let r=J(S(),e,s),o=J(S(),i,t),a=J(S(),s,t),n=V(r,r),l=V(o,o),c=V(o,a),u=0,f=0;if(n<=Yi&&l<=Yi)return[s,t];if(n<=Yi)f=ce(c/l,0,1);else{let d=V(r,a);if(l<=Yi)u=ce(-d/n,0,1);else{let p=V(r,o),m=n*l-p*p;Math.abs(m)>Yi&&(u=ce((p*c-d*l)/m,0,1)),f=(p*u+c)/l,f<0?(f=0,u=ce(-d/n,0,1)):f>1&&(f=1,u=ce((p-d)/n,0,1))}}return[D(S(),s,r,u),D(S(),t,o,f)]}function tu(s,e,t,i,r,o,a){let n=r?t:i,l=r?i:t,c=r?a:ee(S(),a),u=gd(n,o,c),f=bd(l,u.normal),d=yd(l,f,u.normal),p=[[u.u,u.extentU],[ee(S(),u.u),u.extentU],[u.v,u.extentV],[ee(S(),u.v),u.extentV]];for(let[g,b]of p)if(d=vd(d,g,V(g,u.center)+b),!d.length)return[];let m=new ra(s,e),h=(r?ea:ru)<<24|(o&255)<<16|(f&255)<<8;for(let g=0;g<d.length&&m.contacts.length<iu;g++){let b=d[g],y=V(J(S(),b,u.center),u.normal);if(y>Gn)continue;let A=D(S(),b,u.normal,-y),v=r?A:b,x=r?b:A;m.add(v,x,h|g&255)}return m.contacts.length||m.add(ia(t,a),ia(i,ee(S(),a)),h),m.contacts}function Ad(s,e,t,i,r,o,a){let[n,l]=eu(t,r,a),[c,u]=eu(i,o,ee(S(),a)),[f,d]=xd(n,l,c,u),p=new ra(s,e),m=ta<<24|(r&255)<<8|o&255;return p.add(f,d,m),p.contacts.length||p.add(ia(t,a),ia(i,ee(S(),a)),m),p.contacts}function ou(s,e,t,i=!0){let r=Zc(s),o=Zc(e),a=J(S(),o.center,r.center),n={type:ea,indexA:0,indexB:0,separation:-Fn,normalAB:S(),valid:!1},l={type:ta,indexA:0,indexB:0,separation:-Fn,normalAB:S(),valid:!1};for(let f=0;f<3;f++)if(!Dn(r,o,a,r.axis[f],ea,f,-1,n))return[];for(let f=0;f<3;f++)if(!Dn(r,o,a,o.axis[f],ru,-1,f,n))return[];let c=S();for(let f=0;f<3;f++)for(let d=0;d<3;d++)if(Dt(c,r.axis[f],o.axis[d]),!Dn(r,o,a,c,ta,f,d,l))return[];if(!n.valid)return[];let u=n;return l.valid&&(i?l.separation>.95*n.separation+.01:.95*l.separation>n.separation+.01)&&(u=l),zs(t,ee(S(),u.normalAB)),u.type===ta?Ad(s,e,r,o,u.indexA,u.indexB,u.normalAB):u.type===ea?tu(s,e,r,o,!0,u.indexA,u.normalAB):tu(s,e,r,o,!1,u.indexB,u.normalAB)}var de=(s,e)=>s.map((t,i)=>t+e[i]),T=(s,e)=>s.map((t,i)=>t-e[i]),q=(s,e)=>s.map(t=>t*e),F=(s,e)=>s.reduce((t,i,r)=>t+i*e[r],0),xt=(s,e)=>[s[1]*e[2]-s[2]*e[1],s[2]*e[0]-s[0]*e[2],s[0]*e[1]-s[1]*e[0]],Tt=s=>q(s,1/(Math.hypot(...s)||1)),Ee=(s,e)=>Array.from(le(S(),s,e)),au=(s,e)=>Te(S(),s.positionAng,T(e,s.positionLin)),Ot=(s,e)=>de(s.positionLin,Ee(s.positionAng,e)),wd=[[1,3,7,5],[0,4,6,2],[2,6,7,3],[0,1,5,4],[4,5,7,6],[0,2,3,1]],Bd=[[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]];function qr(s){if(De(s)||Fe(s)){let a=(De(s),s.size[0]/2),n=Fe(s)?Math.max(0,s.size[1]/2-a):0;return{body:s,radius:a,spine:[Ot(s,[0,-n,0]),Ot(s,[0,n,0])]}}let e=Ct(s),t=e?Array.from({length:e.vertices.length/3},(a,n)=>Ot(s,e.vertices.slice(n*3,n*3+3))):Array.from({length:8},(a,n)=>Ot(s,s.size.map((l,c)=>l/2*(n>>c&1?1:-1)))),i=e?e.faces.map(a=>({vertices:a.verts.map(n=>t[n]),normal:Ee(s.positionAng,a.normal)})):wd.map((a,n)=>({vertices:a.map(l=>t[l]),normal:Ee(s.positionAng,Bd[n])})),r=[],o=new Set;for(let a of i)for(let n=0;n<a.vertices.length;n++){let l=a.vertices[n],c=a.vertices[(n+1)%a.vertices.length],u=t.indexOf(l),f=t.indexOf(c),d=`${Math.min(u,f)},${Math.max(u,f)}`;o.has(d)||(o.add(d),r.push([l,c]))}return{body:s,vertices:t,faces:i,edges:r}}function Ss(s,e){let t=s.spine??s.vertices,i=t[0];for(let r of t)F(r,e)>F(i,e)&&(i=r);return s.spine?de(i,q(e,s.radius)):i}function Cd(s,e,t){let i=T(e,s);return de(s,q(i,Math.max(0,Math.min(1,F(T(t,s),i)/(F(i,i)||1)))))}function sa([s,e],[t,i]){let r=T(e,s),o=T(i,t),a=T(s,t),n=F(r,r),l=F(o,o),c=F(o,a),u=0,f=0,d=p=>Math.max(0,Math.min(1,p));if(n<1e-16)f=l>1e-16?d(c/l):0;else{let p=F(r,a);if(l<1e-16)u=d(-p/n);else{let m=F(r,o),h=n*l-m*m;u=h>1e-12*n*l?d((m*c-p*l)/h):0,f=(m*u+c)/l,f<0?(f=0,u=d(-p/n)):f>1&&(f=1,u=d((m-p)/n))}}return[de(s,q(r,u)),de(t,q(o,f))]}function Sd(s,e,t){let i=[];for(let r=0;r<s.length;r++){let o=s[r],a=s[(r+1)%s.length],n=F(o,e)-t,l=F(a,e)-t;n<=1e-8&&i.push(o),n<0!=l<0&&i.push(de(o,q(T(a,o),n/(n-l))))}return i}function kd(s,e,t,i){let r=T(t,e),o=T(i,e),a=T(s,e),n=F(r,a),l=F(o,a);if(n<=0&&l<=0)return e;let c=T(s,t),u=F(r,c),f=F(o,c);if(u>=0&&f<=u)return t;let d=n*f-u*l;if(d<=0&&n>=0&&u<=0)return de(e,q(r,n/(n-u)));let p=T(s,i),m=F(r,p),h=F(o,p);if(h>=0&&m<=h)return i;let g=m*l-n*h;if(g<=0&&l>=0&&h<=0)return de(e,q(o,l/(l-h)));let b=u*h-m*f;if(b<=0&&f-u>=0&&m-h>=0)return de(t,q(T(i,t),(f-u)/(f-u+m-h)));let y=1/(b+g+d);return de(e,de(q(r,g*y),q(o,d*y)))}function Pd(s,e){let t=null,i=1/0;for(let r of s.faces)for(let o=1;o<r.vertices.length-1;o++){let a=kd(e,r.vertices[0],r.vertices[o],r.vertices[o+1]),n=F(T(e,a),T(e,a));n<i&&(t=a,i=n)}return t}function nu(s,e,t,i,r){if(!De(s)&&!De(e)&&!Fe(s)&&!Fe(e)&&!Ct(s)&&!Ct(e))return ou(s,e,t,s.solver.faceBias!==!1);i??=qr(s),r??=qr(e);let o=-1/0,a=[0,0,1],n=null,l=(f,d=null)=>{if(Math.hypot(...f)<1e-9)return;let p=Tt(f),m=F(T(Ss(i,q(p,-1)),Ss(r,p)),p),h=F(T(Ss(r,q(p,-1)),Ss(i,p)),p);h>m&&(m=h,p=q(p,-1)),m>o+1e-7&&(o=m,a=p,n=d)};for(let f of[i,r])for(let d of f.faces??[])l(d.normal);if(i.edges&&r.edges)for(let f of i.edges)for(let d of r.edges)l(xt(T(f[1],f[0]),T(d[1],d[0])),[f,d]);if(i.spine&&r.spine){let f=sa(i.spine,r.spine);l(T(...f))}for(let[f,d]of[[i,r],[r,i]])if(f.spine&&d.faces){for(let p of d.vertices)l(T(p,Cd(...f.spine,p)));for(let p of d.edges){let m=sa(f.spine,p);l(T(...m))}}if(o===-1/0&&l(T(s.positionLin,e.positionLin)),o>0)return[];o===-1/0&&(a=[0,0,1],o=-(i.radius+r.radius));let c=Tt(xt(a,Math.abs(a[0])<.7?[1,0,0]:[0,1,0]));t.set([...a,...c,...xt(a,c)]);let u=[];if(i.spine&&r.spine){let[f,d]=sa(i.spine,r.spine);u=[[de(f,q(a,-i.radius)),de(d,q(a,r.radius))]]}else if(i.spine||r.spine){let f=i.spine?i:r,d=i.spine?r:i,p=i.spine?q(a,-1):a,m=Ss(f,p),h=Pd(d,m);u=[i.spine?[m,h]:[h,m]]}else if(n)u=[sa(...n)];else{let f=(A,v)=>A.faces.reduce((x,w)=>F(w.normal,v)>F(x.normal,v)?w:x,A.faces[0]),d=f(i,q(a,-1)),p=f(r,a),m=F(d.normal,q(a,-1))>=F(p.normal,a),h=m?d:p,b=f(m?r:i,q(h.normal,-1)).vertices,y=q(h.vertices.reduce((A,v)=>de(A,v),[0,0,0]),1/h.vertices.length);for(let A=0;A<h.vertices.length&&b.length;A++){let v=h.vertices[A],x=h.vertices[(A+1)%h.vertices.length],w=Tt(xt(T(x,v),h.normal));F(T(y,v),w)>0&&(w=q(w,-1)),b=Sd(b,w,F(v,w))}for(let A of b){let v=F(T(A,h.vertices[0]),h.normal);if(v<=1e-6){let x=T(A,q(h.normal,v));u.push(m?[x,A]:[A,x])}}}return u.slice(0,8).map(([f,d],p)=>({feature:p+1,rA:au(s,f),rB:au(e,d)}))}var oa=(s,e,t)=>Math.max(e,Math.min(t,s)),Ld=(s,e)=>[F(s.slice(0,3),e),F(s.slice(3,6),e),F(s.slice(6,9),e)];function qn(s,e=!1){if(e){s.rest=Math.hypot(...T(Ot(s.bodyA,s.rA),Ot(s.bodyB,s.rB)));return}let t=s.bodyA?.positionAng??[0,0,0,1];s.cpuRest=$r(jt(),Sa(jt(),t),s.bodyB.positionAng),s.evaluateAng=i=>{let r=$r(jt(),s.bodyA?.positionAng??[0,0,0,1],s.cpuRest);ut(i,r,s.bodyB.positionAng);for(let o=0;o<3;o++)i[o]*=s.torqueArm;return i}}var Un=class extends ai{initialize(){let e=this.bodyA,t=this.bodyB;if(!((e.group??4294967295)&(t.collidesWith??4294967295))||!((t.group??4294967295)&(e.collidesWith??4294967295)))return!1;let i=this.contacts,r=De(e)||De(t)||Fe(e)||Fe(t);this.friction=Math.sqrt(e.friction*t.friction),this.contacts=nu(e,t,this.basis,this.solver.cpuGeometry.get(e),this.solver.cpuGeometry.get(t)).map(o=>{let a=i.find(n=>n.feature===o.feature);return{feature:o.feature,rA:a?.stick&&!r?a.rA:o.rA,rB:a?.stick&&!r?a.rB:o.rB,C0:S(),penalty:a?a.penalty.slice():S(),lambda:a?a.lambda.slice():S(),stick:a?.stick??!1}});for(let o of this.contacts){o.C0.set(Ld(this.basis,T(Ot(e,o.rA),Ot(t,o.rB)))),o.C0[0]+=Rs;for(let a=0;a<3;a++)o.lambda[a]*=this.solver.alpha*this.solver.gamma,o.penalty[a]=oa(o.penalty[a]*this.solver.gamma,Et,Ve);if(this.solver.massPenalty!==!1){let a=Math.min(e.mass>0?e.mass:1/0,t.mass>0?t.mass:1/0);o.penalty[0]=Math.max(o.penalty[0],oa(a/this.solver.dt**2,Et,Ve))}}return this.contacts.length>0}updatePrimal(...e){!this.bodyA.isTrigger&&!this.bodyB.isTrigger&&super.updatePrimal(...e)}updateDual(...e){!this.bodyA.isTrigger&&!this.bodyB.isTrigger&&super.updateDual(...e)}},Nn=class extends Ft{constructor(e,t,i){super(e,t.bodyA,t.bodyB),this.options={...i},this.pen=[Et,Et],this.lam=[0,0],this.source=t;let r=i.axisA;this.ta=Tt(Math.abs(r[0])>Math.abs(r[2])?[-r[1],r[0],0]:[0,-r[2],r[1]]);let o=this.bodyA?Ee(this.bodyA.positionAng,this.ta):this.ta,a=Array.from(Te(S(),this.bodyB.positionAng,o));a=T(a,q(i.axisB,F(a,i.axisB))),this.tb=Tt(a)}frame(){let e=this.bodyA?Ee(this.bodyA.positionAng,this.options.axisA):this.options.axisA,t=this.bodyA?Ee(this.bodyA.positionAng,this.ta):this.ta,i=Ee(this.bodyB.positionAng,this.tb);return{axis:e,angle:Math.atan2(F(e,xt(t,i)),F(t,i))}}initialize(){let e=this.frame().angle;this.c0=this.options.type==="motor"?[e,0]:[Math.min(0,e-this.options.minAngle),Math.max(0,e-this.options.maxAngle)];for(let t=0;t<2;t++)this.lam[t]*=this.solver.alpha*this.solver.gamma,this.pen[t]=oa(this.pen[t]*this.solver.gamma,Et,Ve);return!this.source.broken}evaluate(e){let{angle:t}=this.frame(),i=this.options,r=i.type==="motor"?[Math.atan2(Math.sin(t-this.c0[0]),Math.cos(t-this.c0[0]))-i.speed*this.solver.dt,0]:[t-i.minAngle-e*this.c0[0],t-i.maxAngle-e*this.c0[1]],o=r.map((a,n)=>this.pen[n]*a+this.lam[n]);return{c:r,f:i.type==="motor"?[oa(o[0],-i.maxTorque,i.maxTorque),0]:[Math.min(0,o[0]),Math.max(0,o[1])]}}updatePrimal(e,t,i){let{f:r}=this.evaluate(t),o=this.options;if(o.type==="motor"&&o.maxTorque===0)return;let a=q(this.frame().axis,e===this.bodyA?-1:1);for(let n=0;n<(o.type==="motor"?1:2);n++)if(!(o.type==="limit"&&r[n]===0))for(let l=0;l<3;l++){i.rhsAng[l]+=a[l]*r[n];for(let c=0;c<3;c++)i.lhsAng[l*3+c]+=a[l]*a[c]*this.pen[n]}}updateDual(e){let{c:t,f:i}=this.evaluate(e);this.lam=i;for(let r=0;r<2;r++)this.pen[r]=Math.min(Ve,this.pen[r]+this.solver.betaAng*(this.options.type==="motor"?Math.abs(t[r]):r===0?Math.max(0,-t[r]):Math.max(0,t[r])))}};function aa(s){if(!s.cpuPrepared){s.cpuPrepared=!0;for(let e of[...s.forces]){let t=fs(e);if(t){e.unlinkFromBodies(),s.forces.splice(s.forces.indexOf(e),1),e.cpuAngular=new Nn(s,e,t);continue}if(e instanceof ke&&e.stiffnessAng>0&&qn(e),e instanceof dt){let i=e.initialize.bind(e);e.initialize=()=>{if(e.broken)return!1;let r=Ui(e);if(r){let o=Math.max(0,Math.hypot(...T(Ot(e.bodyA,e.rA),Ot(e.bodyB,e.rB)))-e.rest);if(o/Math.max(e.rest,1e-6)>r.breakStrain||o*e.stiffness>r.breakForce)return e.broken=!0,!1}return i()}}}}}function lu(s){let e=s.bodies;s.cpuGeometry=new Map;for(let l of e)(De(l)||Fe(l)||Ct(l))&&s.cpuGeometry.set(l,qr(l));let t=e.filter(l=>l.mass>0).slice(0,1024).map(l=>l.radius).sort((l,c)=>l-c),i=Math.max(.1,(t[Math.floor(t.length/2)]??1)*2),r=new Map,o=[],a=new Set,n=(l,c)=>{if(l===c||e[l].mass<=0&&e[c].mass<=0)return;let u=Math.max(l,c),f=Math.min(l,c),d=u*e.length+f;if(a.has(d))return;a.add(d);let p=e[u],m=e[f];if(!((p.group??4294967295)&(m.collidesWith??4294967295))||!((m.group??4294967295)&(p.collidesWith??4294967295)))return;let h=p.radius+m.radius;F(T(p.positionLin,m.positionLin),T(p.positionLin,m.positionLin))<=h*h&&!p.constrainedTo(m)&&new Un(s,p,m)};for(let l=0;l<e.length;l++){let c=e[l],u=c.positionLin.map(d=>Math.floor((d-c.radius)/i)),f=c.positionLin.map(d=>Math.floor((d+c.radius)/i));if((f[0]-u[0]+1)*(f[1]-u[1]+1)*(f[2]-u[2]+1)>128){o.push(l);continue}for(let d=u[0];d<=f[0];d++)for(let p=u[1];p<=f[1];p++)for(let m=u[2];m<=f[2];m++){let h=`${d},${p},${m}`,g=r.get(h)??[];for(let b of g)n(l,b);g.push(l),r.set(h,g)}}for(let l of o)for(let c=0;c<e.length;c++)n(l,c)}function na(s,e){if(!(e===3?s.bodies.some(r=>r.restitution>0):[...s.restitution.values()].some(r=>r>0)))return null;if(e===2)return Float64Array.from(s.velocity);let i=new Float64Array(s.bodies.length*6);return s.bodies.forEach((r,o)=>{i.set(r.velocityLin,o*6),i.set(r.velocityAng,o*6+3)}),i}function la(s,e,t){if(!t)return;let i=e===3?s.bodies.length:s.bodyCount,r=e===3?6:4,o=e===3?new Float64Array(i*r):s.velocity;e===3&&s.bodies.forEach((h,g)=>{o.set(h.velocityLin,g*r),o.set(h.velocityAng,g*r+3)});let a=h=>e===3?s.bodies[h].mass>0&&!s.bodies[h].sleeping?1/s.bodies[h].mass:0:s.dynamic[h]?1/s.shape[h*4+2]:0,n=(h,g)=>{if(!a(h))return e===3?[0,0,0]:0;if(e===2)return s.shape[h*4+3]>0?g/s.shape[h*4+3]:0;let b=s.bodies[h],y=b.positionAng,A=Ee([-y[0],-y[1],-y[2],y[3]],g);return Ee(y,A.map((v,x)=>b.moment[x]>0?v/b.moment[x]:0))},l=(h,g,b)=>{let y=g*r;return e===3?T(h.subarray(y,y+3),xt(b,h.subarray(y+3,y+6))):[h[y]-h[y+2]*b[1],h[y+1]+h[y+2]*b[0]]},c=(h,g)=>e===3?xt(h,g):h[0]*g[1]-h[1]*g[0],u=(h,g)=>e===3?F(h,g):h*g,f;if(e===3){let h=new Map(s.bodies.map((g,b)=>[g,b]));f=s.forces.filter(g=>g.contacts?.length&&!g.bodyA.isTrigger&&!g.bodyB.isTrigger).map(g=>{let b=(y,A)=>{let v=[0,0,0];for(let x of g.contacts){let w=Ee(y.positionAng,x[A]);for(let B=0;B<3;B++)v[B]+=w[B]/g.contacts.length}return v};return{a:h.get(g.bodyA),b:h.get(g.bodyB),n:g.basis.slice(0,3),ra:b(g.bodyA,"rA"),rb:b(g.bodyB,"rB"),e:Math.max(g.bodyA.restitution??0,g.bodyB.restitution??0)}})}else{let h=(g,b)=>{let y=Math.cos(s.pose[g*4+2]),A=Math.sin(s.pose[g*4+2]);return[y*b[0]-A*b[1],A*b[0]+y*b[1]]};f=s.contactPairs.filter(g=>!s.sensors.has(g.a)&&!s.sensors.has(g.b)).map(g=>({...g,ra:h(g.a,g.ra),rb:h(g.b,g.rb),e:Math.max(s.restitution.get(g.a)??0,s.restitution.get(g.b)??0)}))}let d=new Uint32Array(i);if(e===3)s.bodies.forEach((h,g)=>{d[g]=h.forces.length});else for(let h=0;h<i;h++)d[h]=s.adjStart[h+1]-s.adjStart[h];let p=[];for(let h of f){if(h.e<=0)continue;let g=F(h.n,T(l(t,h.a,h.ra),l(t,h.b,h.rb)));if(g>=-1)continue;let b=c(h.ra,h.n),y=c(h.rb,h.n),A=n(h.a,b),v=n(h.b,y),x=a(h.a)+a(h.b)+u(b,A)+u(y,v);x>0&&p.push({...h,inertiaA:A,inertiaB:v,k:x,target:-h.e*g,impulse:0})}let m=new Float64Array(o.length);for(let h=0;h<12&&p.length;h++){m.fill(0);for(let g of p){let b=F(g.n,T(l(o,g.a,g.ra),l(o,g.b,g.rb))),y=Math.max(0,g.impulse+(g.target-b)/(g.k*Math.max(1,d[g.a],d[g.b]))),A=y-g.impulse;g.impulse=y;for(let[v,x,w]of[[g.a,1,g.inertiaA],[g.b,-1,g.inertiaB]]){let B=v*r,L=a(v);for(let M=0;M<e;M++)m[B+M]+=x*A*L*g.n[M];if(e===3)for(let M=0;M<3;M++)m[B+3+M]+=x*A*w[M];else m[B+2]+=x*A*w}}for(let g=0;g<o.length;g++)o[g]+=m[g]}e===3&&s.bodies.forEach((h,g)=>{h.velocityLin.set(o.subarray(g*r,g*r+3)),h.velocityAng.set(o.subarray(g*r+3,g*r+6))})}function cu(s,e,t){let i=e.windSpeed??0;if(!ar(s)||s.mass<=0||i===0)return null;let r=e.windAngle??0,o=[Math.cos(r),Math.sin(r),0],a=[-o[1],o[0],0],n=s.positionLin,l=t*e.dt,c=F(n,o),u=F(n,a),f=.5*Math.sin(1.1*l-.35*c+.2*u)+.3*Math.sin(2.9*l-.8*c+.6*n[2])+.2*Math.sin(6.1*l-1.7*c+1.3*n[2]+.9*u),d=.6*Math.sin(1.7*l-.6*c+.4*n[2])+.4*Math.sin(4.3*l-1.3*c-.7*n[2]),p=Math.sin(2.3*l-.9*c+1.1*u),m=e.windGust??.4,h=o.map((x,w)=>i*x*(1+m*f)+m*i*(a[w]*.25*d+(w===2?.1*p:0))-s.velocityLin[w]),g=Ee(s.positionAng,[0,0,1]),b=(e.windPressure??.72)*s.size[0]*s.size[1]/s.mass,y=F(h,g),A=h.map((x,w)=>x-g[w]*y),v=b*y*Math.abs(y)/(1+2*e.dt*b*Math.abs(y));return g.map((x,w)=>x*v+A[w]*.06*b*Math.hypot(...A))}var _d=()=>({dt:1/60,gravity:-10,iterations:10,betaLin:1e4,betaAng:100,alpha:.99,gamma:.999}),ca=class{dt=1/60;gravity=-10;iterations=10;alpha=.99;betaLin=1e4;betaAng=100;gamma=.999;massPenalty=!0;faceBias=!0;up=[0,0,1];cpuStep=0;bodies=[];forces=[];constructor(){this.defaultParams()}defaultParams(){Object.assign(this,_d())}clear(){this.forces=[],this.bodies=[]}pick(e,t){let r=null,o=S(),a=S();for(let n=this.bodies.length-1;n>=0;n--){let l=this.bodies[n];if(l.mass<=0)continue;Te(o,l.positionAng,J(o,e,l.positionLin)),Te(a,l.positionAng,t);let c=0,u=1/0,f=!0;for(let p=0;p<3&&f;p++){let m=l.size[p]*.5;if(Math.abs(a[p])<1e-6){(o[p]<-m||o[p]>m)&&(f=!1);continue}let h=1/a[p],g=(-m-o[p])*h,b=(m-o[p])*h;g>b&&([g,b]=[b,g]),c=Math.max(c,g),u=Math.min(u,b),c>u&&(f=!1)}if(!f)continue;let d=c>=0?c:u;d<0||(!r||d<r.t)&&(r={body:l,local:D(S(),o,a,d),t:d})}return r}sys=Os();dxLin=S();dxAng=S();dp=S();accel=S();step(){let{dt:e,gravity:t,bodies:i,sys:r,dp:o}=this,a=na(this,3);aa(this),lu(this);let n=[];for(let l of this.forces)l.initialize()?n.push(l):l.unlinkFromBodies();this.forces=n;for(let l=i.length-1;l>=0;l--){let c=i[l];D(c.inertialLin,c.positionLin,c.velocityLin,e),c.mass>0&&D(c.inertialLin,c.inertialLin,this.up,t*e*e);let u=cu(c,this,this.cpuStep);u&&D(c.inertialLin,c.inertialLin,u,e*e),si(c.inertialAng,c.positionAng,uu(c.velocityAng,e)),_t(this.accel,J(this.accel,c.velocityLin,c.prevVelocityLin),e);let f=V(this.accel,this.up)*Es(t),d=ce(f/Math.abs(t),0,1);Number.isFinite(d)||(d=0),c.initialLin.set(c.positionLin),c.initialAng.set(c.positionAng),c.mass>0&&!c.sleeping&&(D(c.positionLin,c.positionLin,c.velocityLin,e),D(c.positionLin,c.positionLin,this.up,t*d*e*e),si(c.positionAng,c.positionAng,uu(c.velocityAng,e)))}for(let l=0;l<this.iterations;l++){for(let c=i.length-1;c>=0;c--){let u=i[c];if(u.mass<=0||u.sleeping)continue;let f=u.mass,d=u.moment;Ce(r.lhsLin,f/(e*e),f/(e*e),f/(e*e)),Ce(r.lhsAng,d[0]/(e*e),d[1]/(e*e),d[2]/(e*e)),r.lhsCross.fill(0),ue(r.rhsLin,r.lhsLin,J(o,u.positionLin,u.inertialLin)),ue(r.rhsAng,r.lhsAng,ut(o,u.positionAng,u.inertialAng));let p=u.forces;for(let h=p.length-1;h>=0;h--)p[h].updatePrimal(u,this.alpha,r);let m=u.moment.every(h=>h===0);m&&(Ce(r.lhsAng,1,1,1),r.lhsCross.fill(0),r.rhsAng.fill(0)),Is(r.lhsLin,r.lhsAng,r.lhsCross,ee(r.rhsLin,r.rhsLin),ee(r.rhsAng,r.rhsAng),this.dxLin,this.dxAng),D(u.positionLin,u.positionLin,this.dxLin,1),m||si(u.positionAng,u.positionAng,this.dxAng)}for(let c of this.forces)c.updateDual(this.alpha)}for(let l of i)l.prevVelocityLin.set(l.velocityLin),l.mass>0&&!l.sleeping&&(_t(l.velocityLin,J(l.velocityLin,l.positionLin,l.initialLin),e),_t(l.velocityAng,ut(l.velocityAng,l.positionAng,l.initialAng),e));la(this,3,a),this.cpuStep++}},Ed=S(),uu=(s,e)=>ne(Ed,s,e);var Ps=(s,e)=>s.map((t,i)=>t+e[i]),Re=(s,e)=>s.map((t,i)=>t-e[i]),Lt=(s,e)=>s.map(t=>t*e),ot=(s,e)=>s[0]*e[0]+s[1]*e[1],ks=(s,e)=>[Math.cos(s)*e[0]-Math.sin(s)*e[1],Math.sin(s)*e[0]+Math.cos(s)*e[1]],du=s=>Math.max(0,Math.min(1,s)),fu=(s,e,t)=>Ps(s,Lt(Re(e,s),du(ot(Re(t,s),Re(e,s))/(ot(Re(e,s),Re(e,s))||1))));function ua(s,e){let t=ei(s)?.get(e)??[0,0,0,0],i=Array.from(s.pose.subarray(e*4,e*4+2)),r=s.pose[e*4+2],o=l=>Ps(i,ks(r,l)),a=[s.shape[e*4]/2,s.shape[e*4+1]/2],n=t[0]===4?Array.from({length:t.vertices.length/4},(l,c)=>o(t.vertices.slice(c*4,c*4+2))):t[0]===0?[[-1,-1],[1,-1],[1,1],[-1,1]].map(l=>o([l[0]*a[0],l[1]*a[1]])):null;return{kind:t[0],p:i,angle:r,vertices:n,radius:t[1],spine:[o([-t[2]||0,0]),o([t[2]||0,0])]}}function Qi(s,e){if(s.vertices){let r=-1/0,o=[];for(let a of s.vertices){let n=ot(a,e);n>r+1e-7?(r=n,o=[a]):Math.abs(n-r)<1e-7&&o.push(a)}return[o[0],o.at(-1)]}let t=Ps(s.spine[0],Lt(e,s.radius)),i=Ps(s.spine[1],Lt(e,s.radius));return Math.abs(ot(t,e)-ot(i,e))<1e-7?[t,i]:ot(t,e)>ot(i,e)?[t,t]:[i,i]}function hu(s,e,t,i){let r=ua(s,e),o=ua(s,t),a=s.pose,n=s.shape;if(r.kind===0&&o.kind===0)return _o(...a.subarray(e*4,e*4+3),n[e*4]/2,n[e*4+1]/2,...a.subarray(t*4,t*4+3),n[t*4]/2,n[t*4+1]/2,i);let l=[];if(r.kind===3||o.kind===3){let u=r.kind===3,f=u?r:o,d=u?o:r;if(d.kind===3)return 0;let p=ks(f.angle,[0,1]),m=Qi(d,Lt(p,-1));for(let h of m){let g=ot(Re(h,f.p),p);if(g<=0){let b=Re(h,Lt(p,g));l.push({a:u?b:h,b:u?h:b,n:u?Lt(p,-1):p})}}}else{let u=-1/0,f=[0,1],d=x=>{let w=Math.hypot(...x);if(w<1e-9)return;let B=Lt(x,1/w),L=ot(Re(Qi(r,Lt(B,-1))[0],Qi(o,B)[0]),B),M=ot(Re(Qi(o,Lt(B,-1))[0],Qi(r,B)[0]),B);Math.max(L,M)>u+1e-7&&(u=Math.max(L,M),f=L>=M?B:Lt(B,-1))};for(let[x,w]of[[r,o],[o,r]])if(x.vertices)for(let B=0;B<x.vertices.length;B++){let L=Re(x.vertices[(B+1)%x.vertices.length],x.vertices[B]);d([L[1],-L[0]]),w.vertices||d(Re(x.vertices[B],fu(...w.spine,x.vertices[B])))}else if(d(ks(x.angle,[0,1])),!w.vertices)for(let B of x.spine)d(Re(B,fu(...w.spine,B)));if(u===-1/0&&d([0,1]),u>0)return 0;let p=Qi(r,Lt(f,-1)),m=Qi(o,f),h=[-f[1],f[0]],g=p.map(x=>ot(x,h)),b=m.map(x=>ot(x,h)),y=Math.max(Math.min(...g),Math.min(...b)),A=Math.min(Math.max(...g),Math.max(...b)),v=(x,w)=>{let B=ot(Re(x[1],x[0]),h);return Math.abs(B)<1e-9?x[0]:Ps(x[0],Lt(Re(x[1],x[0]),du((w-ot(x[0],h))/B)))};for(let x of A-y>1e-6?[y,A]:[(y+A)/2])l.push({a:v(p,x),b:v(m,x),n:f})}let c=0;for(let u of l){if(c&&Math.hypot(...Re(u.a,l[0].a))<1e-7)continue;let f=ks(-r.angle,Re(u.a,r.p)),d=ks(-o.angle,Re(u.b,o.p));if(i.set([268435456+c,...f,...d,...u.n],c*7),c++,c===2)break}return c}var pu=(s,e,t)=>[Math.cos(s)*e-Math.sin(s)*t,Math.sin(s)*e+Math.cos(s)*t],mu=function(){let{pose:s,shape:e,props:t}=this,i=this.broadphase.pairs,r=this.contactOut;for(let o=0;o<this.broadphase.pairCount;o++){let a=i[o],n=Math.floor(a/2097152),l=a-n*2097152,c=this.collideBodies(n,l,r);if(c===0)continue;let u=0,f=this.prevCount;for(;u<f;){let m=u+f>>>1;this.prevKeys[m]<a?u=m+1:f=m}let d=u,p=Math.sqrt(t[n*4]*t[l*4]);for(let m=0;m<c;m++){let h=this.jointCount+this.contactCount++;this.info=this.grow(this.info,(h+1)*j),this.data=this.grow(this.data,(h+1)*O);let g=this.data,b=h*O,y=m*7,A=r[y+0];this.info.set([bs,n,l,A],h*j),g.fill(0,b,b+O),g[b+Q]=g[b+Q+1]=1/0,g[b+_e]=-1/0,g[b+Ae]=0,g[b+Pt]=g[b+Pt+1]=1/0,g[b+N]=r[y+1],g[b+N+1]=r[y+1+1],g[b+Y]=r[y+3],g[b+Y+1]=r[y+3+1],g[b+re]=p,g[b+be]=r[y+5],g[b+Ue]=r[y+5+1];let v=-1;for(let P=d;P<this.prevCount&&this.prevKeys[P]===a;P++)this.prevInfo[P*j+3]===A&&(v=P);if(v<0&&this.params.matchNearest){let P=Mn*Math.min(e[n*4],e[n*4+1],e[l*4],e[l*4+1]);for(let C=d;C<this.prevCount&&this.prevKeys[C]===a;C++){let _=Math.hypot(this.prevData[C*O+N]-g[b+N],this.prevData[C*O+N+1]-g[b+N+1]);_<=P&&(P=_,v=C)}}if(v>=0){let P=v*O;g[b+se]=this.prevData[P+se],g[b+se+1]=this.prevData[P+se+1],g[b+te]=this.prevData[P+te],g[b+te+1]=this.prevData[P+te+1],this.prevData[P+Hi]&&(g[b+N]=this.prevData[P+N],g[b+N+1]=this.prevData[P+N+1],g[b+Y]=this.prevData[P+Y],g[b+Y+1]=this.prevData[P+Y+1])}let[x,w]=pu(s[n*4+2],g[b+N],g[b+N+1]),[B,L]=pu(s[l*4+2],g[b+Y],g[b+Y+1]),M=g[b+be],I=g[b+Ue],E=s[n*4]+x-s[l*4]-B,k=s[n*4+1]+w-s[l*4+1]-L;g[b+fe]=M*E+I*k+5e-4,g[b+fe+1]=I*E-M*k}}};var fa=class extends Dr{constructor(e,t,i){if(super({precision:i==="soa-colored"?"f32":"f64",order:i==="soa-colored"?"colored":"sequential"}),Object.assign(this,e),this.options={...this.options,precision:i==="soa-colored"?"f32":"f64",order:i==="soa-colored"?"colored":"sequential"},this.options.precision==="f64")for(let[r,o]of Object.entries(this))o instanceof Float32Array&&(this[r]=Float64Array.from(o));for(let[r,o]of ei(e)??[]){let a=this.shape[r*4+2];Fr(this,r,{geometry:o,area:a,momentPerMass:a>0?this.shape[r*4+3]/a:0,radius:this.props[r*4+1]},1)}this.filters=new Map(t?.filters??[]),this.sensors=new Set(t?.sensors??[]),this.restitution=new Map(t?.restitution??[]),this.contactPairs=[],t&&(t.topology=this)}narrowphase(){this.contactPairs=[],mu.call(this)}collideBodies(e,t,i){let r=this.filters.get(e)??[4294967295,4294967295],o=this.filters.get(t)??[4294967295,4294967295];if(!(r[0]&o[1])||!(o[0]&r[1]))return 0;let a=hu(this,e,t,i);if(a){let n=[i[5],i[6]],l=[0,0],c=[0,0];for(let p=0;p<a;p++)for(let m=0;m<2;m++)l[m]+=i[p*7+1+m]/a,c[m]+=i[p*7+3+m]/a;let u=this.pose[e*4+2],f=Math.cos(u),d=Math.sin(u);this.contactPairs.push({a:e,b:t,n,ra:l,rb:c,point:[this.pose[e*4]+f*l[0]-d*l[1],this.pose[e*4+1]+d*l[0]+f*l[1],0],impulse:0})}return this.sensors.has(e)||this.sensors.has(t)?0:a}initJoints(){for(let e=0;e<this.jointCount;e++){let t=e*O,i=this.info[e*j];if(this.data[t+Q]===0&&this.data[t+Q+1]===0&&this.data[t+Q+2]===0){i!==0&&(this.info[e*j]=0,this.noCollideDirty=!0,this.handles[e]&&(this.handles[e].alive=!1));continue}i===1&&this.jointC(this.info[e*j+1],this.info[e*j+2],t,this.pose,this.data,t+fe)}for(let e=0;e<this.jointCount;e++)if(this.info[e*j]===5){let t=e*O,i=this.info[e*j+1],r=this.info[e*j+2],o=(i<0?0:this.pose[i*4+2])-this.pose[r*4+2]-this.data[t+re];this.data[t+fe]=Math.min(0,o-this.data[t+be]),this.data[t+fe+1]=Math.max(0,o-this.data[t+Ue])}}warmStartConstraints(e,t){let i=[];for(let r=0;r<this.jointCount;r++)this.info[r*j]===5&&(i.push(r),this.info[r*j]=4);super.warmStartConstraints(e,t);for(let r of i)this.info[r*j]=5}evalConstraint(e,t,i){if(this.info[e*j]!==5)return super.evalConstraint(e,t,i);let r=e*O,o=this.info[e*j+1],a=this.info[e*j+2],n=this.data,l=(o<0?0:this.pose[o*4+2])-this.pose[a*4+2]-n[r+re];this.eC[0]=l-n[r+be]-t*n[r+fe],this.eC[1]=l-n[r+Ue]-t*n[r+fe+1],this.eG.fill(0),this.eJ.fill(0);for(let c=0;c<2;c++){this.eMin[c]=n[r+_e+c],this.eMax[c]=n[r+Ae+c];let u=Math.max(this.eMin[c],Math.min(this.eMax[c],n[r+se+c]*this.eC[c]+n[r+te+c]));i>=0&&u!==0&&(this.eJ[c*3+2]=i===o?1:-1)}return 2}step(){let e=na(this,2);super.step(),la(this,2,e);let t=new Map(this.contactPairs.map(i=>[`${i.a},${i.b}`,i]));for(let i=this.jointCount;i<this.jointCount+this.contactCount;i++){let r=t.get(`${this.info[i*j+1]},${this.info[i*j+2]}`);r&&(r.impulse+=Math.abs(this.data[i*O+te])*this.params.dt)}}};var ha=(s,e,t)=>{let i=T(e,s);return de(s,q(i,Math.max(0,Math.min(1,F(T(t,s),i)/(F(i,i)||1)))))};function da(s,e,t,i){let r=T(s,t),o=F(r,e),a=o*o-F(r,r)+i*i;if(a<0)return null;let n=-o-Math.sqrt(a);return n<0?null:{t:n,n:Tt(T(de(s,q(e,n)),t))}}function Vr(s,e){return e&&(!s||e.t<s.t)?e:s}function Vn(s,e,t,i,r){let o=T(i,t),a=T(s,t),n=F(o,o);if(n<1e-16)return da(s,e,t,r);let l=F(o,e),c=F(o,a),u=F(a,e),f=n-l*l,d=n*u-c*l,p=n*F(a,a)-c*c-r*r*n,m=d*d-f*p,h=null;if(f>1e-12*n&&m>=0){let g=(-d-Math.sqrt(m))/f,b=c+g*l;g>=0&&b>=0&&b<=n&&(h={t:g,n:Tt(T(de(s,q(e,g)),de(t,q(o,b/n))))})}return Vr(Vr(h,da(s,e,t,r)),da(s,e,i,r))}function gu(s,e){let t=q(e.vertices.reduce((i,r)=>de(i,r),[0,0,0]),1/e.vertices.length);for(let i=0;i<e.vertices.length;i++){let r=e.vertices[i],o=e.vertices[(i+1)%e.vertices.length],a=xt(T(o,r),e.normal);if(F(a,T(s,r))*(F(a,T(t,r))>=0?1:-1)<-1e-6)return!1}return!0}function Md(s,e,t,i){if(i===0){let n=-1/0,l=1/0,c=q(t,-1);for(let u of s.faces){let f=F(u.normal,t),d=F(u.normal,T(u.vertices[0],e));if(Math.abs(f)<1e-12){if(d<0)return null}else{let p=d/f;f<0?p>n&&(n=p,c=u.normal):l=Math.min(l,p)}if(n>l)return null}return l<0?null:{t:Math.max(0,n),n:n<=0?q(t,-1):c}}let r=!0,o=1/0,a=null;for(let n of s.faces){let l=F(n.normal,T(e,n.vertices[0]));l>0&&(r=!1),gu(T(e,q(n.normal,l)),n)&&(o=Math.min(o,l*l));let c=F(n.normal,t);if(c<-1e-12){let u=(i-l)/c;u>=0&&gu(T(de(e,q(t,u)),q(n.normal,i)),n)&&(a=Vr(a,{t:u,n:n.normal}))}}for(let[n,l]of s.edges){let c=T(e,ha(n,l,e));o=Math.min(o,F(c,c)),a=Vr(a,Vn(e,t,n,l,i))}return r||o<=i*i?{t:0,n:q(t,-1)}:a}var At=(s,e)=>s[0]*e[0]+s[1]*e[1];function zd(s,e,t,i){let r=!0,o=1/0,a=null;for(let n=0;n<s.vertices.length;n++){let l=s.vertices[n],c=s.vertices[(n+1)%s.vertices.length],u=T(c,l),f=Tt([u[1],-u[0]]),d=At(T(e,l),f);d>0&&(r=!1);let p=T(e,ha(l,c,e));o=Math.min(o,At(p,p));let m=At(t,f);if(m<-1e-12){let h=(i-d)/m,g=T(de(e,q(t,h)),q(f,i)),b=At(T(g,l),u),y=1e-6*At(u,u);h>=0&&b>=-y&&b<=At(u,u)+y&&(a=Vr(a,{t:h,n:f}))}i>0&&(a=Vr(a,da(e,t,l,i)))}return r||o<=i*i?{t:0,n:q(t,-1)}:a}function Id(s,e,t,i){if(s.vertices)return zd(s,e,t,i);if(s.kind===3){let p=[-Math.sin(s.angle),Math.cos(s.angle)],m=At(T(e,s.p),p)-i,h=At(t,p);return m<=0?{t:0,n:q(t,-1)}:h<-1e-12?{t:-m/h,n:p}:null}let r=s.kind===1?s.p:s.spine[0],o=s.kind===1?s.p:s.spine[1],a=i+s.radius,n=T(e,ha(r,o,e));if(At(n,n)<=a*a)return{t:0,n:q(t,-1)};if(a>0)return Vn(e,t,r,o,a);let l=T(o,r),c=t[0]*l[1]-t[1]*l[0];if(Math.abs(c)<1e-12){let p=T(e,r);if(Math.abs(p[0]*l[1]-p[1]*l[0])/Math.max(Math.hypot(...l),1e-20)>1e-6)return null;let h=Math.min(At(T(r,e),t),At(T(o,e),t));return Math.max(At(T(r,e),t),At(T(o,e),t))<0?null:{t:Math.max(0,h),n:q(t,-1)}}let u=T(r,e),f=(u[0]*l[1]-u[1]*l[0])/c,d=(u[0]*t[1]-u[1]*t[0])/c;return f>=0&&d>=0&&d<=1?{t:f,n:q(Tt([l[1],-l[0]]),c>0?-1:1)}:null}function bu(s,e,t,i,{maxDistance:r=1e30,ignore:o=[],collidesWith:a=4294967295,includeTriggers:n=!0}={}){let l=s.dimension,c=me(e,l,"origin"),u=me(i,l,"direction"),f=Math.hypot(...u);if(!f||!Number.isFinite(t)||t<0||!Number.isFinite(r)||r<0)throw Error("Provide a nonzero direction, finite nonnegative radius and distance");if(!Number.isInteger(a)||a<0||a>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");let d=new Set(o);for(let h of d)s.liveIndex(h);let p=u.map(h=>h/f),m=null;for(let h=0;h<s.bodyCount;h++){if(d.has(h))continue;let g=l===3?s.solver.bodies[h]:null,b=g?g.group??4294967295:s.solver.filters.get(h)?.[0]??4294967295,y=g?g.isTrigger:s.solver.sensors.has(h);if(!(b&a)||!n&&y)continue;let A;if(l===2)A=Id(ua(s.solver,h),c,p,t);else{let x=qr(g);if(x.spine){let w=x.radius+t,B=T(c,ha(...x.spine,c));A=F(B,B)<=w*w?{t:0,n:q(p,-1)}:Vn(c,p,...x.spine,w)}else A=Md(x,c,p,t)}if(!A||A.t>r||m&&A.t>=m.distance)continue;let v=de(c,q(p,A.t));m={index:h,distance:A.t,normal:A.n,center:v,point:T(v,q(A.n,t))}}return m}var pa=class{constructor(e,{speedThreshold:t=.08,timeThreshold:i=.6}={}){if(!Number.isFinite(t)||t<=0||!Number.isFinite(i)||i<=0)throw Error("Sleep thresholds must be positive and finite");this.world=e,this.speedThreshold=t,this.timeThreshold=i,this.time=new Float64Array(e.bodyCount),this.asleep=new Set}wake(){let e=this.world;for(let t of this.asleep)e.dimension===3?e.solver.bodies[t].sleeping=!1:e.solver.dynamic[t]=+(e.solver.shape[t*4+2]>0);this.asleep.clear(),this.time.fill(0)}after(){let e=this.world,t=e.solver,i=e.bodyCount,r=Int32Array.from({length:i},(d,p)=>p),o=new Set,a=[],n=d=>e.dimension===3?t.bodies[d].mass:t.shape[d*4+2],l=d=>{for(;r[d]!==d;)r[d]=r[r[d]],d=r[d];return d},c=(d,p)=>{if(d<0){o.add(p);return}n(d)<=0?o.add(p):n(p)<=0?o.add(d):r[l(d)]=l(p),a.push([d,p])};if(e.dimension===3){let d=new Map(t.bodies.map((p,m)=>[p,m]));for(let p of t.forces)!p.broken&&!p.bodyA?.isTrigger&&!p.bodyB?.isTrigger&&c(p.bodyA?d.get(p.bodyA):-1,d.get(p.bodyB))}else{for(let d of t.contactPairs)!t.sensors.has(d.a)&&!t.sensors.has(d.b)&&c(d.a,d.b);for(let d=0;d<t.jointCount;d++)(t.data[d*32+6]||t.data[d*32+7]||t.data[d*32+8])&&c(t.info[d*4+1],t.info[d*4+2])}let u=new Set([...o].map(l)),f=new Map;for(let d=0;d<i;d++)if(n(d)>0){let p=l(d),m=e.dimension===3?t.bodies[d]:null,h=m?m.allowSleep!==!1:t.avbdSleepEligible?.get(d)!==!1,g=m?Math.hypot(...m.velocityLin,...m.velocityAng):Math.hypot(...t.velocity.subarray(d*4,d*4+3));f.has(p)||f.set(p,u.has(p)),f.set(p,f.get(p)&&h&&g<=this.speedThreshold)}for(let d=0;d<i;d++)n(d)>0&&(this.time[d]=f.get(l(d))?this.time[d]+e.params.dt:0,this.time[d]>=this.timeThreshold&&(this.asleep.add(d),e.dimension===3?(t.bodies[d].sleeping=!0,t.bodies[d].velocityLin.fill(0),t.bodies[d].velocityAng.fill(0)):(t.dynamic[d]=0,t.velocity.fill(0,d*4,d*4+4))));a.some(([d,p])=>d>=0&&n(d)>0&&n(p)>0&&this.asleep.has(d)!==this.asleep.has(p))&&this.wake()}};var ma=class{constructor(e,t,i={}){if(this.backend="cpu",this.dimension=t,this.scene=e,this.stepCount=0,this.pending=new ti,this.events=[],this.previous=new Map,this.watched=null,t===3){this.solver=Object.assign(new ca,e.ref),this.solver.up=[...e.up??[0,0,1]],this.nativeRef=e.ref,this.constraints=this.solver.forces.slice();for(let r of this.solver.bodies)r.solver=this.solver;for(let r of this.constraints)r.solver=this.solver;this.constraints.forEach((r,o)=>{let a=e.handles?.get(r);a&&(a.slot=o)}),aa(this.solver)}else this.solver=new fa(e.topology,e,i.order==="colored"?"soa-colored":"soa-seq"),this.topology=this.solver,this.builder=Object.assign(Object.create(Object.getPrototypeOf(e)),{topology:this.solver,filters:this.solver.filters,sensors:this.solver.sensors,restitution:this.solver.restitution});this.params=t===3?this.solver:this.solver.params,Nr(this,t===3?{bodies:this.solver.bodies}:null,t,{setVelocities:this.setPackedVelocities,readSelectedBodies:this.readSelectedBodies}),(i.sleeping||e.sleepOptIn||[...e.topology?.avbdSleepEligible?.values()??[]].some(Boolean))&&this.enableSleeping(i.sleeping===!0?{}:i.sleeping)}get bodyCount(){return this.dimension===3?this.solver.bodies.length:this.solver.bodyCount}get jointCount(){return this.dimension===3?this.constraints.length:this.solver.jointCount}gpuIndex(e){return this.liveIndex(e),e}liveIndex(e){if(this.assertLive(),!Number.isInteger(e)||e<0||e>=this.bodyCount)throw Error("A live body index is required")}assertLive(){if(this.destroyed)throw Error("The solver has been destroyed")}prepareBodyCommands(){return this.wakeAll(),{enqueueValidated:e=>{this.pending.reserve(this.pending.count+e.count),this.pending.u32.set(e.u32.subarray(0,e.count*12),this.pending.count*12),this.pending.count+=e.count}}}setLinearVelocity(e,t){return this.editBodies([{body:e,linearVelocity:t}])}setAngularVelocity(e,t){return this.editBodies([{body:e,angularVelocity:t}])}applyImpulse(e,t,i){return this.editBodies([{body:e,impulse:t,worldPoint:i}])}applyForce(e,t,i){return this.editBodies([{body:e,force:t,worldPoint:i}])}applyAngularImpulse(e,t){return this.editBodies([{body:e,angularImpulse:t}])}applyTorque(e,t){return this.editBodies([{body:e,torque:t}])}teleport(e,t,i){return this.editBodies([{body:e,position:t,rotation:i}])}setPackedVelocities(e,t){let i=Array.from(e),r=t?.linear,o=t?.angular,a=this.dimension,n=a===3?3:1;if(r===void 0&&o===void 0)throw Error("Provide linear or angular velocities");let l=-1;i.forEach(d=>{if(this.liveIndex(d),d<=l)throw Error("Velocity batch indices must be unique and ascending GPU slots");l=d});for(let[d,p]of[[r,a],[o,n]])if(d!==void 0&&(d.length!==i.length*p||!Array.from(d).every(m=>Number.isFinite(Math.fround(m)))))throw Error("Provide finite packed velocity components per body");let c=r===void 0?null:Array.from(r),u=o===void 0?null:Array.from(o),f=i.map((d,p)=>({body:d,...c===null?{}:{linearVelocity:c.slice(p*a,(p+1)*a)},...u===null?{}:{angularVelocity:a===3?u.slice(p*n,(p+1)*n):u[p]}}));return this.editBodies(f),this.flushEdits(),this}flushEdits(){if(this.destroyed)throw Error("The solver has been destroyed");let{words:e,u32:t,count:i}=this.pending,r=this.solver,o=this.dimension;for(let a=0;a<i;a++){let n=a*12,l=t[n],c=t[n+1],u=t[n+2]!==0,f=o===3?r.bodies[l]:null,d=f?.velocityLin??r.velocity.subarray(l*4,l*4+2),p=f?.mass??r.shape[l*4+2],m=f?.positionLin??r.pose.subarray(l*4,l*4+2),h=g=>{if(!(p<=0))if(o===2)r.velocity[l*4+2]+=g[0]/Math.max(1e-10,r.shape[l*4+3]);else{let b=f.positionAng,y=Ee([-b[0],-b[1],-b[2],b[3]],g),A=Ee(b,y.map((v,x)=>v/Math.max(1e-10,f.moment[x])));for(let v=0;v<3;v++)f.velocityAng[v]+=A[v]}};if(c===0)d.set(e.subarray(n+4,n+4+o));else if(c===1)f?f.velocityAng.set(e.subarray(n+4,n+7)):r.velocity[l*4+2]=e[n+4];else if(c===4)if(m.set(e.subarray(n+4,n+4+o)),f){u&&f.positionAng.set(e.subarray(n+8,n+12)),f.initialLin.set(m),f.inertialLin.set(m),f.initialAng.set(f.positionAng),f.inertialAng.set(f.positionAng);for(let g of[...f.forces])g.contacts&&g.destroy()}else u&&(r.pose[l*4+2]=e[n+6]),r.initial.set(r.pose.subarray(l*4,l*4+4),l*4),r.inertial.set(r.pose.subarray(l*4,l*4+4),l*4),r.prevCount=0;else if(c===2||c===3){if(p<=0)continue;let g=Array.from(e.subarray(n+4,n+4+o),b=>b*(c===3?e[n+7]:1));for(let b=0;b<o;b++)d[b]+=g[b]/p;if(u){let b=Array.from(e.subarray(n+8,n+8+o),(y,A)=>y-m[A]);h(o===3?xt(b,g):[b[0]*g[1]-b[1]*g[0]])}}else(c===5||c===6)&&h(Array.from(e.subarray(n+4,n+4+(o===3?3:1)),g=>g*(c===6?e[n+7]:1)))}this.pending.count=0}step(){this.flushEdits(),this.solver.step(),this.sleeping?.after(),this.stepCount++,this.captureEvents()}attachToScene(e,t){return Yo.call(this,e,t)}detachFromScene(){return Qo.call(this)}setFilters(e,t,i){let r=Array.from(e),o=Array.from(t),a=Array.from(i);if(o.length!==r.length||a.length!==r.length)throw Error("Provide one group and mask per body");r.forEach(n=>this.liveIndex(n));for(let n of[...o,...a])if(!Number.isInteger(n)||n<0||n>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");r.forEach((n,l)=>{this.dimension===3?Object.assign(this.solver.bodies[n],{group:o[l],collidesWith:a[l]}):this.solver.filters.set(n,[o[l],a[l]])}),this.wakeAll()}setSensor(e,t){if(this.liveIndex(e),typeof t!="boolean")throw Error("Trigger flag must be boolean");this.dimension===3?this.solver.bodies[e].isTrigger=t:t?this.solver.sensors.add(e):this.solver.sensors.delete(e),this.wakeAll()}setRestitution(e,t){if(this.liveIndex(e),!Number.isFinite(t)||t<0||t>1)throw Error("restitution must be between 0 and 1");this.dimension===3?this.solver.bodies[e].restitution=t:this.solver.restitution.set(e,t),this.wakeAll()}setMotor(e,t){if(this.assertLive(),this.dimension===3){let i=this.constraints[e];if(!i?.cpuAngular)throw Error("A motor constraint is required");Object.assign(i.cpuAngular.options,kt({...i.cpuAngular.options,...t}))}else{let i=this.solver,r=e*O;if(!Number.isInteger(e)||e<0||e>=i.jointCount||i.info[e*4]!==3)throw Error("A motor constraint is required");let o=t.speed??i.data[r+re],a=t.maxTorque??i.data[r+Ae];if(!Number.isFinite(o)||!Number.isFinite(a)||a<0)throw Error("Provide finite motor speed and nonnegative torque");i.data[r+re]=o,i.data[r+_e]=-a,i.data[r+Ae]=a}this.wakeAll()}setAngleLimits(e,t){if(this.assertLive(),this.dimension!==2)throw Error("Use a 3D hinge constraint");if(this.solver.info[e*4]!==5)throw Error("An angular limit is required");Bs(this.solver,e,ki(t)),this.wakeAll()}releaseJoints(e){for(let t of e)this.disableConstraint(t)}disableConstraint(e){if(this.assertLive(),!Number.isInteger(e)||e<0||e>=this.jointCount)throw Error("A live constraint slot is required");if(this.dimension===3){let t=this.constraints[e];t.broken=!0,(t.cpuAngular??t).destroy()}else this.solver.disable(e),this.solver.info[e*4]=0,this.solver.noCollideDirty=!0;this.wakeAll()}setWorldAnchor(e,t,i){if(this.assertLive(),this.dimension===2){let r=this.solver;if(!Number.isInteger(e)||e<0||e>=r.jointCount||r.info[e*4+1]!==-1)throw Error("A world-anchor constraint is required");r.data.set(me([t,i],2,"point"),e*O+21)}else{let r=this.constraints[e];if(!r||r.bodyA)throw Error("A world-anchor constraint is required");r.rA.set(me(t,3,"point"))}this.wakeAll()}addBox(...e){return this.addDynamic("addBox",e)}addCircle(...e){return this.addDynamic("addCircle",e)}addCapsule(...e){return this.addDynamic("addCapsule",e)}addHull(...e){return this.addDynamic("addHull",e)}addSegment(...e){return this.addDynamic("addSegment",e)}addPlane(...e){return this.addDynamic("addPlane",e)}addDynamic(e,t){if(this.destroyed)throw Error("The solver has been destroyed");if(this.dimension!==2)throw Error("Build 3D bodies before creating the solver");this.wakeAll();let i=this.sleeping?{speedThreshold:this.sleeping.speedThreshold,timeThreshold:this.sleeping.timeThreshold}:null,r=this.builder[e](...t);return i&&this.enableSleeping(i),r}appendJoint(e,t,i,r,o,a=1/0){if(this.assertLive(),this.dimension!==2)throw Error("Build 3D constraints before creating the solver");return this.wakeAll(),this.builder.addJoint(e,t,i,r,{stiffness:o,breakForce:a}).slot}captureConstraintFrames(e){if(this.assertLive(),this.dimension!==3)throw Error("Constraint frame capture requires a 3D world");let t=Array.from(e);for(let{slot:i,spring:r}of t){let o=this.constraints[i];if(!Number.isInteger(i)||!o||o.broken||o.cpuAngular||(r?o.rest===void 0:o.stiffnessAng===void 0))throw Error("A live spring or joint slot is required")}this.flushEdits();for(let{slot:i,spring:r}of t)qn(this.constraints[i],r);t.length&&this.wakeAll()}setSpringMaterial(e,t={}){this.assertLive();let i=this.constraints[e];if(!i||i.rest===void 0)throw Error("A spring constraint is required");xr(i,It(t)),this.wakeAll()}packBodyRecords(e,t=!1){let i=this.solver,r=this.dimension,o=t?r===3?8:4:r===3?40:24,a=e?.length??this.bodyCount,n=new Float32Array(a*o);for(let l=0;l<a;l++){let c=e?.[l]??l,u=l*o;if(t){if(r===3){let f=i.bodies[c];n.set(f.positionLin,u),n[u+3]=f.friction,n.set(f.positionAng,u+4)}else n.set(i.pose.subarray(c*4,c*4+4),u),n[u+3]=i.props[c*4];continue}if(r===3){let f=i.bodies[c];n.set(f.positionLin,u),n[u+3]=f.friction,n.set(f.positionAng,u+4),n.set(f.initialLin,u+8),n[u+11]=+!!f.isTrigger,n.set(f.initialAng,u+12),n.set(f.size,u+16),n[u+19]=f.sleeping?0:f.mass,n.set(f.moment,u+20),n[u+23]=f.radius,n.set(f.inertialLin,u+24),n.set(f.inertialAng,u+28),n.set(f.velocityLin,u+32),n[u+35]=f.prevVelocityLin.reduce((d,p,m)=>d+p*i.up[m],0),n.set(f.velocityAng,u+36),n[u+39]=De(f)?1:Fe(f)?-1:Ct(f)?3:ar(f)?2:0}else n.set(i.pose.subarray(c*4,c*4+4),u),n[u+3]=i.props[c*4],n.set(i.initial.subarray(c*4,c*4+4),u+4),n.set(i.inertial.subarray(c*4,c*4+4),u+8),n.set(i.velocity.subarray(c*4,c*4+4),u+12),n.set(i.prevVelocity.subarray(c*4,c*4+4),u+16),n.set(i.shape.subarray(c*4,c*4+4),u+20)}return n}async readBodies(){return this.flushEdits(),this.packBodyRecords()}async readSelectedBodies(e,{posesOnly:t=!1}={}){let i=Array.from(e);return i.forEach(r=>this.liveIndex(r)),this.flushEdits(),this.packBodyRecords(i,t)}async readBodyState(e){this.liveIndex(e),this.flushEdits();let t=this.solver;if(this.dimension===3){let i=t.bodies[e],r=this.sleeping?.asleep.has(e)??!1;return{position:Array.from(i.positionLin),rotation:Array.from(i.positionAng),linearVelocity:Array.from(i.velocityLin),angularVelocity:Array.from(i.velocityAng),mass:i.mass,effectiveMass:r?0:i.mass,sleeping:r}}return{position:Array.from(t.pose.subarray(e*4,e*4+2)),angle:t.pose[e*4+2],linearVelocity:Array.from(t.velocity.subarray(e*4,e*4+2)),angularVelocity:t.velocity[e*4+2],mass:t.shape[e*4+2],moment:t.shape[e*4+3],sleeping:this.sleeping?.asleep.has(e)??!1}}async readJoints(){return this.flushEdits(),this.packJointRecords()}packJointRecords(){let e=this.dimension===3?32:36,t=new Float32Array(this.jointCount*e),i=r=>r===1/0?3e38:r===-1/0?-3e38:r;if(this.dimension===2){let r=this.solver.data;for(let o=0;o<this.jointCount;o++){let a=o*36,n=o*O;[se,te,Q,_e,Ae,Pt,fe].forEach((l,c)=>{for(let u=0;u<3;u++)t[a+c*4+u]=i(r[n+l+u])}),t.set([r[n+N],r[n+N+1],r[n+Y],r[n+Y+1]],a+28),t.set([r[n+re],r[n+re+1],r[n+re+2],0],a+32)}}else this.constraints.forEach((r,o)=>{let a=o*32;if(r.cpuAngular){let n=r.cpuAngular,l=n.options;t.set(n.pen,a),t[a+3]=r.broken?0:1,t.set(n.lam,a+8),t.set(n.ta,a+16),t.set(n.tb,a+20),t.set(l.axisA,a+24),t.set(l.axisB,a+28),t[a+19]=n.c0?.[0]??0,t[a+23]=n.c0?.[1]??0,t[a+27]=l.type==="motor"?l.speed:l.minAngle,t[a+31]=l.type==="motor"?l.maxTorque:l.maxAngle;return}for(let[n,l]of[["penaltyLin",0],["penaltyAng",4],["lambdaLin",8],["lambdaAng",12],["C0Lin",16],["C0Ang",20],["rA",24],["rB",28]])r[n]&&t.set(r[n],a+l);if(t[a+3]=r.broken?0:i(r.stiffnessLin??r.stiffness??0),t[a+7]=r.broken?0:i(r.stiffnessAng??0),t[a+11]=i(r.fracture??0),t[a+15]=r.torqueArm??0,t[a+27]=r.rest??0,r.cpuRest&&(t[a+19]=r.cpuRest[0],t[a+23]=r.cpuRest[1],t[a+27]=r.cpuRest[2],t[a+31]=r.cpuRest[3]),r.rest!==void 0){let n=Ui(r);t[a+11]=Number.isFinite(n?.breakStrain)?n.breakStrain:0,t[a+15]=Number.isFinite(n?.breakForce)?n.breakForce:0}});return t}async readCounters(){this.assertLive();let e=this.dimension===2?this.solver.contactCount:this.solver.forces.reduce((i,r)=>i+(r.contacts?.length??0),0),t=this.dimension===2?this.solver.contactPairs.length:this.solver.forces.filter(i=>i.contacts?.length).length;return{pairs:t,contacts:e,manifolds:t,joints:this.jointCount,overflow:0,clashes:0,colors:0,sleeping:this.sleeping?.asleep.size??0}}adapt(){}watchContacts({indices:e,maxPairs:t=this.maxPairs??8192,maxEvents:i=this.maxEvents??4096}={}){if(this.assertLive(),!Number.isInteger(i)||i<1||!Number.isInteger(t)||t<1)throw Error("Contact capacities must be positive integers");return e!==void 0?(e.forEach(r=>this.liveIndex(r)),this.watched=new Set(e)):this.watched??=new Set(Array.from({length:this.bodyCount},(r,o)=>o)),this.maxEvents=i,this.maxPairs=t,this}captureEvents(){if(!this.watched)return;let e=this.dimension===3?new Map(this.solver.bodies.map((i,r)=>[i,r])):null,t=this.dimension===2?this.solver.contactPairs:this.solver.forces.filter(i=>i.contacts?.length).map(i=>{let r=Array.from(i.bodyA.positionLin);for(let o of i.contacts){let a=Ee(i.bodyA.positionAng,o.rA);for(let n=0;n<3;n++)r[n]+=a[n]/i.contacts.length}return{a:e.get(i.bodyA),b:e.get(i.bodyB),point:r,normal:Array.from(i.basis.slice(0,3)),impulse:i.bodyA.isTrigger||i.bodyB.isTrigger?0:i.contacts.reduce((o,a)=>o+Math.abs(a.lambda[0])*this.params.dt,0)}});this.trackContactPairs(t)}trackContactPairs(e){let t=new Map,i=(a,n)=>{this.events.length<(this.maxEvents??4096)?this.events.push({...a,normal:a.normal??[...a.n,0],type:n,kind:n==="begin"?1:2,step:this.stepCount,isTrigger:a.isTrigger??(this.dimension===3?!!(this.solver.bodies[a.a].isTrigger||this.solver.bodies[a.b].isTrigger):this.solver.sensors.has(a.a)||this.solver.sensors.has(a.b))}):this.dropped=(this.dropped??0)+1},r=new Set,o=[];for(let a of e){if(!this.watched.has(a.a)&&!this.watched.has(a.b))continue;let n=`${Math.max(a.a,a.b)},${Math.min(a.a,a.b)}`;r.add(n),this.previous.has(n)&&t.size<this.maxPairs?t.set(n,a):o.push([n,a])}for(let[a,n]of o)if(!t.has(a)){if(t.size>=this.maxPairs){this.pairFull=!0;continue}t.set(a,n),this.previous.has(a)||i(n,"begin")}for(let[a,n]of this.previous)r.has(a)||i({...n,impulse:0},"end");this.previous=t}async readContactEvents(){this.watchContacts();let e={events:this.events,dropped:this.dropped??0,full:!!this.dropped||!!this.pairFull};return this.events=[],this.dropped=0,this.pairFull=!1,e}async raycast(e,t,i){return this.sphereCast(e,0,t,i)}async circleCast(e,t,i,r){return this.sphereCast(e,t,i,r)}async sphereCast(e,t,i,r){return this.flushEdits(),bu(this,e,t,i,r)}async raycastAll(e,t){return Promise.all(e.map(i=>this.raycast(i.origin,i.direction,{...t,maxDistance:i.maxDistance??t?.maxDistance})))}async sphereCastAll(e,t){return Promise.all(e.map(i=>this.sphereCast(i.origin,i.radius,i.direction,{...t,maxDistance:i.maxDistance??t?.maxDistance})))}async circleCastAll(e,t){return this.sphereCastAll(e,t)}setSleepEnabled(e,t){if(this.liveIndex(e),typeof t!="boolean")throw Error("Sleep flag must be boolean");return this.dimension===3?this.solver.bodies[e].allowSleep=t:(this.solver.avbdSleepEligible??=new Map,this.solver.avbdSleepEligible.set(e,t)),t&&!this.sleeping&&this.enableSleeping(),this.wakeAll(),this}enableSleeping(e={}){return this.assertLive(),this.disableSleeping(),this.sleeping=new pa(this,e),this}disableSleeping(){return this.sleeping?.wake(),this.sleeping=null,this}async readSleepStats(){return this.assertLive(),{sleeping:this.sleeping?.asleep.size??0,wakeRequested:!1}}wakeUp(e){return this.liveIndex(e),this.wakeAll()}wakeAll(){return this.sleeping?.wake(),this}destroy(){this.destroyed||(this.detachFromScene(),this.disableSleeping(),this.pending.count=0,this.events=[],this.previous.clear(),this.destroyed=!0)}};var yu=new WeakSet,ga=s=>s!==null&&typeof s=="object"&&yu.has(s),vu=s=>yu.add(s);async function xu({backend:s="webgpu",device:e,gl:t,validate3D:i=!0,...r}={}){if(!["webgpu","cpu"].includes(s))throw Error(`Unsupported solver backend: ${s}`);if(s!=="webgpu"&&e!==void 0)throw Error("Only WebGPU initialization accepts a GPU device");if(t!==void 0)throw Error("Solver pipelines do not accept a WebGL context");let o,a=!1,n=!1;s==="webgpu"&&(e?i&&await Ni(e):({device:e,adapter:o}=await Sr({...r,preferredLimits:{maxStorageBuffersPerShaderStage:9,maxStorageBufferBindingSize:512*1024*1024,maxBufferSize:1024*1024*1024,...r.preferredLimits},validate3D:i}),a=!0));let l=new Set,c={backend:s,device:e,adapter:o,createSolver(u,f={}){if(n)throw Error("The solver pipeline has been destroyed");if(!u||typeof u.assertEditable!="function"||!u.ref&&!u.topology)throw Error("An AVBD scene builder is required");u.assertEditable();let d;if(s==="webgpu")d=u.createSolver(e,f);else{let m=u.ref?3:u.topology?2:0;if(f.bodyBuffer!==void 0)throw Error("A GPU body buffer requires the WebGPU backend");d=new ma(u,m,f),u.gpu=d,u.created=!0}Object.defineProperty(d,"backend",{value:s,configurable:!0}),l.add(d);let p=d.destroy;return d.destroy=function(){p.call(this),l.delete(this)},d},destroy(){if(!n){for(let u of l)u.destroy();l.clear(),a&&e.destroy(),n=!0}}};return vu(c),c}var ie=(s,e,t)=>{let i=Array.from(s);if(i.length!==e||!i.every(Number.isFinite))throw Error(`${t} requires ${e} finite components`);return i},K=(s,e,t=!1)=>{if(!Number.isFinite(s)||(t?s<0:s<=0))throw Error(`${e} must be ${t?"nonnegative":"positive"} and finite`);return s},Au=s=>{if(!Number.isInteger(s)||s<0||s>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");return s};function ba(s){for(let t of["allowSleep","isTrigger"])if(s[t]!==void 0&&typeof s[t]!="boolean")throw Error(`${t} must be a boolean`);let e=s.restitution??0;if(!Number.isFinite(e)||e<0||e>1)throw Error("restitution must be between 0 and 1");if(s.mass!==void 0&&(K(s.mass,"mass",!0),s.mass>0&&s.density===0))throw Error("A positive mass needs positive density");for(let t of["velocity","angularVelocity"])s[t]!==void 0&&ie(s[t],3,t);if(s.rotation!==void 0&&!Math.hypot(...ie(s.rotation,4,"rotation")))throw Error("rotation must be nonzero");Au(s.group??4294967295),Au(s.collidesWith??4294967295)}function wu(s,e){if(e.timeStep!==void 0&&(s.dt=K(e.timeStep,"timeStep")),e.iterations!==void 0){if(K(e.iterations,"iterations"),!Number.isInteger(e.iterations))throw Error("iterations must be an integer");s.iterations=e.iterations}if(e.gravity!==void 0){if(!Number.isFinite(e.gravity))throw Error("gravity must be finite");s.gravity=e.gravity}}var ya=class{constructor(e={}){if(this.ref=new ni,wu(this.ref,e),this.up=ie(e.up??[0,1,0],3,"up"),Math.abs(Math.hypot(...this.up)-1)>1e-5)throw Error("up must be a unit vector");this.points=!1,this.handles=new Map,this.bodySet=new Set}get bodies(){return this.ref.bodies}get constraints(){return[...this.handles.values()]}assertEditable(){if(this.created)throw Error("Build this scene before createSolver; use the solver's GPU edit methods afterwards")}addBox(e,t={}){this.assertEditable(),ba(t);let i=ie(e,3,"size");i.forEach(o=>K(o,"size"));let r=new Ze(this.ref,i,K(t.density??1,"density",!0),K(t.friction??.6,"friction",!0),ie(t.position??[0,0,0],3,"position"));return this.configure(r,t)}addSphere(e,t={}){return this.assertEditable(),ba(t),this.configure(nr(this.ref,K(e,"radius"),K(t.density??1,"density",!0),K(t.friction??.6,"friction",!0),ie(t.position??[0,0,0],3,"position")),t)}addHull(e,t={}){if(this.assertEditable(),ba(t),e.length%3||!Array.from(e).every(Number.isFinite))throw Error("Hull points must contain finite xyz triples");let i=Xr(e);if(!i)throw Error("A convex hull requires finite points spanning a volume");return this.hulls=!0,this.configure(lr(this.ref,i,K(t.density??1,"density",!0),K(t.friction??.6,"friction",!0),ie(t.position??[0,0,0],3,"position")),t)}addCapsule(e,t,i={}){return this.assertEditable(),ba(i),this.configure(Cr(this.ref,e,t,K(i.density??1,"density",!0),K(i.friction??.6,"friction",!0),ie(i.position??[0,0,0],3,"position")),i)}addHeightfield(e){return this.addTerrain(Mr(e),e)}addStaticMesh(e){return this.addTerrain(zr(e),e)}addTerrain(e,t={}){this.assertEditable();let i=this.ref.bodies.length,r=vo(this.ref,e,t);r.forEach(a=>this.bodySet.add(a)),this.hulls=!0;let o=!1;return{bodies:r,triangleCount:e.triangleCount,kind:e.kind,dispose:()=>{if(!o&&(o=!0,r.forEach(a=>{a.group=0,a.collidesWith=0}),this.gpu&&!this.gpu.destroyed)){let a=r.map((n,l)=>this.gpu.gpuIndex(i+l));this.gpu.setFilters(a,a.map(()=>0),a.map(()=>0)),this.gpu.wakeAll?.()}}}}configure(e,t){if(t.allowSleep!==void 0&&typeof t.allowSleep!="boolean")throw Error("allowSleep must be a boolean");e.allowSleep=t.allowSleep??!0,this.sleepOptIn||=t.allowSleep===!0;let i=t.restitution??0;if(!Number.isFinite(i)||i<0||i>1)throw Error("restitution must be between 0 and 1");if(e.restitution=i,t.isTrigger!==void 0&&typeof t.isTrigger!="boolean")throw Error("isTrigger must be a boolean");if(e.isTrigger=t.isTrigger??!1,e.group=t.group??4294967295,e.collidesWith=t.collidesWith??4294967295,t.mass!==void 0){let r=K(t.mass,"mass",!0);if(e.mass===0&&r>0)throw Error("A positive mass needs positive density");let o=e.mass>0?r/e.mass:0;e.mass=r,e.moment.forEach((a,n)=>e.moment[n]=a*o)}if(t.rotation){let r=ie(t.rotation,4,"rotation"),o=Math.hypot(...r);if(!o)throw Error("rotation must be nonzero");e.positionAng.set(r.map(a=>a/o))}return t.velocity&&e.velocityLin.set(ie(t.velocity,3,"velocity")),t.angularVelocity&&e.velocityAng.set(ie(t.angularVelocity,3,"angularVelocity")),this.bodySet.add(e),e}addPoint(e,{mass:t=.02,radius:i=.05,friction:r=.5}={}){let o=this.addSphere(i,{position:e,mass:t,friction:r});return o.moment.fill(0),this.points=!0,o}addFabric({columns:e=16,rows:t=16,spacing:i=.2,origin:r=[0,3,0],mass:o=.02,stiffness:a=1e3,anchorStiffness:n=a,materialAt:l,breakStrain:c=1/0,breakForce:u=1/0,bendingStiffness:f=Number.isFinite(c)||Number.isFinite(u)?0:a/50,pinCorners:d=!1,pinEdges:p=!d}={}){for(let[E,k]of Object.entries({columns:e,rows:t}))if(!Number.isInteger(k)||k<2)throw Error(`${E} must be an integer >= 2`);if(K(i,"spacing"),K(o,"mass"),K(a,"stiffness"),K(n,"anchorStiffness"),l!==void 0&&typeof l!="function")throw Error("materialAt must be a function");if(K(f,"bendingStiffness",!0),typeof d!="boolean"||typeof p!="boolean")throw Error("Fabric pin options must be boolean");let m=It({breakStrain:c,breakForce:u}),h=ie(r,3,"origin"),g=(E,k)=>`${Math.min(E,k)},${Math.max(E,k)}`;function*b(){for(let E=0;E<t;E++)for(let k=0;k<e;k++){let P=E*e+k;k&&(yield[P,P-1,a]),E&&(yield[P,P-e,a]),k&&E&&(yield[P,P-e-1,a/2],yield[P-1,P-e,a/2]),k>1&&f&&(yield[P,P-2,f]),E>1&&f&&(yield[P,P-2*e,f])}}let y=new Map;if(l)for(let[E,k]of b()){let P=l((E%e+k%e)/(2*(e-1)),(Math.floor(E/e)+Math.floor(k/e))/(2*(t-1)))??{};if(typeof P!="object"||Array.isArray(P))throw Error("materialAt must return a material object");y.set(g(E,k),{scale:K(P.stiffnessScale??1,"materialAt.stiffnessScale"),material:It({...m,...P})})}let A=Array.from({length:t},(E,k)=>Array.from({length:e},(P,C)=>this.addPoint([h[0]+(C-(e-1)/2)*i,h[1],h[2]+(k-(t-1)/2)*i],{mass:p&&(C===0||k===0||C===e-1||k===t-1)||d&&(C===0||C===e-1)&&(k===0||k===t-1)?0:o,radius:i/Math.SQRT2}))),v=A.flat(),x=new Map(v.map((E,k)=>[E,k])),w=[],B=new Map,L=(E,k,P)=>{(E.mass===0||k.mass===0)&&(P*=n/a);let C=x.get(E),_=x.get(k),z=y.get(g(C,_)),R=this.addSpring(E,k,[0,0,0],[0,0,0],{stiffness:P*(z?.scale??1),...z?.material??m});return B.set(g(x.get(E),x.get(k)),w.length),w.push(R),R};for(let[E,k,P]of b())L(v[E],v[k],P);let M=[];for(let E=0;E<t;E++)for(let k=0;k<e;k++)if(k&&E){let P=(E-1)*e+k-1,C=P+1,_=E*e+k-1,z=_+1;M.push(P,_,C,C,_,z)}let I=[];for(let E=0;E<M.length;E+=3){let[k,P,C]=M.slice(E,E+3);I.push(B.get(g(k,P)),B.get(g(P,C)),B.get(g(C,k)))}return{points:v,grid:A,indices:Uint32Array.from(M),connections:w,triangleConnections:Uint32Array.from(I)}}addRope({segments:e=12,length:t=12,origin:i=[0,12,0],width:r=.15,endMass:o=20}={}){if(!Number.isInteger(e)||e<1)throw Error("segments must be a positive integer");K(t,"length"),K(r,"width"),K(o,"endMass",!0);let a=ie(i,3,"origin"),n=t/e,l=this.addBox([r,r,r],{mass:0,position:a}),c=[];for(let u=0;u<e;u++){let f=this.addBox([r,n,r],{mass:1,position:[a[0],a[1]-(u+.5)*n,a[2]]});this.addJoint(u?c[u-1]:l,f,[0,u?-n/2:0,0],[0,n/2,0]),c.push(f)}if(o){let u=this.addBox([.6,.6,.6],{mass:o,position:[a[0],a[1]-t-.3,a[2]]});this.addJoint(c.at(-1),u,[0,-n/2,0],[0,.3,0]),c.push(u)}return{anchor:l,links:c}}addRagdoll({origin:e=[0,2,0],mass:t=10}={}){let i=ie(e,3,"origin");K(t,"mass");let r=(l,c)=>this.addBox(l,{mass:t/10,position:c.map((u,f)=>u+i[f])}),o=r([.7,1.2,.35],[0,2,0]),a=this.addSphere(.25,{mass:t/10,position:[i[0],i[1]+2.9,i[2]]}),n=[o,a];this.addJoint(o,a,[0,.6,0],[0,-.3,0]);for(let l of[-1,1]){let c=r([.3,.8,.3],[l*.5,1.95,0]),u=r([.26,.7,.26],[l*.5,1.2,0]);this.addJoint(o,c,[l*.35,.35,0],[-l*.15,.4,0]),this.addJoint(c,u,[0,-.4,0],[0,.35,0]);let f=r([.28,.8,.3],[l*.2,1,0]),d=r([.26,.75,.28],[l*.2,.225,0]);this.addJoint(o,f,[l*.2,-.6,0],[0,.4,0]),this.addJoint(f,d,[0,-.4,0],[0,.375,0]),n.push(c,u,f,d)}return{torso:o,head:a,bodies:n}}addJoint(e,t,i=[0,0,0],r=[0,0,0],{linearStiffness:o=1/0,angularStiffness:a=0,breakForce:n=1/0,breakOnPull:l=!1}={}){this.assertEditable(),this.checkBodies(e,t);for(let c of[o,a,n])c!==1/0&&K(c,"joint stiffness/breakForce",!0);return this.handle(new ke(this.ref,e,t,ie(i,3,"anchorA"),ie(r,3,"anchorB"),o,a,l&&n!==1/0?-n:n))}addSpring(e,t,i=[0,0,0],r=[0,0,0],{stiffness:o=1e3,rest:a=-1,breakStrain:n=1/0,breakForce:l=1/0}={}){if(this.assertEditable(),this.checkBodies(e,t),!e)throw Error("A spring requires two bodies");K(o,"stiffness",!0),a!==-1&&K(a,"rest",!0);let c=It({breakStrain:n,breakForce:l}),u=new dt(this.ref,e,t,ie(i,3,"anchorA"),ie(r,3,"anchorB"),o,a);return xr(u,c),this.handle(u)}checkBodies(e,t){if(!t||e===t||!this.bodySet.has(t)||e&&!this.bodySet.has(e))throw Error("Constraint endpoints must be distinct bodies in this scene")}addMotor(e,t,i={}){this.assertEditable(),this.checkBodies(e,t);let r=kt({...i,type:"motor"}),o=new ke(this.ref,e,t,[0,0,0],[0,0,0],1/0,0);return Br(o,r),this.handle(o)}addHinge(e,t,i={}){this.assertEditable(),this.checkBodies(e,t);let r=kt({...i,type:"limit"}),o=K(i.span??1,"span"),a=ie(i.anchorA??[0,0,0],3,"anchorA"),n=ie(i.anchorB??[0,0,0],3,"anchorB"),l=[-1,1].map(f=>this.addJoint(e,t,a.map((d,p)=>d+f*o*.5*r.axisA[p]),n.map((d,p)=>d+f*o*.5*r.axisB[p]))),c,u;if(i.minAngle!==void 0||i.maxAngle!==void 0){let f=new ke(this.ref,e,t,[0,0,0],[0,0,0],1/0,0);Br(f,r),c=this.handle(f)}return i.motor&&(u=this.addMotor(e,t,{axisA:r.axisA,axisB:r.axisB,...i.motor})),{joints:l,limit:c,motor:u,dispose(){for(let f of[...l,c,u])f?.dispose()}}}handle(e){let t={slot:-1,disposed:!1,dispose:()=>{t.disposed||(this.gpu?this.gpu.destroyed||this.gpu.releaseJoints([t.slot]):e.destroy(),this.handles.delete(e),t.disposed=!0)}};return t.destroy=t.dispose,this.handles.set(e,t),t}createSolver(e,t={}){if(ga(e))return e.createSolver(this,t);if(this.assertEditable(),this.hulls&&e.limits.maxStorageBuffersPerShaderStage<9)throw Error("Hull collisions require nine storage buffer bindings");let i=new Zo(e,this.ref,go(this.ref,{...t,...this.points?{shaders:{...t.shaders,solve:Qc}}:{}})),r=[];this.ref.forces.forEach((l,c)=>{this.handles.get(l).slot=c,l instanceof ke&&l.stiffnessAng>0&&r.push({slot:c})}),i.captureConstraintFrames(r),i.params.up=[...this.up];let o=[],a=[],n=[];for(let[l,c]of this.ref.bodies.entries())(c.group!==4294967295||c.collidesWith!==4294967295)&&(o.push(i.gpuIndex(l)),a.push(c.group),n.push(c.collidesWith)),c.isTrigger&&i.setSensor(i.gpuIndex(l),!0),c.restitution>0&&i.setRestitution(i.gpuIndex(l),c.restitution);return o.length&&i.setFilters(o,a,n),(t.sleeping||this.sleepOptIn)&&i.enableSleeping(this.ref,t.sleeping===!0?{}:t.sleeping),this.gpu=i,this.created=!0,i}},va=class{constructor(e={}){if(this.topology=new Dr,Object.assign(this.topology.params,ko()),wu(this.topology.params,e),e.alpha!==void 0){if(!Number.isFinite(e.alpha)||e.alpha<0||e.alpha>1)throw Error("alpha must be between zero and one");this.topology.params.alpha=e.alpha}for(let t of["postStabilize","matchNearest"])if(e[t]!==void 0){if(typeof e[t]!="boolean")throw Error(`${t} must be boolean`);this.topology.params[t]=e[t]}}assertEditable(){if(this.created)throw Error("Build this scene before createSolver; use GPU edit methods afterwards")}get bodyCount(){return this.topology.bodyCount}addShape(e,t={}){let i=e.options??t,r=this.addBox(e.size,i);return Fr(this.topology,r,e,i.density??1),r}addCircle(e,t={}){return this.addShape(qo(e),t)}addHull(e,t={}){return this.addShape(No(e),t)}addCapsule(e,t,i={}){return this.addShape(Vo(e,t),i)}addSegment(e,t,i={}){return this.addShape(Wo(e,t,i))}addPlane(e=[0,1],t=0,i={}){return this.addShape(Ho(e,t,i))}addBox(e,{density:t=1,friction:i=.6,position:r=[0,0],angle:o=0,velocity:a=[0,0,0],restitution:n=0,isTrigger:l=!1,group:c=4294967295,collidesWith:u=4294967295,allowSleep:f}={}){if(this.assertEditable(),f!==void 0&&typeof f!="boolean")throw Error("allowSleep must be boolean");let d=ie(e,2,"size");d.forEach(h=>K(h,"size"));let p=ie(r,2,"position");if(!Number.isFinite(o))throw Error("angle must be finite");if(!Number.isFinite(n)||n<0||n>1)throw Error("restitution must be between 0 and 1");if(typeof l!="boolean")throw Error("isTrigger must be boolean");for(let h of[c,u])if(!Number.isInteger(h)||h<0||h>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");let m=this.topology.addBody(d,K(t,"density",!0),K(i,"friction",!0),[...p,o],ie(a,3,"velocity"));return this.restitution??=new Map,n>0&&this.restitution.set(m,n),this.sensors??=new Set,l&&this.sensors.add(m),this.filters??=new Map,(c!==4294967295||u!==4294967295)&&this.filters.set(m,[c,u]),this.topology.avbdSleepEligible??=new Map,f!==void 0&&this.topology.avbdSleepEligible.set(m,f),m}checkBodies(e,t){if(!Number.isInteger(e)||!Number.isInteger(t)||e<-1||e>=this.bodyCount||t<0||t>=this.bodyCount||e===t)throw Error("Invalid 2D constraint endpoints")}addJoint(e,t,i=[0,0],r=[0,0],{stiffness:o=[1/0,1/0,0],breakForce:a=1/0}={}){if(this.assertEditable(),this.checkBodies(e,t),!o||o.length!==3||Array.from(o).some(l=>l!==1/0&&(!Number.isFinite(l)||l<0))||a!==1/0&&(!Number.isFinite(a)||a<0))throw Error("Joint stiffness and break force must be nonnegative or Infinity");let n=this.topology.addJoint(e,t,ie(i,2,"anchorA"),ie(r,2,"anchorB"),o,a);return this.constraintHandle(n.slot,n)}constraintHandle(e,t={}){return Object.assign(t,{slot:e,alive:!0,disposed:!1}),t.dispose=()=>{t.disposed||(this.gpu&&!this.gpu.destroyed?this.gpu.disableConstraint(e):this.gpu||this.topology.data.fill(0,e*O+Q,e*O+Q+3),t.alive=!1,t.disposed=!0)},t.destroy=t.dispose,this.topology.handles[e]=t,t}addSpring(e,t,i=[0,0],r=[0,0],{stiffness:o=1e3,rest:a=1}={}){if(this.assertEditable(),this.checkBodies(e,t),e<0)throw Error("A spring requires two bodies");let n=this.topology.jointCount;return this.topology.addSpring(e,t,ie(i,2,"anchorA"),ie(r,2,"anchorB"),K(o,"stiffness",!0),K(a,"rest",!0)),this.constraintHandle(n)}addMotor(e,t,{speed:i=1,maxTorque:r=100}={}){if(this.assertEditable(),this.checkBodies(e,t),!Number.isFinite(i))throw Error("speed must be finite");let o=this.topology.jointCount;return this.topology.addMotor(e,t,i,K(r,"maxTorque",!0)),this.constraintHandle(o)}addAngularLimit(e,t,i={}){this.assertEditable(),this.checkBodies(e,t);let r=ki(i),o=this.topology.addJoint(e,t,[0,0],[0,0],[0,0,0]);Bs(this.topology,o.slot,r);let a=this.constraintHandle(o.slot,o);return a.setLimits=n=>{if(a.disposed)throw Error("The angular limit has been disposed");return this.gpu?this.gpu.setAngleLimits(a.slot,n):Bs(this.topology,a.slot,ki(n)),a},a}addHinge(e,t,i=[0,0],r=[0,0],o={}){this.assertEditable(),this.checkBodies(e,t);let a=ie(i,2,"anchorA"),n=ie(r,2,"anchorB"),l=o.minAngle!==void 0||o.maxAngle!==void 0?ki(o):null,c=o.motor;if(c){if(!Number.isFinite(c.speed??1))throw Error("speed must be finite");K(c.maxTorque??100,"maxTorque",!0)}let u=this.addJoint(e,t,a,n),f=l?this.addAngularLimit(e,t,l):null,d=c?this.addMotor(e,t,c):null;return{joint:u,limits:f,motor:d,disposed:!1,dispose(){this.disposed||(this.joint.dispose(),this.limits?.dispose(),this.motor?.dispose(),this.disposed=!0)},destroy(){this.dispose()}}}createSolver(e,t={}){if(ga(e))return e.createSolver(this,t);this.assertEditable();let i=new Ko(e,this.topology,t);for(let[r,o]of this.restitution??[])i.setRestitution(r,o);for(let r of this.sensors??[])i.setSensor(r,!0);for(let[r,o]of this.filters??[])i.setFilters([r],[o[0]],[o[1]]);return this.gpu=i,this.created=!0,i}};var Wr=class{constructor(e){if(this.device=e,this.latestMs=null,this.samples=0,this.slots=[],!!e.features.has("timestamp-query"))for(let t=0;t<3;t++)this.slots.push({query:e.createQuerySet({type:"timestamp",count:2}),resolve:e.createBuffer({size:256,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),read:e.createBuffer({size:16,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),busy:!1})}begin(){let e=this.slots.find(t=>!t.busy);return!e||this.disposed?null:(e.busy=!0,e)}descriptor(e){return e?{timestampWrites:{querySet:e.query,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1}}:{}}encode(e,t){t&&(e.resolveQuerySet(t.query,0,2,t.resolve,0),e.copyBufferToBuffer(t.resolve,0,t.read,0,16))}resolve(e){if(e)return e.pending=e.read.mapAsync(GPUMapMode.READ).then(()=>{let t=new BigUint64Array(e.read.getMappedRange());this.latestMs=Number(t[1]-t[0])/1e6,this.samples++,e.read.unmap()}).catch(()=>{}).finally(()=>{e.busy=!1,e.pending=null}),e.pending}settled(){return Promise.all(this.slots.map(e=>e.pending))}destroy(){this.disposed=!0;for(let e of this.slots)e.query.destroy(),e.resolve.destroy(),e.read.destroy()}};var Bu=(s,e)=>Math.ceil(s/e)*e,Cu=s=>String(s>>>0),Hr=class{constructor(e,t={}){this.device=e,this.maxFreeBytes=t.maxFreeBytes??201326592,this.freeBytes=0,this.free=new Map,this.all=new Set}acquire(e,t,i="recycled-buffer"){let r=Bu(Math.max(4,e),4),o=Cu(t),a=this.free.get(o);if(a){let l=-1,c=1/0;for(let u=0;u<a.length;u+=1){let f=a[u];f.size>=r&&f.size<c&&(l=u,c=f.size)}if(l>=0){let[u]=a.splice(l,1);return this.freeBytes-=u.size,u.buffer}}let n=this.device.createBuffer({label:i,size:r,usage:t,mappedAtCreation:!1});return this.all.add(n),n}release(e,t,i){if(!e)return;let r=Bu(Math.max(4,t),4);if(this.freeBytes+r>this.maxFreeBytes){e.destroy(),this.all.delete(e);return}let o=Cu(i),a=this.free.get(o);a||(a=[],this.free.set(o,a)),a.push({buffer:e,size:r,usage:i}),this.freeBytes+=r}trim(e=this.maxFreeBytes){this.maxFreeBytes=e;for(let[t,i]of this.free.entries()){for(;this.freeBytes>this.maxFreeBytes&&i.length>0;){let r=i.pop();r.buffer.destroy(),this.all.delete(r.buffer),this.freeBytes-=r.size}i.length===0&&this.free.delete(t)}}destroy(){for(let e of this.all)e.destroy();this.free.clear(),this.all.clear(),this.freeBytes=0}};var Su=`const EPS : f32 = 1.0e-7;
5230
+ }`);var Qc=ii;var iu=8,Kc=16,Yi=1e-6,Gn=1e-5,md=1e-6,Fn=34028234663852886e22,ea=0,ru=1,ta=2;function Zc(s){let e=s.positionAng;return{center:s.positionLin,half:ne(S(),s.size,.5),axis:[le(S(),e,[1,0,0]),le(S(),e,[0,1,0]),le(S(),e,[0,0,1])]}}var Xi=(s,e)=>Math.abs(V(s,e));function ia(s,e){let t=V(e,s.axis[0])>=0?1:-1,i=V(e,s.axis[1])>=0?1:-1,r=V(e,s.axis[2])>=0?1:-1,o=D(S(),s.center,s.axis[0],s.half[0]*t);return D(o,o,s.axis[1],s.half[1]*i),D(o,o,s.axis[2],s.half[2]*r)}function su(s,e){return e===0?{u:s.axis[1],v:s.axis[2],extentU:s.half[1],extentV:s.half[2]}:e===1?{u:s.axis[0],v:s.axis[2],extentU:s.half[0],extentV:s.half[2]}:{u:s.axis[0],v:s.axis[1],extentU:s.half[0],extentV:s.half[1]}}function gd(s,e,t){let i=V(t,s.axis[e])>=0?1:-1,r=ne(S(),s.axis[e],i),o=D(S(),s.center,r,s.half[e]);return{normal:r,center:o,...su(s,e)}}function bd(s,e){let t=0,i=-Fn;for(let r=0;r<3;r++){let o=Xi(s.axis[r],e);o>i&&(i=o,t=r)}return t}function yd(s,e,t){let i=V(s.axis[e],t)>0?-1:1,r=ne(S(),s.axis[e],i),o=D(S(),s.center,r,s.half[e]),{u:a,v:n,extentU:l,extentV:c}=su(s,e),u=(f,d)=>{let h=D(S(),o,a,f*l);return D(h,h,n,d*c)};return[u(1,1),u(-1,1),u(-1,-1),u(1,-1)]}function vd(s,e,t){let i=[];if(s.length===0)return i;let r=s[s.length-1],o=V(e,r)-t;for(let a of s){let n=V(e,a)-t,l=o<=Gn,c=n<=Gn;if(l!==c){let u=0,f=o-n;Math.abs(f)>Yi&&(u=ce(o/f,0,1)),i.length<Kc&&i.push(D(S(),r,J(S(),a,r),u))}c&&i.length<Kc&&i.push(a),r=a,o=n}return i}var ra=class{contacts=[];midpoints=[];bodyA;bodyB;constructor(e,t){this.bodyA=e,this.bodyB=t}add(e,t,i){let r=ne(S(),Li(S(),e,t),.5);for(let n of this.midpoints)if(qe(J(S(),r,n))<md)return;if(this.contacts.length>=iu)return;let{bodyA:o,bodyB:a}=this;this.contacts.push({feature:i,rA:Te(S(),o.positionAng,J(S(),e,o.positionLin)),rB:Te(S(),a.positionAng,J(S(),t,a.positionLin))}),this.midpoints.push(r)}};function Dn(s,e,t,i,r,o,a,n){let l=qe(i);if(l<Yi)return!0;let c=1/Math.sqrt(l),u=ne(S(),i,c);V(u,t)<0&&ee(u,u);let f=Math.abs(V(t,u)),d=s.half[0]*Xi(u,s.axis[0])+s.half[1]*Xi(u,s.axis[1])+s.half[2]*Xi(u,s.axis[2]),h=e.half[0]*Xi(u,e.axis[0])+e.half[1]*Xi(u,e.axis[1])+e.half[2]*Xi(u,e.axis[2]),m=f-(d+h);return m>0?!1:((!n.valid||m>n.separation)&&(n.valid=!0,n.type=r,n.indexA=o,n.indexB=a,n.separation=m,n.normalAB=u),!0)}function eu(s,e,t){let i=(e+1)%3,r=(e+2)%3,o=V(t,s.axis[i])>=0?1:-1,a=V(t,s.axis[r])>=0?1:-1,n=D(S(),s.center,s.axis[i],s.half[i]*o);D(n,n,s.axis[r],s.half[r]*a);let l=ne(S(),s.axis[e],s.half[e]);return[J(S(),n,l),Li(S(),n,l)]}function xd(s,e,t,i){let r=J(S(),e,s),o=J(S(),i,t),a=J(S(),s,t),n=V(r,r),l=V(o,o),c=V(o,a),u=0,f=0;if(n<=Yi&&l<=Yi)return[s,t];if(n<=Yi)f=ce(c/l,0,1);else{let d=V(r,a);if(l<=Yi)u=ce(-d/n,0,1);else{let h=V(r,o),m=n*l-h*h;Math.abs(m)>Yi&&(u=ce((h*c-d*l)/m,0,1)),f=(h*u+c)/l,f<0?(f=0,u=ce(-d/n,0,1)):f>1&&(f=1,u=ce((h-d)/n,0,1))}}return[D(S(),s,r,u),D(S(),t,o,f)]}function tu(s,e,t,i,r,o,a){let n=r?t:i,l=r?i:t,c=r?a:ee(S(),a),u=gd(n,o,c),f=bd(l,u.normal),d=yd(l,f,u.normal),h=[[u.u,u.extentU],[ee(S(),u.u),u.extentU],[u.v,u.extentV],[ee(S(),u.v),u.extentV]];for(let[g,b]of h)if(d=vd(d,g,V(g,u.center)+b),!d.length)return[];let m=new ra(s,e),p=(r?ea:ru)<<24|(o&255)<<16|(f&255)<<8;for(let g=0;g<d.length&&m.contacts.length<iu;g++){let b=d[g],y=V(J(S(),b,u.center),u.normal);if(y>Gn)continue;let A=D(S(),b,u.normal,-y),v=r?A:b,x=r?b:A;m.add(v,x,p|g&255)}return m.contacts.length||m.add(ia(t,a),ia(i,ee(S(),a)),p),m.contacts}function Ad(s,e,t,i,r,o,a){let[n,l]=eu(t,r,a),[c,u]=eu(i,o,ee(S(),a)),[f,d]=xd(n,l,c,u),h=new ra(s,e),m=ta<<24|(r&255)<<8|o&255;return h.add(f,d,m),h.contacts.length||h.add(ia(t,a),ia(i,ee(S(),a)),m),h.contacts}function ou(s,e,t,i=!0){let r=Zc(s),o=Zc(e),a=J(S(),o.center,r.center),n={type:ea,indexA:0,indexB:0,separation:-Fn,normalAB:S(),valid:!1},l={type:ta,indexA:0,indexB:0,separation:-Fn,normalAB:S(),valid:!1};for(let f=0;f<3;f++)if(!Dn(r,o,a,r.axis[f],ea,f,-1,n))return[];for(let f=0;f<3;f++)if(!Dn(r,o,a,o.axis[f],ru,-1,f,n))return[];let c=S();for(let f=0;f<3;f++)for(let d=0;d<3;d++)if(Dt(c,r.axis[f],o.axis[d]),!Dn(r,o,a,c,ta,f,d,l))return[];if(!n.valid)return[];let u=n;return l.valid&&(i?l.separation>.95*n.separation+.01:.95*l.separation>n.separation+.01)&&(u=l),zs(t,ee(S(),u.normalAB)),u.type===ta?Ad(s,e,r,o,u.indexA,u.indexB,u.normalAB):u.type===ea?tu(s,e,r,o,!0,u.indexA,u.normalAB):tu(s,e,r,o,!1,u.indexB,u.normalAB)}var de=(s,e)=>s.map((t,i)=>t+e[i]),T=(s,e)=>s.map((t,i)=>t-e[i]),q=(s,e)=>s.map(t=>t*e),F=(s,e)=>s.reduce((t,i,r)=>t+i*e[r],0),xt=(s,e)=>[s[1]*e[2]-s[2]*e[1],s[2]*e[0]-s[0]*e[2],s[0]*e[1]-s[1]*e[0]],Tt=s=>q(s,1/(Math.hypot(...s)||1)),Ee=(s,e)=>Array.from(le(S(),s,e)),au=(s,e)=>Te(S(),s.positionAng,T(e,s.positionLin)),Ot=(s,e)=>de(s.positionLin,Ee(s.positionAng,e)),wd=[[1,3,7,5],[0,4,6,2],[2,6,7,3],[0,1,5,4],[4,5,7,6],[0,2,3,1]],Bd=[[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]];function qr(s){if(De(s)||Ue(s)){let a=(De(s),s.size[0]/2),n=Ue(s)?Math.max(0,s.size[1]/2-a):0;return{body:s,radius:a,spine:[Ot(s,[0,-n,0]),Ot(s,[0,n,0])]}}let e=Ct(s),t=e?Array.from({length:e.vertices.length/3},(a,n)=>Ot(s,e.vertices.slice(n*3,n*3+3))):Array.from({length:8},(a,n)=>Ot(s,s.size.map((l,c)=>l/2*(n>>c&1?1:-1)))),i=e?e.faces.map(a=>({vertices:a.verts.map(n=>t[n]),normal:Ee(s.positionAng,a.normal)})):wd.map((a,n)=>({vertices:a.map(l=>t[l]),normal:Ee(s.positionAng,Bd[n])})),r=[],o=new Set;for(let a of i)for(let n=0;n<a.vertices.length;n++){let l=a.vertices[n],c=a.vertices[(n+1)%a.vertices.length],u=t.indexOf(l),f=t.indexOf(c),d=`${Math.min(u,f)},${Math.max(u,f)}`;o.has(d)||(o.add(d),r.push([l,c]))}return{body:s,vertices:t,faces:i,edges:r}}function Ss(s,e){let t=s.spine??s.vertices,i=t[0];for(let r of t)F(r,e)>F(i,e)&&(i=r);return s.spine?de(i,q(e,s.radius)):i}function Cd(s,e,t){let i=T(e,s);return de(s,q(i,Math.max(0,Math.min(1,F(T(t,s),i)/(F(i,i)||1)))))}function sa([s,e],[t,i]){let r=T(e,s),o=T(i,t),a=T(s,t),n=F(r,r),l=F(o,o),c=F(o,a),u=0,f=0,d=h=>Math.max(0,Math.min(1,h));if(n<1e-16)f=l>1e-16?d(c/l):0;else{let h=F(r,a);if(l<1e-16)u=d(-h/n);else{let m=F(r,o),p=n*l-m*m;u=p>1e-12*n*l?d((m*c-h*l)/p):0,f=(m*u+c)/l,f<0?(f=0,u=d(-h/n)):f>1&&(f=1,u=d((m-h)/n))}}return[de(s,q(r,u)),de(t,q(o,f))]}function Sd(s,e,t){let i=[];for(let r=0;r<s.length;r++){let o=s[r],a=s[(r+1)%s.length],n=F(o,e)-t,l=F(a,e)-t;n<=1e-8&&i.push(o),n<0!=l<0&&i.push(de(o,q(T(a,o),n/(n-l))))}return i}function kd(s,e,t,i){let r=T(t,e),o=T(i,e),a=T(s,e),n=F(r,a),l=F(o,a);if(n<=0&&l<=0)return e;let c=T(s,t),u=F(r,c),f=F(o,c);if(u>=0&&f<=u)return t;let d=n*f-u*l;if(d<=0&&n>=0&&u<=0)return de(e,q(r,n/(n-u)));let h=T(s,i),m=F(r,h),p=F(o,h);if(p>=0&&m<=p)return i;let g=m*l-n*p;if(g<=0&&l>=0&&p<=0)return de(e,q(o,l/(l-p)));let b=u*p-m*f;if(b<=0&&f-u>=0&&m-p>=0)return de(t,q(T(i,t),(f-u)/(f-u+m-p)));let y=1/(b+g+d);return de(e,de(q(r,g*y),q(o,d*y)))}function Pd(s,e){let t=null,i=1/0;for(let r of s.faces)for(let o=1;o<r.vertices.length-1;o++){let a=kd(e,r.vertices[0],r.vertices[o],r.vertices[o+1]),n=F(T(e,a),T(e,a));n<i&&(t=a,i=n)}return t}function nu(s,e,t,i,r){if(!De(s)&&!De(e)&&!Ue(s)&&!Ue(e)&&!Ct(s)&&!Ct(e))return ou(s,e,t,s.solver.faceBias!==!1);i??=qr(s),r??=qr(e);let o=-1/0,a=[0,0,1],n=null,l=(f,d=null)=>{if(Math.hypot(...f)<1e-9)return;let h=Tt(f),m=F(T(Ss(i,q(h,-1)),Ss(r,h)),h),p=F(T(Ss(r,q(h,-1)),Ss(i,h)),h);p>m&&(m=p,h=q(h,-1)),m>o+1e-7&&(o=m,a=h,n=d)};for(let f of[i,r])for(let d of f.faces??[])l(d.normal);if(i.edges&&r.edges)for(let f of i.edges)for(let d of r.edges)l(xt(T(f[1],f[0]),T(d[1],d[0])),[f,d]);if(i.spine&&r.spine){let f=sa(i.spine,r.spine);l(T(...f))}for(let[f,d]of[[i,r],[r,i]])if(f.spine&&d.faces){for(let h of d.vertices)l(T(h,Cd(...f.spine,h)));for(let h of d.edges){let m=sa(f.spine,h);l(T(...m))}}if(o===-1/0&&l(T(s.positionLin,e.positionLin)),o>0)return[];o===-1/0&&(a=[0,0,1],o=-(i.radius+r.radius));let c=Tt(xt(a,Math.abs(a[0])<.7?[1,0,0]:[0,1,0]));t.set([...a,...c,...xt(a,c)]);let u=[];if(i.spine&&r.spine){let[f,d]=sa(i.spine,r.spine);u=[[de(f,q(a,-i.radius)),de(d,q(a,r.radius))]]}else if(i.spine||r.spine){let f=i.spine?i:r,d=i.spine?r:i,h=i.spine?q(a,-1):a,m=Ss(f,h),p=Pd(d,m);u=[i.spine?[m,p]:[p,m]]}else if(n)u=[sa(...n)];else{let f=(A,v)=>A.faces.reduce((x,w)=>F(w.normal,v)>F(x.normal,v)?w:x,A.faces[0]),d=f(i,q(a,-1)),h=f(r,a),m=F(d.normal,q(a,-1))>=F(h.normal,a),p=m?d:h,b=f(m?r:i,q(p.normal,-1)).vertices,y=q(p.vertices.reduce((A,v)=>de(A,v),[0,0,0]),1/p.vertices.length);for(let A=0;A<p.vertices.length&&b.length;A++){let v=p.vertices[A],x=p.vertices[(A+1)%p.vertices.length],w=Tt(xt(T(x,v),p.normal));F(T(y,v),w)>0&&(w=q(w,-1)),b=Sd(b,w,F(v,w))}for(let A of b){let v=F(T(A,p.vertices[0]),p.normal);if(v<=1e-6){let x=T(A,q(p.normal,v));u.push(m?[x,A]:[A,x])}}}return u.slice(0,8).map(([f,d],h)=>({feature:h+1,rA:au(s,f),rB:au(e,d)}))}var oa=(s,e,t)=>Math.max(e,Math.min(t,s)),Ld=(s,e)=>[F(s.slice(0,3),e),F(s.slice(3,6),e),F(s.slice(6,9),e)];function qn(s,e=!1){if(e){s.rest=Math.hypot(...T(Ot(s.bodyA,s.rA),Ot(s.bodyB,s.rB)));return}let t=s.bodyA?.positionAng??[0,0,0,1];s.cpuRest=$r(jt(),Sa(jt(),t),s.bodyB.positionAng),s.evaluateAng=i=>{let r=$r(jt(),s.bodyA?.positionAng??[0,0,0,1],s.cpuRest);ut(i,r,s.bodyB.positionAng);for(let o=0;o<3;o++)i[o]*=s.torqueArm;return i}}var Un=class extends ai{initialize(){let e=this.bodyA,t=this.bodyB;if(!((e.group??4294967295)&(t.collidesWith??4294967295))||!((t.group??4294967295)&(e.collidesWith??4294967295)))return!1;let i=this.contacts,r=De(e)||De(t)||Ue(e)||Ue(t);this.friction=Math.sqrt(e.friction*t.friction),this.contacts=nu(e,t,this.basis,this.solver.cpuGeometry.get(e),this.solver.cpuGeometry.get(t)).map(o=>{let a=i.find(n=>n.feature===o.feature);return{feature:o.feature,rA:a?.stick&&!r?a.rA:o.rA,rB:a?.stick&&!r?a.rB:o.rB,C0:S(),penalty:a?a.penalty.slice():S(),lambda:a?a.lambda.slice():S(),stick:a?.stick??!1}});for(let o of this.contacts){o.C0.set(Ld(this.basis,T(Ot(e,o.rA),Ot(t,o.rB)))),o.C0[0]+=Rs;for(let a=0;a<3;a++)o.lambda[a]*=this.solver.alpha*this.solver.gamma,o.penalty[a]=oa(o.penalty[a]*this.solver.gamma,Et,We);if(this.solver.massPenalty!==!1){let a=Math.min(e.mass>0?e.mass:1/0,t.mass>0?t.mass:1/0);o.penalty[0]=Math.max(o.penalty[0],oa(a/this.solver.dt**2,Et,We))}}return this.contacts.length>0}updatePrimal(...e){!this.bodyA.isTrigger&&!this.bodyB.isTrigger&&super.updatePrimal(...e)}updateDual(...e){!this.bodyA.isTrigger&&!this.bodyB.isTrigger&&super.updateDual(...e)}},Nn=class extends Ft{constructor(e,t,i){super(e,t.bodyA,t.bodyB),this.options={...i},this.pen=[Et,Et],this.lam=[0,0],this.source=t;let r=i.axisA;this.ta=Tt(Math.abs(r[0])>Math.abs(r[2])?[-r[1],r[0],0]:[0,-r[2],r[1]]);let o=this.bodyA?Ee(this.bodyA.positionAng,this.ta):this.ta,a=Array.from(Te(S(),this.bodyB.positionAng,o));a=T(a,q(i.axisB,F(a,i.axisB))),this.tb=Tt(a)}frame(){let e=this.bodyA?Ee(this.bodyA.positionAng,this.options.axisA):this.options.axisA,t=this.bodyA?Ee(this.bodyA.positionAng,this.ta):this.ta,i=Ee(this.bodyB.positionAng,this.tb);return{axis:e,angle:Math.atan2(F(e,xt(t,i)),F(t,i))}}initialize(){let e=this.frame().angle;this.c0=this.options.type==="motor"?[e,0]:[Math.min(0,e-this.options.minAngle),Math.max(0,e-this.options.maxAngle)];for(let t=0;t<2;t++)this.lam[t]*=this.solver.alpha*this.solver.gamma,this.pen[t]=oa(this.pen[t]*this.solver.gamma,Et,We);return!this.source.broken}evaluate(e){let{angle:t}=this.frame(),i=this.options,r=i.type==="motor"?[Math.atan2(Math.sin(t-this.c0[0]),Math.cos(t-this.c0[0]))-i.speed*this.solver.dt,0]:[t-i.minAngle-e*this.c0[0],t-i.maxAngle-e*this.c0[1]],o=r.map((a,n)=>this.pen[n]*a+this.lam[n]);return{c:r,f:i.type==="motor"?[oa(o[0],-i.maxTorque,i.maxTorque),0]:[Math.min(0,o[0]),Math.max(0,o[1])]}}updatePrimal(e,t,i){let{f:r}=this.evaluate(t),o=this.options;if(o.type==="motor"&&o.maxTorque===0)return;let a=q(this.frame().axis,e===this.bodyA?-1:1);for(let n=0;n<(o.type==="motor"?1:2);n++)if(!(o.type==="limit"&&r[n]===0))for(let l=0;l<3;l++){i.rhsAng[l]+=a[l]*r[n];for(let c=0;c<3;c++)i.lhsAng[l*3+c]+=a[l]*a[c]*this.pen[n]}}updateDual(e){let{c:t,f:i}=this.evaluate(e);this.lam=i;for(let r=0;r<2;r++)this.pen[r]=Math.min(We,this.pen[r]+this.solver.betaAng*(this.options.type==="motor"?Math.abs(t[r]):r===0?Math.max(0,-t[r]):Math.max(0,t[r])))}};function aa(s){if(!s.cpuPrepared){s.cpuPrepared=!0;for(let e of[...s.forces]){let t=fs(e);if(t){e.unlinkFromBodies(),s.forces.splice(s.forces.indexOf(e),1),e.cpuAngular=new Nn(s,e,t);continue}if(e instanceof ke&&e.stiffnessAng>0&&qn(e),e instanceof dt){let i=e.initialize.bind(e);e.initialize=()=>{if(e.broken)return!1;let r=Ui(e);if(r){let o=Math.max(0,Math.hypot(...T(Ot(e.bodyA,e.rA),Ot(e.bodyB,e.rB)))-e.rest);if(o/Math.max(e.rest,1e-6)>r.breakStrain||o*e.stiffness>r.breakForce)return e.broken=!0,!1}return i()}}}}}function lu(s){let e=s.bodies;s.cpuGeometry=new Map;for(let l of e)(De(l)||Ue(l)||Ct(l))&&s.cpuGeometry.set(l,qr(l));let t=e.filter(l=>l.mass>0).slice(0,1024).map(l=>l.radius).sort((l,c)=>l-c),i=Math.max(.1,(t[Math.floor(t.length/2)]??1)*2),r=new Map,o=[],a=new Set,n=(l,c)=>{if(l===c||e[l].mass<=0&&e[c].mass<=0)return;let u=Math.max(l,c),f=Math.min(l,c),d=u*e.length+f;if(a.has(d))return;a.add(d);let h=e[u],m=e[f];if(!((h.group??4294967295)&(m.collidesWith??4294967295))||!((m.group??4294967295)&(h.collidesWith??4294967295)))return;let p=h.radius+m.radius;F(T(h.positionLin,m.positionLin),T(h.positionLin,m.positionLin))<=p*p&&!h.constrainedTo(m)&&new Un(s,h,m)};for(let l=0;l<e.length;l++){let c=e[l],u=c.positionLin.map(d=>Math.floor((d-c.radius)/i)),f=c.positionLin.map(d=>Math.floor((d+c.radius)/i));if((f[0]-u[0]+1)*(f[1]-u[1]+1)*(f[2]-u[2]+1)>128){o.push(l);continue}for(let d=u[0];d<=f[0];d++)for(let h=u[1];h<=f[1];h++)for(let m=u[2];m<=f[2];m++){let p=`${d},${h},${m}`,g=r.get(p)??[];for(let b of g)n(l,b);g.push(l),r.set(p,g)}}for(let l of o)for(let c=0;c<e.length;c++)n(l,c)}function na(s,e){if(!(e===3?s.bodies.some(r=>r.restitution>0):[...s.restitution.values()].some(r=>r>0)))return null;if(e===2)return Float64Array.from(s.velocity);let i=new Float64Array(s.bodies.length*6);return s.bodies.forEach((r,o)=>{i.set(r.velocityLin,o*6),i.set(r.velocityAng,o*6+3)}),i}function la(s,e,t){if(!t)return;let i=e===3?s.bodies.length:s.bodyCount,r=e===3?6:4,o=e===3?new Float64Array(i*r):s.velocity;e===3&&s.bodies.forEach((p,g)=>{o.set(p.velocityLin,g*r),o.set(p.velocityAng,g*r+3)});let a=p=>e===3?s.bodies[p].mass>0&&!s.bodies[p].sleeping?1/s.bodies[p].mass:0:s.dynamic[p]?1/s.shape[p*4+2]:0,n=(p,g)=>{if(!a(p))return e===3?[0,0,0]:0;if(e===2)return s.shape[p*4+3]>0?g/s.shape[p*4+3]:0;let b=s.bodies[p],y=b.positionAng,A=Ee([-y[0],-y[1],-y[2],y[3]],g);return Ee(y,A.map((v,x)=>b.moment[x]>0?v/b.moment[x]:0))},l=(p,g,b)=>{let y=g*r;return e===3?T(p.subarray(y,y+3),xt(b,p.subarray(y+3,y+6))):[p[y]-p[y+2]*b[1],p[y+1]+p[y+2]*b[0]]},c=(p,g)=>e===3?xt(p,g):p[0]*g[1]-p[1]*g[0],u=(p,g)=>e===3?F(p,g):p*g,f;if(e===3){let p=new Map(s.bodies.map((g,b)=>[g,b]));f=s.forces.filter(g=>g.contacts?.length&&!g.bodyA.isTrigger&&!g.bodyB.isTrigger).map(g=>{let b=(y,A)=>{let v=[0,0,0];for(let x of g.contacts){let w=Ee(y.positionAng,x[A]);for(let B=0;B<3;B++)v[B]+=w[B]/g.contacts.length}return v};return{a:p.get(g.bodyA),b:p.get(g.bodyB),n:g.basis.slice(0,3),ra:b(g.bodyA,"rA"),rb:b(g.bodyB,"rB"),e:Math.max(g.bodyA.restitution??0,g.bodyB.restitution??0)}})}else{let p=(g,b)=>{let y=Math.cos(s.pose[g*4+2]),A=Math.sin(s.pose[g*4+2]);return[y*b[0]-A*b[1],A*b[0]+y*b[1]]};f=s.contactPairs.filter(g=>!s.sensors.has(g.a)&&!s.sensors.has(g.b)).map(g=>({...g,ra:p(g.a,g.ra),rb:p(g.b,g.rb),e:Math.max(s.restitution.get(g.a)??0,s.restitution.get(g.b)??0)}))}let d=new Uint32Array(i);if(e===3)s.bodies.forEach((p,g)=>{d[g]=p.forces.length});else for(let p=0;p<i;p++)d[p]=s.adjStart[p+1]-s.adjStart[p];let h=[];for(let p of f){if(p.e<=0)continue;let g=F(p.n,T(l(t,p.a,p.ra),l(t,p.b,p.rb)));if(g>=-1)continue;let b=c(p.ra,p.n),y=c(p.rb,p.n),A=n(p.a,b),v=n(p.b,y),x=a(p.a)+a(p.b)+u(b,A)+u(y,v);x>0&&h.push({...p,inertiaA:A,inertiaB:v,k:x,target:-p.e*g,impulse:0})}let m=new Float64Array(o.length);for(let p=0;p<12&&h.length;p++){m.fill(0);for(let g of h){let b=F(g.n,T(l(o,g.a,g.ra),l(o,g.b,g.rb))),y=Math.max(0,g.impulse+(g.target-b)/(g.k*Math.max(1,d[g.a],d[g.b]))),A=y-g.impulse;g.impulse=y;for(let[v,x,w]of[[g.a,1,g.inertiaA],[g.b,-1,g.inertiaB]]){let B=v*r,L=a(v);for(let M=0;M<e;M++)m[B+M]+=x*A*L*g.n[M];if(e===3)for(let M=0;M<3;M++)m[B+3+M]+=x*A*w[M];else m[B+2]+=x*A*w}}for(let g=0;g<o.length;g++)o[g]+=m[g]}e===3&&s.bodies.forEach((p,g)=>{p.velocityLin.set(o.subarray(g*r,g*r+3)),p.velocityAng.set(o.subarray(g*r+3,g*r+6))})}function cu(s,e,t){let i=e.windSpeed??0;if(!ar(s)||s.mass<=0||i===0)return null;let r=e.windAngle??0,o=[Math.cos(r),Math.sin(r),0],a=[-o[1],o[0],0],n=s.positionLin,l=t*e.dt,c=F(n,o),u=F(n,a),f=.5*Math.sin(1.1*l-.35*c+.2*u)+.3*Math.sin(2.9*l-.8*c+.6*n[2])+.2*Math.sin(6.1*l-1.7*c+1.3*n[2]+.9*u),d=.6*Math.sin(1.7*l-.6*c+.4*n[2])+.4*Math.sin(4.3*l-1.3*c-.7*n[2]),h=Math.sin(2.3*l-.9*c+1.1*u),m=e.windGust??.4,p=o.map((x,w)=>i*x*(1+m*f)+m*i*(a[w]*.25*d+(w===2?.1*h:0))-s.velocityLin[w]),g=Ee(s.positionAng,[0,0,1]),b=(e.windPressure??.72)*s.size[0]*s.size[1]/s.mass,y=F(p,g),A=p.map((x,w)=>x-g[w]*y),v=b*y*Math.abs(y)/(1+2*e.dt*b*Math.abs(y));return g.map((x,w)=>x*v+A[w]*.06*b*Math.hypot(...A))}var _d=()=>({dt:1/60,gravity:-10,iterations:10,betaLin:1e4,betaAng:100,alpha:.99,gamma:.999}),ca=class{dt=1/60;gravity=-10;iterations=10;alpha=.99;betaLin=1e4;betaAng=100;gamma=.999;massPenalty=!0;faceBias=!0;up=[0,0,1];cpuStep=0;bodies=[];forces=[];constructor(){this.defaultParams()}defaultParams(){Object.assign(this,_d())}clear(){this.forces=[],this.bodies=[]}pick(e,t){let r=null,o=S(),a=S();for(let n=this.bodies.length-1;n>=0;n--){let l=this.bodies[n];if(l.mass<=0)continue;Te(o,l.positionAng,J(o,e,l.positionLin)),Te(a,l.positionAng,t);let c=0,u=1/0,f=!0;for(let h=0;h<3&&f;h++){let m=l.size[h]*.5;if(Math.abs(a[h])<1e-6){(o[h]<-m||o[h]>m)&&(f=!1);continue}let p=1/a[h],g=(-m-o[h])*p,b=(m-o[h])*p;g>b&&([g,b]=[b,g]),c=Math.max(c,g),u=Math.min(u,b),c>u&&(f=!1)}if(!f)continue;let d=c>=0?c:u;d<0||(!r||d<r.t)&&(r={body:l,local:D(S(),o,a,d),t:d})}return r}sys=Os();dxLin=S();dxAng=S();dp=S();accel=S();step(){let{dt:e,gravity:t,bodies:i,sys:r,dp:o}=this,a=na(this,3);aa(this),lu(this);let n=[];for(let l of this.forces)l.initialize()?n.push(l):l.unlinkFromBodies();this.forces=n;for(let l=i.length-1;l>=0;l--){let c=i[l];D(c.inertialLin,c.positionLin,c.velocityLin,e),c.mass>0&&D(c.inertialLin,c.inertialLin,this.up,t*e*e);let u=cu(c,this,this.cpuStep);u&&D(c.inertialLin,c.inertialLin,u,e*e),si(c.inertialAng,c.positionAng,uu(c.velocityAng,e)),_t(this.accel,J(this.accel,c.velocityLin,c.prevVelocityLin),e);let f=V(this.accel,this.up)*Es(t),d=ce(f/Math.abs(t),0,1);Number.isFinite(d)||(d=0),c.initialLin.set(c.positionLin),c.initialAng.set(c.positionAng),c.mass>0&&!c.sleeping&&(D(c.positionLin,c.positionLin,c.velocityLin,e),D(c.positionLin,c.positionLin,this.up,t*d*e*e),si(c.positionAng,c.positionAng,uu(c.velocityAng,e)))}for(let l=0;l<this.iterations;l++){for(let c=i.length-1;c>=0;c--){let u=i[c];if(u.mass<=0||u.sleeping)continue;let f=u.mass,d=u.moment;Ce(r.lhsLin,f/(e*e),f/(e*e),f/(e*e)),Ce(r.lhsAng,d[0]/(e*e),d[1]/(e*e),d[2]/(e*e)),r.lhsCross.fill(0),ue(r.rhsLin,r.lhsLin,J(o,u.positionLin,u.inertialLin)),ue(r.rhsAng,r.lhsAng,ut(o,u.positionAng,u.inertialAng));let h=u.forces;for(let p=h.length-1;p>=0;p--)h[p].updatePrimal(u,this.alpha,r);let m=u.moment.every(p=>p===0);m&&(Ce(r.lhsAng,1,1,1),r.lhsCross.fill(0),r.rhsAng.fill(0)),Is(r.lhsLin,r.lhsAng,r.lhsCross,ee(r.rhsLin,r.rhsLin),ee(r.rhsAng,r.rhsAng),this.dxLin,this.dxAng),D(u.positionLin,u.positionLin,this.dxLin,1),m||si(u.positionAng,u.positionAng,this.dxAng)}for(let c of this.forces)c.updateDual(this.alpha)}for(let l of i)l.prevVelocityLin.set(l.velocityLin),l.mass>0&&!l.sleeping&&(_t(l.velocityLin,J(l.velocityLin,l.positionLin,l.initialLin),e),_t(l.velocityAng,ut(l.velocityAng,l.positionAng,l.initialAng),e));la(this,3,a),this.cpuStep++}},Ed=S(),uu=(s,e)=>ne(Ed,s,e);var Ps=(s,e)=>s.map((t,i)=>t+e[i]),Re=(s,e)=>s.map((t,i)=>t-e[i]),Lt=(s,e)=>s.map(t=>t*e),ot=(s,e)=>s[0]*e[0]+s[1]*e[1],ks=(s,e)=>[Math.cos(s)*e[0]-Math.sin(s)*e[1],Math.sin(s)*e[0]+Math.cos(s)*e[1]],du=s=>Math.max(0,Math.min(1,s)),fu=(s,e,t)=>Ps(s,Lt(Re(e,s),du(ot(Re(t,s),Re(e,s))/(ot(Re(e,s),Re(e,s))||1))));function ua(s,e){let t=ei(s)?.get(e)??[0,0,0,0],i=Array.from(s.pose.subarray(e*4,e*4+2)),r=s.pose[e*4+2],o=l=>Ps(i,ks(r,l)),a=[s.shape[e*4]/2,s.shape[e*4+1]/2],n=t[0]===4?Array.from({length:t.vertices.length/4},(l,c)=>o(t.vertices.slice(c*4,c*4+2))):t[0]===0?[[-1,-1],[1,-1],[1,1],[-1,1]].map(l=>o([l[0]*a[0],l[1]*a[1]])):null;return{kind:t[0],p:i,angle:r,vertices:n,radius:t[1],spine:[o([-t[2]||0,0]),o([t[2]||0,0])]}}function Qi(s,e){if(s.vertices){let r=-1/0,o=[];for(let a of s.vertices){let n=ot(a,e);n>r+1e-7?(r=n,o=[a]):Math.abs(n-r)<1e-7&&o.push(a)}return[o[0],o.at(-1)]}let t=Ps(s.spine[0],Lt(e,s.radius)),i=Ps(s.spine[1],Lt(e,s.radius));return Math.abs(ot(t,e)-ot(i,e))<1e-7?[t,i]:ot(t,e)>ot(i,e)?[t,t]:[i,i]}function pu(s,e,t,i){let r=ua(s,e),o=ua(s,t),a=s.pose,n=s.shape;if(r.kind===0&&o.kind===0)return _o(...a.subarray(e*4,e*4+3),n[e*4]/2,n[e*4+1]/2,...a.subarray(t*4,t*4+3),n[t*4]/2,n[t*4+1]/2,i);let l=[];if(r.kind===3||o.kind===3){let u=r.kind===3,f=u?r:o,d=u?o:r;if(d.kind===3)return 0;let h=ks(f.angle,[0,1]),m=Qi(d,Lt(h,-1));for(let p of m){let g=ot(Re(p,f.p),h);if(g<=0){let b=Re(p,Lt(h,g));l.push({a:u?b:p,b:u?p:b,n:u?Lt(h,-1):h})}}}else{let u=-1/0,f=[0,1],d=x=>{let w=Math.hypot(...x);if(w<1e-9)return;let B=Lt(x,1/w),L=ot(Re(Qi(r,Lt(B,-1))[0],Qi(o,B)[0]),B),M=ot(Re(Qi(o,Lt(B,-1))[0],Qi(r,B)[0]),B);Math.max(L,M)>u+1e-7&&(u=Math.max(L,M),f=L>=M?B:Lt(B,-1))};for(let[x,w]of[[r,o],[o,r]])if(x.vertices)for(let B=0;B<x.vertices.length;B++){let L=Re(x.vertices[(B+1)%x.vertices.length],x.vertices[B]);d([L[1],-L[0]]),w.vertices||d(Re(x.vertices[B],fu(...w.spine,x.vertices[B])))}else if(d(ks(x.angle,[0,1])),!w.vertices)for(let B of x.spine)d(Re(B,fu(...w.spine,B)));if(u===-1/0&&d([0,1]),u>0)return 0;let h=Qi(r,Lt(f,-1)),m=Qi(o,f),p=[-f[1],f[0]],g=h.map(x=>ot(x,p)),b=m.map(x=>ot(x,p)),y=Math.max(Math.min(...g),Math.min(...b)),A=Math.min(Math.max(...g),Math.max(...b)),v=(x,w)=>{let B=ot(Re(x[1],x[0]),p);return Math.abs(B)<1e-9?x[0]:Ps(x[0],Lt(Re(x[1],x[0]),du((w-ot(x[0],p))/B)))};for(let x of A-y>1e-6?[y,A]:[(y+A)/2])l.push({a:v(h,x),b:v(m,x),n:f})}let c=0;for(let u of l){if(c&&Math.hypot(...Re(u.a,l[0].a))<1e-7)continue;let f=ks(-r.angle,Re(u.a,r.p)),d=ks(-o.angle,Re(u.b,o.p));if(i.set([268435456+c,...f,...d,...u.n],c*7),c++,c===2)break}return c}var hu=(s,e,t)=>[Math.cos(s)*e-Math.sin(s)*t,Math.sin(s)*e+Math.cos(s)*t],mu=function(){let{pose:s,shape:e,props:t}=this,i=this.broadphase.pairs,r=this.contactOut;for(let o=0;o<this.broadphase.pairCount;o++){let a=i[o],n=Math.floor(a/2097152),l=a-n*2097152,c=this.collideBodies(n,l,r);if(c===0)continue;let u=0,f=this.prevCount;for(;u<f;){let m=u+f>>>1;this.prevKeys[m]<a?u=m+1:f=m}let d=u,h=Math.sqrt(t[n*4]*t[l*4]);for(let m=0;m<c;m++){let p=this.jointCount+this.contactCount++;this.info=this.grow(this.info,(p+1)*j),this.data=this.grow(this.data,(p+1)*O);let g=this.data,b=p*O,y=m*7,A=r[y+0];this.info.set([bs,n,l,A],p*j),g.fill(0,b,b+O),g[b+Q]=g[b+Q+1]=1/0,g[b+_e]=-1/0,g[b+Ae]=0,g[b+Pt]=g[b+Pt+1]=1/0,g[b+N]=r[y+1],g[b+N+1]=r[y+1+1],g[b+Y]=r[y+3],g[b+Y+1]=r[y+3+1],g[b+re]=h,g[b+be]=r[y+5],g[b+Ne]=r[y+5+1];let v=-1;for(let P=d;P<this.prevCount&&this.prevKeys[P]===a;P++)this.prevInfo[P*j+3]===A&&(v=P);if(v<0&&this.params.matchNearest){let P=Mn*Math.min(e[n*4],e[n*4+1],e[l*4],e[l*4+1]);for(let C=d;C<this.prevCount&&this.prevKeys[C]===a;C++){let _=Math.hypot(this.prevData[C*O+N]-g[b+N],this.prevData[C*O+N+1]-g[b+N+1]);_<=P&&(P=_,v=C)}}if(v>=0){let P=v*O;g[b+se]=this.prevData[P+se],g[b+se+1]=this.prevData[P+se+1],g[b+te]=this.prevData[P+te],g[b+te+1]=this.prevData[P+te+1],this.prevData[P+Hi]&&(g[b+N]=this.prevData[P+N],g[b+N+1]=this.prevData[P+N+1],g[b+Y]=this.prevData[P+Y],g[b+Y+1]=this.prevData[P+Y+1])}let[x,w]=hu(s[n*4+2],g[b+N],g[b+N+1]),[B,L]=hu(s[l*4+2],g[b+Y],g[b+Y+1]),M=g[b+be],I=g[b+Ne],E=s[n*4]+x-s[l*4]-B,k=s[n*4+1]+w-s[l*4+1]-L;g[b+fe]=M*E+I*k+5e-4,g[b+fe+1]=I*E-M*k}}};var fa=class extends Dr{constructor(e,t,i){if(super({precision:i==="soa-colored"?"f32":"f64",order:i==="soa-colored"?"colored":"sequential"}),Object.assign(this,e),this.options={...this.options,precision:i==="soa-colored"?"f32":"f64",order:i==="soa-colored"?"colored":"sequential"},this.options.precision==="f64")for(let[r,o]of Object.entries(this))o instanceof Float32Array&&(this[r]=Float64Array.from(o));for(let[r,o]of ei(e)??[]){let a=this.shape[r*4+2];Fr(this,r,{geometry:o,area:a,momentPerMass:a>0?this.shape[r*4+3]/a:0,radius:this.props[r*4+1]},1)}this.filters=new Map(t?.filters??[]),this.sensors=new Set(t?.sensors??[]),this.restitution=new Map(t?.restitution??[]),this.contactPairs=[],t&&(t.topology=this)}narrowphase(){this.contactPairs=[],mu.call(this)}collideBodies(e,t,i){let r=this.filters.get(e)??[4294967295,4294967295],o=this.filters.get(t)??[4294967295,4294967295];if(!(r[0]&o[1])||!(o[0]&r[1]))return 0;let a=pu(this,e,t,i);if(a){let n=[i[5],i[6]],l=[0,0],c=[0,0];for(let h=0;h<a;h++)for(let m=0;m<2;m++)l[m]+=i[h*7+1+m]/a,c[m]+=i[h*7+3+m]/a;let u=this.pose[e*4+2],f=Math.cos(u),d=Math.sin(u);this.contactPairs.push({a:e,b:t,n,ra:l,rb:c,point:[this.pose[e*4]+f*l[0]-d*l[1],this.pose[e*4+1]+d*l[0]+f*l[1],0],impulse:0})}return this.sensors.has(e)||this.sensors.has(t)?0:a}initJoints(){for(let e=0;e<this.jointCount;e++){let t=e*O,i=this.info[e*j];if(this.data[t+Q]===0&&this.data[t+Q+1]===0&&this.data[t+Q+2]===0){i!==0&&(this.info[e*j]=0,this.noCollideDirty=!0,this.handles[e]&&(this.handles[e].alive=!1));continue}i===1&&this.jointC(this.info[e*j+1],this.info[e*j+2],t,this.pose,this.data,t+fe)}for(let e=0;e<this.jointCount;e++)if(this.info[e*j]===5){let t=e*O,i=this.info[e*j+1],r=this.info[e*j+2],o=(i<0?0:this.pose[i*4+2])-this.pose[r*4+2]-this.data[t+re];this.data[t+fe]=Math.min(0,o-this.data[t+be]),this.data[t+fe+1]=Math.max(0,o-this.data[t+Ne])}}warmStartConstraints(e,t){let i=[];for(let r=0;r<this.jointCount;r++)this.info[r*j]===5&&(i.push(r),this.info[r*j]=4);super.warmStartConstraints(e,t);for(let r of i)this.info[r*j]=5}evalConstraint(e,t,i){if(this.info[e*j]!==5)return super.evalConstraint(e,t,i);let r=e*O,o=this.info[e*j+1],a=this.info[e*j+2],n=this.data,l=(o<0?0:this.pose[o*4+2])-this.pose[a*4+2]-n[r+re];this.eC[0]=l-n[r+be]-t*n[r+fe],this.eC[1]=l-n[r+Ne]-t*n[r+fe+1],this.eG.fill(0),this.eJ.fill(0);for(let c=0;c<2;c++){this.eMin[c]=n[r+_e+c],this.eMax[c]=n[r+Ae+c];let u=Math.max(this.eMin[c],Math.min(this.eMax[c],n[r+se+c]*this.eC[c]+n[r+te+c]));i>=0&&u!==0&&(this.eJ[c*3+2]=i===o?1:-1)}return 2}step(){let e=na(this,2);super.step(),la(this,2,e);let t=new Map(this.contactPairs.map(i=>[`${i.a},${i.b}`,i]));for(let i=this.jointCount;i<this.jointCount+this.contactCount;i++){let r=t.get(`${this.info[i*j+1]},${this.info[i*j+2]}`);r&&(r.impulse+=Math.abs(this.data[i*O+te])*this.params.dt)}}};var pa=(s,e,t)=>{let i=T(e,s);return de(s,q(i,Math.max(0,Math.min(1,F(T(t,s),i)/(F(i,i)||1)))))};function da(s,e,t,i){let r=T(s,t),o=F(r,e),a=o*o-F(r,r)+i*i;if(a<0)return null;let n=-o-Math.sqrt(a);return n<0?null:{t:n,n:Tt(T(de(s,q(e,n)),t))}}function Vr(s,e){return e&&(!s||e.t<s.t)?e:s}function Vn(s,e,t,i,r){let o=T(i,t),a=T(s,t),n=F(o,o);if(n<1e-16)return da(s,e,t,r);let l=F(o,e),c=F(o,a),u=F(a,e),f=n-l*l,d=n*u-c*l,h=n*F(a,a)-c*c-r*r*n,m=d*d-f*h,p=null;if(f>1e-12*n&&m>=0){let g=(-d-Math.sqrt(m))/f,b=c+g*l;g>=0&&b>=0&&b<=n&&(p={t:g,n:Tt(T(de(s,q(e,g)),de(t,q(o,b/n))))})}return Vr(Vr(p,da(s,e,t,r)),da(s,e,i,r))}function gu(s,e){let t=q(e.vertices.reduce((i,r)=>de(i,r),[0,0,0]),1/e.vertices.length);for(let i=0;i<e.vertices.length;i++){let r=e.vertices[i],o=e.vertices[(i+1)%e.vertices.length],a=xt(T(o,r),e.normal);if(F(a,T(s,r))*(F(a,T(t,r))>=0?1:-1)<-1e-6)return!1}return!0}function Md(s,e,t,i){if(i===0){let n=-1/0,l=1/0,c=q(t,-1);for(let u of s.faces){let f=F(u.normal,t),d=F(u.normal,T(u.vertices[0],e));if(Math.abs(f)<1e-12){if(d<0)return null}else{let h=d/f;f<0?h>n&&(n=h,c=u.normal):l=Math.min(l,h)}if(n>l)return null}return l<0?null:{t:Math.max(0,n),n:n<=0?q(t,-1):c}}let r=!0,o=1/0,a=null;for(let n of s.faces){let l=F(n.normal,T(e,n.vertices[0]));l>0&&(r=!1),gu(T(e,q(n.normal,l)),n)&&(o=Math.min(o,l*l));let c=F(n.normal,t);if(c<-1e-12){let u=(i-l)/c;u>=0&&gu(T(de(e,q(t,u)),q(n.normal,i)),n)&&(a=Vr(a,{t:u,n:n.normal}))}}for(let[n,l]of s.edges){let c=T(e,pa(n,l,e));o=Math.min(o,F(c,c)),a=Vr(a,Vn(e,t,n,l,i))}return r||o<=i*i?{t:0,n:q(t,-1)}:a}var At=(s,e)=>s[0]*e[0]+s[1]*e[1];function zd(s,e,t,i){let r=!0,o=1/0,a=null;for(let n=0;n<s.vertices.length;n++){let l=s.vertices[n],c=s.vertices[(n+1)%s.vertices.length],u=T(c,l),f=Tt([u[1],-u[0]]),d=At(T(e,l),f);d>0&&(r=!1);let h=T(e,pa(l,c,e));o=Math.min(o,At(h,h));let m=At(t,f);if(m<-1e-12){let p=(i-d)/m,g=T(de(e,q(t,p)),q(f,i)),b=At(T(g,l),u),y=1e-6*At(u,u);p>=0&&b>=-y&&b<=At(u,u)+y&&(a=Vr(a,{t:p,n:f}))}i>0&&(a=Vr(a,da(e,t,l,i)))}return r||o<=i*i?{t:0,n:q(t,-1)}:a}function Id(s,e,t,i){if(s.vertices)return zd(s,e,t,i);if(s.kind===3){let h=[-Math.sin(s.angle),Math.cos(s.angle)],m=At(T(e,s.p),h)-i,p=At(t,h);return m<=0?{t:0,n:q(t,-1)}:p<-1e-12?{t:-m/p,n:h}:null}let r=s.kind===1?s.p:s.spine[0],o=s.kind===1?s.p:s.spine[1],a=i+s.radius,n=T(e,pa(r,o,e));if(At(n,n)<=a*a)return{t:0,n:q(t,-1)};if(a>0)return Vn(e,t,r,o,a);let l=T(o,r),c=t[0]*l[1]-t[1]*l[0];if(Math.abs(c)<1e-12){let h=T(e,r);if(Math.abs(h[0]*l[1]-h[1]*l[0])/Math.max(Math.hypot(...l),1e-20)>1e-6)return null;let p=Math.min(At(T(r,e),t),At(T(o,e),t));return Math.max(At(T(r,e),t),At(T(o,e),t))<0?null:{t:Math.max(0,p),n:q(t,-1)}}let u=T(r,e),f=(u[0]*l[1]-u[1]*l[0])/c,d=(u[0]*t[1]-u[1]*t[0])/c;return f>=0&&d>=0&&d<=1?{t:f,n:q(Tt([l[1],-l[0]]),c>0?-1:1)}:null}function bu(s,e,t,i,{maxDistance:r=1e30,ignore:o=[],collidesWith:a=4294967295,includeTriggers:n=!0}={}){let l=s.dimension,c=me(e,l,"origin"),u=me(i,l,"direction"),f=Math.hypot(...u);if(!f||!Number.isFinite(t)||t<0||!Number.isFinite(r)||r<0)throw Error("Provide a nonzero direction, finite nonnegative radius and distance");if(!Number.isInteger(a)||a<0||a>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");let d=new Set(o);for(let p of d)s.liveIndex(p);let h=u.map(p=>p/f),m=null;for(let p=0;p<s.bodyCount;p++){if(d.has(p))continue;let g=l===3?s.solver.bodies[p]:null,b=g?g.group??4294967295:s.solver.filters.get(p)?.[0]??4294967295,y=g?g.isTrigger:s.solver.sensors.has(p);if(!(b&a)||!n&&y)continue;let A;if(l===2)A=Id(ua(s.solver,p),c,h,t);else{let x=qr(g);if(x.spine){let w=x.radius+t,B=T(c,pa(...x.spine,c));A=F(B,B)<=w*w?{t:0,n:q(h,-1)}:Vn(c,h,...x.spine,w)}else A=Md(x,c,h,t)}if(!A||A.t>r||m&&A.t>=m.distance)continue;let v=de(c,q(h,A.t));m={index:p,distance:A.t,normal:A.n,center:v,point:T(v,q(A.n,t))}}return m}var ha=class{constructor(e,{speedThreshold:t=.08,timeThreshold:i=.6}={}){if(!Number.isFinite(t)||t<=0||!Number.isFinite(i)||i<=0)throw Error("Sleep thresholds must be positive and finite");this.world=e,this.speedThreshold=t,this.timeThreshold=i,this.time=new Float64Array(e.bodyCount),this.asleep=new Set}wake(){let e=this.world;for(let t of this.asleep)e.dimension===3?e.solver.bodies[t].sleeping=!1:e.solver.dynamic[t]=+(e.solver.shape[t*4+2]>0);this.asleep.clear(),this.time.fill(0)}after(){let e=this.world,t=e.solver,i=e.bodyCount,r=Int32Array.from({length:i},(d,h)=>h),o=new Set,a=[],n=d=>e.dimension===3?t.bodies[d].mass:t.shape[d*4+2],l=d=>{for(;r[d]!==d;)r[d]=r[r[d]],d=r[d];return d},c=(d,h)=>{if(d<0){o.add(h);return}n(d)<=0?o.add(h):n(h)<=0?o.add(d):r[l(d)]=l(h),a.push([d,h])};if(e.dimension===3){let d=new Map(t.bodies.map((h,m)=>[h,m]));for(let h of t.forces)!h.broken&&!h.bodyA?.isTrigger&&!h.bodyB?.isTrigger&&c(h.bodyA?d.get(h.bodyA):-1,d.get(h.bodyB))}else{for(let d of t.contactPairs)!t.sensors.has(d.a)&&!t.sensors.has(d.b)&&c(d.a,d.b);for(let d=0;d<t.jointCount;d++)(t.data[d*32+6]||t.data[d*32+7]||t.data[d*32+8])&&c(t.info[d*4+1],t.info[d*4+2])}let u=new Set([...o].map(l)),f=new Map;for(let d=0;d<i;d++)if(n(d)>0){let h=l(d),m=e.dimension===3?t.bodies[d]:null,p=m?m.allowSleep!==!1:t.avbdSleepEligible?.get(d)!==!1,g=m?Math.hypot(...m.velocityLin,...m.velocityAng):Math.hypot(...t.velocity.subarray(d*4,d*4+3));f.has(h)||f.set(h,u.has(h)),f.set(h,f.get(h)&&p&&g<=this.speedThreshold)}for(let d=0;d<i;d++)n(d)>0&&(this.time[d]=f.get(l(d))?this.time[d]+e.params.dt:0,this.time[d]>=this.timeThreshold&&(this.asleep.add(d),e.dimension===3?(t.bodies[d].sleeping=!0,t.bodies[d].velocityLin.fill(0),t.bodies[d].velocityAng.fill(0)):(t.dynamic[d]=0,t.velocity.fill(0,d*4,d*4+4))));a.some(([d,h])=>d>=0&&n(d)>0&&n(h)>0&&this.asleep.has(d)!==this.asleep.has(h))&&this.wake()}};var ma=class{constructor(e,t,i={}){if(this.backend="cpu",this.dimension=t,this.scene=e,this.stepCount=0,this.pending=new ti,this.events=[],this.previous=new Map,this.watched=null,t===3){this.solver=Object.assign(new ca,e.ref),this.solver.up=[...e.up??[0,0,1]],this.nativeRef=e.ref,this.constraints=this.solver.forces.slice();for(let r of this.solver.bodies)r.solver=this.solver;for(let r of this.constraints)r.solver=this.solver;this.constraints.forEach((r,o)=>{let a=e.handles?.get(r);a&&(a.slot=o)}),aa(this.solver)}else this.solver=new fa(e.topology,e,i.order==="colored"?"soa-colored":"soa-seq"),this.topology=this.solver,this.builder=Object.assign(Object.create(Object.getPrototypeOf(e)),{topology:this.solver,filters:this.solver.filters,sensors:this.solver.sensors,restitution:this.solver.restitution});this.params=t===3?this.solver:this.solver.params,Nr(this,t===3?{bodies:this.solver.bodies}:null,t,{setVelocities:this.setPackedVelocities,readSelectedBodies:this.readSelectedBodies}),(i.sleeping||e.sleepOptIn||[...e.topology?.avbdSleepEligible?.values()??[]].some(Boolean))&&this.enableSleeping(i.sleeping===!0?{}:i.sleeping)}get bodyCount(){return this.dimension===3?this.solver.bodies.length:this.solver.bodyCount}get jointCount(){return this.dimension===3?this.constraints.length:this.solver.jointCount}gpuIndex(e){return this.liveIndex(e),e}liveIndex(e){if(this.assertLive(),!Number.isInteger(e)||e<0||e>=this.bodyCount)throw Error("A live body index is required")}assertLive(){if(this.destroyed)throw Error("The solver has been destroyed")}prepareBodyCommands(){return this.wakeAll(),{enqueueValidated:e=>{this.pending.reserve(this.pending.count+e.count),this.pending.u32.set(e.u32.subarray(0,e.count*12),this.pending.count*12),this.pending.count+=e.count}}}setLinearVelocity(e,t){return this.editBodies([{body:e,linearVelocity:t}])}setAngularVelocity(e,t){return this.editBodies([{body:e,angularVelocity:t}])}applyImpulse(e,t,i){return this.editBodies([{body:e,impulse:t,worldPoint:i}])}applyForce(e,t,i){return this.editBodies([{body:e,force:t,worldPoint:i}])}applyAngularImpulse(e,t){return this.editBodies([{body:e,angularImpulse:t}])}applyTorque(e,t){return this.editBodies([{body:e,torque:t}])}teleport(e,t,i){return this.editBodies([{body:e,position:t,rotation:i}])}setPackedVelocities(e,t){let i=Array.from(e),r=t?.linear,o=t?.angular,a=this.dimension,n=a===3?3:1;if(r===void 0&&o===void 0)throw Error("Provide linear or angular velocities");let l=-1;i.forEach(d=>{if(this.liveIndex(d),d<=l)throw Error("Velocity batch indices must be unique and ascending GPU slots");l=d});for(let[d,h]of[[r,a],[o,n]])if(d!==void 0&&(d.length!==i.length*h||!Array.from(d).every(m=>Number.isFinite(Math.fround(m)))))throw Error("Provide finite packed velocity components per body");let c=r===void 0?null:Array.from(r),u=o===void 0?null:Array.from(o),f=i.map((d,h)=>({body:d,...c===null?{}:{linearVelocity:c.slice(h*a,(h+1)*a)},...u===null?{}:{angularVelocity:a===3?u.slice(h*n,(h+1)*n):u[h]}}));return this.editBodies(f),this.flushEdits(),this}flushEdits(){if(this.destroyed)throw Error("The solver has been destroyed");let{words:e,u32:t,count:i}=this.pending,r=this.solver,o=this.dimension;for(let a=0;a<i;a++){let n=a*12,l=t[n],c=t[n+1],u=t[n+2]!==0,f=o===3?r.bodies[l]:null,d=f?.velocityLin??r.velocity.subarray(l*4,l*4+2),h=f?.mass??r.shape[l*4+2],m=f?.positionLin??r.pose.subarray(l*4,l*4+2),p=g=>{if(!(h<=0))if(o===2)r.velocity[l*4+2]+=g[0]/Math.max(1e-10,r.shape[l*4+3]);else{let b=f.positionAng,y=Ee([-b[0],-b[1],-b[2],b[3]],g),A=Ee(b,y.map((v,x)=>v/Math.max(1e-10,f.moment[x])));for(let v=0;v<3;v++)f.velocityAng[v]+=A[v]}};if(c===0)d.set(e.subarray(n+4,n+4+o));else if(c===1)f?f.velocityAng.set(e.subarray(n+4,n+7)):r.velocity[l*4+2]=e[n+4];else if(c===4)if(m.set(e.subarray(n+4,n+4+o)),f){u&&f.positionAng.set(e.subarray(n+8,n+12)),f.initialLin.set(m),f.inertialLin.set(m),f.initialAng.set(f.positionAng),f.inertialAng.set(f.positionAng);for(let g of[...f.forces])g.contacts&&g.destroy()}else u&&(r.pose[l*4+2]=e[n+6]),r.initial.set(r.pose.subarray(l*4,l*4+4),l*4),r.inertial.set(r.pose.subarray(l*4,l*4+4),l*4),r.prevCount=0;else if(c===2||c===3){if(h<=0)continue;let g=Array.from(e.subarray(n+4,n+4+o),b=>b*(c===3?e[n+7]:1));for(let b=0;b<o;b++)d[b]+=g[b]/h;if(u){let b=Array.from(e.subarray(n+8,n+8+o),(y,A)=>y-m[A]);p(o===3?xt(b,g):[b[0]*g[1]-b[1]*g[0]])}}else(c===5||c===6)&&p(Array.from(e.subarray(n+4,n+4+(o===3?3:1)),g=>g*(c===6?e[n+7]:1)))}this.pending.count=0}step(){this.flushEdits(),this.solver.step(),this.sleeping?.after(),this.stepCount++,this.captureEvents()}attachToScene(e,t){return Yo.call(this,e,t)}detachFromScene(){return Qo.call(this)}setFilters(e,t,i){let r=Array.from(e),o=Array.from(t),a=Array.from(i);if(o.length!==r.length||a.length!==r.length)throw Error("Provide one group and mask per body");r.forEach(n=>this.liveIndex(n));for(let n of[...o,...a])if(!Number.isInteger(n)||n<0||n>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");r.forEach((n,l)=>{this.dimension===3?Object.assign(this.solver.bodies[n],{group:o[l],collidesWith:a[l]}):this.solver.filters.set(n,[o[l],a[l]])}),this.wakeAll()}setSensor(e,t){if(this.liveIndex(e),typeof t!="boolean")throw Error("Trigger flag must be boolean");this.dimension===3?this.solver.bodies[e].isTrigger=t:t?this.solver.sensors.add(e):this.solver.sensors.delete(e),this.wakeAll()}setRestitution(e,t){if(this.liveIndex(e),!Number.isFinite(t)||t<0||t>1)throw Error("restitution must be between 0 and 1");this.dimension===3?this.solver.bodies[e].restitution=t:this.solver.restitution.set(e,t),this.wakeAll()}setMotor(e,t){if(this.assertLive(),this.dimension===3){let i=this.constraints[e];if(!i?.cpuAngular)throw Error("A motor constraint is required");Object.assign(i.cpuAngular.options,kt({...i.cpuAngular.options,...t}))}else{let i=this.solver,r=e*O;if(!Number.isInteger(e)||e<0||e>=i.jointCount||i.info[e*4]!==3)throw Error("A motor constraint is required");let o=t.speed??i.data[r+re],a=t.maxTorque??i.data[r+Ae];if(!Number.isFinite(o)||!Number.isFinite(a)||a<0)throw Error("Provide finite motor speed and nonnegative torque");i.data[r+re]=o,i.data[r+_e]=-a,i.data[r+Ae]=a}this.wakeAll()}setAngleLimits(e,t){if(this.assertLive(),this.dimension!==2)throw Error("Use a 3D hinge constraint");if(this.solver.info[e*4]!==5)throw Error("An angular limit is required");Bs(this.solver,e,ki(t)),this.wakeAll()}releaseJoints(e){for(let t of e)this.disableConstraint(t)}disableConstraint(e){if(this.assertLive(),!Number.isInteger(e)||e<0||e>=this.jointCount)throw Error("A live constraint slot is required");if(this.dimension===3){let t=this.constraints[e];t.broken=!0,(t.cpuAngular??t).destroy()}else this.solver.disable(e),this.solver.info[e*4]=0,this.solver.noCollideDirty=!0;this.wakeAll()}setWorldAnchor(e,t,i){if(this.assertLive(),this.dimension===2){let r=this.solver;if(!Number.isInteger(e)||e<0||e>=r.jointCount||r.info[e*4+1]!==-1)throw Error("A world-anchor constraint is required");r.data.set(me([t,i],2,"point"),e*O+21)}else{let r=this.constraints[e];if(!r||r.bodyA)throw Error("A world-anchor constraint is required");r.rA.set(me(t,3,"point"))}this.wakeAll()}addBox(...e){return this.addDynamic("addBox",e)}addCircle(...e){return this.addDynamic("addCircle",e)}addCapsule(...e){return this.addDynamic("addCapsule",e)}addHull(...e){return this.addDynamic("addHull",e)}addSegment(...e){return this.addDynamic("addSegment",e)}addPlane(...e){return this.addDynamic("addPlane",e)}addDynamic(e,t){if(this.destroyed)throw Error("The solver has been destroyed");if(this.dimension!==2)throw Error("Build 3D bodies before creating the solver");this.wakeAll();let i=this.sleeping?{speedThreshold:this.sleeping.speedThreshold,timeThreshold:this.sleeping.timeThreshold}:null,r=this.builder[e](...t);return i&&this.enableSleeping(i),r}appendJoint(e,t,i,r,o,a=1/0){if(this.assertLive(),this.dimension!==2)throw Error("Build 3D constraints before creating the solver");return this.wakeAll(),this.builder.addJoint(e,t,i,r,{stiffness:o,breakForce:a}).slot}captureConstraintFrames(e){if(this.assertLive(),this.dimension!==3)throw Error("Constraint frame capture requires a 3D world");let t=Array.from(e);for(let{slot:i,spring:r}of t){let o=this.constraints[i];if(!Number.isInteger(i)||!o||o.broken||o.cpuAngular||(r?o.rest===void 0:o.stiffnessAng===void 0))throw Error("A live spring or joint slot is required")}this.flushEdits();for(let{slot:i,spring:r}of t)qn(this.constraints[i],r);t.length&&this.wakeAll()}setSpringMaterial(e,t={}){this.assertLive();let i=this.constraints[e];if(!i||i.rest===void 0)throw Error("A spring constraint is required");xr(i,It(t)),this.wakeAll()}packBodyRecords(e,t=!1){let i=this.solver,r=this.dimension,o=t?r===3?8:4:r===3?40:24,a=e?.length??this.bodyCount,n=new Float32Array(a*o);for(let l=0;l<a;l++){let c=e?.[l]??l,u=l*o;if(t){if(r===3){let f=i.bodies[c];n.set(f.positionLin,u),n[u+3]=f.friction,n.set(f.positionAng,u+4)}else n.set(i.pose.subarray(c*4,c*4+4),u),n[u+3]=i.props[c*4];continue}if(r===3){let f=i.bodies[c];n.set(f.positionLin,u),n[u+3]=f.friction,n.set(f.positionAng,u+4),n.set(f.initialLin,u+8),n[u+11]=+!!f.isTrigger,n.set(f.initialAng,u+12),n.set(f.size,u+16),n[u+19]=f.sleeping?0:f.mass,n.set(f.moment,u+20),n[u+23]=f.radius,n.set(f.inertialLin,u+24),n.set(f.inertialAng,u+28),n.set(f.velocityLin,u+32),n[u+35]=f.prevVelocityLin.reduce((d,h,m)=>d+h*i.up[m],0),n.set(f.velocityAng,u+36),n[u+39]=De(f)?1:Ue(f)?-1:Ct(f)?3:ar(f)?2:0}else n.set(i.pose.subarray(c*4,c*4+4),u),n[u+3]=i.props[c*4],n.set(i.initial.subarray(c*4,c*4+4),u+4),n.set(i.inertial.subarray(c*4,c*4+4),u+8),n.set(i.velocity.subarray(c*4,c*4+4),u+12),n.set(i.prevVelocity.subarray(c*4,c*4+4),u+16),n.set(i.shape.subarray(c*4,c*4+4),u+20)}return n}async readBodies(){return this.flushEdits(),this.packBodyRecords()}async readSelectedBodies(e,{posesOnly:t=!1}={}){let i=Array.from(e);return i.forEach(r=>this.liveIndex(r)),this.flushEdits(),this.packBodyRecords(i,t)}async readBodyState(e){this.liveIndex(e),this.flushEdits();let t=this.solver;if(this.dimension===3){let i=t.bodies[e],r=this.sleeping?.asleep.has(e)??!1;return{position:Array.from(i.positionLin),rotation:Array.from(i.positionAng),linearVelocity:Array.from(i.velocityLin),angularVelocity:Array.from(i.velocityAng),mass:i.mass,effectiveMass:r?0:i.mass,sleeping:r}}return{position:Array.from(t.pose.subarray(e*4,e*4+2)),angle:t.pose[e*4+2],linearVelocity:Array.from(t.velocity.subarray(e*4,e*4+2)),angularVelocity:t.velocity[e*4+2],mass:t.shape[e*4+2],moment:t.shape[e*4+3],sleeping:this.sleeping?.asleep.has(e)??!1}}async readJoints(){return this.flushEdits(),this.packJointRecords()}packJointRecords(){let e=this.dimension===3?32:36,t=new Float32Array(this.jointCount*e),i=r=>r===1/0?3e38:r===-1/0?-3e38:r;if(this.dimension===2){let r=this.solver.data;for(let o=0;o<this.jointCount;o++){let a=o*36,n=o*O;[se,te,Q,_e,Ae,Pt,fe].forEach((l,c)=>{for(let u=0;u<3;u++)t[a+c*4+u]=i(r[n+l+u])}),t.set([r[n+N],r[n+N+1],r[n+Y],r[n+Y+1]],a+28),t.set([r[n+re],r[n+re+1],r[n+re+2],0],a+32)}}else this.constraints.forEach((r,o)=>{let a=o*32;if(r.cpuAngular){let n=r.cpuAngular,l=n.options;t.set(n.pen,a),t[a+3]=r.broken?0:1,t.set(n.lam,a+8),t.set(n.ta,a+16),t.set(n.tb,a+20),t.set(l.axisA,a+24),t.set(l.axisB,a+28),t[a+19]=n.c0?.[0]??0,t[a+23]=n.c0?.[1]??0,t[a+27]=l.type==="motor"?l.speed:l.minAngle,t[a+31]=l.type==="motor"?l.maxTorque:l.maxAngle;return}for(let[n,l]of[["penaltyLin",0],["penaltyAng",4],["lambdaLin",8],["lambdaAng",12],["C0Lin",16],["C0Ang",20],["rA",24],["rB",28]])r[n]&&t.set(r[n],a+l);if(t[a+3]=r.broken?0:i(r.stiffnessLin??r.stiffness??0),t[a+7]=r.broken?0:i(r.stiffnessAng??0),t[a+11]=i(r.fracture??0),t[a+15]=r.torqueArm??0,t[a+27]=r.rest??0,r.cpuRest&&(t[a+19]=r.cpuRest[0],t[a+23]=r.cpuRest[1],t[a+27]=r.cpuRest[2],t[a+31]=r.cpuRest[3]),r.rest!==void 0){let n=Ui(r);t[a+11]=Number.isFinite(n?.breakStrain)?n.breakStrain:0,t[a+15]=Number.isFinite(n?.breakForce)?n.breakForce:0}});return t}async readCounters(){this.assertLive();let e=this.dimension===2?this.solver.contactCount:this.solver.forces.reduce((i,r)=>i+(r.contacts?.length??0),0),t=this.dimension===2?this.solver.contactPairs.length:this.solver.forces.filter(i=>i.contacts?.length).length;return{pairs:t,contacts:e,manifolds:t,joints:this.jointCount,overflow:0,clashes:0,colors:0,sleeping:this.sleeping?.asleep.size??0}}adapt(){}watchContacts({indices:e,maxPairs:t=this.maxPairs??8192,maxEvents:i=this.maxEvents??4096}={}){if(this.assertLive(),!Number.isInteger(i)||i<1||!Number.isInteger(t)||t<1)throw Error("Contact capacities must be positive integers");return e!==void 0?(e.forEach(r=>this.liveIndex(r)),this.watched=new Set(e)):this.watched??=new Set(Array.from({length:this.bodyCount},(r,o)=>o)),this.maxEvents=i,this.maxPairs=t,this}captureEvents(){if(!this.watched)return;let e=this.dimension===3?new Map(this.solver.bodies.map((i,r)=>[i,r])):null,t=this.dimension===2?this.solver.contactPairs:this.solver.forces.filter(i=>i.contacts?.length).map(i=>{let r=Array.from(i.bodyA.positionLin);for(let o of i.contacts){let a=Ee(i.bodyA.positionAng,o.rA);for(let n=0;n<3;n++)r[n]+=a[n]/i.contacts.length}return{a:e.get(i.bodyA),b:e.get(i.bodyB),point:r,normal:Array.from(i.basis.slice(0,3)),impulse:i.bodyA.isTrigger||i.bodyB.isTrigger?0:i.contacts.reduce((o,a)=>o+Math.abs(a.lambda[0])*this.params.dt,0)}});this.trackContactPairs(t)}trackContactPairs(e){let t=new Map,i=(a,n)=>{this.events.length<(this.maxEvents??4096)?this.events.push({...a,normal:a.normal??[...a.n,0],type:n,kind:n==="begin"?1:2,step:this.stepCount,isTrigger:a.isTrigger??(this.dimension===3?!!(this.solver.bodies[a.a].isTrigger||this.solver.bodies[a.b].isTrigger):this.solver.sensors.has(a.a)||this.solver.sensors.has(a.b))}):this.dropped=(this.dropped??0)+1},r=new Set,o=[];for(let a of e){if(!this.watched.has(a.a)&&!this.watched.has(a.b))continue;let n=`${Math.max(a.a,a.b)},${Math.min(a.a,a.b)}`;r.add(n),this.previous.has(n)&&t.size<this.maxPairs?t.set(n,a):o.push([n,a])}for(let[a,n]of o)if(!t.has(a)){if(t.size>=this.maxPairs){this.pairFull=!0;continue}t.set(a,n),this.previous.has(a)||i(n,"begin")}for(let[a,n]of this.previous)r.has(a)||i({...n,impulse:0},"end");this.previous=t}async readContactEvents(){this.watchContacts();let e={events:this.events,dropped:this.dropped??0,full:!!this.dropped||!!this.pairFull};return this.events=[],this.dropped=0,this.pairFull=!1,e}async raycast(e,t,i){return this.sphereCast(e,0,t,i)}async circleCast(e,t,i,r){return this.sphereCast(e,t,i,r)}async sphereCast(e,t,i,r){return this.flushEdits(),bu(this,e,t,i,r)}async raycastAll(e,t){return Promise.all(e.map(i=>this.raycast(i.origin,i.direction,{...t,maxDistance:i.maxDistance??t?.maxDistance})))}async sphereCastAll(e,t){return Promise.all(e.map(i=>this.sphereCast(i.origin,i.radius,i.direction,{...t,maxDistance:i.maxDistance??t?.maxDistance})))}async circleCastAll(e,t){return this.sphereCastAll(e,t)}setSleepEnabled(e,t){if(this.liveIndex(e),typeof t!="boolean")throw Error("Sleep flag must be boolean");return this.dimension===3?this.solver.bodies[e].allowSleep=t:(this.solver.avbdSleepEligible??=new Map,this.solver.avbdSleepEligible.set(e,t)),t&&!this.sleeping&&this.enableSleeping(),this.wakeAll(),this}enableSleeping(e={}){return this.assertLive(),this.disableSleeping(),this.sleeping=new ha(this,e),this}disableSleeping(){return this.sleeping?.wake(),this.sleeping=null,this}async readSleepStats(){return this.assertLive(),{sleeping:this.sleeping?.asleep.size??0,wakeRequested:!1}}wakeUp(e){return this.liveIndex(e),this.wakeAll()}wakeAll(){return this.sleeping?.wake(),this}destroy(){this.destroyed||(this.detachFromScene(),this.disableSleeping(),this.pending.count=0,this.events=[],this.previous.clear(),this.destroyed=!0)}};var yu=new WeakSet,ga=s=>s!==null&&typeof s=="object"&&yu.has(s),vu=s=>yu.add(s);async function xu({backend:s="webgpu",device:e,gl:t,validate3D:i=!0,...r}={}){if(!["webgpu","cpu"].includes(s))throw Error(`Unsupported solver backend: ${s}`);if(s!=="webgpu"&&e!==void 0)throw Error("Only WebGPU initialization accepts a GPU device");if(t!==void 0)throw Error("Solver pipelines do not accept a WebGL context");let o,a=!1,n=!1;s==="webgpu"&&(e?i&&await Ni(e):({device:e,adapter:o}=await Sr({...r,preferredLimits:{maxStorageBuffersPerShaderStage:9,maxStorageBufferBindingSize:512*1024*1024,maxBufferSize:1024*1024*1024,...r.preferredLimits},validate3D:i}),a=!0));let l=new Set,c={backend:s,device:e,adapter:o,createSolver(u,f={}){if(n)throw Error("The solver pipeline has been destroyed");if(!u||typeof u.assertEditable!="function"||!u.ref&&!u.topology)throw Error("An AVBD scene builder is required");u.assertEditable();let d;if(s==="webgpu")d=u.createSolver(e,f);else{let m=u.ref?3:u.topology?2:0;if(f.bodyBuffer!==void 0)throw Error("A GPU body buffer requires the WebGPU backend");d=new ma(u,m,f),u.gpu=d,u.created=!0}Object.defineProperty(d,"backend",{value:s,configurable:!0}),l.add(d);let h=d.destroy;return d.destroy=function(){h.call(this),l.delete(this)},d},destroy(){if(!n){for(let u of l)u.destroy();l.clear(),a&&e.destroy(),n=!0}}};return vu(c),c}var ie=(s,e,t)=>{let i=Array.from(s);if(i.length!==e||!i.every(Number.isFinite))throw Error(`${t} requires ${e} finite components`);return i},K=(s,e,t=!1)=>{if(!Number.isFinite(s)||(t?s<0:s<=0))throw Error(`${e} must be ${t?"nonnegative":"positive"} and finite`);return s},Au=s=>{if(!Number.isInteger(s)||s<0||s>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");return s};function ba(s){for(let t of["allowSleep","isTrigger"])if(s[t]!==void 0&&typeof s[t]!="boolean")throw Error(`${t} must be a boolean`);let e=s.restitution??0;if(!Number.isFinite(e)||e<0||e>1)throw Error("restitution must be between 0 and 1");if(s.mass!==void 0&&(K(s.mass,"mass",!0),s.mass>0&&s.density===0))throw Error("A positive mass needs positive density");for(let t of["velocity","angularVelocity"])s[t]!==void 0&&ie(s[t],3,t);if(s.rotation!==void 0&&!Math.hypot(...ie(s.rotation,4,"rotation")))throw Error("rotation must be nonzero");Au(s.group??4294967295),Au(s.collidesWith??4294967295)}function wu(s,e){if(e.timeStep!==void 0&&(s.dt=K(e.timeStep,"timeStep")),e.iterations!==void 0){if(K(e.iterations,"iterations"),!Number.isInteger(e.iterations))throw Error("iterations must be an integer");s.iterations=e.iterations}if(e.gravity!==void 0){if(!Number.isFinite(e.gravity))throw Error("gravity must be finite");s.gravity=e.gravity}}var ya=class{constructor(e={}){if(this.ref=new ni,wu(this.ref,e),this.up=ie(e.up??[0,1,0],3,"up"),Math.abs(Math.hypot(...this.up)-1)>1e-5)throw Error("up must be a unit vector");this.points=!1,this.handles=new Map,this.bodySet=new Set}get bodies(){return this.ref.bodies}get constraints(){return[...this.handles.values()]}assertEditable(){if(this.created)throw Error("Build this scene before createSolver; use the solver's GPU edit methods afterwards")}addBox(e,t={}){this.assertEditable(),ba(t);let i=ie(e,3,"size");i.forEach(o=>K(o,"size"));let r=new Ze(this.ref,i,K(t.density??1,"density",!0),K(t.friction??.6,"friction",!0),ie(t.position??[0,0,0],3,"position"));return this.configure(r,t)}addSphere(e,t={}){return this.assertEditable(),ba(t),this.configure(nr(this.ref,K(e,"radius"),K(t.density??1,"density",!0),K(t.friction??.6,"friction",!0),ie(t.position??[0,0,0],3,"position")),t)}addHull(e,t={}){if(this.assertEditable(),ba(t),e.length%3||!Array.from(e).every(Number.isFinite))throw Error("Hull points must contain finite xyz triples");let i=Xr(e);if(!i)throw Error("A convex hull requires finite points spanning a volume");return this.hulls=!0,this.configure(lr(this.ref,i,K(t.density??1,"density",!0),K(t.friction??.6,"friction",!0),ie(t.position??[0,0,0],3,"position")),t)}addCapsule(e,t,i={}){return this.assertEditable(),ba(i),this.configure(Cr(this.ref,e,t,K(i.density??1,"density",!0),K(i.friction??.6,"friction",!0),ie(i.position??[0,0,0],3,"position")),i)}addHeightfield(e){return this.addTerrain(Mr(e),e)}addStaticMesh(e){return this.addTerrain(zr(e),e)}addTerrain(e,t={}){this.assertEditable();let i=this.ref.bodies.length,r=vo(this.ref,e,t);r.forEach(a=>this.bodySet.add(a)),this.hulls=!0;let o=!1;return{bodies:r,triangleCount:e.triangleCount,kind:e.kind,dispose:()=>{if(!o&&(o=!0,r.forEach(a=>{a.group=0,a.collidesWith=0}),this.gpu&&!this.gpu.destroyed)){let a=r.map((n,l)=>this.gpu.gpuIndex(i+l));this.gpu.setFilters(a,a.map(()=>0),a.map(()=>0)),this.gpu.wakeAll?.()}}}}configure(e,t){if(t.allowSleep!==void 0&&typeof t.allowSleep!="boolean")throw Error("allowSleep must be a boolean");e.allowSleep=t.allowSleep??!0,this.sleepOptIn||=t.allowSleep===!0;let i=t.restitution??0;if(!Number.isFinite(i)||i<0||i>1)throw Error("restitution must be between 0 and 1");if(e.restitution=i,t.isTrigger!==void 0&&typeof t.isTrigger!="boolean")throw Error("isTrigger must be a boolean");if(e.isTrigger=t.isTrigger??!1,e.group=t.group??4294967295,e.collidesWith=t.collidesWith??4294967295,t.mass!==void 0){let r=K(t.mass,"mass",!0);if(e.mass===0&&r>0)throw Error("A positive mass needs positive density");let o=e.mass>0?r/e.mass:0;e.mass=r,e.moment.forEach((a,n)=>e.moment[n]=a*o)}if(t.rotation){let r=ie(t.rotation,4,"rotation"),o=Math.hypot(...r);if(!o)throw Error("rotation must be nonzero");e.positionAng.set(r.map(a=>a/o))}return t.velocity&&e.velocityLin.set(ie(t.velocity,3,"velocity")),t.angularVelocity&&e.velocityAng.set(ie(t.angularVelocity,3,"angularVelocity")),this.bodySet.add(e),e}addPoint(e,{mass:t=.02,radius:i=.05,friction:r=.5}={}){let o=this.addSphere(i,{position:e,mass:t,friction:r});return o.moment.fill(0),this.points=!0,o}addFabric({columns:e=16,rows:t=16,spacing:i=.2,origin:r=[0,3,0],mass:o=.02,stiffness:a=1e3,anchorStiffness:n=a,materialAt:l,breakStrain:c=1/0,breakForce:u=1/0,bendingStiffness:f=Number.isFinite(c)||Number.isFinite(u)?0:a/50,pinCorners:d=!1,pinEdges:h=!d}={}){for(let[E,k]of Object.entries({columns:e,rows:t}))if(!Number.isInteger(k)||k<2)throw Error(`${E} must be an integer >= 2`);if(K(i,"spacing"),K(o,"mass"),K(a,"stiffness"),K(n,"anchorStiffness"),l!==void 0&&typeof l!="function")throw Error("materialAt must be a function");if(K(f,"bendingStiffness",!0),typeof d!="boolean"||typeof h!="boolean")throw Error("Fabric pin options must be boolean");let m=It({breakStrain:c,breakForce:u}),p=ie(r,3,"origin"),g=(E,k)=>`${Math.min(E,k)},${Math.max(E,k)}`;function*b(){for(let E=0;E<t;E++)for(let k=0;k<e;k++){let P=E*e+k;k&&(yield[P,P-1,a]),E&&(yield[P,P-e,a]),k&&E&&(yield[P,P-e-1,a/2],yield[P-1,P-e,a/2]),k>1&&f&&(yield[P,P-2,f]),E>1&&f&&(yield[P,P-2*e,f])}}let y=new Map;if(l)for(let[E,k]of b()){let P=l((E%e+k%e)/(2*(e-1)),(Math.floor(E/e)+Math.floor(k/e))/(2*(t-1)))??{};if(typeof P!="object"||Array.isArray(P))throw Error("materialAt must return a material object");y.set(g(E,k),{scale:K(P.stiffnessScale??1,"materialAt.stiffnessScale"),material:It({...m,...P})})}let A=Array.from({length:t},(E,k)=>Array.from({length:e},(P,C)=>this.addPoint([p[0]+(C-(e-1)/2)*i,p[1],p[2]+(k-(t-1)/2)*i],{mass:h&&(C===0||k===0||C===e-1||k===t-1)||d&&(C===0||C===e-1)&&(k===0||k===t-1)?0:o,radius:i/Math.SQRT2}))),v=A.flat(),x=new Map(v.map((E,k)=>[E,k])),w=[],B=new Map,L=(E,k,P)=>{(E.mass===0||k.mass===0)&&(P*=n/a);let C=x.get(E),_=x.get(k),z=y.get(g(C,_)),R=this.addSpring(E,k,[0,0,0],[0,0,0],{stiffness:P*(z?.scale??1),...z?.material??m});return B.set(g(x.get(E),x.get(k)),w.length),w.push(R),R};for(let[E,k,P]of b())L(v[E],v[k],P);let M=[];for(let E=0;E<t;E++)for(let k=0;k<e;k++)if(k&&E){let P=(E-1)*e+k-1,C=P+1,_=E*e+k-1,z=_+1;M.push(P,_,C,C,_,z)}let I=[];for(let E=0;E<M.length;E+=3){let[k,P,C]=M.slice(E,E+3);I.push(B.get(g(k,P)),B.get(g(P,C)),B.get(g(C,k)))}return{points:v,grid:A,indices:Uint32Array.from(M),connections:w,triangleConnections:Uint32Array.from(I)}}addRope({segments:e=12,length:t=12,origin:i=[0,12,0],width:r=.15,endMass:o=20}={}){if(!Number.isInteger(e)||e<1)throw Error("segments must be a positive integer");K(t,"length"),K(r,"width"),K(o,"endMass",!0);let a=ie(i,3,"origin"),n=t/e,l=this.addBox([r,r,r],{mass:0,position:a}),c=[];for(let u=0;u<e;u++){let f=this.addBox([r,n,r],{mass:1,position:[a[0],a[1]-(u+.5)*n,a[2]]});this.addJoint(u?c[u-1]:l,f,[0,u?-n/2:0,0],[0,n/2,0]),c.push(f)}if(o){let u=this.addBox([.6,.6,.6],{mass:o,position:[a[0],a[1]-t-.3,a[2]]});this.addJoint(c.at(-1),u,[0,-n/2,0],[0,.3,0]),c.push(u)}return{anchor:l,links:c}}addRagdoll({origin:e=[0,2,0],mass:t=10}={}){let i=ie(e,3,"origin");K(t,"mass");let r=(l,c)=>this.addBox(l,{mass:t/10,position:c.map((u,f)=>u+i[f])}),o=r([.7,1.2,.35],[0,2,0]),a=this.addSphere(.25,{mass:t/10,position:[i[0],i[1]+2.9,i[2]]}),n=[o,a];this.addJoint(o,a,[0,.6,0],[0,-.3,0]);for(let l of[-1,1]){let c=r([.3,.8,.3],[l*.5,1.95,0]),u=r([.26,.7,.26],[l*.5,1.2,0]);this.addJoint(o,c,[l*.35,.35,0],[-l*.15,.4,0]),this.addJoint(c,u,[0,-.4,0],[0,.35,0]);let f=r([.28,.8,.3],[l*.2,1,0]),d=r([.26,.75,.28],[l*.2,.225,0]);this.addJoint(o,f,[l*.2,-.6,0],[0,.4,0]),this.addJoint(f,d,[0,-.4,0],[0,.375,0]),n.push(c,u,f,d)}return{torso:o,head:a,bodies:n}}addJoint(e,t,i=[0,0,0],r=[0,0,0],{linearStiffness:o=1/0,angularStiffness:a=0,breakForce:n=1/0,breakOnPull:l=!1}={}){this.assertEditable(),this.checkBodies(e,t);for(let c of[o,a,n])c!==1/0&&K(c,"joint stiffness/breakForce",!0);return this.handle(new ke(this.ref,e,t,ie(i,3,"anchorA"),ie(r,3,"anchorB"),o,a,l&&n!==1/0?-n:n))}addSpring(e,t,i=[0,0,0],r=[0,0,0],{stiffness:o=1e3,rest:a=-1,breakStrain:n=1/0,breakForce:l=1/0}={}){if(this.assertEditable(),this.checkBodies(e,t),!e)throw Error("A spring requires two bodies");K(o,"stiffness",!0),a!==-1&&K(a,"rest",!0);let c=It({breakStrain:n,breakForce:l}),u=new dt(this.ref,e,t,ie(i,3,"anchorA"),ie(r,3,"anchorB"),o,a);return xr(u,c),this.handle(u)}checkBodies(e,t){if(!t||e===t||!this.bodySet.has(t)||e&&!this.bodySet.has(e))throw Error("Constraint endpoints must be distinct bodies in this scene")}addMotor(e,t,i={}){this.assertEditable(),this.checkBodies(e,t);let r=kt({...i,type:"motor"}),o=new ke(this.ref,e,t,[0,0,0],[0,0,0],1/0,0);return Br(o,r),this.handle(o)}addHinge(e,t,i={}){this.assertEditable(),this.checkBodies(e,t);let r=kt({...i,type:"limit"}),o=K(i.span??1,"span"),a=ie(i.anchorA??[0,0,0],3,"anchorA"),n=ie(i.anchorB??[0,0,0],3,"anchorB"),l=[-1,1].map(f=>this.addJoint(e,t,a.map((d,h)=>d+f*o*.5*r.axisA[h]),n.map((d,h)=>d+f*o*.5*r.axisB[h]))),c,u;if(i.minAngle!==void 0||i.maxAngle!==void 0){let f=new ke(this.ref,e,t,[0,0,0],[0,0,0],1/0,0);Br(f,r),c=this.handle(f)}return i.motor&&(u=this.addMotor(e,t,{axisA:r.axisA,axisB:r.axisB,...i.motor})),{joints:l,limit:c,motor:u,dispose(){for(let f of[...l,c,u])f?.dispose()}}}handle(e){let t={slot:-1,disposed:!1,dispose:()=>{t.disposed||(this.gpu?this.gpu.destroyed||this.gpu.releaseJoints([t.slot]):e.destroy(),this.handles.delete(e),t.disposed=!0)}};return t.destroy=t.dispose,this.handles.set(e,t),t}createSolver(e,t={}){if(ga(e))return e.createSolver(this,t);if(this.assertEditable(),this.hulls&&e.limits.maxStorageBuffersPerShaderStage<9)throw Error("Hull collisions require nine storage buffer bindings");let i=new Zo(e,this.ref,go(this.ref,{...t,...this.points?{shaders:{...t.shaders,solve:Qc}}:{}})),r=[];this.ref.forces.forEach((l,c)=>{this.handles.get(l).slot=c,l instanceof ke&&l.stiffnessAng>0&&r.push({slot:c})}),i.captureConstraintFrames(r),i.params.up=[...this.up];let o=[],a=[],n=[];for(let[l,c]of this.ref.bodies.entries())(c.group!==4294967295||c.collidesWith!==4294967295)&&(o.push(i.gpuIndex(l)),a.push(c.group),n.push(c.collidesWith)),c.isTrigger&&i.setSensor(i.gpuIndex(l),!0),c.restitution>0&&i.setRestitution(i.gpuIndex(l),c.restitution);return o.length&&i.setFilters(o,a,n),(t.sleeping||this.sleepOptIn)&&i.enableSleeping(this.ref,t.sleeping===!0?{}:t.sleeping),this.gpu=i,this.created=!0,i}},va=class{constructor(e={}){if(this.topology=new Dr,Object.assign(this.topology.params,ko()),wu(this.topology.params,e),e.alpha!==void 0){if(!Number.isFinite(e.alpha)||e.alpha<0||e.alpha>1)throw Error("alpha must be between zero and one");this.topology.params.alpha=e.alpha}for(let t of["postStabilize","matchNearest"])if(e[t]!==void 0){if(typeof e[t]!="boolean")throw Error(`${t} must be boolean`);this.topology.params[t]=e[t]}}assertEditable(){if(this.created)throw Error("Build this scene before createSolver; use GPU edit methods afterwards")}get bodyCount(){return this.topology.bodyCount}addShape(e,t={}){let i=e.options??t,r=this.addBox(e.size,i);return Fr(this.topology,r,e,i.density??1),r}addCircle(e,t={}){return this.addShape(qo(e),t)}addHull(e,t={}){return this.addShape(No(e),t)}addCapsule(e,t,i={}){return this.addShape(Vo(e,t),i)}addSegment(e,t,i={}){return this.addShape(Wo(e,t,i))}addPlane(e=[0,1],t=0,i={}){return this.addShape(Ho(e,t,i))}addBox(e,{density:t=1,friction:i=.6,position:r=[0,0],angle:o=0,velocity:a=[0,0,0],restitution:n=0,isTrigger:l=!1,group:c=4294967295,collidesWith:u=4294967295,allowSleep:f}={}){if(this.assertEditable(),f!==void 0&&typeof f!="boolean")throw Error("allowSleep must be boolean");let d=ie(e,2,"size");d.forEach(p=>K(p,"size"));let h=ie(r,2,"position");if(!Number.isFinite(o))throw Error("angle must be finite");if(!Number.isFinite(n)||n<0||n>1)throw Error("restitution must be between 0 and 1");if(typeof l!="boolean")throw Error("isTrigger must be boolean");for(let p of[c,u])if(!Number.isInteger(p)||p<0||p>4294967295)throw Error("Collision masks must be unsigned 32-bit integers");let m=this.topology.addBody(d,K(t,"density",!0),K(i,"friction",!0),[...h,o],ie(a,3,"velocity"));return this.restitution??=new Map,n>0&&this.restitution.set(m,n),this.sensors??=new Set,l&&this.sensors.add(m),this.filters??=new Map,(c!==4294967295||u!==4294967295)&&this.filters.set(m,[c,u]),this.topology.avbdSleepEligible??=new Map,f!==void 0&&this.topology.avbdSleepEligible.set(m,f),m}checkBodies(e,t){if(!Number.isInteger(e)||!Number.isInteger(t)||e<-1||e>=this.bodyCount||t<0||t>=this.bodyCount||e===t)throw Error("Invalid 2D constraint endpoints")}addJoint(e,t,i=[0,0],r=[0,0],{stiffness:o=[1/0,1/0,0],breakForce:a=1/0}={}){if(this.assertEditable(),this.checkBodies(e,t),!o||o.length!==3||Array.from(o).some(l=>l!==1/0&&(!Number.isFinite(l)||l<0))||a!==1/0&&(!Number.isFinite(a)||a<0))throw Error("Joint stiffness and break force must be nonnegative or Infinity");let n=this.topology.addJoint(e,t,ie(i,2,"anchorA"),ie(r,2,"anchorB"),o,a);return this.constraintHandle(n.slot,n)}constraintHandle(e,t={}){return Object.assign(t,{slot:e,alive:!0,disposed:!1}),t.dispose=()=>{t.disposed||(this.gpu&&!this.gpu.destroyed?this.gpu.disableConstraint(e):this.gpu||this.topology.data.fill(0,e*O+Q,e*O+Q+3),t.alive=!1,t.disposed=!0)},t.destroy=t.dispose,this.topology.handles[e]=t,t}addSpring(e,t,i=[0,0],r=[0,0],{stiffness:o=1e3,rest:a=1}={}){if(this.assertEditable(),this.checkBodies(e,t),e<0)throw Error("A spring requires two bodies");let n=this.topology.jointCount;return this.topology.addSpring(e,t,ie(i,2,"anchorA"),ie(r,2,"anchorB"),K(o,"stiffness",!0),K(a,"rest",!0)),this.constraintHandle(n)}addMotor(e,t,{speed:i=1,maxTorque:r=100}={}){if(this.assertEditable(),this.checkBodies(e,t),!Number.isFinite(i))throw Error("speed must be finite");let o=this.topology.jointCount;return this.topology.addMotor(e,t,i,K(r,"maxTorque",!0)),this.constraintHandle(o)}addAngularLimit(e,t,i={}){this.assertEditable(),this.checkBodies(e,t);let r=ki(i),o=this.topology.addJoint(e,t,[0,0],[0,0],[0,0,0]);Bs(this.topology,o.slot,r);let a=this.constraintHandle(o.slot,o);return a.setLimits=n=>{if(a.disposed)throw Error("The angular limit has been disposed");return this.gpu?this.gpu.setAngleLimits(a.slot,n):Bs(this.topology,a.slot,ki(n)),a},a}addHinge(e,t,i=[0,0],r=[0,0],o={}){this.assertEditable(),this.checkBodies(e,t);let a=ie(i,2,"anchorA"),n=ie(r,2,"anchorB"),l=o.minAngle!==void 0||o.maxAngle!==void 0?ki(o):null,c=o.motor;if(c){if(!Number.isFinite(c.speed??1))throw Error("speed must be finite");K(c.maxTorque??100,"maxTorque",!0)}let u=this.addJoint(e,t,a,n),f=l?this.addAngularLimit(e,t,l):null,d=c?this.addMotor(e,t,c):null;return{joint:u,limits:f,motor:d,disposed:!1,dispose(){this.disposed||(this.joint.dispose(),this.limits?.dispose(),this.motor?.dispose(),this.disposed=!0)},destroy(){this.dispose()}}}createSolver(e,t={}){if(ga(e))return e.createSolver(this,t);this.assertEditable();let i=new Ko(e,this.topology,t);for(let[r,o]of this.restitution??[])i.setRestitution(r,o);for(let r of this.sensors??[])i.setSensor(r,!0);for(let[r,o]of this.filters??[])i.setFilters([r],[o[0]],[o[1]]);return this.gpu=i,this.created=!0,i}};var Wr=class{constructor(e){if(this.device=e,this.latestMs=null,this.samples=0,this.slots=[],!!e.features.has("timestamp-query"))for(let t=0;t<3;t++)this.slots.push({query:e.createQuerySet({type:"timestamp",count:2}),resolve:e.createBuffer({size:256,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),read:e.createBuffer({size:16,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),busy:!1})}begin(){let e=this.slots.find(t=>!t.busy);return!e||this.disposed?null:(e.busy=!0,e)}descriptor(e){return e?{timestampWrites:{querySet:e.query,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1}}:{}}encode(e,t){t&&(e.resolveQuerySet(t.query,0,2,t.resolve,0),e.copyBufferToBuffer(t.resolve,0,t.read,0,16))}resolve(e){if(e)return e.pending=e.read.mapAsync(GPUMapMode.READ).then(()=>{let t=new BigUint64Array(e.read.getMappedRange());this.latestMs=Number(t[1]-t[0])/1e6,this.samples++,e.read.unmap()}).catch(()=>{}).finally(()=>{e.busy=!1,e.pending=null}),e.pending}settled(){return Promise.all(this.slots.map(e=>e.pending))}destroy(){this.disposed=!0;for(let e of this.slots)e.query.destroy(),e.resolve.destroy(),e.read.destroy()}};var Bu=(s,e)=>Math.ceil(s/e)*e,Cu=s=>String(s>>>0),Hr=class{constructor(e,t={}){this.device=e,this.maxFreeBytes=t.maxFreeBytes??201326592,this.freeBytes=0,this.free=new Map,this.all=new Set}acquire(e,t,i="recycled-buffer"){let r=Bu(Math.max(4,e),4),o=Cu(t),a=this.free.get(o);if(a){let l=-1,c=1/0;for(let u=0;u<a.length;u+=1){let f=a[u];f.size>=r&&f.size<c&&(l=u,c=f.size)}if(l>=0){let[u]=a.splice(l,1);return this.freeBytes-=u.size,u.buffer}}let n=this.device.createBuffer({label:i,size:r,usage:t,mappedAtCreation:!1});return this.all.add(n),n}release(e,t,i){if(!e)return;let r=Bu(Math.max(4,t),4);if(this.freeBytes+r>this.maxFreeBytes){e.destroy(),this.all.delete(e);return}let o=Cu(i),a=this.free.get(o);a||(a=[],this.free.set(o,a)),a.push({buffer:e,size:r,usage:i}),this.freeBytes+=r}trim(e=this.maxFreeBytes){this.maxFreeBytes=e;for(let[t,i]of this.free.entries()){for(;this.freeBytes>this.maxFreeBytes&&i.length>0;){let r=i.pop();r.buffer.destroy(),this.all.delete(r.buffer),this.freeBytes-=r.size}i.length===0&&this.free.delete(t)}}destroy(){for(let e of this.all)e.destroy();this.free.clear(),this.all.clear(),this.freeBytes=0}};var Su=`const EPS : f32 = 1.0e-7;
5188
5231
 
5189
5232
  struct Bullet {
5190
5233
  posLife: vec4<f32>,