From 2761ef75c4c2bd1105270d9fcaf2c4ebffe586f7 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Wed, 28 Apr 2021 11:16:05 -0500 Subject: [PATCH] sand and water simulation! --- site/sand_toy.wasm | Bin 33417 -> 38334 bytes src/sand_toy.onyx | 56 +++++++++++-- src/simulation.onyx | 191 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 237 insertions(+), 10 deletions(-) diff --git a/site/sand_toy.wasm b/site/sand_toy.wasm index 1a9832b22846f2c382d38df1cf028e066532250e..ceff70b1508a06ed28cf83586b0063bc680739bd 100644 GIT binary patch literal 38334 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� z`&zm-Q5x*Xh+~k*=2ZBpyzIsoEO3JNo-g3cFYJ>keTWDLq!}Wn0QY%i8qpD^_eKP5 zNyk)U73hJ+Fj2*16sTb;^{2zjVe$FH=Xu!F{ouMEp4I&@>dF@F$QFjWfGl3r9*DhJ z#;Kj>uts>_vdFN@0!4)sCrp^fA4Fk)Co)OIDNX-zLgPWVSNaJt%CiqMz;nAF&hLKM zOnPV{Hm?B4*lJeOel2p+41Mx_m2RH*}nF~kT zZTWkYvN7UeNJi4X2)o~B2VjJ0rgPA0Qfe?Qs@%sF5WyXFb%y%MzHIXu5K!?@G* z2O(2zU?0Z1+eZXs=lSxGn2_S-<)P>;FL`;0MJ&Lg=Z8^`C`u2g0cFcAU^cf8y%u2; zOf92;WNhQcjf#oF_floc(=7Q&KBbbjJmXG37%}Wl6)@%9qqlT@eCzlc4tg4X=Is$& z(>2g%-X4yr=ZCn9rKBUhx%Wu<0;coy6tkh(?#9gBA#p!UEkzOhmWbzg1tre|wa;f# ztu>P3Ere;BixQ_~Ovz>?mngYH3BwT2CAnV7jY@u2$qprZl+5?2K0a`#6HMsC&rWKb z+&HB%(m1uTv2j{slW8WKM3k{R&0jWZVaD!M?}8ZdnWu;{V|TJ>GIl448e=ysI*b*@ zh7P7MHt9ELNSnCei~5VHCR#Ad;LFL&tR4Yl>goZ-+BH=vxd(r$;2xk5-- zOp**fmQCx&lvWEQ)C#n3xT(4rN6Cah7b|@LPUT5MjP=2ur-yr9O|H z?}iu0hkKsB*nW}_`AW~z@Ao`$3?m=jm(hCrPRQ(ew26o~I{x8jC(2 zW`FzlpL(+In(VJ)efvw^3&XgbP%-!s$DeJxp$?lj8=MhLFNb!1*Y-=h(qLZ@MNud( zN&281(Of?o;-<>}x}0rdDKXnYoAYY^K(DrtOGm`lQB|{J&aUL^VIlOoN#Na;6HWp- zNNuK!gPv8CAz&KiQ6dWDE`Y$%E$k#oUcB1IMa|zmj@icEM|=%F?eG;oEDu!`N}Edm zwLf-IfkT^bUL^jxRZ0A>Q0#wbBz`wA`oW5<-r4i??w+T6+D{_6gFR38^*p_={iHTO z(0&p*ez521!|f-P{AHem%1@(OJ=IO|^78N_?fM$iM=d5M`I6#mkjI;mq3QGB@%in! z_U)Atd>m!bqJAyH7tKwqnZzU~^Gi^HBqs!Iv&^$3XP+2-^a`;MM6k^!H@O(GJ7X`D znx-;pwCJ|tSxQbIoSmQ`d}k{A!4KkFh#JK>*Exyyc_Tkm!cWd~C8_IQDivOAuNV73 z6vmPJ&;zQ<3a4uswj-%N{GrG2q4e!x_Ps$U_j`l9@-&N15ZKNVf}K(%(uBV^bZ!uU zCuQ0pm20x!t!Ag^oPgX?_T7K{#NY0}CVOW!8}->787i8X&JL99bhS08?tze(e3qrF zkn-)>lta6-aOghYwhVY$WTQ}0S$E>pDT3HIwy)Xsk`k(}_bN>5jL5=t{RPcPPuhau zJz%wLV4y3<9oiA9k5$fBpkYwRN;yboSgQhoa{bteWy;&(rGM|?M5q=yK9(AfHc?NV zzB(;WXX!pn$kD!WVvD`1Z&TT+PcZMI)KTAoERlQw_N~xk830u5fz5sTHB7(s;V>Ob zo+GPJ2VAlP2M!1GkJ#nV{SI+}!!tNIv^C(zpJR`*;H4;}2clPMOHe*uhzpGCFo-Dh zS4-h(UJw3At_KIE2lM3wq_b(Tfjx3l4r;`j3U_^Esx)V$0*~ z7@WN>I3c=yVTZKaZ%E8*6(V1>uY`1G7cVQ+H&kcFVTtIAYD`z2M=e{KQU?kuVA9(FO?n%^X;tpv0;T~_m_Ca7_VH49vgjnvo(Rmu7f<}c z8mfe+fx|NBj2gI;Hi|)YHICh@U35!}g-!7Ls{fYrDD<`TV||WfMDdh0cZyg<&7Ca7 z)*NoSlnX~VM!2B+ZsGzC9T#vo#swU1<^m2c;Q|h?-~tY{4FL|faY-%@ujc{|Z_MC% z5c{ehAt?YGXoEQD?>-+ka5}>V++Yg_G?A-Q4nK6t2e8#i{*4myp9rQokXwU!yP8}Z zBtRjmCIJG`EeWF+-I6eJ(Jcw17TuCC;`23L==MhjZJof#H;QNdPH6n7CpmCs`W)C+ zn4X?}vjKP%nBb_X8-)JaM0r}f8oRTpmo0VLm+~&jrDD6oX+OVpgaAtfY#k6osAlFr)gad zI*eHQ5Hq9~F~f7Yu#o9a3z-hJkm*eenf|npU(SVvOvhTtH*!fY4|i~3A@2dF-_9+3 zprb>%lt}2T8yvdnhN%E&OpS~6lhE+_Y8I~l^q>nE0?>g>L09Dhbc{gI(Y>Gpse;aN z0Xl&Ubep*V-6dRr4)h8-MkMG2GSD#~L3bl_XI8bJ%llI)$sGnTH3 zI!dT}w^8z!5gXR&-t3V|wk}=2k+qgGMo_jPdt!rBqDQs(X0mu@<$ksqI6-d+ zOnI<4 z^Bf^!=kj$Yt3iSxw7XV=uqH`|Qu+rWT62E?hR<@G7`s{DNx9JlUbl~kLl?(D@jCKr zeo{fTJ6T1Z(Cu19P{%M*Uu0iUZ-g2fr1g@_WzWfZlm9?lgX5T9C141&Y`%mO@mBzF z)8Wf`>WzfgD?p8Y<*&d3z&{aX@l+P=YhbBi*sZaV%38pA&Oz<&{ZH%_Y#FTzDY}YT zNIwy#kA~^T!sMR5XqXLW6dLa;hDeOuZ_|zElx=DkWyl3ZJVi7vqf!I3Pt427ye_~M zQtW>AoSay3hGNCzunt$)L7F39oEvDXwEM`#N@Y_=FyI`r$>1D{oPl%b2?a+_a1NT4 zf}>0n9A%>5C=(@7n^Pz_`4J!$K}l2*i#x$$R*_QsGmQ}-i&}_rDu=j+q997LgO%)* z^j%T*W!tru36~unwkg)_myNd^9;RBV$eP}qv&^Z4?D0a2#;cF`Du?d(T;tGv4d2)! zv`Qo78>1rsB(wmRH54((nVFE?iz7b|B1OTg5$V4T8>jR>@(KG5{3pWW6nFA{2On@J zxe>b|R+G7mDBaOFf*^Ou@;wKy7NV}X)3iBRa~ri0S#zhZd4i(*3k4R>Y0e^6smx?J z2h^jr&boY_g=_(7PFqHfH+0C+Y-*DF#*N7zgq%Dr?*{?>=>nh1w-0`S5+cGqO8C=C6;3vupd3g>bY#1> z(3lVdjXecoLIt*l!bd{q>083&@hBXW%I4Q1usjJ75t7SVI1-%vwd3__1fcolqcA#7 zgE!9t|E)RuNQST~*+6H-YVSWU7|`ec2{<}0V3*nUkac8cK$ZrFWOQg|9H0@Pw?*C z*Js<92!LuIU0D^XuJGr<<)V(OFp_f*3bLVbD+iq5Qj7jp+7yC=_AG$We@2Qg*ksj3 zWc_1dOS5rGLF-brq%VPQ<@+yCp%Lieg%rwyQ5J!!k1V!|+q83AZQt@%l@2MOfl1NF zLdIrcF=y2F>qUylV;H za?tsVeA>Kcwmi*e`qd+!FEtmZvh&-*Cs`dYe3CfIa}Ou6fw@0Y&1%~wZ{0goi()W* zX1mJ^S}_-BXE3?{6|EwI^v=o$kW6b1|P|&@wgmGmn0^B%YsU{EpZZ zS;*0pRTWK@J1F(dAr7Fq_A+4FWy_KyTB7!dR7UP}8L{?kR|c_cyC`|L`T!fXw1cCu z@AnKoGAYc!C7gVM_~b9wDEz^s7c&v_l`2e{JWNkBX5L{h(VSw$#YgxWkOe04UQ%VX z8nTki0y>j$<>(Fw_wn$dE$(gp<}IVqmIL2--#04z`SU?rbgF}oz?taur_NoBBn6c^ z*Mk(otBnZYlAp{GROcI1jS$JH558sm0Wt;xNA(Mj3evyB!lYt*w#59$)nyy?>HUSXP%xW4cquKNkXW@&liwuVqeHfk zg$8T&K#NKqK!Dju}WMABXCj=EG{aaXIF^6JVojJVJFF+}0_H{7Wg2S@~3v;V^ zMc9&1&m{h{J}hkPSw$(>pQDuH-Xw$xqJkK%?pd0)JBh9*2Z7%m5>%_e2v;h3N09%^ z7J3|;(E{MlUr?QIY8F9YM`?&5vumnjTlQxbZL{?%)!ugWiUzCp5%~-!3~Qc0DQH_d zCf-bi0tJK(#3=i0P0*;<01ZGTK42~HNC9~Q*Mc<>nOgb=Jgx&xFomT96M0mi`Oc6Y znO?x=V9!+gr#*kn<8KF)9xA-~H;Od%W#5lWmj7TEL>%awsYk$eS7TqVb6uX}H zMG3$BPlPASwK>xok`#v?{q5V*Mx+n-H6+1kvQAW+Lb zZvLkP|6NGFmkCdux?nKnGbM4UuUx6t`jh&=;1Ejo=Ak<21w(b@^Myn8!6bXZP<gXI74b}UT?BXH*++23a5Pz60yL6~tNwUv!eyyBj|A9+il0D9)lw_ad z5+~Vz`XdMzq8s#hVX;YlOje-jy}f9PY>9{>v{`y2ntn#1BJJ$-kzRV@ z^OYc5wLwm5IGu6(q-0c%7}N^t+)UHT_VGb){~GG$0HlHI*L=u zF0vTbHr0#&A3^i!UlVNB^P-zXCE8c8h`;G&5x%q4ScFKtb1YRuIg&-32w4Id4t?zu<$j)adQ@q(9AcokH@-Xy>`#ThhpN~I!idcvscl0GHB}x|9nh9 zN=N)dJ0{SXgtn@+$J7X|+vEQm^Ial)ZDRGlM!xJP<)qNDb^f%WT4nz|B4EZHe1!rmXD3irelV#7sF36wly()p5KYf$AAOjn8$#VLB_$+TiB3uTmG6n z77phQ{}3DJ*fq@#i#2g^rMWOhb3fqa(g!oVka!aDhnN#f{2fw5wVf$CIF`+vre4si|!lbBHtAOpu$APv+z}@!p)a zV*_ULo+w<`EnnW(D_@@ImM_qlbXI)ZG8##|Z$o!5UU}q6#*}PU!nv#!2h9|MN8XKH z-jLN|lI0;;FKV`UfYQCJuPeCV zXBp>$pJf}DJ_V_nJDxBlO%W>=mPjh@dLnrG6V~ieLWYhcd6vS{^7@?!lJBhFwMqV- z&_^}pC`x~&SFiIrOpzReB%UgIW?OS>jyIbeO)8V4No8_0sW{#=sqB@&0FIcP z1leO?T_Wf}5RNbPLVJrFpk=uGMPpT%5W6`~VJ@g#AJG zg&;X6o0*y0Ik7l7yW8E`nj>A9d}Gty+?w0#=I7>S+=PEW*P`0@gJdXMSZKBu-OUq| zGtFI>!O;$cNoh}WVpot6^YQ$fCTAyFw{O3-HM!W_zA!Vnv*{-NC~lo=O{Gsa;ZO$$R*&|eUle0AR+hH=k`GN~y@WK~ebnzvZW?Qyib@eqb+4jT=&ZB zU-jx6Uh~@5{nU-G|LKXFcJ6B4ynD~&)bz~W*}3^!S__Ly`)7HQMZc4K=VzMgtGUbF-dt=1*?m#6Nk!H!@o<#%-8?a~(9{>nlG?=f#pZ2`OD!J% zz3MJ7-W;kUTmM>=^iOP`pIew*oSd5_f+tFz{W?(Ayv;4_nb_5A<+yW;bIi%!dGHuy zcg0C*v9-kA+vB9R)amb@IH^o*-#Irk*9!O&Thh3uHL+XJJVj%V#>vUox8`=YAO$~9 z>T70lb~?y@FJ}BZ=N8r;|92RQNFv|>VsgrBUUQ9m#l-H(o$k7&y*Dv3lv z)veZC%No|i&igK*lMj`W%F=cwd_9H=+=o@(SNIHG|i+JG-znKR*YF?s7Z9s|G~pm$|cc(fhkANlCc@A%f5YOZV2v*}h6lLG$skYI5q4lkZ#M^%rQ;S%rWzc**HGucXOUTl-Em*?iUl=vmz3 zx#(Gw=YoRC-Lp=2b2Ga%A7{-&kT8?k1#ZFbM{3CjqcaMaU$A+zYcBNn&rCo*i({TQ zgNqlt&1Y-$`7;;~T4$y09pv#&YI%d4E4$s)rZ4eMQwg z=R$Hi#rDlXqI)MMXUEQVKi}{8**&xU`kdo2R5dYH4DwvJ`CNCw*|e^LdBYTHkIrZ3 zt=o%sPy5+Z;8RA)CyzwXJi=_!$b>1LT-poO&dg0L(#_KBq$b`iOo;QhF1*UM`RV2D zmp4ha*-sCnp}I$M7YYijcVnQ9sGDKOTg9EJc_dmUZ+2rn?HBk`&+V$hn8&v}$K|k7 zEx$XrgL;stiu+v?(UfC;jh6C~{f5Cu2b0oYZhwn#IhbsIC=TqWO#0YzKs-t3S$E~G zXT9gh-Voo_=O*G;l~tgRU$s!-x5{sgU;Qv+0qdVyj}9dztCD?+`gO7f_#NbTh~Jc7 q!exW?{BGcPnBU^(B;62%mCz|W#Yq?{-k8=b{|Vh`D1;LGy#EgoBA{ge delta 9989 zcmai43w%`7nZM`Ey>}*alg!DJBm{D2NJzrl2mwJQho{IJEb9XeLzskwyqrvUC@=&O z5dk5`XLT)Ne-%qvQCOC0S8c1URkljCE%jAxyQ^)t741t}UHAW;JCg^syUFi&=X~FJ zedl|B=iX1jTwf)USLC4nMwQ^tBeDoQpOHcg_B$GXRNZeZq;~;x|1xq ziYK=k-e3S8)>xIHM|(4TXdA0ol5Jh(+e}Ml^>um!*cP^Bl`pv!>tqrp{b#J=Teo5s zrf%Uol6Ez3Y7MM!j&11dh$jrgY>KwUf?bJdJW=1;(a~uz^k+sBiD<*x ziq*_A{HeW{cds6Z@^{4&%bRbC>2)%@^Z}N4bjKTFhDkF*YhtaSv~P2Dh84x=fKF?3 z`?@|f5P6!26lNe5xlOUemppnGbTmX0%^mGV029pS_U43U7LD+z@8gWY)goS+q{HSk z#ADG!Y=y_rcs#nv$N)OiL#KEi1SYs99^D{mK$j*y$D@7VL_4FUt3I|q)}H9HaPsa> z@7&%%kK>wiS>EEwt701y-SL>-FojE>nP{*YT4T|;o{=IawFY%&HFUIfHn+x76w*<$ zR%@X`2D74xs9^vlJQTr;Iy9E}?vMst6}!^g-O@^8#x{aqv`nT)?|_Aanvj_ttsQa0 z!H5veA9Qfl<10)CeDAaWWL7B4hT^e8n->bx2#J7c8iAnAY}+<7gC;kELEA12+Ga2S zjBOaU$%8rh=nis*QN>muE5|S`VOy5POgq;$3yN&Ue4N`MpY5|lm}fJ~3RosH8OyR+ zfSE%A$zWDiiDhH;pcxGEpq0nCWdt#cXJKK}1dd~-ZCgAbU~8t&FrgsVEbXs^4P+B$6xBR+hT1U@l6;AgM%3x z&oEP4@P|xZ&av5U(?r$*LA<%0cL#sQHy+%tK7vqHeA%P99>eAw`RLjJ1fz zSqY}RXtYQ}7K)!S$y&lbmwPLiv@jk4@dlGd*yMG-I@ff4SIo{zEpeEIEtk8Ncw4Vi z)#6%`-6)N@Sk4gd0BOkp!DgMeCnl)8s;a^-9

GHB=o238sa8G?9ndy0Gb3ZiW#4TZ-X*iBc9RI{<89~IB8{#&8Twebbmi&wX zvyH7QH^5))Hxc{EunY;S#Km^>!!=vvFAZsG(DmWRk*=g(Jj$JXk4W%d6AB`Y62~DV z4k3QYoK4J1iu)O)9VR+TAS7Sd40AV+yJjtS>2$Tc3jK0dNSz9nS!f;1S8oN&f@lq` zeKhfeERlEqQAWo^Pf>YRo>QwIH<13tLjQ@(MCE1s#)0vfQ zj{3bQQ+Zj}bEqOAk7SKZAx~#7&-6Qx6r|rG{)@U-vQ>Kg>Fn$I``-99p@>GtGc9i{ zbn*l0nyfAri}|m;QQs5ZR-5^62vMsJJew^I_1?yj>do>xwofG^a|*u6!X`ukW(DX0zL{dPx}kg` zyHlMnaDAuPY<1(XieaQBUOxyBn?VBc7f4@=cv{sLj#hUS)szH`5KOz8P$;npiek?JXP0 z4yqGnBQ__I2O_V9 zBUP$B{xY>ITrqHu0TN|tnW`1;lnP?K79NS}UdDY%a|^*$^l%rGmlK=RWea;$cvKyX zp=V;ADjA)rK8yI(u2Eb2Fn6fP$Xxz!Ox+nCu09x{`rRw>`Z)vH!h&LuGJ z5k?rwBE>qmfFd<}eD&3Hm@g^6itTH;LBFDwoAeuKiNFtVxFzz^ybglni?c}YS3~_| zeoL565jv9DX0hSt1s zza8-oV?l2wIXrA*$SE!IPo^}}KJbisGb-~bvSN9;(wOhDTC2}2oX-%yV?tZu6$C93 z0d-l$aG3GRij~QfvnT5}Nu}XONq$%B<%m(P<=U>_4a_v~ryrso6u>}xp^`WCHC?ke z1^ol89^fQdfH-7o-nyoGwl;&s)l0Qa<98r?A)z9~iXjn1GRP+j8V08iYcplfy(_seHYSw_)BTmnXapUH3vu-!mYhL; zcMot8fwT(1buM>8@1+aShwPw0G9+m!6!NuJU^%e7f1vGQv9L^H)g<=f<;+koPO3p} z%91K$#>8by(70f4BpV>4h#pm-LWHTGmLQBFzynPyqmF zRE8zGywSzQ(ikvI4K459mzw zj7ayGy#qVlK(DBG!gRD3^VG8y#pAbVO#%dVuX9c?mXVZ)v*k8HqJp1+(4g!P)db4o zrm3&T!fNWAg%j=zVOUy%52P(|1P&7j^DrX=gtj;t-d6DaZL>#RcRLGZ`rw+VSNj}G z+zzP^0B^$xK6nJ77#y@ApW>9sk&!x=dEBDyC>{HRscUW?t5(e{%sM~F;l5%`!O6%G zpM)-?={=)fu`1QQo3fQ}*2v`J4BD;z@Db3Z(-ne{k&vrKQcU~n0o04cM)FoF5W-L_ zZ{8u+`o$9+ne-<1uSE;O$9~S!(L&8zl38_OI&H zk_kg;vH%lPXMm^Z1C(!R<&@VTj)4dCNgqTTo*e|e(FYwv-&=#A zclsgKvm!719a9eR)SoIR6`cD$wo{#%TjT5m3*B5dOGOG)&b;Aj%oPrLrd)Bq?ypqm zHEhkBl&44L%ruN`(|f}?n%!!`){03`E1ftwk8>S|5u!EoVVYuxj=&i3cSbaI@rq1s zB8V?c{E4Xt7f0sPIZBW`h8<8+YP$Biqca4iNBokog0QLPIw{t}xkLhWhD=i2G(rvr$^Gh)&JlUk zpk-Wt3*w=N|5>M7d;+EhU9dq5IdZtwN15wKmia9dg^o@5?l zZic?)Q2gqutVjG8Y=5D7?do$$B+@;DpnZd&{e2K=d+#9Vu0hZ}eGsjAUmrvobilJEW4!3VnxIiJHD_I-s-57F)Efsoq*Pe;BoF*EgQo z-t7+(E400>9y@;5^1ZC!!aI_O8ERQIHac|CaQWU)d0#$d8zZO*OThn$Jks=S`gvQ8 z?5UEc^7>=9KW3g6o~><2!5)YnbbUmdkjJl^D;Hx24W0-5;y=aMLuWAT)If2%tMDepC>I; zJ~=j`lxrX$p1@5l)iXZW7f4c{-(Xii_C>s6;go>EKR5@?Nj0wi>{!5AeVonqT1Qzp z~p;Rr*>lOyJ0& zi@!4Un>C}8gH#AAGf;yJ`2{)@Bo*2ADzxl0u9FDp83=3#@c4G__1rQLfLaOZJU|tS zK<%?DL>Drs-SG^_ZLSnzRG7(wxyY)vxezMJR(y@A4_j+P2lLU97WCJdlGm37Fq5wC z0xI{$(aBoW{3sd`CrPxpTz#F(ktAA_aSRUFrE5R3YRo_=qv(N$GmDbaU#0A(Ro1i+ zw{X*YiY%x_evW8k{9QjE-0xh&0)E&E8H$QFT{PwhZf9{_*PqC^uoNgZ{5aLrS=dwD z!^DG3?1!qiO~RGOfwrmqZl*?;O!k2A-B2&kcUqevL&}Y6_;yaQ!fVG=*EQY2{>Y#{ zzGiIcZd_^74h1?T7Kd^01ftGi7ROcA5B;my8FlrI!$W_t<%AI+SBh47E~iB`FO8^2 zZ|thp=K37P2OXuHV)zaiiylHcM`zrF~odH%dDhkHCH zgGU7Beflek287x(w8KA_M_iO?O%^!tiA@-<5iOPLg~ru^`;lYiPWN1pe~h=*3sUVApEbEkPE z0`>59rOCeJNQ*9=A5ng#g-N98D{x(1LBzD3ULu`yS#{~0%Ns)H)dMh1Byd)t!9WC& zS?d8ZF4xvn$7}h;w3;`-Q=TuT067{gjJyIKYHC-Hn%Q%4mi8u@t>l@YKksx+VvXut z<4mU?-=;p=UZkGtE==9RkR$?X%Z4FpX1sLR39rbd{J|&oc=fD_Bv2Qz>b2@cq3PZg zJjDSxy9ugsSLMuJ1_jVjfMHCQveD7_RpoGliVsP!2a zu}SbMc@go1=SeQ{lpQ$+DLe8V>AHqKntEcFtM=Sh3A*Q865azMXZ?jv}&o@_+stkp@7`Qt5cyGq1j*>mob2KHMV{q9V97`+7 ztv&O>gfl(M@Ky~xOtEHq&t%nldl0y#+w<6;HLrKx9AbY__uRaIxX#9@54V={kBNAx zRwQe94_Il3)!Q3}dPllUnY&B*d8Q(}KhMog5d&3_F3Phfn0jbu$?=bG4RQ6|TMJeF zO@%4NMsAlng{Roh%4+p$_fYmRZb>dzqt<8A<-3L!sq=1$s$E~po>y(_=kcF1b!z>C z1FfL9XX5bw_4N72rX~Fe6kd!{yKfJxj~Zt<{loOOnwW*Gzdh6GXRk+?wQW}B0Ev3Y z-FFm&XVB*HF`c|Z$DtbJz`QrKgEXcey_2iSw^Tx7>Tg*vMAP|zj}0a9ff@Qv>3`Vq z@7!_+Q{UV)EAx|nJ@R&aeq$m3BU5i}Z05IeHFr~7K~{V_S5GD9du&x>{Xy?EYRn$N zcW`z2o^7eF-z-XXrQpvt5gfjKepY6mEI^am?Vls2dU8xtbxKA3qe(p8+mOq&d?wra zF^aDw z)=Y&-PjJk&vFI8@PE>REUYz+$1LA9LN5}hyI=wesxq~@oBHkTCoMDdD7;WuBb1!p( z(fZDgu4esdiM$uN&OW#5ICK2b`Ud?;gnSAU+oBsg4fzanGNSePFh+mZflGLGcwYs_ zd(RK|x`7?sDUCLCbg7H>mGFaHy|S-l%t`K;O|6?6>0;0+`BMAZX!{zF>#lB2v_(7X z@fl3aZHN*fuXFXno>9raa>w6Yzo8@Eii7m{9J{-oJ|9BD>vM+8j>kLVuJ>g~b9HBkQvUhp{?-TmMXnNRK9 zJB#C9t$F`M{*0-v-#23F+a?7T`Htxfx$3Gp?!stObA!96yKQwW?rw;8v^RwfyhC!# z1{}$d=h14#r#c1|TYuZ{PP*U1ytOfR1HLNh*x+u6cDeCb7d{(WgL%g+$MzsYp0psr zw!}s-%TnhL49k1Xats5}-5DlZX~{%vje74uVevW3$z2d@Ot`DN6N!#?x1qJUVI3CR zt{&Pymp^Z-hYv*fFKo5yKmq@Qt>*SlbRO|zZK#JKA64rQRF}N$cWgIGs~YkQwcW;e z3}X1HU%h_kNPgb0&KwxY9|)*V?_9^XXQ)s1jN`{Ljz6U87(eG6-_l#gGInP>4D_AN zR_@&sn+}E?^LO<-fH;@qOnBL6=sz3J14+X;GXSQJV_bI|>3*vH98=?vZs9utDg)Dq VZFy*6D?{$cQ>*Tt7&wta{4d*Lzr_Fm diff --git a/src/sand_toy.onyx b/src/sand_toy.onyx index 6d78cfb..10deb91 100644 --- a/src/sand_toy.onyx +++ b/src/sand_toy.onyx @@ -3,11 +3,12 @@ use package core #private_file events :: package js_events #private_file gl :: package gl +particle_board: ParticleBoard; world_texture : gl.GLTexture world_texture_data : [] u8 -world_width := 256 -world_height := 256 +world_width := 512 +world_height := 512 init :: () { events.init(); @@ -26,6 +27,8 @@ init :: () { gl.bindTexture(gl.TEXTURE_2D, -1); imgui.immediate_renderer_init(); + + particle_board = create_board(world_width, world_height); } window_width := 0 @@ -45,28 +48,67 @@ poll_events :: () { case .MouseDown { if event.mouse.button == .Left { - println("Left button click!"); + mx := (cast(f32) event.mouse.pos_x / cast(f32) window_width) * ~~world_width; + my := (cast(f32) event.mouse.pos_y / cast(f32) window_height) * ~~world_height; + + radius := 10.0f; + for i: 100 { + rx := random.float(-1, 1); + ry := random.float(-1, 1); + + particle_set(^particle_board, + get_index(^particle_board, ~~(mx + rx * radius), ~~(my + ry * radius)), + .{ .Water }); + } } } } } update :: () { - world_texture_data[(100 * world_width + 50) * 3 + 0] = 255; - world_texture_data[(100 * world_width + 50) * 3 + 2] = 255; + if random.between(0, 10) > 1 { + radius := 10.0f; + for i: 100 { + rx := random.float(-1, 1); + ry := random.float(-1, 1); + + particle_set(^particle_board, + get_index(^particle_board, ~~(200 + rx * radius), ~~(100 + ry * radius)), + .{ .Sand }); + } + } + + update_particles(^particle_board); +} + +prepare_world_texture :: () { + for y: particle_board.height { + for x: particle_board.width { + index := get_index(^particle_board, x, y); + color := particle_type_to_color(particle_board.particles[index].type); + world_texture_data[index * 3 + 0] = color.r; + world_texture_data[index * 3 + 1] = color.g; + world_texture_data[index * 3 + 2] = color.b; + } + } + + gl.bindTexture(gl.TEXTURE_2D, world_texture); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, world_width, world_height, gl.RGB, gl.UNSIGNED_BYTE, world_texture_data); + gl.bindTexture(gl.TEXTURE_2D, -1); } draw :: () { + prepare_world_texture(); + gl.clearColor(0, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); use imgui { immediate_set_texture, immediate_textured_quad, immediate_flush }; gl.bindTexture(gl.TEXTURE_2D, world_texture); - gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, world_width, world_height, gl.RGB, gl.UNSIGNED_BYTE, world_texture_data); immediate_set_texture(0); - immediate_textured_quad(.{ -1, -1 }, .{ 2, 2 }, .{ 0, 0 }, .{ 1, 1 }, color=.{ 1, 1, 1 }); + immediate_textured_quad(.{ -1, 1 }, .{ 2, -2 }, .{ 0, 0 }, .{ 1, 1 }, color=.{ 1, 1, 1 }); immediate_flush(); diff --git a/src/simulation.onyx b/src/simulation.onyx index 89ddba6..d5c68fe 100644 --- a/src/simulation.onyx +++ b/src/simulation.onyx @@ -1,27 +1,212 @@ +use package core + +Color :: struct { + Empty :: Color.{ 22, 22, 22 }; + Sand :: Color.{ 226, 214, 173 }; + Water :: Color.{ 100, 100, 255 }; + + r, g, b: u8; +} Vec2 :: struct { - zero :: Vec2.{ 0, 0 }; + zero :: Vec2.{ 0, 0 }; + up :: Vec2.{ 0, -1 }; + down :: Vec2.{ 0, 1 }; + left :: Vec2.{ -1, 0 }; + right :: Vec2.{ 1, 0 }; x, y: f32; } ParticleBoard :: struct { particles: [] Particle; + particle_allocator: Allocator; + width, height: u32; + + time: u32 = 0; } Particle :: struct { Type :: enum { Empty; Sand; + Water; } type: Type = .Empty; + life: f32 = 0; velocity: Vec2 = .zero; } -init_particles :: (particles: [] Particle) { +particle_type_to_color :: (t: Particle.Type) -> Color { + switch t { + case .Sand do return .Sand; + case .Water do return .Water; + case #default do return .Empty; + } +} + +create_board :: (width: u32, height: u32, allocator := context.allocator) -> ParticleBoard { + board := ParticleBoard.{ + particles = memory.make_slice(Particle, width * height, allocator=allocator), + particle_allocator = allocator, + width = width, + height = height + }; + + init_particles(^board); + + return board; +} + +init_particles :: (use board: ^ParticleBoard) { for ^particle: particles { - *particle = .{ .Sand }; + *particle = .{ .Empty }; + } +} + +update_particles :: (use board: ^ParticleBoard) { + time += 1; + + // CLEANUP: Iterating backwards in a for loop should be easier + // This is iterating backwards because in general, particles that are lower on the screen + // should update first to beable to "fall", and then particles above them can "fall" where + // the first particle was. Obviously this is wrong for particles that "float", but it is + // less noticeable for those particles. Ideally, this would all work on a secondary buffer, + // then a buffer swap would take place between each update. + while y := cast(i32) (height - 1); y >= 0 { + defer y -= 1; + + // This for loop should alternate from L2R to R2L + x := 0; + x_step := 1; + x_ne := width; + if time % 2 == 1 { + x = width - 1; + x_step = cast(i32) -1; + x_ne = cast(i32) -1; + } + + while x != x_ne { + defer x += x_step; + + particle_type := particles[get_index(board, x, y)].type; + + switch particle_type { + case .Sand do update_sand(board, x, y); + case .Water do update_water(board, x, y); + case .Empty --- + } + } + } +} + +particle_set :: (use board: ^ParticleBoard, index: i32, particle: Particle) { + if index < 0 do return; + + particles[index] = particle; +} + +// This should get inlined by Onyx, when inlining is a thing. +get_index :: (use board: ^ParticleBoard, x: i32, y: i32) -> i32 { + if x < 0 || y < 0 || x >= width || y >= height do return -1; + return y * width + x; +} + + +#private_file +update_sand :: (use board: ^ParticleBoard, x: i32, y: i32) { + index := get_index(board, x, y); + + b_index := get_index(board, x, y + 1); + bl_index := get_index(board, x - 1, y + 1); + br_index := get_index(board, x + 1, y + 1); + + // NOTE: These do NOT short circuit so we are accessing memory that is not + // technically in our control on the second part of the condition!! This + // does not affect too many things as the accessing does not modify or damage + // the data. + if b_index > 0 && particles[b_index].type == .Empty { + particle_set(board, b_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + else { + if time % 2 == 0 { + if bl_index > 0 && particles[bl_index].type == .Empty { + particle_set(board, bl_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + elseif br_index > 0 && particles[br_index].type == .Empty { + particle_set(board, br_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + } else { + if br_index > 0 && particles[br_index].type == .Empty { + particle_set(board, br_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + elseif bl_index > 0 && particles[bl_index].type == .Empty { + particle_set(board, bl_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + } + } +} + +#private_file +update_water :: (use board: ^ParticleBoard, x: i32, y: i32) { + index := get_index(board, x, y); + + b_index := get_index(board, x, y + 1); + bl_index := get_index(board, x - 1, y + 1); + br_index := get_index(board, x + 1, y + 1); + l_index := get_index(board, x - 1, y); + r_index := get_index(board, x + 1, y); + + // NOTE: These do NOT short circuit so we are accessing memory that is not + // technically in our control on the second part of the condition!! This + // does not affect too many things as the accessing does not modify or damage + // the data. + if b_index > 0 && particles[b_index].type == .Empty { + particle_set(board, b_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + else { + if time % 2 == 1 { + if bl_index > 0 && particles[bl_index].type == .Empty { + particle_set(board, bl_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + elseif br_index > 0 && particles[br_index].type == .Empty { + particle_set(board, br_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + elseif l_index > 0 && particles[l_index].type == .Empty { + particle_set(board, l_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + elseif r_index > 0 && particles[r_index].type == .Empty { + particle_set(board, r_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + } else { + if br_index > 0 && particles[br_index].type == .Empty { + particle_set(board, br_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + elseif bl_index > 0 && particles[bl_index].type == .Empty { + particle_set(board, bl_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + elseif r_index > 0 && particles[r_index].type == .Empty { + particle_set(board, r_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + elseif l_index > 0 && particles[l_index].type == .Empty { + particle_set(board, l_index, particles[index]); + particle_set(board, index, .{ .Empty }); + } + } } } -- 2.25.1