From 7a58ba9733ca0553a824d52b8227be499dbb0dbc Mon Sep 17 00:00:00 2001 From: zomseffen <steffen@tom.bi> Date: Wed, 5 Mar 2025 16:56:48 +0100 Subject: [PATCH] optimize light selection --- shaders/compiled/frag_rt_quad.spv | Bin 46712 -> 47560 bytes src/app_data.rs | 1 + src/main.rs | 1 + src/scene/empty_volume.rs | 13 +++---- src/scene/generators.rs | 6 ++-- src/scene/light.rs | 54 +++++++++++++++++++++++++++--- 6 files changed, 62 insertions(+), 13 deletions(-) diff --git a/shaders/compiled/frag_rt_quad.spv b/shaders/compiled/frag_rt_quad.spv index 216c16163e7f1d0cc4d8c28b80cc265169eb0e96..6669b9359a3e387ab109a46747b81fec9ae0244f 100644 GIT binary patch literal 47560 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 literal 46712 zcma)_2b^71`Lz!)nFI)(&`Uz^JwT|ThTe<RVMr!qAejkCCNzOiMFa&z1VIo`x`>L1 zh=3RyBBCN7sE7>}MG*u+%Kv%pJuBIBh~MwKdf02Nx9oEE-lxpW%>whUKD4Uls}`;n zsm=iTS)!UBr9$g$mE-m~c%O}?&zP{$7Na-OzG$_8Ma#BWHN5Hodrax>?Nk3+XH|Wj z<6(|RIi`{KG>+3b7AIC;t6G5n%}@C#m334LRpa*Q8n^%c<M!FDYy8xyUDIcrHo2#3 za&KQx*M#0_J>zHe&g{`|SmD>(H-7TKgwkOM9%WmGP}9QHG0-=)d;CdV<NGJ~Pg`eT z(`}KeA=JMR<;?EM;6<vXz|*^@Or_esp57BC9p68#YvQ#2DP7aY_t1*ozKQ*Y&K%fm z+g64ljL+i6_fH;}(nEv0r_F$pYY1aVzq_Z;=$Y0vwSRiMt|ieXw(N^kD^dRc)HSiF zYk6YkRo4pW&AL`ZYu7crT5WD!t^WVNI%S_${U7y=L~qtJ3N7`l1Frk@zw4<xWIb!* zKd=6*HII7Mo>R}TYD4e|Ju{daCrp~*@b=E=?eA-!RmXk<>}^|b--Mo1QHEAd+_^Dx zr-A+(f53lOwK-Z}|FkLHle;E54Z6qo_MK2q9Ou|(*xRD#c33qAKCNfsWaeqtO#Z_x zn>lgw%#$J2R@m!l-0vbW$JT>#bW}UQ51H1giP0I-;z(6b--OmA>O|GYwW-$X1vt8E zNxeO$b9Gm%dfFR**Ga9@-nsrmYJL1^<0rG^=Cq{~JgIwn*QDMVbLw;*w@>zzfypi3 zb{mI*&E1|a<`~*)`+~JzjzuTqXTMyF=ASXGyKnl`?rA-JGg@^GVFi!FhCaTBjHk6$ zA*1UEPu$c&=KsgH7Pa$gEWRI{SDn>P=&eP{scf%G&qHUmbM$O9oFV7TE_3uL-KRQw ztx+;&NVV%6TYHq$c0<!M<7V#N(Yhy3?mwlgo*i)ea{%R>`DlCQOi4R6bK(}Q&b8aO z55Dv2&%Wp%?9b3@KlJ`-y>-s6_L4+%&h1axp4ak)s>9(EdM8dCnBL>KXO_Fi74x^V zIvBqXwqZzh2zql*I26rI&;9i<aC?7Ps5%xrue#V02Gw;We)Fp9DD-AsN28^#W5DgY zhE?Oi<0rG3cg^Up7er<a?dq($vCpfH<J<XKI|>lr;nft%?g`B0_WE|OsoU$-z|%F5 z(}n+#>ID2}_V%1oZv-d{RFlx!ZR@OhwSVB6u|Rbqdb=;3)k)y?x|(zPTDe_gwLW0G z?8{V2=Uv~xl=hz3y54kFEa~cCFI{_b<=S~*;>4b5cn@jmm?|%5xVG|o;hKAyQ(Le) z9nHMGT*bQGVyAaa<$BiIS~0bJ&ZeByJ$WKar#*@46U3EoYCCslbpbxLJfW8f+c&<4 z*v{(Wx%$-p-o6>}zXF|c@Pgah*E{1hDE=MQrzp8rZyJ70o4Xaa?AN#X=HWND`4(+H zw7MJ6J&paNYeLWT@zds9uwCo-Vr!3U+aniqZTDlF(Lc4lM7yT<p5D_nkem;G&^9x+ zM*+w8&zQj-M19KIq2~O-JZ&@S$I$8tY?FH?&KMkJABR>?&BJDe+Mc6i*>g=CR9(yV z!n|w*8uv$R+~=^{elYIkdD-f?SFs&G=dNn*z?k#RdDzm<cd<F1b8fQgAvJCRE^Z&R zIWEJh1+mrR*$i#j7yDoKR(pq4Be1u|^#jq4!?0?_dE0Gv%RUNwdwf5b!1%TQhrQiz z?pv_8$9dlIoBt1c;>TcbjrRw`TkYF%-uAlvoz-sG2hZd7`QOvH<~(inxwG0ATVpO# z*U;)f^yXY^kJHfVP;AZl)V6h2M_AY3IYYkA>KOEL{c-Qms^=v156p-9eDs^E-R?mn zl6FkT{=xIz?(-?w=5a1tb)JE39_OiLJKH*Kf1^hC{qwMuyNCP!EocL5Y~s7YGh4W$ zx=+2eWVCfu4`?g+L-Ov)1KxjW{|%g5qVD#d-%<Ux!CxH2hgN@r|F6C7Wo+eGmwVkS z*apv$xqIEeK4`1w7V90`2j&o=&XsrOX>0Fw^UeQ(`PHh>xXyXl+G~MlI&97PXP|M5 z&&x)jwh`Exb2D)(%*$5Ct%|KNZ|Aggjd|GG?Hp3Ai_P(Li)+uzA=QTZx94q3cJ6G7 z)|#uequOY+b|2fK+8DHU`{!!go6k8}#O{RFoQvIPnTx&P%*B({i@7(Tt>CB0i@A6? zyqt?SH294Tep7?L1)qBl+EKkd$j(m6155dQV80haEAPTxPs7pL_e&ksqTuqrdvSPu zkJWw%Y^|ftYRS2}w-~3k&q-&s>|njV=jg0f8mxOuL~A;#QRt`E4-xV;TfA>zGB;@Q zb>XKK_6=Knu6<MZ>4klCi^tA+hBu!%wr%AY{2a1<E3VW!s<CL(dZrId=BCcEJGhmL zw;2<-0c^E@NOfE**I;dOD_5xvtxiSj>*<*=oel5Q`jI<1ZpX&6;GE}5&&eHV-W-YV z1h>~gXLT32m+|hJ&Lj2Yp6N6VpU&#uwtiYuf3U5e-qfE#Pl`N}xvqb$e;+rh(|uFa z-&a20Ey9CttM%ElTXlC-OQ4tYc&P?odJt!h!0S7t)?1?XICNAi4)W`$R&MZB2JvCl zc5t7K+qsIT-B!DXRlC>rdj1Y_@IGS??Cn^dxyz^JI{xH3zP{&f#1E|oYP$=dG@ARA z+SYzoFv#3GUsqwzbI{B=_vXW@>uP;Q`$b*dxAr>$pC!JCeP-|U-s5{G6V=r{(KlmB z)Oz0Ts2;+nJRgq?;>_eB?2)beTb^`UePsrr)#qf+^U!d#!Ot!2b+9=4oM)Lje)%~$ z^RB3~T7Ql<cNcO^Z-73xeeBur!Fy6iHKyUS<D6WrRx*aH&p|#N)h_V4>$RiWwPD}A z!S`tJy&8O<2H&s24;aKdtJC4_F`U*vaKfa%p6NcjcT{H#^6RM1Z1A%O@uAhZ@c;GR z;WBLHo`3nE*df)G@WJPCNOcw3Kv)07iPL-BE@;z`>PEDg4ec(pQybbtXs0!_XV6X` zq;*t(K}!wx`BnJbbKFtA*5I!<_!|wrSm)sQB^rFm248v*@2r-G*Xw@J^=XyC`kd?2 z>Vx(A`qWvigFcD1!j3y<LwCR3H2P_S^=+b`K3Lxc-M3do8qPvzHLli+G%bDaS})SH z^a<!$?sNBzp;bTnyywiY>dYdB9ewU%Y|Vv^>MZQ#xtcYI53SA{9M4wg>n-O|M|J)n z-;V0S2EVAmFK+Nl8vN1*|HL3ZthyTBp5NTPO(}Q2c6+WF<lj+U*Wfoa_)UZOkm{@O z*88rW_Pb)wkw1r-IIa7H!&>i}4sQK;LfxOuIOYe`Z_e9mtE0MqP)?pn2JxZQx8SK` z@O!w<*3WvZ>!8-pJjmQSN1fHTjq!&rU4!=)e=gL%#<ctYok4YVRNrmz?+@ZbtH<E; zo;RJ<v#~X<_rDyJqoaDh!GAr7cUFIZx7*&HdKsrb4)W`$UTW~aH2BMd_|WQA_@RBh z{9Iv5`>ovm$Dhb$lQT1<WwV|s{S$ifK3#tvp?F{H%;|6Kh4JOqx%IBmm}uMzRa2++ z`#KS=vz3!eX*Irk3NP~7cSgRCH!s^4&jdYPt=!Wmb$g5Gz1wTp29ED<t(CXH<vM%2 z!QW}{_Zpn42F1@mh%ZnLfw%7m`6=KaTSqm#!53@r#T$Id24AYdM>P1d@P2+Y=&g+R zkt5;tb*QJOuWQDn*0gQU(NT@qH5z>F24AniH*fGQ8+=TIZ`a^EHu%niI6r@Y*KM!w zg*vLk2l;eVM>P0R4Sr06_cZv#2A|a6CpP%x2Jaihc^3`uADFR=TZHq~{mGvdPwDL| zx006b&yTs^8l;b7FF%<$rW~lM_Q1212)sInpK;7*HP?my&b8Gz{DhAJyO#8I-(0k| ziB|!;{`7V4l(&65TKk^dkFoA+i4|*0z5j&s|JKip_aK++&yQ=+c890krAF5W#o3-R zPHx;-j>M@o<7{^sCpT^uN8;3)arU8%lN<L4N8;4x#<lz7InmDnjGuYb7Dsc;?6-9~ zzV17#f&GM!YSR{XzLewbT*-KgwOOZmoiDM8wORL4)MkC7@UhL}5kz@9MsoNW2`8j= zs4olmXPRR3kK(`nEK^NC?Tb)qH=ps=txbItmc=NwtHrhqEf@hG$zhIVDCNnqELeYa zb1X-h9I>g}x3nd>)z>KW_*>6<=+<NZ?aTU<YSv}jN7q<w6r;8!r8v4i{t|`$=2@B+ zZ%3)VeXYw^q4zsb8k_O6{l-}8qs=k0l#k-)k~>lwXMXGSNPTM7VL$eyG?(YZy7!{g zu09I1H>G)#N4vSS9aPvHGj;v69Z}dEx4AanofI~8>+PX5);^A6W=y2C-o&MT{Swm; zb__hWC5POf<;hp(%w%6%1?>JMw=VCkoF8h&$=%a3j|adbIp*V7AG_T5Fn)|bg;L+L zULPFf@jnA>y#8m^HuG4Y+@JfE{<Gkjv**{g5tRDNFQ~QTzYy-+OTLS1d;G5`{H^Dc z991>z?8JW>=2{597VOxEe-6BO&5gf@Bki@kk0bH&hd44`^4T2r$9(d~IBakDlVImu z_|stbmhczBp7ZdRz-gcP{?6h45&LW4g$n)_c;SM-4<26dAvD%CllX<<&f)MS;O;l! z%fid?SQ)-VVP74-WWm>kFIDi3;Y$~MG~Dx>{M*8pDfmus*G=pf!u_nosC^#n7<f*c zUtfSbR_gkj_aO(rI(wJ!pSSp2`%^7G>){Q^<U0EWTptf@iF+PgRkL=C->+&P{j^2@ zUComt`k&Fw*VJFBHFIc-|LZkRO!PNuJ$cf;_t5!_bsTnNf;kTEd)i%ZJE1vN>oNP> z8+V4swktSuM&I4*_|!QLZu@ei&STN}?CAbEib-sKCFA64aCp9Q=(i@C_3LLIW41?g zUT#3Eo!dLW)e<LOw{CYYIPIPS&fNE0p9BB#<BxA2`?GNVKga(CNY<AA3qlrp=H_i3 zvrmB?Gy9+ZokZgndS><QwBHM+E3Njrx5&MxQ`3H5jh#c<<=*4P{!opb+uG&+UZeKp z^FB|$9QJ>Jz4q9C=X&n>Tz{)DO5W?}Qy$i>pY8b<rBgyb^UJ*_Qq%r=jg66?Oy@l( z)~UbTdn7gOr-J7LyH{wJd!M8h?!A$GOGepxY`Y(G{0GIc*LO6f?-_7!aZBGBglqSm zLAdMRcLw1-aNh@nTl(A|uD{Ry;g&x4hnwH${%}j5^-JzEez^I3#t*mj89&^7KI4a5 z`fML=ywCRG`ul7jZt1gqxOShF!!3PQF1gRj;rjcm9Pao?!nMy|aQ6qFm1DQ`c{yBv zpO;JS^K!WNPd+b)Tl&0Qa-WyOy~px-Iox=km&2`ZWWm*aMvmR<k<ZBC`umI=Zs{{} zxOShB!!3PAF8P>(>+dsi?2ez$$l=;|Zg8KGW4HAAINbAnM8S>s`8ak<pO3?}`+OX3 z>GN^PeLfD?-{<3S+w1djxOSh9<vX!sokHmkD809vSs&Z84w*8QFMze}z$%?u^Td1@ zo*3`r5_2Y4n=#(+$rE!9I5D%pi8&Xn?ZebNKzSaAnmN1&lqbhWz{znTI5{o?Yct0P z%8zoWnd5?*>udgxahUgfb{+X89J4soXVu!JVD<D(zmId2ai4(Cs`bQO23I#O`7Z~X zPn+$zm{Kimy%Oxbr#A0N<>}WqI1ye;w7Cz;wYfKc6YO<Fn|q>s3};T;gW&O$#%R;W zeO29fuQiW=z0PQJ50$6h+2GXc{wYt~_rUra=UysL+z-HBtF*bV%EvI<ymtQ(ybh)L zjMJ{4`?a>67<=dCkHBhP<CFJsxcXGu?)m*OSnVQW<WGRryr)Z^pTN!IeRuLa30F^^ zpMuqr=VxHGGSAQ9=9yjOc?zzcJih>|CC}4fHS-)$wa>{jaNB7e+U>j78uhgAIdI0^ z>x^8R=j&JCjJwwydE$Np&bWL1kvr}b)eHP*B}(%dr`@`}u4zk---6ZdWK6vedl9VW zd3Y25--G?UO?$Ncj^i*+nAdM{^85*$K6tH@rw@Myrw?BD<l3CGe+4^7ZJXCXd2;>@ zoc?(|l#gLn8TWVav6R+jPGj{kkJn!9spA!}bvQ@7&-pjUYaHGW#^;S%KMx=CzX>-^ zeRzE?{{v=NTECC2-MZeQR8O1#3r?Hg2Fqi67o0JA2P{wh?}IZAUc2SmTto9Q-p)nq zbFs)1w*c7wYV(>dAH&_dedqvBp|p**#X8Mx4t+CL`Xyf{xE!mY@a9+zLsQRKEeJMF z-8@#YFgShnUP7MnUj*FDxhR^tZSr12F7`gd{N{DdF9CMH)aE^hT<rZuxpyoL_gbXQ zdk?wT`wpLV#_$yE^UyNzag?^vdacjA<}*%z<Ger8H~Y+TV9&{8#HP>7qp4?qSOKh- z{b5D0n)`z}z2{Lgr}soFfvv}9GjqBgSB9&*7FVV8<62Z-g=0Ss*P=LWTMcZUS@@=H z{xz1m^?ENQ*WY`oHNpB{Tl;%YzZP6wfA6*A`j5u84p@Kh9n9}sTNkdbzxQJDv}b*= z{ukE%&W{b?>iT=HCePa55PUd3w$r-Jr%&qI2<#quLA_Qth8v@vHf{p8PM=*9w<%mb zahrjSRks}@Db<o=3$QtSu1t>6aCQB?r<A9kTY;PX+!{??fA2Zv@!tll|EywMwuP(f z?>(tJ?b#lze>v_uz}5Blo>i{D_kd%;`saSey<{i2y8hnN%G0-9z>a~oohjwnOLhgj zm)K|fVcV?F9Qqn#tbXQmt?mwXjwk;(uzS_V>+`k;Tur~k><Ko;y~P}Rfql=Qo;-Vl ztt)x<0jueIPMv#Su=%yww%sVz-eRq|j$AXYoz%NOxNPeI@UpE3!qxOk%t7F?tp~$x zt9sgY2-tTt+S0Z|!RFJJwyBkEvyF1Ezqa)-xb?brJ_OF*dN^3F&HIHT!MWBR0hViX zjUEloHRdR=JUNdA=el(aSf2IRB`4mx%xSDXX}k8+aU8h3essf|d;Rff>bZW52OFoJ zYwZMZuC>~&tA|oOZ9V~<Hctf0W9tQHj3$BQY2!)YjKhgwxi;6w6mYJ!lfm-D^@E*9 zwxy3!p7k*m?E0{cw#7QlZ4P}iR{E9a)$^PD)3KTVz<Tb_0IT_lHc)GhO|+S{#x&!; zb7<?G%_(Tc>#yB;X&a`2wY|&eZq4Dl8T;)!VL!e<+X_EiTJHdzd%hp`J&oF@I4r}j zY4GbC{N|e5N9XQU91C$gO1<){YwgpNw$J=(@&621|Jk+wbzn8GRmt&LuzGUXCbi_a z0bJ&|5w7+*j^wxrtezb9LoGQz4=!_j0j{Qha@+z|PY(O8mK?W&)xvKBTTl4yVA~#k z2iWoOoO+J#<S>VE`f7iV^P`?~>6rR{-H-3-b1oOJvDbUw&qw#&yytjn%AC`?!R0x= zx54jk@CO_G(FXrPgFn&WPc`^+4gNxd|FOYeZtzzd{LKb`x4{=+F_r!G?}1A0-~W`{ zzxOG*f8SH`Q4Q|j@051`UZ>>#eNM^!dz_N{_ctZ??`=x%-`SMhzpW{`e^XO(|Bj~Q z{_RZ3{hOJR`?oSB_wQp$?%%_d+`oY-xqtUka{tz)<mVOKpV{2f;QoC}>F?jTl-$2@ zDY<{+BF{Sd64?1atKLJt3|6~`BR*dNPvwZuSHb$JyDzyW)Z+g&uv+}T4pzI5Lx0zd zTKvBO)<5sG9stka@Lo<^{Jsg+W)9bxJhpFv%Q_#1t3AY#ypMpBS9@Z=4c2B}*Q-3X z?|{p^--WBq=1AV}fs<EzV!sd8W?t95JhmT#%e+5=t3Ae%ypMyES9@ZA4Ay2|_YZk& zKLM9{e+pN7k|TM422Nh>iTycPn|Yt0l*jf9aGCcRxZ2Yk$@?rgd9^3@mtbw?eTq^Z z+w<Tu@2}u$&cEdSH8^>-C-ygBZRT}fl*jg4aGCdaaJ3gXlK1!E<kg<oKY+EF*Zox< z+n>N?-ao_DUgAjJzkrihdt(0z)@EM!X?bja1DAPUfvf$UBYFP;PG0Sa{U=zPdEM{j zvHc5N=6xNm_8Ld>{u`XU+7tT*SetoYrIg3^A8?uXZMfQ79Lf7%aPn$T>^op>=6#b= z9@~51GOstfYVUI-?|f*<t39#vgSDCWUHs*-b%4vfop7}w9LYNroV?l-I}EJNyj~CG zu`L8H^A3lr`MUwhy9hXWwI_B_ur~90U6se??`f5JmxQbNI|j+S6gYXcCw6JDHuHLY zmdCaXxXim8T+N@AChzj#<kg<o6~Nle>vdip+e+Xv?<#OLf9D~2R|O}p_QZ|^YcsF+ z3-Z`j1DAQ%fUB*}k-TeylUI9U*8*!ZulF7D*wz7;dDnxh`8ycNyFNI1wI_B1ur~90 z|00iVBXF5_6S$hc%aOdBf|FN!VmAY8Gq3kS^4PWjmwC5@tNA-2$-5Oed9^2YYp^!+ zdOszPZ5wczcRRS6zgv>L+k=x=dt!GGbC}orvKFtOWyZqGygS3ycJkoq<`mZFF5u+V zp1iw)wVBuZJ9%uogYPFcd>s5ixIbI!q}&6pkGk=@QL4p%FR<6*@V(()LleIbTpxAg zy?<1T|9;>niunEEPZjY8!1Yl#-uq3p#2*CqS`~gU+-pqgKLoCiy7Aths>S~>u-A_8 z!{P4viT@B>A9drspH++hkzn`o@T1`F!HGW_u8+F$-v6q_|5)(7MSK_BG0wf-abSJa z6VnZL9OH95SU>gnj0Zbb@tFYDPdz?8V8<gq6T$ka$L9pFeU8s0uzu?C=>^-b_?!sV zPu)IykFOU0$zZQ1;ZxuXaAeH-!1|~ge-foy{HKB!EcnS__vOS-1M8!1d_SdH;%9)} zZ^H+`?vsh13D!s5`012t@jn&p{uh24cx{fvpAObX-S|@|)#CqQ@P-9H6YM^c__M(J zs2hI<rCQ==fyWg59I)#;@#li|Q8)f<O0~qF5B8jdUjSZ`^KlnzemlyKz|}6~xSd_V zec&Rn`a@v##C{a)`AOXugY{L<eE67l4sD6M1YFj6DO}C`sq^D-^=6%)K=YiY&db31 zs;AD&!PcuSbzT83>-;2KZFW)Tm2mZDou5K;9;D8z!1}7E&QF7_S6k}58eG<S4P4FV zlJxU4aP?-L*P=OhQs;GGebrOvXTjF1Ep=WGF6+DjuI4jK>iisBy;<jtXwJ9Pc@tP) z_0)MY*m|`&zs{pnOZ~Tk%k_O5yj-uh!$%bUcYsF~{7!JWKJJ1$-w)u8;pZv8$YCAk zHJ9<m=x2Lwq0}es`4ZUuCHx-nVg>&)c*TN$1-y2_zY5;G;P--EZ)wlhz}8`2a~W@p zezxasN_|rQ*TJ42e|9pI@_x8&R*%m&!0N`|M=6i(o8U73LAZ6O$LCvMb>knPl*jfk z*mIWp9|12xJIZzaZ8Y`7JPI~X=EZlw`l!ceHrTdiANej=%{i8N_dU3J=3VlAAI+TF zGtYhiwyoOI)*pgxtMRG#F*Nn?AAxOa+VMD8t!&4S;p)wHJb`9D?P<qPz_vwO?zNr- z=Uz*D>i#KMo8$fvr98Hufz^DEDlXrnu0((QEXR@erOVfNS;`d(eMPYEQCFtSd(_{M z&$%RDl=8O)SAVhQj^noQU%<_ob3Ow6G@80U7m+^$=Krnt!P=&f+iStIU~S3uOR%|e zPK<pHO+C4u2lM|{E^W#6E3mc$XxAdxe+@RjddBSquw&tv+E2OIKI$L8-+>()ZT455 z-%<HJcqweg8>ij#pq}$E4Et&vepcbgd04f^j_b%m9|iV2tWKHp@F()+JXpTm;IB0J zzZ(3_27jl)=bL|U{>}#XJ7voH{T`W;``s}m_xoZ>?svqL-0y`cx!(m-a=!<r<bDTC z$^HJ9lKb5+CHH$@O1@LUzd+x+8{F@FDgFK4my-LvFD3VTUrO%xzQ{9YUZM`qZ`S&s z;cC7wi_c%+QwyKJ!u3;ku6fSY;{P|WT5|p!tacwc^mk6E#s42*{j<0H6P&$8Tl`)H zYcq%QNFLj3;Ihuw;cBkQ<o!21d9^3@4X`%zIv?e+{Rdp;eG9HOyU6=CJbASz_P=0l z=5=1nV|y1|=6w&YR=%%&AD+D06U&mTw3*lSA&+f-aG7@jxSIDq8HWyd@@h})5U@7$ zy3XXW4F#8Zhr!j#_q7YclUI9U7XoWDuj^GF+i-B1cM-Un^DpgP6rQ}=6T28#n|WRL z^4OLDmwA_jtG!s{T?(GO+7r7pSetp>Kjg7311|F}3s-xo$h#aod9^2Yd9XI~x(~@? zTM=C5T?wvMzOP*wp1j%<y9!vFdEL+Cv5f?mc}Kz3%J;Ra!IM{eVpj)iGq3xiJhnB# zW!|;mYUTUdwc*LDJ+bS6wVBubRUX@VVApo|`f%4|?vplv>!WVG`>|U5Hv+rX!Z(Jy zMiRdXTpxAg-M`i1zZuxMAHF%*Ih*(`!1|~gzbU0!{I>)<7sIy#JBJd#HCP{Y<Gntp z#eW;Hb0d6Pu;(=K+ky2_H{R=sTKsnad#=KF1Utrw9}Ct;-FUA*YVqG0?EW0S3w#uF zJNJ^i!qqOsC-=0w!PRpwnb_UYJU^*>99UoVTpRWPTc@_f?FlaH+zYN|{?xfQT)kQ6 zK4_lP)VVKMU-i_vAJ}@erOy4qWt|7W)!gS(=YeqbW}OG2IS*3j!C-yWQ|BRI>(!Pz z4+WQX9tKw{pN$WPt2gWX5Snu*bshoMS3Pwe3ASEssq-jsS?AGkHLnlp=P_{gW}U~P zIp0!e7g%5Q)Oj4(dbK&fcA`{E{l|mL^*tV5uGb0ha{cwd%k?x7UapT5;Hz@vS#%QE zI?QV><BieJ_H<L~llGhlc7F*!3GRLoJ{jIw_)h`5o@4I=yFSDF!E11&JyXHfVP10? zZ;XDnr<YQn#7_fze)7CG9d4V|<1+)SZv4rV^4MmA%lK2^)}bDsQ^D%S4^YZuJ00vf zOZ{hnN75eGdwf2OrXGGK*mex(>Bi@yv%t9XH-)^%0~@PP{LcnkZ|2b~urccKIR|Xc z>^tXz)tr-=r{}@dGf$K6d^B@v&%C?<Y~Qq{Zx@0`lF#_m`w=wt@Qc8<HGTUiIDKpR zLiCCM#kGIh{V}*&+3ri=>dkgvie`T8Y4^v$wq0B9hdu$$bya)nz6`9*^LiSkJhm&q zYT7QRl#k(=(`UX<f)}P#_nA;$J`=8k&CePfc_v)5#y*>`Rp@JjeI{I&GS7rJkT1_5 zK11GEaP^yNp6BVS;O5Mn^LhHyXzF>Mz8dU#u>IQdJbevVTXKB{Y_6PRb6tz3o?O>~ zlS^B2eHN@O&*s;I&99zu{T$e_a9r)DTx=ipkKfH;$3~m|mFMqvJ`Y|EoAJhJ_dKZQ zJgkR(Lk>UdbL2d@#vJdBC{x$1#HnWv-3C{43^Ipqhi49HPwX9FZTZ`&JHcwP-vusn ze-W-WyU2YvJh`<e_Df)G$$bx4E%q;i%iLdqtCi10Uxg>P_Qc)`)|T8~1FPk4gYE;{ z7wgpK_^OrTy9s^pQ;zS(aL0F3%GC7@;?y&~55U#RXRL3+(@yP)eGsfIf4A^0uv-3Z z;bE}aLmY{D1YFklZMa(b?DZ%-^=VJ+cfi_G-)yj2>iaHOt*q~R@Up(|!_~@XvLC=x zpZ3)EL$J2g_ZV0$_5BE}W_>v~kAv;EZPD(zQ7g~Q=8U(W^4x3&_uOnjnfiZ1ocbN? zZT>9hNw}JO$(yXbpMm}OcOBY(%AsZ+v338V=IY7&47kkuEL_bsW!~q&e$1=wmmF&5 z6`S{0HCIpG-+;@!FTmAYPv(6Q?8m&?e#@a|Ua@(9S9A5`{R6nn`$xE%YstJXf&G|Q z+n+ep%quqUpKGq3ynh9kd0&RBIrq)`cd#GxYWo|9nt8?MeWm8=$@@=mnfFz=nseN| zuYvuTSKGfh)XXb3@9Q;Jm%l+-&Y>~w6s_;U*@~Q_;ajzi_U~YC4L094lwP~EzeSE* zyDZ<XdD{KoRvqnqU7OtNs{8djVCSv6`@Xr<jMe@w*!siYZ*W3dF;|k$>(+d5eboKC z8nyYs@1bc+o&~_xmA{MVfUD`7zXKQowtj7nl{{m$19``B_}P)ev9j-DYwWn}RN$R! z?0fZHYOMdR1>UX3+f(k&;W+O>nQ`{}qK%Q8$M1>`w?4loI^5FliY~d|6<u<_Bf8{% zH+0GUPUvvkG^)YZY;eB|y7c$EpiAy|L6_X`f)2MoeiwAf{T}F&`yJ5Xen-IAf*bGm zKgTXVuEG7@=h*F!-}xMF>GwRB-0yfUx!>~~ZoJ?1TynqTx#WJgbGYsCJDtNlUw)T! zxTW9UTynp+Iox|fzqdKu((i2!?}7Wh&Eb}QUvs$eeqVFArQg>aZoJ>u9B#RL!ELYK z#~i!){Ql)|?S9{KxTW8*9B%*pPUUd@{VwH_``yVU_j{7VEgz|Q*6@OipX<tf!?hvT zHUe#7@GiB@bs|sPB4F31ajqG;wobIgz`NEq*N;55CBS2An`=oP+frb)-0v(6R`Z&g z`^gdT+z)6^>@r|&w#PLok8L?{nRj`(T6v$k0z7%OCw4`!HuJi+<*}^{F7vJeSDQ`$ z(%x0!$*VoFBf;9t>mDJ`v&3p(&qeuMvN~M-f%<-94Y1nJ=Wpk5Ur|erwZP3BYon>( zTjy8@td<<^MQX{h9@rd?lkIj+tPfXDJ2n8TC5QW$T5@azZsyn+O+D?{1gw@E?s;m- zu^HGLj%(VnIb1#M*aEDU9PX29$+0E4nPV$7^|WJauv&7sx2mPiZNRPr&zbwIJhtr$ zn|rQ2wjBza`>)(~x&Q3~9xGQTuY6~DZQl*7eOC_c^4MMfd(?LSCRV%L?{f0*(e|YD z`e*qD=WlPyeK`DR-?z3~+E&-@eqh&Z`2Jw8srS@#<^Z@p>fR&C_u??Ob%_&uAlO`4 z&j*3k&LE#{)utBzL%>TG{7~@X9Em>+tX4j!9S+a>(w<x&0&A0de|`kmHIjEaM}pOy z+pe>`(>V&wSna9zXs~V5mgkLQ!0P#%)-JHxu^jg8U`n;LryIO%!H)-*eH#x~E1&Hq zz|%MF$<+hamcC5{yYAAr6ToWCzD+_iR(tx^3$|_A(zg@A>gn4_V72t^IIvpUGX=a- z!TZ2v-}>Qd<#Xgzc>1P2xlRUaOW&q}UCZg)bg){pZ!^%0)t<f$fNh($^lc_sJ$*X` ztd_n_2CI1vPo;FNr7fp{*W|dZo>QlT)qHOFFr^>Yg!&mAYOV>fIov<b1UomfFP#M* z&Qb35XT#Og##vzF)Dw3Oco;_+cP?B#&%oz_ja9clV<^>J`)QkH`gcBfLyq+C0<fC> z`v|2U`=@>(hnoEpr+*iLkK;%?KMJ;g<u&ADxO)2cF|cv!iMs@B|H`;a;p*w%$HB&` z+rMoo)$Cu|W|{td0z8@{{ksgTX8*3BO#jp`=TNhM;`Hy6;K>|m=apdlH=E%2d<w3f z{#^w&PCap-2HU?f?rOMt`gaZ3SatiiJ*ArcOWQ0{?`OcC<M3<23voPD@7>pd^-+({ zXTgqJ`1Rm2<_5Sv>bKT;J_k0Jw#3~iF8EF0GSAI$ebkfZ^I&sn^BmklnRB4+3mms` zcn-w&d+(a7J0`bNx(38|6!^{>r+r_9mt%7`+<xC*_vuSuebf_k54eo^vNn#yd<CqJ zdiwNLu(`C^rn@NBlJjfea=h<@TSsz!9juRfV(tf*G2hU}k(dX>9O`MuH^Ju8W;^bs zR7=ipi3|P^*mgWvkH^Dcebf{4h`8Y22HUR0JPOuFJ?;1o*j(Cd$Agq==JdKe8|)Zm zfB!C6E&F@?zK1rd@cTYkEq>Yae}Lwi(w=Mj55eZumVA$a9h21iBd}WX#qV*nbql{A zgVo}fdY?e^+O0kH{se4ZZSi{&Y<sk&j-P@Zm++r~H|5Aa^>eUV#`Gz$G3sgmFTm=} zc0G+|o!T9L*Nd8Uc|Cd-?0FCWCD?O1oTo<Z&w*K9t)D&Ut3AHYi#g)^D{y>`({7#5 zP--*I_ffwA53jj(ya3iG_TPesapb+yi(obV&S8F<<9A^5XtR!AQ>vN6dG&j6Ij{Zz zSIhWhAO0hnvFhp9pWy2Gxy?&p`{ki6KezcaSetR)JO2f|EXTRDQT|u3KI)khFN1B1 zwzTzcVCQ1^-@(p@Tk5s=3RoZYobP{t)tmkKCz|~!?+adqtEWHz0;fOP(x2DB+R~rb z!Ao+aKmP{nqn`e}0k$pLGRNNp+fQwtn>#4g(!c+JJvZTRf$e|#`!-k~_4N0@VD)By z-$Ap#<#qI3xO)2g9ytBgmj1pE)|UQq8e8|V>F<1Sebm$6`N6hDTiU+>*z=XPcEHt| zZ5@JUTg$oDiKd>m4h5&J+S1lxU~OsZg5YwlEd<v`J#AeWY+JPD+zbcX2W_64J86$v z@-7PYe1$It*C#)lTpX^CdVH1yFOHA-eBUM)`>sv@_>BO&|7i2Qn>@caybRdi8#dlJ z?fUsXPg`;<2QJ&UJiKh*3UGbY6SERH?el$}+}ys)(?5Qzg3~_V>&f%8(~;oSXrJ-M zX*Y-O3$>ZUpAoMHR@)yoigI-hH4i_YTVC0;es1LVB(KGx&l()plEb}g?OOMqXkD-$ z@4MC4;n<18dm?e#z8=`I%6I;)4_0#@FwchI<k7YP$F>~i5hu?^VDs2F$4nmE#$dI~ zrA^>!){*yJo5J&4r#-Qofwh^}Jw+bd=HN2#7H~D!N%D?{C$ILzZVA@bIv3=X$F>!? z%)2#QZFZ4&3_N+YCw3dKHuJ7TUb*+5j-zAd*lF{9?+zSZPkjHoBX}(SdB-8wUf#Q! zL+-gXm*+F}?hJPPa~^jAtK~fI2KM88(6*~K4)chUXB^nR+s56&a@#nX*ge6vad!^= zy`Jucrmp`Ul=9@-8(hu_d2IWD%Q4;;u2#;8{oom6?TOtVtj#)|6Y|&&0GD|WgsYWv z;vjhPYESIJU~T4gkCexD2)N99C|qqeW01La7(98kC-!i#HuE|s<QdZsfybhiV|oOd zx<0;pKN7qwhhvkRN5R$ee&T4bTAl%q0jv3Q?BqEXZk}96yw~W0t0&KKV727w2CJ2M zj)$9PHt}iCc({7<OaQATPY+nlJo&l$M7Zs=4(<6az7xQXf%c5kByh&bag^()-S?p< z*7jW)OYQPrj<oM2u;(vhF}e1iMXdgEee`!;_kq2aO#S_}{}f97<@)IF{yi1!m}qlt z%TxC>aCz;S4ll1gGvNBD8-FsTTG}!b?Db#U09c;fr-F0sIRz|tKKe7C)4*eib8cns zc;9?Fy0-Y8QTSzU==WiCZSgy^@SBa@Ht2U2y0+ZUpAGhUwN9Nwdu+1`o9)my&!gvp zwV%V`wdZ_FKkixD&f`#X&k~n=qq^LEPWy$F8NZK!9lxB*i{OsSOmaJ>a(yzU9|b$6 znJX99{ukE%a((po+<y%0x!2#l{1UMFvzN>DN&ZX0<$U-!yqpi8fa{}fPJiBa8Q7fH z)@_jMr``E~d2QbbANwRP=l>P(a{hm^_McVflk1Z)yAoW^|4-Hang4QqGDe>UI|h%D zFa5k4uAV*N8n9aSgwKH0+!ON7>st8paBcSEDoQo$@f!45u;Wnfm)E1Ir!6;tZA<37 z``qW?>S@c3V70X6Ca_w$&)p0+Pu7HaJ`Yz<o-csalIIq%TAAloxOrw5V{;o^J$Y^i zt0m7JV6}3;yc2FatwVeE%e%mifp*92I!d*i%e%p9a@XsZz>aI4lkWlRqi*~cDb*ZL z_mMAy)iR#u_zGM-K3}bUGFJNBi>4l*uhl-Yv865dp{Zwo_&PXyhw<8DyT7nmzrJ}# z`3<mk_YQM=Kl}iAcgno~_$FLGb@!KVQTlOz(e@z6(;V&};*8(JVAq0U^AK3B&H3<c zaQ5Fv!18<t`=c#P8!5FJZyxpJ{th^M`*3XXjMr?i{^huT7fn4szx*CpEkAqoU6)#N zd>`D*@dGsV{QUBVV725}lN@Tv@fg?~<+=S4ntIytI9M$?*2P~fIerXo=6C{4J?;1j zSS>j=B!^mZJP9_(Y{uR3bB_HKO+D@S8CWejd>^Kk96tv)b3CO#N80fVa7$w!@|=w( zhnm+H=Zy2ic~V|~)XVG7ZZ%)G_P5l23%QK9l<!k>OZlEP-<vXh{3Wqt3jQ2?TX@#R z^KjS9njHFSPwcP6h3~HmU*oiAY<>eCi|@0P_FJyMxt#021uu$SfA33QgzNtTrT%h# zw0lkZU2XT8WRBMRH8l0Sqx=K-_Z*4&BiNkY$0g=ZXzE$VFM*9ycOCzQ(vRy{+n+hq z9A|OvU;YX<ck_PeWpr)v`&;2x&iTKiYm472h2L!I&zS!MU0cr2Kf&44%%MHDR|}i% z&^Px({{m}2hr@opPU**fYI}`C&3=kAhW`fJ&)f^hdpT^M_qK0<_u$ZfH2h6)#>Mj} z*T?yo{FaIT4|sqh@o#~R&;68KAN{>QdK<hQhyLCl{THl%?vLd9=<hsx2fRCn{?4;^ z!TQev+djEI@qZ6|3P=3k2kU=f?Jw6yfB%M^w5@w={k^xE53Yait>pUH|I8yx<9EO` zf9>z@C5rQViH_|79DerZ*owB={(WlfSnpfoy(sr9^!>q}#{((-9Yf>%x9BbNJBa=} z^x>BN8}udj-<~hI|L%Oab^CA5hg<q@&4+uP_urZixAfnc4>#U_XFl9=Y{7SA{B|k0 z_FW5Zy#L00;^qDu^WoO-zcC+f>Ax{wa{rC_aQ7Ggjd{6q!m-MAa!<6OaL3p8X`Yv1 z`ql@uwI12t=iCD=giRm+-LG>v`Nk{^_IGr(S%>4VmU*`bcq)G3i^5Nb=RN9TaDCK` z_k5{|Jy*8ZIkp7Yb8qSI+bl)7G>0GUBWk;4>RJYDj__r{=FjijEC<#{-TgwoB!{`J zOPtshz|PUUpIZ^Gb`M&7R)Ram@mU$HpSt_uDfq4e&ifDTiCq<}&3-#4<*|(ftL69M zM}gHG8~41`!G7$6w$(V)?1R|xNuSh{cTKQ))3&w1X`8nAtqs<e`qu%grT+E6sbAZ= z9Gh`izc_g|1Y4hdbY02wd)6DtNusX5b8BO;dx6hA@=f6Sshh*KswQ?_`b=bBZI5-^ zhSa?|xa{i|@bpz%{6>SdrLS9p)x5?z)?0)9IM&*>;!v|baq?^fPG84><>~9TVEd}> z&nE2Kc3`i6yK!hgyB>q>!P?Saxpj=dZwK%dmUaK-_CM{hEXTufN&9vJr+s6=^0aSf z@FwI{H@AD5T4HwtyB4&$f62Akk8xnnnKt(_d2D-vJ!jhXpp<K~FMESMhuZd{l&8LZ z!LDO%`%ubb+aK(j*0vv|TzmlK&g{4OcS{b0kE0&jYrCx9ddz2>{>HgK>+5yT{qrEO zT6uqVFkC(NXNQ2*{27&fITWnseDogMT<+zEp_!|EE<YTup6ARDfz`~BaXSL+wJ-cg zxZ{|)a}+ppN86RuXFHAt8>>C{QpbSx^}UmJ+n2hJg<HQq*5xtV0!j)SXt_%RnL z=CrLF-T9K|?&HD6s7D(Qwk~by(*$t(WZQe-=H8h@Tl^+A{7xwRv{{GolfdTCo_DFe zVD%inM{v%bh-RC#r=F9*ogBH&O$Mv!>pan>=DGFyItA>x^*-Mm-lO%w)%AD&%46#X z58=qQVk%h8eMWz6YVkiAtQI~^JHB^Qzt0TQ;rgh%PYqD|ai7vQgG0@IN?cwO)a6Up zc1!sZHD8L-dL64%!1mqyI&pblcX+Et)&^zn>kh85_mGFw*tKwIjUBtgIBeI4D7}yC zp*)@3+H#+FM#0T>X2JD4yWo4l&n>w1T~=`YFE6<ED+~T9@Kp_dW5K--yQ{$;YVc<Y zZvMX%-1=WFxc1iyZu?&^xb`<{p7Z}<xMS;Factz;7C}1;>{x4aoaBj{1$Ml(IcD<w z9QGXWYS_$YoOb;@7uqt{&jYLFUedXKK3qNT>Mj7Q<z3x{V72m{-$&r)$@8OmE`qBk z&qu*($#XGSt<3W=xOrw1pMG8fS5KZx!D`9#aj;tZ-C_IR0Qm&mc3Ova_iy{}T+)`@ zSAa8y&LerQou35z_hRbCI`7oP&N1(m%`<?{r{QN)o>lX!;cEIi|KzU2YbaeGmfrhb zOL-lKAMKy5?Uu=XJ=h%KH-N3{tMz{IIk-OR?h*3OaG2Y=#EHELT(<LOxSH*BUC3?6 z=P8Y~w4Jw5-pb)e`)#$|GP!RDn<M-VaM{i~;rgiCPWcx&%xzs_V@FWO7r_@$CfD6? z$DqHqe+jIXYs5WZW7Lgt{(Twjxy}9GSKw;pT>omr=U%v)^Ekg}^EJ4!+LHS|aGCq- zaJ46kxclM8YD?TVz-8P6aJ8q4xNpLZ)t38^2f^yO4@tkjg=XKidk)>p)U3~Od>DKI zrQCV?2)rD}Z^PA+?@_QZ>S^<Lz-60f!_~?)`rU@l_uy)e75)0YF&x^`uOEQboBjGB znr+c;zaFAgOTQiiUr_YxM{ws}=Evh;we;)9U}MzNuP4A|zkUK&E9b|P4WFOF)ynzt zGq|zZ(yyO`)tmi#3eC1?PhWlkwtwEAc+Q>%tLdA*tHu9W@C8NRe+e)9{v2E_eSaQo zjC%V1D{$HOU&Ga$zw!A^!{-IKS~*vL3pZ9<;$8%oxqk;&bG~Fv{T^<tw#5AbT*mzo zu2#;WKf#UFma%>btlk{!KdW(QcO0LgRI@(E`LAHtOZdxR&qMg%z{cdB^Y36|^wVa} zzfh_hvmQBL0UuhAq5L0keRA*lPq04f#<)-Y3!Ll!t6;ggU!&AtKkwiF4L-NFy-q1l zy>Egqt8H&k%JXlS{Reyi@#Z$CvHBS6p70j<V#=(Yx8Z8(_kY1^IdZT44w|{OrycKt zujEL7-vg`ZYoD~Kc@4Rh(tY1DZFwK;T=rhtwmCp*X8?`YrdD2~Zb6e@M`=FG<eLxQ ztKi8uKU^*Ow5b_?O&x!29q;*D09&ig*u~{N^0C<c9Kn%$<RfdmEag!(9!+_4jlEwy zhQoGtQRbd_F>-5@dr!PX!Hr+C;QB3HbMNE4hwX%0U-qsM;Gt;h`JKsOV4uT$N3AWt zGr1sGTXHP~HdpTD%(XC@dU6d1CzrP5T0|d?{2t_@VDqbcPAICy`H$n|`Ly41v3=G* zb7?8C<EG92%adaS*m2b6SjaQqmjV0yVs3L9tB=n)+RAe{9zQ?FapW9!*Vu7Cp2KrB zfimZ6d2-}jS+3IHs~6mJvrdC=+ThzX_%01TuEF=NdB$P|xNXk!=ZbJO=R)2Gt_06J zGVO_78LZ85v|sYrRt1-NN5a*d7s)#cp1j%<yBb)Vc^w~lY-@naylcYMW*2$af+w%` z#I6n2W?six9^1NL`w+e!xU6S=xY}byJsZGNkM_iF2-cP{-3V-c^*o1c3|9A@rfXyq zu-dV_tFnEbceUi)4D48hZw@Zow*_3yYjDPQG(7Fop4ctH+S0zQz~)y^`?dzFr+s6< zYH6SIP%SyP1v{qU+kwmWZ4X!T`k(gg08jh0Cw51$wzO|7*!=2g-%eolv~OpyTH5Ej zP)p8T!Jgm5?*>*&{O(}2#Ji5v62Ax7@lX7oV70{W1y)PE>rO54`+yyv#P17MOZ<Ld zwZywl)v~Yd4|YE(_vi!A)UCrgbRgJv=N;cc;Q7#f$EUCM_#O;)j>Y#7u)b?@7^gjT z9}2eaa!)@DO+EPz2ixc5`w%#F>#IG!M}VC_@jVipx{cGGx{m@|x9dCcN295S9|Ly0 zlJ8h>>eg3#e7nHTjrbl1PTj_7&%H}G*m1Fa`gsjdE3W}lXqTUf99{$5_fM#?`}?E< z_tsdS6KmW<c~YTI27Aruqx72LHDCgD=9*z_e}kXd;Aa)wxLF1FXOHI<T>JS2H~)nV zeo?_~&&35d{*ng2wBWuw|3tyfe|5o)zoy{czg$;v{ck9^{x{X!IU?_YJBIGfo@Zz^ zk^iV?y`2D7%X^<mU^U<SWDWMheGbs(9_+ZQW$v5^R?F|tOa`l+#PKHneUyHDKcQ_3 zhnnY8oc2xy+up2YXmv9GQBQlPfz{I9>0q_;eb)@Qd9p5{)d2rdPo9}zwd6SktXAeZ z6>graF=%xf|4~n#)4^)Va|T$g{obtov#SroZKri;cMP4Y>W-oJ#Aky~pw#9(mFJwD z19rV=bI!{1`(fv{Fz?7Hwdv!$S5N!}VAq&7=d?Waegy2A)8_n^$M#XMxwJXg<=RHz z|1ofWw&uK->*t&=&)>)4{ybZo^ItA@?)&>B`T5gj@NxLrKHFh^<~5&j`WxpO)z>-W z8oC^;R{s3y3b=ZFK3V(h${M%*{ygAHH1#|?e+q1zx^wo^lzyDE+OFbIbIyu0XFmhB z{#p2%8(3Y-f7ETSYgn$oYxuKZ{jaV4eII>2TwQ<HxLkkN_~*d-&#e8OD>uT`^>+`D zr#&}=^}n$82UefwKkE9sN62$u{{^u3^|sTx&8JW1z%5|ss_#9l`&O_q>gIFLQj7m> zVE1ad^W=8;1di+_cYxhX)bn$-JHf_jOP;&H=1!h3g3XhdyTSUXpHsK(OJH+pvu(CR c&F9dZJ4<;VW$SuEnL6(Q8{_p%?Dg#b0E~6%;s5{u diff --git a/src/app_data.rs b/src/app_data.rs index 789c374..f7e5b20 100644 --- a/src/app_data.rs +++ b/src/app_data.rs @@ -62,6 +62,7 @@ pub struct AppData { pub scene_rt_memory_size: u64, // values passed to shader pub num_lights_per_volume: u32, + pub min_light_weight: f32, pub max_iterations_per_light: u32, pub diffuse_raster_steps: u32, pub diffuse_raster_size: f32, diff --git a/src/main.rs b/src/main.rs index db7c7a7..a1a99cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -192,6 +192,7 @@ impl App { let mut data = app_data::AppData::default(); data.use_geometry_shader = false; data.num_lights_per_volume = 5; + data.min_light_weight = 0.0001; data.max_iterations_per_light = 20; data.diffuse_raster_steps = 0; data.diffuse_raster_size = 0.01; diff --git a/src/scene/empty_volume.rs b/src/scene/empty_volume.rs index cf265b7..6466572 100644 --- a/src/scene/empty_volume.rs +++ b/src/scene/empty_volume.rs @@ -969,12 +969,13 @@ impl EmptyVolume { quads } - pub fn select_lights(&self, lights: LightsIter, light_number: u32) -> Vec<u32> { - let center = self.position + Vector3{x: self.size_x / 2, y: self.size_y / 2, z: self.size_z / 2}; + pub fn select_lights(&self, lights: LightsIter, light_number: u32, min_light_weight: f32) -> Vec<u32> { let mut weighted_indices = vec![]; - for light in lights { - let weight = light.borrow().weighted_distance(center); - weighted_indices.push((weight, light.borrow().get_memory_start())); + for light in lights { + let weight = light.borrow().weighted_distance(self.position + self.tree_offset * self.tree_size, Vector3{x: self.size_x, y: self.size_y, z: self.size_z}); + if weight >= min_light_weight { + weighted_indices.push((weight, light.borrow().get_memory_start())); + } } weighted_indices.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap()); @@ -1213,7 +1214,7 @@ impl Memorizable for EmptyVolume { v[mem_index] = self.size_z as u32; mem_index += 1; //Todo: insert lights - let selected_lights = self.select_lights(scene.get_light_iter(), data.num_lights_per_volume); + let selected_lights = self.select_lights(scene.get_light_iter(), data.num_lights_per_volume, data.min_light_weight); for light in selected_lights { v[mem_index] = light; mem_index += 1; diff --git a/src/scene/generators.rs b/src/scene/generators.rs index 3b3a6fa..0552b27 100644 --- a/src/scene/generators.rs +++ b/src/scene/generators.rs @@ -54,7 +54,7 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi let shade = (rng.gen_range(0..25) as f32) / 100.0; let cube = Cube { pos: vec3(10.0, 10.0, 10.0), - color: vec3(0.9, 0.9, 0.9), + color: vec3(0.0, 0.0, 0.9), tex_coord: vec2(0.0, 0.0), transparent: true, roughness: 32, @@ -63,7 +63,7 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi let cube = Cube { pos: vec3(10.0, 10.0, 9.0), - color: vec3(0.9, 0.9, 0.9), + color: vec3(0.0, 0.0, 0.9), tex_coord: vec2(0.0, 0.0), transparent: true, roughness: 32, @@ -212,7 +212,7 @@ pub fn generate_test_scene2(scene: &mut Scene, data: &mut AppData, chunk_num_x: cube.draw(&data.topology, index, scene); } - scene.directional_lights.push(Rc::new(RefCell::new(DirectionalLight { direction: vec3(0.0, 0.0, -1.0), color: vec3(0.1, 0.1, 0.1), memory_start: 0 }))); + //scene.directional_lights.push(Rc::new(RefCell::new(DirectionalLight { direction: vec3(0.5, 0.0, -1.0), color: vec3(0.1, 0.1, 0.1), memory_start: 0 }))); scene.oct_trees = oct_trees; Ok(cgmath::point3((max_x as f32 / 2.0) as f32, (max_y as f32 / 2.0) as f32, height_map[(max_x as f32 / 2.0).floor() as usize][(max_y as f32 / 2.0).floor() as usize] + 2000.0)) diff --git a/src/scene/light.rs b/src/scene/light.rs index d6a4c82..bf39edc 100644 --- a/src/scene/light.rs +++ b/src/scene/light.rs @@ -1,3 +1,4 @@ +use cgmath::AbsDiffEq; use cgmath::{InnerSpace, MetricSpace, Vector3}; use crate::vertex; @@ -12,7 +13,7 @@ pub enum LightType { pub trait Light { fn get_light_type(&self) -> LightType; - fn weighted_distance(&self, center: Vector3<usize>) -> f32; + fn weighted_distance(&self, pos: Vector3<usize>, size: Vector3<usize>) -> f32; } pub trait LightSource: Light + Memorizable {} @@ -57,8 +58,53 @@ impl Light for PointLight { LightType::POINT } - fn weighted_distance(&self, center: Vector3<usize>) -> f32 { - let distance = self.pos.distance(vertex::Vec3{x: center.x as f32, y: center.y as f32, z: center.z as f32}); + fn weighted_distance(&self, pos: Vector3<usize>, size: Vector3<usize>) -> f32 { + let low_end = vertex::Vec3{x: pos.x as f32, y: pos.y as f32, z: pos.z as f32}; + let high_end = vertex::Vec3{x: (pos.x + size.x) as f32, y: (pos.y + size.y) as f32, z: (pos.z + size.z) as f32}; + let distance; + if low_end.x <= self.pos.x && self.pos.x <= high_end.x && low_end.y <= self.pos.y && self.pos.y <= high_end.y && low_end.z <= self.pos.z && self.pos.z <= high_end.z { + let diff_low = self.pos - low_end; + let diff_high = self.pos - high_end; + distance = diff_low.x.abs().min(diff_low.y.abs().min(diff_low.z.abs().min(diff_high.x.abs().min(diff_high.y.abs().min(diff_high.z.abs()))))); + } else { + let mut offset_vec = vertex::Vec3 {x: 0.0, y: 0.0, z: 0.0}; + + while !(low_end.x <= self.pos.x + offset_vec.x && self.pos.x + offset_vec.x <= high_end.x && low_end.y <= self.pos.y + offset_vec.y && self.pos.y + offset_vec.y <= high_end.y && low_end.z <= self.pos.z + offset_vec.z && self.pos.z + offset_vec.z <= high_end.z) { + let diff_low = (self.pos + offset_vec) - low_end; + let diff_high = (self.pos + offset_vec) - high_end; + + let mut new_diff = vertex::Vec3 {x: 0.0, y: 0.0, z: 0.0}; + if diff_low.x.abs() < diff_high.x.abs() { + new_diff.x += diff_low.x; + } else { + new_diff.x += diff_high.x; + } + + if diff_low.y.abs() < diff_high.y.abs() { + new_diff.y += diff_low.y; + } else { + new_diff.y += diff_high.y; + } + + if diff_low.z.abs() < diff_high.z.abs() { + new_diff.z += diff_low.z; + } else { + new_diff.z += diff_high.z; + } + + if ((new_diff.x < new_diff.y || new_diff.y == 0.0) && (new_diff.x < new_diff.z || new_diff.z == 0.0) && new_diff.x != 0.0) { + offset_vec.x -= new_diff.x; + } else { + if (new_diff.y < new_diff.z || new_diff.z == 0.0) && new_diff.y != 0.0 { + offset_vec.y -= new_diff.y; + } else { + offset_vec.z -= new_diff.z; + } + } + } + + distance = offset_vec.magnitude(); + } let light_intensity = self.color.magnitude(); light_intensity / distance.powf(2.0) @@ -106,7 +152,7 @@ impl Light for DirectionalLight { LightType::DIRECTION } - fn weighted_distance(&self, center: Vector3<usize>) -> f32 { + fn weighted_distance(&self, pos: Vector3<usize>, size: Vector3<usize>) -> f32 { let light_intensity = self.color.magnitude(); light_intensity