From 457d3e2d6b391dd2a51bdc7a713776c06475de36 Mon Sep 17 00:00:00 2001 From: zomseffen <steffen@tom.bi> Date: Wed, 26 Feb 2025 12:31:58 +0100 Subject: [PATCH] fixes double neighbor assignement and cubes inside of empty volumes after skipping to grow --- shaders/compiled/frag_rt_quad.spv | Bin 44228 -> 44360 bytes shaders/rt_quad.frag | 6 +- src/main.rs | 4 +- src/scene/empty_volume.rs | 233 ++++++++++++++++++------------ src/scene/generators.rs | 19 ++- src/scene/mod.rs | 1 + src/scene/oct_tree.rs | 7 +- 7 files changed, 165 insertions(+), 105 deletions(-) diff --git a/shaders/compiled/frag_rt_quad.spv b/shaders/compiled/frag_rt_quad.spv index 6cb39ac357fec59ae52c44ff2fa0be971b8177d2..8bba5d6966405ff9e36e0baea864df3bf264924b 100644 GIT binary patch literal 44360 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 EKf?d;Z2$lO literal 44228 zcmaK#2Y_8w*|iTaGYP#{X`zK)q#1heC4e+hCzE6b29iujgCIyRHoAo(9TAYCh=}M% z7ey?9QUoL*Ac6t{QU(9#x%aGO&msO-Pxe~tExVk(_bD@TnQP9Khg8)Z)x6dG)lwio z3s-ZZRA^nTa_2qv+hg6yQ^u~l(Z=g*U!a=HqGemKny2ajdyMbtpP+tVS5+O%(ZeyC zV-fN$M2tRGF&F=vlky%a=^%dRJ-T<^d+(k1*s*)e#EIRLr%WH$+dZy-LT~rj{z<)K zru0wi)o*Cw*FRy*xT#}HhfX}oHgr<cywovu!o;32M|6)F7&kC!^{E?dj#PD0|2&k_ zdd7k0uNDPQ?ioLkYA5veA9~p6fl1wclLp3jPae}tEBYt&4H!CY>ZdnvW$0vF7BYTd z+|=>CG`MHd6ezhm8M~^Q)H8WX@1*XD1C!fzErQn9vd>p7O<C8~YSaI(BI{WK|Jl{E zBzm)+rO?{-46RlGAKE*GaXj>}DK@2lO8>xw_6XR{<*~PI{S(Ia9*r`jT4_+stRd5X z*eCplR;!{-7??D^XIyumL)J5<f5M^lAbUPm!QK`fhoRM4@JYRW<2a|?)A)xoGOcgJ zjA>`J2KM@t4>*y`vF4y09hDRCvy)miF*=<sj#Twd7~2}~E>wM-ziO>sfTKI_)Z1e^ zOLs=Ar@iraPSrZ?o#o$I>tm*m8OQXT*%qdIby&~j?!)@0%&gNn-#*#nr;cm+w%a%q zZ0`1XG{=xu+vl$JaxA(SKl|mpHUE@JJrgER?3vU%VM?p6PG<WEZ0KWp$vC|=V;NmX zxNidong5S&Edb}$r}6#dyy~hpL~l)KPGx%rdmg%~jiP5!a)z8U8_(3o_Z;o$wMNO9 z&T5mHw)QBgZHlI6#?9QHLF*YeZs4fydUn9=&vukE=dkUWIVJ7Xw7!j6oolymD|~0y zpRLh9*`FcRHs}MB`s<wC?InrkoZFVNJ+I~SRJ+2*_V@Koo!slVXO_Dk6!W*M+7Z7` zwxP4y3B9>icSduAa4*^goOQbwc+5C9qwXmK^(4)i#J8*31N-di*t4ClwaS6`&Q~2o z*)x{;)n0S1|GK^IW)9)h3?crV)xP*o>+e0PUYsa%Rr{f}+tyWmR{JORyt%6V(c69L zsty3R=laYcZRI|2mOgbn*uES>>0FpFb$olDYVDU@)fdqBbL-ueop-ybeSN)?@a}Bs zm?}49Tw8g&DQ9idYI9evNAvcx3-`F~P41q^e%#vbFtvORr#!4@Tp!c9ePZhq#Lhjj zox7`=h)*q#?Pn5A7}HB^S2cB(K5?Lb!j$+Qht4>7!RVjRKV>=;|BmVeO0G2<grCyp zF2R=lD{a1E_?d0)lEXfvx`4805^K79Z13bTlV)CUv|Wm=J>G4PT#U3`iEYZj#P+i3 zp4@*-Z?{cv<-F#TwrR2502n<mWeQio`c$?<&3VggZPQvgZ^t&Sw{ObesCIpK&c<ei z=DeShrO0(^P<1WagR`>{XxtyLah+xd{AAo?v$NH4Ph%TB^R8glz?k#-+1S#~m$5mX zGj9^=AvNx`+1ebJq1D^wY>#I%v}OO`f7x5@<to9&tTnEmh;|%?R$a5V+w7KoKJ4xB z{bT~;7x^FdcE5*KOJQ%1^X%i7{~z|muY$cb-k%I_wQtSY+w1mot;9Zf9=Ff`M#eSg zX{*m%Q?NDWB6SU^wm@&rwe~o1O~BTiPi<RQwS#pHo-^d@s&+vy*B{sORy_xxe`2oG z=i_tcn$3JjJHCkhljpnL=h4_^b1qwT_F<dNd1~1Xw@%wX=p2}{vzmad+&$d)&q15Y z#wNZ1JgtR0s>{_|OGaBqb+xvFUn}n!H`P7Z@xBZGzxJ;Cv6W+2?p?paHu#*++Pfb5 zq^+JSL#l_dePT`!YFi$gt*yOxJ%z0?Us@F!H)A%o_S_y)y@;(jpA0namD$+{)b={I z=3GnM+q1LPaqnYm%)^=O{CGCDb~`zX-1s`4ZdvVlMk~<jv1-ZAg?Z6h<4`-QEr{0c zV_Q^P6s_I<S=y53bB-0UpF(TSt<BLgx3&joZtbpK%%#1x6?{MW%(>N39RcSSxTk$T z(NWz4pLO5XQQbSp-dQ~iFYl@C$D?TFovZWxPsX+G%{r>b!R5W`lkoZ;sQuv7n&(~B zQ?qn$0gi5uaaT2CuwLI2bX6}7){klXcT}&SA6?&gyS`p)@d;DM@!%kT6F$ALztiHg z>>t37DeND&c<i0koIL0>@6$WbrZ?{0yU>mqq;*ttqfP3aJaya@+tOJr+seh$@>p)r zTI0YoTr1aLZR1w1QX5iji#DORckE;~q@(M{)a00ijpwJC&tjgF$!OlZh^K(t^O}1x za6jYSJ(<VQalMmi8a`dsaczBiQ$Mw>AJfz?Lr;oy+jaUq{U>lEIoUT60~5+;qQ|hc zTAw|&Rd+}AXY_JjKHcEY4C2fYczp-cdJEAWhmPunL4F<8OAY?FL40U6HxH{mPuBCZ zctmtehF0@pZ`Z?fX!!)$YWL7;!#ck0Gbp?jzj1A^?}-OFI94NSy9=N+TKDF)t^IsG z$lN+#pTnN#lxZ{XorhMVYJE!kMNoaG*M5%nUjIn!)A}d(kM18wRCiCGZ(fq9^^Dq4 z9gR<UK8_j0JF7e4?ROzOiL}O|v$_kdJ|{DuSAK~$__?CJ4jx3G`K(dLKRPpK-mkFc zXKJ%{A=mUv=(F0_S-lD$yeD;3Z#8`0pP8%GO2)9G`e2YxNA(eW)_U!zK5p0vD(da1 z=4|ke2JdR{p$$IIAkI4jczX;d4NN`sunE1BectV;HXh{HQEl4bBL;Eq+2H@{S$#Kb z<(|L$pxDl8FZkf|*jbH4o7z3l*EhM>?SeLSR)?TXYiNCFM>n*i(WW=FbI^_%q;*tR zqNN7=d_8>DIqs-#Xz&{w{N_QttGWwbuj@hAm-`3nGp{cX4%X}IOIP)K^uu`8V#l1h zA-i8b5q<h#{kiDJ4Ax&k_l-@FhEeRQUaR#YO-p~X){8XgyrboX+3e5l&}wOHvzBu4 z;;D7cI;v%`mt(r@AU>p8VQ@TKlCN$&-yPM8gM2%xl^T4N24AhgS8wn&8houmysKIV zp1zd(+h*wP`N`eX_;TlJw{!DBc{-}C8hqOZ-(e8%toDbu-Y508-;a8Zd_UhesprrG zTJLi9YrVc!_np1xVr2ccxV<(ys?QC|*-?Fd5bvtG;h$XRU9I>3*0XQxeK=X`^XAV4 z@}AXmF=kM{j;go84;{pZRENW7KWDnCqho7alcx{L(NTS=!H*lnyQ)**?LM{l>Wsyy zgZw(G(;NIN4gR%3d`NW;eE$jkye}W$ezUdr=)<|RG5Vb?oArzz7~7lo#QJkv&wEg3 z$3SbpiZ8czt@m}tMB|pAnmB2|*IQ^^t(<K8)tH{~ybNpKz4)HlyevuX!+X11xhEgi z<87SxSLb1yI(neBPA&kKYwW@Xzqr9KY4FP${E9(*uIg%d`<|_%x^9rIqxwOE-_+nY zH~5bl{FVm4wZU(L5Afq5Z#UeF?t<6Xir(G{-BS*0UAEfm@a{(JeGUFVgFo2dk2d&Y z4gO?<Ki%NZHu&>{cxUw@yl#7aztT~?JIJS_dcVOxZ19g7yptbXl;^&y!G|{ZJPkfy zgD)_MceZ{mI52g}_Wo?n`MNWE!RIMy2B_k__^fxnE5rTl%>4BIu=8Ah-~X<};U|0; z*tMard))%HP3+ITTu=HQT=V$)^UC;&_4Q*O_pI2&+R}!z;rze#Gr?WR>)P_;`mzt< z=|ib8B!l8?TNx)eZX1rosWs#5Lm4MG?gWm+sWs#5Lm4MG?k<kRsm+RO_s8?2pMx1c z^QbL^=9t-U>vXK$Q&s}|2_M#`E$+{VGv135W!x}wShsj_ayYCja`;&hZks&RmxTNC zG_h?P#=rg?O-&!|^HXX!pYfhgZR*3YEJ&$cEjIPV;mH$y30n3k^c6YGy)32N_FDIH zlxpU(uHiLS8^(yQPAQJA&pNe_c^0FU>r$$(SL^cSX{|p8G&cRU&Bj>jqs=~9%7^hY zEPwc5ob9nrkJP7T9rj~$N^?1e*1ZL#cJ*PPEh){bW)AI^+IFCfZGl?X&;IUS*z`B| zNJ{PYV;E;^A4=o3t9yv`voz*&l=jnO^O_%0^W_-*&)0Z)u=|AExGz$A-qnngyLV)6 zjRLR8F$c$5*hf+JaQHEPG^M^}y}dP$e;?d<{rhX%C`#*-dr>w%{zrh#ssBK2bL{n( zPpq~09|?DUC7<s@(jNVftGWK_U*@Q)6OK>(Nics$ApA72V;}xC@Io~={vr;`<hvZ4 zc=c;J>~HKhf$dNDtzg?5eh1ij6@E9^JtO=fu;)Dd5pddPeNS+>repsLc%Fj40G_wt zuYl((_#0r?MdIH9J5R&^175J;bJDqTJchy-F6;}y7b*B+@I?#041BSIuLyT9Nqwuq zmnit!aDT5O_9NkbmSxn=0_U7KU(SX*R_gjYZ%%jctK+v1zqrL`*}vQ3C)~L<nOtX= z!1eLambk0HRdvGF@w>YA(NA0S>ua7I(SL|;zNUU#t(ikx{C`pN#6-Wd){`ggdjOr! zHjcwkCYa-}K8N;El=GlDR%<f*-2di<$2LDWb4K3<;l`)Vh2XX?N9r7o&WAA>(wdX6 z!aYCb;r{s#bnA4UuTj^(HYD}056&F+ob3qz?L!Z38T+|#{y)?I0!Y?~{`bP?d3@z9 z?EBsrZ2Kq<`2lpACbjzR9wGOhM@{=dHTK+VmwOKs`=}bbMzqVl57M4|-uuXx!hRNb zbFl4oj^;kdb+bI9<n>>l^003GY|puro=W}9FZVt{P5b#ZHb%ZMo%J+Wr~Y#98`L&o zl#H`2e$?JWaqRRRPU*8S?k#TVb8WbGpKHTM!hNm{xAZwR+<n96)No6mQ^SYDeNGLx z^x3rJ(+h4spGix*&!pkQvHMIKZt1gVxbZ%Vh7X7PEE;a<vuL>X3kt68vt8_#KHG&4 zhx=?7?)Y3*aP3zV+;!=*UHmP5z6;mi=ev^od>8J$iO+Z8mOkH=+~>RS^|1SV7jFD* z1s@K-tKj<iOc#I0&u6-D{e7kjxAd7VT)WS7;g&wrmHf$q>+dsN?2ez$bm7{cZ*ZUK zVz+#^;I{Yuf*bGiT<P!gT)1|h=fW+0o-4V}bK%3W`#cwJdwre@9}f3<PQGo`)w(|# z1NNS(r#`l1-O+?<EQhwOSe1v=JTZsD6VnGy%wb?{#`IFk6XUy)#CQ*tnDJn3$5QVo z$_X55=J4K2o*X`KCWrS`$>BRHZRT*l_1%P;IVRRz-%((H24&t;*k$BLao8U96Kc&L z1gfWRqrkqTE#rJSYn*!Gz64e`F8PlIn@^kV@%~ROZ9N|BJ)bu31?B12A)E-W1=`&A z<l5X@zW_eCwz&t&M{wq}eG$ADr7_x!cOO+x?y=zHc8`>6o1eHou-6dd+%M&cI}Ggg zM4Nl3d;~Mfd%k|~(v;>iPP=~Y$=bGMe4TqofYrPXC+|48`b65`IUEmGJA)Yc1hAU- zOUW|;H;?zU$ukkIo;*j2Ig)1*Sgp)68Ezi$g_CCrTs?WFg4L2|8d%LdBkOTL3T`{C zL%V(VdZM1Z$AB~L)4_6Wj{C9TjJwwrdE&kd&bWJxkvr}b)$#n}J*@eR({9~fyR;?8 z31GGB8Pj#~KM}0vd3YE9lfiyIpgr17;&_L{YqB_bP6MY8r-J3_!x`Z8!E2jboAdIk zVCSK2^ExL_&aZ>hKd*W65zH#%z5(8q(z?uPtUl)P`l>y3oC&rL=ZN<r-{d%t!+W&& ze5=+^#>f2Mh8w3oUwtmW17=uSzaOgIx-OtpPn$0Sr_C3F<*|JioH4o>EKmKHf-?@6 zfaTg;LzjcQIjrw8N_pb01lwP2S5V4FaA#~Et^yxKX&Y^eb(-58`ev;3OTO=c%dxr! z-W;p%qp4@Ct_2&XZXSy2dj3gYuLH|7{x^V|Id4Q$w@p8wl#9KWFu!?S^FIW;Cu;M) zLN4~6qTD-v4EK7Y?G~_Hd@H5T5hHlQTp#;S;3Ft)qxD*!dCg~>{>EKRsc-g~pMpIn zJ{zacx5L%5Kl}`=mi^%lu$udWId222nbZ58pM$N(=N@yq9)AH>cP-vY>BqIG{(l^= zakv)6Y1=(u^OV=rd*SNVdpD(A{{_f*KUn|Mz}D-&^Gmq8{`XPJ^&gJyS780UKhWQ~ z_G`Gh{tr;f)1Kde^)Ii_55d*-e~?n1wf$SLYuk2OxB2u*UB3e#&T%U3vF_i4jZse< z{{Xg5p9>TBFkC%xkARI;w;gv;swKxC!RGK;FFF1MSJ(ehN_qPEIJnu*C(zXOe~eNd z|38EEFVE9caCQBkq?D&U&w%wW$NevGb^V{Fl<V((-VCt*ePG+~Uh*7VUH@k(<>}jB z!H$8p=PBjcOI`rGm)K|fVcV?F9Qqn#tbXQmt-b_yjwk=$z^8DWS)aF;!D{*?=I>x* z+*{1?3fO0O_2hXKY+cFo53riPC)T<D2{ykr+x8-*+WV{(*O6<+wUc^Z2bXPq175cE zUvM@367wdwZ0lQa+p3<ny$$yLhqkos-(d4;OWV}Sw%JDc$&|MB9ZKt^sNUnB138R+ zmr}0Hb^8Ihr?$OMDc9yY`44#i+V&x(JUKrGkFISWQOdI({|k0KT9-ME)hBJ&o;tjl zvkvFr`IK|O&!a4_wR57W=lU@h*f{lEYdgTX)@rvdpL^8P<{{v;x%CWG*yaXjjC>xF zr;YQ1GY&o*$+fvY<_CAvUhDHYNuIa`!OkOXJ~PR)J{AJIK5V0Hu}*WFL*I;*e&u=f z{3idR*v!9AJ@*%btNDqxc&#}$(Uzz+rWxygNb9}Il4!>3uibfR8+^~A?IT9_GaSBe zvETD@_?eqyQ~Ypgy<c<g`R>(sFKQ=nScad{;9qI*Giz=i=^AUGo%bH<m7iQ|CsEqI z6KXB~r^0>DcVF#)I#}&Aj^sE4tezaUNi8|P3NCYe9j^8@j^y|TSUoxHhgx!+1uk=( z4Oi1YInDvACx?AkOOA8FYT@UBttb3^ux$_jCinyn&#C9=TO8&vPG9XGbAHrwE*(?v z`~57)k#o6FjlJG4T<D8{J;%P^&N;mRT%O}g8~n-!zox-&Xz*Ja{PqUFv%&9g@CO_G z4-NiUgFoHi&o}tX4gOk#zun*;G`Jg6IX?c~M#=p<jgtF!8724cFiP&<U6g#42KVnO zO1pnYQF8x&qU8R~M9KYIiIQ*A;5#(9e+yCi`!^6J_wOD`?%z3-d~}2R_Y9@ozhNl3 zf430s&qK~>aQ|*0cFW5f+`nBY?f&h8JnQH}u=C${GOmw{In*xVh|hPyhj7H_60m;i z?n|x-wfJ8KR*U}?V71FR^momu#s4a>{&{b8HMpCjheKQZz6aK34%eAHw(o<>I<JGP zUCWWY*MpN+dt!e8)@I&oDCM!;2rl#93|G5}BYA%aPG0Sa{SjE3d0qGN*nSKy^Zo>` z<}*|B-Ud!y?TP&<Setp>Kjg9f3|!{@Ib7`yj^zCXIC-@v_W!`z%zHbfJhr>QW!`(> zYIk!a@4evU)t=b<z}n1vC#5{LUxLfL55U!&f64nRaPn$T?61Mv%<H}=kL@?$GVgEU zY7cQF@9)6Lt39#52WvC0`>Q;*hrwmuN8xIZa3t>^!O5#Vv3~+<Gq3x!JhsQdW!@*@ zYEN(^@1McRt39z#fwh^}{azm1GvG4svv9S)a3t>xaPn$T>~mmk=6#w{9@}5RW!@Lz zYA<jk?@Qq1)t=bDfwh_Uc}jU~e+QR&Uxll^!jZiH04J~Z#Qqbk&AcyD%42&ST;}~3 zT<r~x<b4yIyxJ4{7Fe5kU!#=A_HS^R_g%Q!I~>XT9yocmC-!}?HuJtsDUa<#aGCcb zxY~a>lJ{e9@@h})f5F<!`vIjqwmIe)oOdp`+MFE8+W}5q?TPIKYcsFcd3kI@z-4>q zhO7De1j#!OIC-@vc3!YH^LoD^k8OT%nRh|Bn!lHjy#6j$@@h})!eDLY^}a(M+oIqy z@8WPZf4?DlmjEZP_QWm;)@EMsU*xeZ4KDM33a;kwNhI&G;N;bw*yX_5%<FxSJhm0U zW!_<MwG}y%cO`K0YESISU~T60eo7wOs^Bv3aJbrP9Lc*nIC-@vb`7vL^Lk$<k8Le* znRgwyn!o>%yz7FKS9@aD18Xy{_jmHxHUM8)%;!(TuYvpXqb|w~;rgf>@BN@!;x`80 zP{eNnzom%Z6t0iD@!mhGC4L0>_9A{W_?<=k=5T$~jrV?2E%94|y;g;91@{`0_HV5( zhr03JpSHBB{fxLR+-pbTw}ZRqCw_alKI+DMKdTo19l`G9;XA?IgA>0qTpxAgz5i8< z|E}Omi}>B(j&bhwb_eUDo|rwrj$?fG1nZ|BpS{42Rebga>!%){kzmIoKKp?6Q;*NS zVEY`O{lNOE$LF(P`xT%4!TPD&XYcXV;(s96>q+=QaIXUyvxDLKs2hI(rCR(C0lUA4 ze;)3>ocJ%m^-(w8X9%_UcY~{fj{>_-CcX!(kGk<bbEqYL4A}iId@Ohoj>PwZ^-(u| zG^JYn4+Sq(@Wa6FBZ=<^>!WUbAEjF2j{vVy@Nr<*b>hc^^-(wea7wkr4}d)<;S<4& zFeE=<&96&239fb|$F=MN?gNv->eqtR6FUX$`AOYV!TPFaK1>5!r?$i$1upA68m?yk z)Hxll-mLQ&G|y@3{1RAS_0)MR*m||4&f~ykonMBl-Bi?hJY2n5=Lu-egVcE<SYP$j zc@o%qwWZFJ!DXGNz}0Ro>O2*$-mLR9H0Mt0JRPjBdg?p_Y`xl2=U2dGonM8k-BHx} zHMn}S&ab06-%{r{!1}7E&NIQ*tIhc}fl@8?p9?P6_j&Mgy`B%R3jc3{=PUTPz~%b* zHr)9>k~fBDQGSQRI?QV><BieJ_MAhhPug=K*!?B^BDniS_{H$9!vDMAMGAfic=>`~ z3U<AvJ(q#4!@TA)-WdIC&jpnFq`oV_o*&;^523sgZkyHPa}`+K_{%Bfv3(C*#$N-s z4)yqaAFOWt)s*tst^<3{Qvdbfg=t5*u77~0o|qfJ=E=Oc5v-4Td~O2U*6brUgVmg4 zS<^p+t7qON-;dDDsXg=T7O-vAmbU&FY+H>_y|<#NhyMg@Thor)z-nbXehOD_w&Qj* z^Jz~zeg?KJ+H$XT2RQdy+Ee$>!P*@6YboWi{Q|7!dsK1WqYkAnOLO>HoFng1m#Faq zluH)+QefYsE<>63sCSXixfFhXga4|*A8PQ28~m{bf2zS}H28}R{z`+t-r#RH`1=k1 zaf8n_=ivSgX>h-TqU^ulKT&eOd!poi??lP{&WZ4|soU?HDEamUSND4-Vz=~rCra-3 zPL$m5osefP+)W*x-^{Ul;A$5YKKH^8DSYmO>!<Gg@|>$B=P$u($@u_S?Q(MH@0?JJ z|F6ONXHGu|&Yad3zu$nhnZtP`kL|bMvd-VZ)m&G}`+IouYESGRz}n2~e3Zxb2)NAq zC|u2Jb@KiZp1j%<`zNqA^E$8Pu{{nh^F9Gr^Lm`TPr{Q|dt(0#)@EMUhdj2Y!DZfO z;A&oTllL$1<kg<oXTjRc>pGLi_8hp(`#fCj?jrAB;mNB#u`htNnRf=IJhqp>W!}HR z)trB6@5}Jy)t=bDgSDC0buW+YRdAX2A8@tuJ>fs$$*VoFuYt9h*Zo5t+Z*6A@4w(` zj}+~F6P~=<6Z;len|a-b<gxu5T;_cTu2#M$d>5X)+7tU8Setp>&*ZUv050=>2v;lL z6aELDyxJ4{5m=jf-52Gt{TE#3<uXvIy-<w99B9d_J+X6wwVBubRUTUh*tH$r33pBA z`rHNAN8Nb$W3~7X1-sV5=Z3pR5<d@IA9ds1zt!SDAK1AcK0ka$5x)RjA9ds1@73bJ z5ZJjGzA)T5l=>He>!WVG*9W!uF9vpQgf9;FoF;w=xIXH}dp%K$|59MjRru0y$2jrJ z!1Yl#-s_KA{Fep0KZh>|_d1_@nC0PWN8*!vsTJVrxra&YifEpn)IAKWuX?TxD}k+3 zTjEv*mvycJS1a$ER)woK>s$@ZbDBDbgY{KUovVYbS6k{_16<a*CS0w2CR+=x-mG(N zH0MF;TnDVLdg@#kY`xl2=X&6>&h_DH<ulm^aP?-LpGI@;q|Ob&`l_eSjlkBcEp=`T zF6-O`uIBY2=W|oIdb7^YpgG@C=LoRA>Zx-xu=Q$letAEmmio5<m+N~=c)4D;f|u)W zYk0Yywt<)HV_UfMJ<mYf!L7r*<}%(G{cMl-Q~IPmJAmC^!gqwbUxe=jcm0R&40k<; z?*eyyhVKe@y`??7!L7r*<}%(G{cO+nl=>uo53uJa&l!8dZL@lO_5!OLzdNNowvpg6 zejm7XsK;ktu)6VkQ_5reEZB3F`u7KW&+mGV&jD!a;Rk|k$9(+8hVN(&0^`o#rSVP% zY^*-<KNxJinMa=k8>1edL%`<DzVmsonsYMq^b2tH%+uuiBAPk1XI^%L?VGmrZ4}tP z8J~K4(A2|6gKca2HU^x&>1*HgiT_xz{%LnFSgmY#A6&iJ?nBYcuRZNP3~bxA<$kDN zjW+jiXiwdTgSB~H_oI}@HV&+&?FdTw2%h_W<{J;5mr~tlLV2DEmqlNJ!_RUYc_v&Q z?6cpBl&NDPaq4ONk#IHpnYK@Yr|sGkI~lAke-APRtQPxJaG84=T&=thKMJ1Q+7o*; zSX**W2dl+?47kkwCAeC7FMcdMxwR+uIIy<l{xVoCe+zLu*uGe&Hpf@39N(1~A3x>z z4ud<sD^sSflZaE#_?`?`EAQ=3fv26?6MHIHTYgXbG_YEJPx}n8+UXpL`3ktK@2haN zyJ<tt=hxt=PkUm&4%U|Xz5!NCeP@Ez%KFZNm-U?uS1X?d&Vi>s?Wylvu(s599#}2) zoex&CzMPwHYUi*m+C4XF<+)jvzWOQ8%_?xu&1#gX|2xE~Usu1oz5uS~{_rkq?jo=s ze~(?;g&b<;5nJ~qHCIpG%fMyc%i(ISDf3<l_G4acS8%AAS8U#^Yp$NW*MQ5s--oNY zp3Hk4*pGR&UCW_nUa@(vueo~i-T*H1-UwH7Et&UbupjekyNN^1ykhhIu;%K?dkeVC z`(wD8bKkr_0sAqpwp%&W%quqUZ8cX<-rK=t-k-tMoa5&GIoOYRwcWv?W?r#*e^GOF z`JI&I99pZLqV>HQo04-ld<_n<?_$>EFrU{;-<xT_haB4S9_`+mr``9#jdMTOCU-w~ zzrG*ryj9n3E;VDd{}OEd;lFC|U&D<#pM0Of??JFW>i!*p+Hb%QaA-@Ohrq_=_rQM( zR?|1X_xwAs^=osi<Qc2=$vc9>&juVBpHJ7=aoMoI8`XFn%8hI6m~B$vO>4X!<!3k? z=glZH&JR<6#@RfN7To&&RB-(sZ}2A@{HX??(cmu@+%~<^;IB3Kn+^U>gMZNA9~a#I z_?@X`|2i7n?@Eo`zkBw3Qp1h+ds0j8cchlw??(-{Kid{u-S0z<-O}$uExF%^8g9Jb ziCS{M3$^5a2Wq(OyR6{D;eO|7?3RAdY03S5({SHs`~9ZjmVUo!_(=GSf~&t!aO3@6 z)A(EZy{0AidriZKWA}SZ!_DvamWG?p?<oz}-|r<2Z<PhN|9<yq?D~&taKB@;wEKOc z;g)`%sAbmhBg`MymHUQkL$1v=|3|RvOq=UOp18-ru1#&O8M!u}2c7`CCbhYK<gxu3 z?E2Q`T9U{1G*~V7JI{dCyr$;<<1g^s4`@&9vtVuJbxq1+dk$RYeIBk>-lzT*p1j%< z`vO>-d0pG`*j@scdH)7iyNUj#y)VO)S9@ar4%TK~_XxSqDW2n3!JZ5It-t5uA8_@b z;j=FMpJ26%In3d{qLv)5gPS?tKvVy5o#S6%wd8OwQcI4vz~*qA(vG*`>S@Qn!D`9j z{-u^2?}D2--a}JQJKhJYC5L;ST5@~{HizSycKipfo_2f$R!a`|NwwtoFSwb5VXM^B zjyd3J$>H9rmOAGGyAB+0_gQ&torTRkS03At!q(b<;kL{DZ$7YluzwF}Ub%m}8T$fY z?S2=Gc6sc>iC?(3`!|5v<$f=We}A(GrPn{pcbG?uQ7+EmNBa`B-O{$Yc9#UZX2X|) zdriH$o-<3s^-=d8NxmqDxvfi_*k!=x%6k43T&<6MwpE*2{Fei}cEgv4m+NZ<xLWy~ zwjw<1OM7C6fwjq9FDrpvBYBswGF;8M?K;c5gjLXt)t+{*3bt+9^1QJcSUrEkw>ntO z@7}R*UPsl^o;ATUioUG{FZ;GOT<s3plf7ddc>1P2xz+`1OW)Q5yYAAr_2FvGzHNYJ ztoHQn(_q`CEq&V%te(DY1XfGmyeCjgdo}^PhlOtnFZ=cxxSIFa>Dvf+`ldaxn}M~Z zZ<~W%%jw$|aJ6RNwnQ^ld-}E&*tTg)-?j#;r*GSU)zUZbZ`3@8+fusL(w6PO?vdZG z=hXIaHJ=-Hr1ayOP~U+=%{3u5hx_<WVCP2mrJccEKg+#-7c}*>aaXW$>WSM8?0#0p z?T)6NXW%`+#;V(&IVsg#`)QkH`nM<8y*K^a3$AAWMpF8*f9iX4sM$Yp`nM0*`H^<+ z3$}mdHDo_D_4MzvVB^#iw?DXf-8cYEJ^ecnY^=Kd>!4J#e`%X#`gai6Jw5$97_Mgj z4xvo{)IZ0eX8*+L-{-;3k+ky*VEb2Io4$yqp8j=%jZ;tDC~)(7)Pts;{*4A3t8V|g zDAnv=+Gd%yjRAX(!^eWXUj1LaclW~eQIAg_*l`O#6kNs}2G>XZnmSKE*j(BYcR1Mg zg&zSf^NfS*qn<qD!RFHDIT)bKInXwN<46wAf!Ka8R&#a7WD=!oKs>p?Q)-;{OoNwW za}?Zu|FrJY(O`Yl6EhuL#vB8;kBRvbSReKD=~%G2wArSqlxoTOWpFv($HT27IZpuV zqn?-(!DY-z@Uk5z!}U>5J5B+cOPlRDj#4c-PXm|d>vXv7_<21ZXMpulPs~@qWz1LM zwkt7T1M8!nc6=RdE^W5sR7y2-dR_ho*fGlfekNEg`+NM(LMyM|XT#Ovmp%U+G}of` zT+`15n^#-%od<SIQt$a-wd9N6H_^&#>$l))@k_nmM)TUOJ@tMEY+h~gy8vu^w55&< z!H!G#MPRRa*{3dst7S~T3pPeQ?Y{)9-fY*UXx6FS@prwbS(n$N%fX)a@GHQc)A@Kx z)P5zH<<)w>q_6h)UIlhO#P@1&e2vp?otIH+GtT!>*MQwKljr+zePX{B?B1C7O4q^F z^gEIHX^!i`=Fw&y-=kDBhx6(O;BsEw09VWSWFNi}%~<uc=O(zif2Z#l+zhr~9@@rJ zhxf`q1Zy)+{v+@V+I<pjl-~l^M?G`m$6(u{Ep5FO>|6~03E27Yy?QO)2G&PC=liE% z^=5x=N3%cWeZkM*>gmrN;PgjZ`tx(Jw)E#0VDHD%pZ|mFqn`fU3AQcTGRN-%+fQwt zo5_@F>EGR8&rSF}VEdo`-V4@8J^j58tlsSJ{b=^Ly#D?YuAcrr08W3krN6%dYfFEB z4fZ}Z{e2Lwk9zw18?bHBmi9jc_I#zSzXhu`+xj~++gi@G-^10@)<1yLR&8nP!(eS` z>m%TDu00CZM?G!*BiOcR%enaz*gk0U+)SZVOWw!9p0DsH!1|12F3!)KeiE#YdVHP& zd%thKKZE7sr`0*)_ZRS_+V%{kJm2N@EO=4!8*iL;b38_=EjgY8m+gBVUbgSAaDCJh z^CCFydjTvr_e+%e$M0ou+V?lGJm2y5cd)-JYrJvV%`t;gn>qa1>MLM1e=hV7%71dG zy~=SBKJHDg)w=gQZ-D)HU#<Q+M@L8do=2Rv{R`|^<U7pX1gp8u&GR-md9=O7F=w4e zoIL*qo5!|0Ci2+c0hiBh@50rrBhPK`!SmdvJ+beDwVBsFLmt});4<%ra5dLK^8N>& zyxJ4{5m;MmtjQ~n?PGA6_rGv8_k!eQSZC(dp4d6iwVBs7FZce^arA!Eu`BO4)#aWq z?Vh9L>I9ePrVFl?b2Aj|$8)T02*++5<`E~)JYf4{n|zNf_d4Z!p83FYQ}==#`g;wW zA5C3<-!sdTYXNY1p5?JE2rkEMA-Gz3o)?Dad}vSXB4BOS>3NpNwkWvFyBJ)pJkN{6 zlUI9UmjG)s?+o(FV_Onj=3NS|R-Wgj;mNB#vCDw9nb-3y&zOD++#J(o(bV<vJ^6Cr z8H~AOlbp+=spp--3ShN7x2*_PJDvKHXBgZ(+55deSP4x%c~%CiCC@5gwKC7DaP#DP zXP(v2)RSj8SS@*02dkMUKMP+2Zab|*d%iDhO|WC2J>#?%IOF6v%JtK}9`&zN+vlfU z+U0(abjE94u;(vhv0m+e1hM+d_0ivXy#d(!ztsQf+TZUe(_gNS{_eROfoIfp`|}lf z>fQugUN1I<m)DEW!1Yl#w?B_jOItPrd(GD7&t~Mwy#+Ye3;&yOa`zqI;cp4fm}TyG zFS!-Ew)kyb_+@VBw+*_s_-$MG<=pGHojx472j3p-{ln^Y4(+k+P}ppTzIpE439Nlb z4zDM>Q2KGt(zY{)ntPVG+#A*9Lu>nPlo`L>!H!?f<sNXyrH9;(sa&6o>7HQ6G;?LI z+W*MfU#^e-p8LJQGirZ-zBaP<@2mag`Xv88;Br3f3oqxxesF!%ZNmcO`7GErpH}CT z>!;oMzkh9?2Os++FX#UO@N)hiSo>%G%k{~a9Rx1t|G~9?=D%E@jL{)r$H4dE>F4Ls z)Uzji0j!oi;fr83_k@}6so+<^wb_r)QFe1!kJq3caOQN{IvPzqZ5ac$Et&J~Ph-*4 z)0SSaTH4YFRx9_pL*eGhnlR5{XzIz+4^~T_!@+80o+IGq$(k|GI5hR-84p%Vo(W*J za=#pa+fM7yp8awn*fG%Vn2n-T%lJ$JtI1ujlfjN_o^7Xq^-(weNJ=&Ry;qzH_V*ZE zlShI5xF*%7ah%QJniQwb>0sxN`Hlw5wb}PCfwN~F1D5CelaB@ayDP?MGu}Mv$$cC+ z`=QV9a?ibc-j~7p=iJ-h<I&XfbGj42YWW$P?{w6X<3w;X$4O}F`8nOmV727%oxECd zoB}pS=8o++6-_<uI1Q|p9KPdGOODgQ%^YW-siz%Z0jnj4@6Oed<EvnEWbWCHuc4`@ z9bX5lC5P{Q)RN;H;AW09(bUt9v%qS};X7_M_hjdc^TT;k?%C?)o;|eYxxcm4K0s-_ zrF`+4Tgn%y`C^pL5&L)^x#leR`S1>Su0!91dyVpUmh{!0*l&Tm3g2%RzQ$?K*n9`< zesnISb5*W?=K6(Tf5xc4_i`7(^}m2pf4M%|-N!Gk?e62|aQ%H3O+D}8E&;10=2EaZ zz4uAXWoYVoUw1j!ICa<Ym6U#5$J(yoP;;Ecx#nL5&VF02sjJbo#qWECUpeQmLDv?) z?-zdMoV*rYTh7mQ;M_x)Lwju37dG3WZ|)&}0M@=EhyA>fGX2zc1BaUZ6lV-?0^84A zKjmw4IG)}Q-VC0XLw~PBKLlr7JdbjHoR7(GnfM=pM{p$m7O?TT2a)TezxNbB25-or zzxNckg7xnMTc2DX{oPZ4qMbv3=h<y?{BwPm>l6Q<f;Z=g|LtJ?bB`m}M}ObB{0zJ? zhyLD=+yU1AG_dWF>tp{jk1UN}AD^Gs{{H@*IKO}A*lx$+XG@Mv$z}Vus<C6eb&a>6 z+@{9r+j4jwx2MeSEZ#|O<MX?AcNJXymks`4gFjku>v*x?#=lf>uQ#t2T>D!EH~#&C zYyY6&Lm9u13a<U*f*a3p59*Kq&0+oQpY?YXT;2cXaO{@;H;2RBU;J+l%ROg~Ro3+8 zXm`W6q1>Ap=y|yZuIAy#^~hE>^S<FebbapSIFW`Lb3gb_oU~bo<FA%^_W<}1{K9_) z?}g`m;jiKPs2lJ3QWJZwY_D_dH(<}brN3A5Tgu;Y_|g9R+HRS;{s1;d_`_iH=l4n; z0qdjgz9@f)!`#*-PV67S&e56gG~sF&p~dGhxMLij$H9N%P<KBZjqelSyfe_A*eAi- z?6-4L9^0S6YWcnIr@(5CjeFiRU_bUj+tVCs_Cf6Uq)+O}`z+YJY1<5N+NLdj&w;h2 z{^!AJss9CV>eu#Hj(>1izc_jR2DU!?=(>{U_laKyuRs!Y{heEX2fG*etRQ~{uAjO& zT&rqg*QL)9_SN=Sw{1w>{{)wPeGQ(zYK!0NU~TE^8(=lBagOzyU_XwvwtsP`S)Vw0 z-Ug?yZ-M3M>%YPFRo!>+_U#?8>upC4?Z?++@Ge+e`YX2%?|I$>A4i$~%k6*KV_A-e z<C6A$2u}OlqvUDdf50n|SKZw1X=;i6Z%c36+`r`7?8hAJH=Z-&+{@&#%?0+HX>(tb zYqKw%V9%j8_c(d#8v=G6YisRyg>7!IYg(IopIq#|H!n@de~(~ZxWD&pdu^BXTaWpS z)89DvXMMfyxqr?FRx9t%=0{V{{n-LwHGdXkUls(bIUl`0HrH_Uh0x4ZzE52kO+C+M zi-6V4k#SoTye;wJi@_bo%$>#InLFCfr#{=U1lU;ZxtCfJtgr8CwA;Say%gN~^|7wa z@mU(Y4P~wo%fQt<{FsXrGu!qlbmvQ+RhNYuqaJNJuytumpOy!wPquvpxVg9E&=$WH z8-BwIKW)}w{7PVRXwUn{mBH#ceD-$Eu7YNpw5Og`!FSP*T<2DUtLf`J(Wd6P_4+y- z?76*w!yMkDt&XOyzw=if+Zy0I(M}*<-!<WC?lbypQ;YvvwSV~9@I&yuk$9gO)`9Dz z?mo31r62bxZR>KVxlf79Yl6Dm>#252d9Jx$JFM5S+5q3X;NI7X%lo=rTQ%}dk23dl zJJ#5H$en8JTG+Y9j@>RC*1H>}_c`AGZbWWvxzF3U;O5%2;QEay_!jUj3O*dZTfz0; zz2MsSD)`>ukqv%G!MzXbYw)8R{G5WD|H^_}|MdmeenY`+|BVILesj%p{x^Z|i0)i* zY~<R!cmE97vDW4|$rHC3*zwlpn91|=#?8V0ywQBdY1hwlp)GTLOR!q*C7r)p!PWDA zYiqDt-fwLKRx96=Z3{O~o*&J#9b7$mwg;;v&kkU<GS7~1^W^!`JUhYFlV@kJTJr1y zR%^d+Yk#-@u5jCF9opT$?Z0zLTgGq??e-a)^GKd+=bqqIv8ii!-l>V5W8N#9XB0mB zzz?VVa?SUJtLf|fle-T0qjY^(dhfeG<pCUiv>#a8EtC5ousOmH23yxH^?va=xIXIc z5%SM+nA^I<iTymdZ08r?YPQpLA-5f0q%_vjc8;R#;qaq<bZxgx?lE9<gpUQ6?d*l? zqi#Fp-5ln&F0rxh`G<lhQYP17aK~Vvw)cb8a*a3~Y>c`w&YL5^p4;62jf1O|bA5cn zX98T!d7R%T8GswBEx9Lx%iKr8)$S<bCc%x>mbl5_GHwc7?d~FOD%@CYxeu8JR?mG% z`h66deb??ebT3o0KF4u7xE#l0;N>`e39goW$AXPfPn(Yemu>zsT&-NA$2WXVfUEg4 zg^c5gaAUQlUnhapoBcW&&9-Q_Uq@4_rC+Cj%YK~-ckX3=oCa1)zfK1mqn>`90WSOX z6}VbCKfc=V`5IiUoF89@8>=n-`UY6N*{?IvY>W2v<t(uM^Zvwhb~ac|-}GHA{^x?r zzMls#`+h!LEq(tc*ckQn{afI&@85>2Ie+8xorcc^aJ6!-UI;f<TjDMPm$@&7t2tjX z7rqNOR$JmO0he)?!qv(-bQ#=OZ5iv!!RpPiz5>m@Yj+≈WUz$N4I->m~eZu;(HC zdthU7&v^~l82z-F^GZr}W4x#OK6vMP4CU9t^~t^Gbzptejd7p)0eDAB^IZ>?i*KOR zU%$<<-vr*Gw%tf6PrW|`?^fGxrj+NuP4pwM_ul3<r?L7NI|}_4@KnmIogc&1((hZr zYB_SR{S!2EYfn3F1MkI={{9rKrmua{rsg%IhthrDGHtmX>|FL<+P3`+tkwrMUYlBZ zjT%++11QaBnS6JEM{*?J&%tWRr%la#`%xOdKV|y!3$ShW9$8%8Bkx6<{Orz=d*nT8 z?0w#z9Om1bGWWiBkz+`~?{Dx23+}z??;HGy27j)>Uup2y8vM<g+dt>t-EiBSXP0~6 zYVLt~mvk>Y?^m=Z_CByS&x`$%$M#EbnfC#>n)_z*{tBMF+7tV0ur~8LKJwUp11|GE z1Xpu!N#5VWlUI9Ue+SlPUdLG;+aJL8A^c%*S<fSIHTR;_^C&#^Xiw}P!P+vWe*&9d zJ@>GWfz|V~^T)wz!+FnP`#kSz$@wJMu?YV&xNP53a5eYuwC`zn+NV9S&w#b1eSZO) zUp?)67ObB3%>b*Vea=I*<a{3Nn1=rqT(<88xSH3FwC_cD+NV9SFM+kCeSZU+Up?)6 z8LXc6{T-~9_PH+9lJixt=Qr{H0IMbbpJ27byN=Wn|2o+5Py8ETwZ#7mtd@A!om%4G z0y{p5e;cfp_<w`d67M=y^Eu6Z;2p60N$yR&e!YvPZXNRXz_vT@hu#OXj9c%A^wl2U z55Uf`_<ji1cU2DKw5RU>fUP^vcGmR~ntJkm47Sh7_g`@8)>nIc-FTco@tp&nx{cGG zy5|I2ckVT<doDEf<m&)CUdh)9Pu==zk8c;)xe?zXwePCrHBNi3dqcskaiP@DYk*pL z4LFE6Kl^Za4RGJzx5n=C`xW@JHP&bU8jqwrpwJHld(AkQ(rbpk^ICtwmu~Q73a;O> z1^4GvD->M&iUl|SN)5hB!JT`n72NpM8+?s|uZMlDf*Ze1!L4tzf}3yig8M#btAgvl zZNc^5q2|sJ`FwE4Flz%^&CfsTS#Jw~)$-0@L9kl+?qMOgc{0zT)x!Lvo;-_y)skmX zuv(dCF}Qg$XQ9>N{G*;cOMumqXGySH`yEF6=Lk!|ZKri;_qyO*P<K9ifB7k}^G%!c zK(39VT8@95f7+ZA^8BvO@?d{g#~5w;IIq+bKMd@g)#jX$r{0yp&S7oNA9-x6g3YDP zxg^)-+8qwg&pDh|a{ZiB<@s9^-dpE)e#!N7Zmr#6KidCo;<e%aEWq~J4(l_o`Ha)w zIM;x_nKSExJx5;8)8F;b)N_v32dm{AZ2(sD9A)4BG~DM7ZPw#lSF;}1!iHe$E`R2* z5nMe!8`nPN?|^KArk>}eO~J;g`%ZWSr61p;X!{I@ntO*h{oDd<{r)aN`ne@s-S)cn z<odhzwg&5eTJ1kS<u-72{au@K{au^ef%WgH{hgEB!`1b7?aI@h9l`qhy9#N~PH=Vo zUEA_JyX*|!6<^zF-R9HBSnJva?3(adSH3IQ7<Kcx*QmvRH?VuG-1)dW+;f)mxd+(u zsh*#u><KnbTk`A$Hh1#u4K`0=MuPQGKe2AxK45ccvu(CR&1a9CJImCuFIXS1J7TXp F{}0N?>d^oI diff --git a/shaders/rt_quad.frag b/shaders/rt_quad.frag index 848e342..091b247 100644 --- a/shaders/rt_quad.frag +++ b/shaders/rt_quad.frag @@ -281,7 +281,7 @@ Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 start_direction, fl uint next_neighbor = sample_neighbor_from_scene_info(volume_index, uvec2(u, v), hit_facing); uvec4 color_sample = sample_color_from_scene_info(volume_index, uvec2(u, v), hit_facing); - if (color_sample == uvec4(0, 0, 0, 0)) { + if (color_sample.xyz == uvec3(0, 0, 0)) { // not a color hit, so check neighbor if (next_neighbor != 0) { volume_index = next_neighbor; @@ -290,6 +290,8 @@ Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 start_direction, fl volume_pos_z = scene_info.infos[volume_index + 2]; } else { // neighbor miss + end_color_transparent = uvec4(255, 0, 0, 255); + result.end_color = uvec4(255, 0, 0, 255); break; } } else { @@ -377,7 +379,7 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa uint light_num = 0; // initialize color - vec3 color_sum = vec3(0.0, 0.0, 0.0) + (orig_color_sample.xyz * 0.01); + vec3 color_sum = vec3(0.0, 0.0, 0.0) + (orig_color_sample.xyz * 0.005); uint max_iterations = max_num_lights * max_iterations_per_light; uint iteration = 0; diff --git a/src/main.rs b/src/main.rs index a5923b6..9f7d013 100644 --- a/src/main.rs +++ b/src/main.rs @@ -223,8 +223,8 @@ impl App { image::create_texture_image_view(&device, &mut data)?; image::create_texture_sampler(&device, &mut data)?; - let cur_pos = generators::generate_test_scene(&mut scene_handler, &mut data)?; - //let cur_pos = generators::generate_test_scene2(&mut scene_handler, &mut data, 1, 1,1, 1)?; + //let cur_pos = generators::generate_test_scene(&mut scene_handler, &mut data)?; + let cur_pos = generators::generate_test_scene2(&mut scene_handler, &mut data, 3, 3,1, 2)?; scene_handler.prepare_data(&instance, &device, &mut data)?; buffer::create_uniform_buffers(&instance, &device, &mut data)?; diff --git a/src/scene/empty_volume.rs b/src/scene/empty_volume.rs index 42474c8..bde0226 100644 --- a/src/scene/empty_volume.rs +++ b/src/scene/empty_volume.rs @@ -105,30 +105,38 @@ impl EmptyVolume { continue; } println!("new starting pos: {}, {}, {}", x_index, y_index, z_index); - println!("start growing volume x"); // MARK: Start new Volume let mut x_size = 0; let mut y_size = 0; let mut z_size = 0; - if query_result.1 > 1 { + + let neighbor_result = neighbors.test_element(x_index, y_index, z_index); + + if query_result.1 > 1 && query_result.2.0 >= neighbor_result.2.0 && query_result.2.1 >= neighbor_result.2.1 && query_result.2.2 >= neighbor_result.2.2 && query_result.1 <= neighbor_result.1 { x_size = query_result.1 - 1 - (x_index - query_result.2.0); y_size = query_result.1 - 1 - (y_index - query_result.2.1); z_size = query_result.1 - 1 - (z_index - query_result.2.2); println!("enhanced starting size: {}, {}, {}", x_size+1, y_size+1, z_size+1); } + println!("start growing volume x"); let mut grow = true; while grow { grow &= (x_index + x_size + 1) < tree.borrow().size; if grow { let mut z = 0; let mut y = 0; - while z < z_size.max(1) && y < y_size.max(1) { + while z < z_size + 1 && y < y_size + 1 { let query_result = tree.borrow().test_element(x_index + x_size + 1, y_index + y, z_index + z); + let neighbor_result = neighbors.test_element(x_index + x_size + 1, y_index + y, z_index + z); check_its += 1; grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) && - neighbors.get_element(x_index + x_size + 1, y_index + y, z_index + z).is_none(); + !neighbor_result.0; + + if !grow { + break; + } - if query_result.1 > 1 { + if query_result.1 > 1 && query_result.2.1 >= neighbor_result.2.1 && query_result.2.2 >= neighbor_result.2.2 && query_result.1 <= neighbor_result.1 { let start_x = query_result.2.0; let start_y = query_result.2.1; let start_z = query_result.2.2; @@ -137,22 +145,20 @@ impl EmptyVolume { let end_y = query_result.2.1 + query_result.1; let end_z = query_result.2.2 + query_result.1; - if start_z <= z && z_index + z_size <= end_z { + if start_z <= z_index + z && z_index + z_size <= end_z { // we can skip iterating z - z = end_z; - if start_y <= y && y_index + y_size <= end_y { + z = end_z - z_index; + if start_y <= y_index + y && y_index + y_size <= end_y && start_z <= z_index { // we can skip iterating y - y = end_y; + y = end_y - y_index; + z = 0; + continue; } } } - - if !grow { - break; - } z += 1; - if z >= z_size { + if z >= z_size + 1 { z = 0; y += 1; } @@ -169,13 +175,18 @@ impl EmptyVolume { if grow { let mut z = 0; let mut x = 0; - while z < z_size.max(1) && x < x_size.max(1) { + while z < z_size + 1 && x < x_size + 1 { let query_result = tree.borrow().test_element(x_index + x, y_index + y_size + 1, z_index + z); + let neighbor_result = neighbors.test_element(x_index + x, y_index + y_size + 1, z_index + z); check_its += 1; grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) && - neighbors.get_element(x_index + x, y_index + y_size + 1, z_index + z).is_none(); - - if query_result.1 > 1 { + !neighbor_result.0; + + if !grow { + break; + } + + if query_result.1 > 1 && query_result.2.0 >= neighbor_result.2.0 && query_result.2.2 >= neighbor_result.2.2 && query_result.1 <= neighbor_result.1 { let start_x = query_result.2.0; let start_y = query_result.2.1; let start_z = query_result.2.2; @@ -184,22 +195,20 @@ impl EmptyVolume { let end_y = query_result.2.1 + query_result.1; let end_z = query_result.2.2 + query_result.1; - if start_z <= z && z_index + z_size <= end_z { + if start_z <= z_index + z && z_index + z_size <= end_z { // we can skip iterating z - z = end_z; - if start_x <= x && x_index + x_size <= end_x { + z = end_z - z_index; + if start_x <= x_index + x && x_index + x_size <= end_x && start_z <= z_index { // we can skip iterating x - x = end_x; + x = end_x - x_index; + z = 0; + continue; } } } - - if !grow { - break; - } z += 1; - if z >= z_size { + if z >= z_size + 1 { z = 0; x += 1; } @@ -217,13 +226,18 @@ impl EmptyVolume { if grow { let mut y = 0; let mut x = 0; - while y < y_size.max(1) && x < x_size.max(1) { + while y < y_size + 1 && x < x_size + 1 { let query_result = tree.borrow().test_element(x_index + x, y_index + y, z_index + z_size + 1); + let neighbor_result = neighbors.test_element(x_index + x, y_index + y, z_index + z_size + 1); check_its += 1; grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) && - neighbors.get_element(x_index + x, y_index + y, z_index + z_size + 1).is_none(); + !neighbor_result.0; + + if !grow { + break; + } - if query_result.1 > 1 { + if query_result.1 > 1 && query_result.2.1 >= neighbor_result.2.1 && query_result.2.0 >= neighbor_result.2.0 && query_result.1 <= neighbor_result.1 { let start_x = query_result.2.0; let start_y = query_result.2.1; let start_z = query_result.2.2; @@ -232,22 +246,20 @@ impl EmptyVolume { let end_y = query_result.2.1 + query_result.1; let end_z = query_result.2.2 + query_result.1; - if start_x <= x && x_index + x_size <= end_x { + if start_x <= x_index + x && x_index + x_size <= end_x { // we can skip iterating x - x = end_x; - if start_y <= y && y_index + y_size <= end_y { + x = end_x - x_index; + if start_y <= y_index + y && y_index + y_size <= end_y && start_x <= x_index { // we can skip iterating y - y = end_y; + y = end_y - y_index; + x = 0; + continue; } } } - - if !grow { - break; - } x += 1; - if x >= x_size { + if x >= x_size + 1 { x = 0; y += 1; } @@ -509,7 +521,7 @@ impl EmptyVolume { x_min_pos = 0; } else { - x_min_pos = reference.borrow().position.x -1; + x_min_pos = reference.borrow().position.x - 1; } let y_min_pos; if reference.borrow().position.y == 0 { @@ -517,7 +529,7 @@ impl EmptyVolume { y_min_pos = 0; } else { - y_min_pos = reference.borrow().position.y -1; + y_min_pos = reference.borrow().position.y - 1; } let z_min_pos; if reference.borrow().position.z == 0 { @@ -525,7 +537,7 @@ impl EmptyVolume { z_min_pos = 0; } else { - z_min_pos = reference.borrow().position.z -1; + z_min_pos = reference.borrow().position.z - 1; } let x_max_pos = reference.borrow().position.x + reference.borrow().size_x; let y_max_pos = reference.borrow().position.y + reference.borrow().size_y; @@ -534,18 +546,16 @@ impl EmptyVolume { let mut bottom_neighbors = vec![]; let mut bottom_elements_num = 0; let mut all_same = true; - if z_min_pos != 0 { - for x in 0..reference.borrow().size_x { - for y in 0..reference.borrow().size_y { - if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_min_pos) { - bottom_elements_num += 1; - bottom_neighbors.push(Some(c.clone())); - all_same = all_same && (bottom_neighbors[0] == Some(c)); - } - else { - bottom_neighbors.push(None); - all_same = all_same && (bottom_neighbors[0] == None); - } + for x in 0..reference.borrow().size_x { + for y in 0..reference.borrow().size_y { + if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, reference.borrow().position.y + y, z_min_pos) { + bottom_elements_num += 1; + bottom_neighbors.push(Some(c.clone())); + all_same = all_same && (bottom_neighbors[0] == Some(c)); + } + else { + bottom_neighbors.push(None); + all_same = all_same && (bottom_neighbors[0] == None); } } } @@ -622,18 +632,16 @@ impl EmptyVolume { let mut front_neighbors = vec![]; let mut front_elements_num = 0; let mut all_same = true; - if y_min_pos != 0{ - for x in 0..reference.borrow().size_x { - for z in 0..reference.borrow().size_z { - if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, y_min_pos, reference.borrow().position.z + z) { - front_elements_num += 1; - front_neighbors.push(Some(c.clone())); - all_same = all_same && (front_neighbors[0] == Some(c)); - } - else { - front_neighbors.push(None); - all_same = all_same && (front_neighbors[0] == None); - } + for x in 0..reference.borrow().size_x { + for z in 0..reference.borrow().size_z { + if let Some(c) = neighbors.get_element(reference.borrow().position.x + x, y_min_pos, reference.borrow().position.z + z) { + front_elements_num += 1; + front_neighbors.push(Some(c.clone())); + all_same = all_same && (front_neighbors[0] == Some(c)); + } + else { + front_neighbors.push(None); + all_same = all_same && (front_neighbors[0] == None); } } } @@ -653,18 +661,16 @@ impl EmptyVolume { let mut left_neighbors = vec![]; let mut left_elements_num = 0; let mut all_same = true; - if x_min_pos != 0 { - for y in 0..reference.borrow().size_y { - for z in 0..reference.borrow().size_z { - if let Some(c) = neighbors.get_element(x_min_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) { - left_elements_num += 1; - left_neighbors.push(Some(c.clone())); - all_same = all_same && (left_neighbors[0] == Some(c)); - } - else { - left_neighbors.push(None); - all_same = all_same && (left_neighbors[0] == None); - } + for y in 0..reference.borrow().size_y { + for z in 0..reference.borrow().size_z { + if let Some(c) = neighbors.get_element(x_min_pos, reference.borrow().position.y + y, reference.borrow().position.z + z) { + left_elements_num += 1; + left_neighbors.push(Some(c.clone())); + all_same = all_same && (left_neighbors[0] == Some(c)); + } + else { + left_neighbors.push(None); + all_same = all_same && (left_neighbors[0] == None); } } } @@ -723,13 +729,20 @@ impl EmptyVolume { if self.color_bottom.len() <= index { continue; } - if self.neighbor_bottom.len() > index { - if let Some(_) = self.neighbor_bottom[index] { + if self.neighbor_bottom.len() > index || self.neighbor_bottom.len() == 1 { + if let Some(_) = self.neighbor_bottom[index.min(self.neighbor_bottom.len() - 1)] { if self.color_bottom[index] == (Vector3 {x: 0, y: 0, z: 0}) { continue; } } } + if self.color_bottom[index] == (Vector3 {x: 0, y: 0, z: 0}) { + println!("No neighbor reference, but no color! x: {}, y: {}, z: {}", self.position.x + x, self.position.y + y, self.position.z); + if self.neighbor_bottom.len() == 1 { + println!("neighbor length is one!"); + } + } + let quad = Quad { pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + y as f32, z: -0.5 }, pos4: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + y as f32, z: -0.5 }, @@ -749,13 +762,21 @@ impl EmptyVolume { if self.color_top.len() <= 0 { continue; } - if self.neighbor_top.len() > index { - if let Some(_) = self.neighbor_top[index] { + if self.neighbor_top.len() > index || self.neighbor_top.len() == 1 { + if let Some(_) = self.neighbor_top[index.min(self.neighbor_top.len() - 1)] { if self.color_top[index] == (Vector3 {x: 0, y: 0, z: 0}) { continue; } } } + + if self.color_top[index] == (Vector3 {x: 0, y: 0, z: 0}) { + println!("No neighbor reference, but no color! x: {}, y: {}, z: {}", self.position.x + x, self.position.y + y, self.position.z + self.size_z); + + if self.neighbor_top.len() == 1 { + println!("neighbor length is one!"); + } + } let quad = Quad { pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + y as f32, z: self.size_z as f32 - 0.5 }, pos1: float_pos + Vector3 { x: 0.5 + x as f32, y: -0.5 + y as f32, z: self.size_z as f32 - 0.5 }, @@ -776,13 +797,20 @@ impl EmptyVolume { if self.color_front.len() <= 0 { continue; } - if self.neighbor_front.len() > index { - if let Some(_) = self.neighbor_front[index] { + if self.neighbor_front.len() > index || self.neighbor_front.len() == 1 { + if let Some(_) = self.neighbor_front[index.min(self.neighbor_front.len() - 1)] { if self.color_front[index] == (Vector3 {x: 0, y: 0, z: 0}) { continue; } } } + + if self.color_front[index] == (Vector3 {x: 0, y: 0, z: 0}) { + println!("No neighbor reference, but no color! x: {}, y: {}, z: {}", self.position.x + x, self.position.y, self.position.z + z); + if self.neighbor_front.len() == 1 { + println!("neighbor length is one!"); + } + } let quad = Quad { pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 - 0.5 }, pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + 0 as f32, z: z as f32 + 0.5 }, @@ -803,13 +831,20 @@ impl EmptyVolume { if self.color_back.len() <= 0 { continue; } - if self.neighbor_back.len() > index { - if let Some(_) = self.neighbor_back[index] { + if self.neighbor_back.len() > index || self.neighbor_back.len() == 1 { + if let Some(_) = self.neighbor_back[index.min(self.neighbor_back.len() - 1)] { if self.color_back[index] == (Vector3 {x: 0, y: 0, z: 0}) { continue; } } } + + if self.color_back[index] == (Vector3 {x: 0, y: 0, z: 0}) { + println!("No neighbor reference, but no color! x: {}, y: {}, z: {}", self.position.x + x, self.position.y + self.size_y, self.position.z + z); + if self.neighbor_back.len() == 1 { + println!("neighbor length is one!"); + } + } let quad = Quad { pos4: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 - 0.5 }, pos1: float_pos + Vector3 { x: -0.5 + x as f32, y: -0.5 + self.size_y as f32, z: z as f32 + 0.5 }, @@ -830,13 +865,20 @@ impl EmptyVolume { if self.color_left.len() <= 0 { continue; } - if self.neighbor_left.len() > index { - if let Some(_) = self.neighbor_left[index] { + if self.neighbor_left.len() > index || self.neighbor_left.len() == 1 { + if let Some(_) = self.neighbor_left[index.min(self.neighbor_left.len() - 1)] { if self.color_left[index] == (Vector3 {x: 0, y: 0, z: 0}) { continue; } } } + + if self.color_left[index] == (Vector3 {x: 0, y: 0, z: 0}) { + println!("No neighbor reference, but no color! x: {}, y: {}, z: {}", self.position.x, self.position.y + y, self.position.z + z); + if self.neighbor_left.len() == 1 { + println!("neighbor length is one!"); + } + } let quad = Quad { pos4: float_pos + Vector3 { x: -0.5 + 0.0 as f32, y: y as f32 - 0.5, z: z as f32 - 0.5 }, pos1: float_pos + Vector3 { x: -0.5 + 0.0 as f32, y: y as f32 - 0.5, z: z as f32 + 0.5 }, @@ -857,13 +899,20 @@ impl EmptyVolume { if self.color_right.len() <= 0 { continue; } - if self.neighbor_right.len() > index { - if let Some(_) = self.neighbor_right[index] { + if self.neighbor_right.len() > index || self.neighbor_right.len() == 1 { + if let Some(_) = self.neighbor_right[index.min(self.neighbor_right.len() - 1)] { if self.color_right[index] == (Vector3 {x: 0, y: 0, z: 0}) { continue; } } } + + if self.color_right[index] == (Vector3 {x: 0, y: 0, z: 0}) { + println!("No neighbor reference, but no color! x: {}, y: {}, z: {}", self.position.x + self.size_x, self.position.y + y, self.position.z + z); + if self.neighbor_right.len() == 1 { + println!("neighbor length is one!"); + } + } let quad = Quad { pos1: float_pos + Vector3 { x: -0.5 + self.size_x as f32, y: y as f32 - 0.5, z: z as f32 - 0.5 }, pos4: float_pos + Vector3 { x: -0.5 + self.size_x as f32, y: y as f32 - 0.5, z: z as f32 + 0.5 }, @@ -1238,7 +1287,7 @@ impl Memorizable for EmptyVolume { mem_index += 2; //color and roughness - //check which endian should be used in conjun´ction of the graphicscard (might already be handled by vulkan) + //check which endian should be used in conjunction of the graphics card (might already be handled by vulkan) if self.color_top.len() > 0 { for index in 0..self.color_top.len() { let value = &self.color_top[index]; @@ -1419,7 +1468,7 @@ impl Memorizable for EmptyVolume { v[mem_index] = 0; mem_index += 1; } - println!("last memory index of volume was {}, equivalent to {}kB", mem_index, mem_index * 32 / 8 / 1024); + //println!("last memory index of volume was {}, equivalent to {}kB", mem_index, mem_index * 32 / 8 / 1024); v } diff --git a/src/scene/generators.rs b/src/scene/generators.rs index 07eb61c..1919378 100644 --- a/src/scene/generators.rs +++ b/src/scene/generators.rs @@ -121,6 +121,7 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi pub fn generate_test_scene2(scene: &mut Scene, data: &mut AppData, chunk_num_x: usize, chunk_num_y: usize, chunk_num_z: usize, num_gaussians: usize) -> Result<(Point3<f32>)> { let mut rng = rand::thread_rng(); + let grid_size = CHUNK_SIZE as i32; let max_x = chunk_num_x * grid_size as usize; @@ -130,7 +131,7 @@ pub fn generate_test_scene2(scene: &mut Scene, data: &mut AppData, chunk_num_x: let mut height_map = vec![vec![0.0; max_y]; max_x]; for i in 0..num_gaussians { - let height = rng.gen_range(0..max_z / 2) as f32; + let height = rng.gen_range(16..max_z / 2) as f32; let center_x = rng.gen_range(0..max_x) as f32; let center_y = rng.gen_range(0..max_y) as f32; @@ -144,7 +145,17 @@ pub fn generate_test_scene2(scene: &mut Scene, data: &mut AppData, chunk_num_x: } } - let oct_trees = vec![vec![vec![Rc::new(RefCell::new(OctTree::<Cube>::create(CHUNK_SIZE)?)); chunk_num_x]; chunk_num_y]; chunk_num_z]; + let mut oct_trees = vec![]; + + for z in 0..chunk_num_z { + oct_trees.push(vec![]); + for y in 0..chunk_num_y { + oct_trees[z].push(vec![]); + for x in 0..chunk_num_x { + oct_trees[z][y].push(Rc::new(RefCell::new(OctTree::<Cube>::create(CHUNK_SIZE)?))); + } + } + } for x in 0..max_x { for y in 0..max_y { @@ -153,7 +164,7 @@ pub fn generate_test_scene2(scene: &mut Scene, data: &mut AppData, chunk_num_x: if height < max_z { let shade = (rng.gen_range(0..50) as f32) / 100.0; let cube = Cube { - pos: vec3(x as f32, y as f32, (height % grid_size as usize) as f32), + pos: vec3((x % grid_size as usize) as f32, (y % grid_size as usize) as f32, (height % grid_size as usize) as f32), color: vec3(shade, 1.0, shade), tex_coord: vec2(0.0, 0.0), transparent: false, @@ -171,7 +182,7 @@ pub fn generate_test_scene2(scene: &mut Scene, data: &mut AppData, chunk_num_x: pillar_height -= 1; let shade = (rng.gen_range(1..50) as f32) / 100.0; let cube = Cube { - pos: vec3(x as f32, y as f32, (pillar_height % grid_size as usize) as f32), + pos: vec3((x % grid_size as usize) as f32, (y % grid_size as usize) as f32, (pillar_height % grid_size as usize) as f32), color: vec3(shade, shade / 2.0, 0.0), tex_coord: vec2(0.0, 0.0), transparent: false, diff --git a/src/scene/mod.rs b/src/scene/mod.rs index b2e933e..2bfed34 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -175,6 +175,7 @@ impl Scene { } if self.rt_vertices.len() != 0 { + println!("number of quad vertices is {}", self.rt_vertices.len()); (self.vertex_buffer_quad, self.vertex_buffer_memory_quad) = buffer::create_vertex_buffer(instance, device, &data, &self.rt_vertices)?; (self.index_buffer_quad, self.index_buffer_memory_quad) = buffer::create_index_buffer(&instance, &device, &data, &self.indices_rt)?; } diff --git a/src/scene/oct_tree.rs b/src/scene/oct_tree.rs index a156557..e1c4970 100644 --- a/src/scene/oct_tree.rs +++ b/src/scene/oct_tree.rs @@ -191,9 +191,6 @@ impl<T: Clone> OctTree<T> { } } else { - if let Some(_) = self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] { - println!("overwriting block!") - } self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] = Some(element); } } @@ -471,10 +468,10 @@ impl<T: Clone> OctTree<T> { } else { if let Some(c) = &self.blocks[z * MIN_CHUNK_SIZE * MIN_CHUNK_SIZE + y * MIN_CHUNK_SIZE + x] { - (true, 1, (x, y, z), Some(c.clone())) + (true, 1, (node_start_x + x, node_start_y + y, node_start_z + z), Some(c.clone())) } else { - (false, 1, (x, y, z), None) + (false, 1, (node_start_x + x, node_start_y + y, node_start_z + z), None) } } }