From efd466fc78d96c82a024f12f877e3a07a0119371 Mon Sep 17 00:00:00 2001 From: redstrate <54911369+redstrate@users.noreply.github.com> Date: Fri, 29 May 2020 21:31:56 -0400 Subject: [PATCH] Add indirect sampling, and update README --- include/camera.h | 2 +- include/scene.h | 114 ++++++++++++++++++++++++++++++++++++++++------- misc/output.png | Bin 23617 -> 36635 bytes src/main.cpp | 29 +++--------- 4 files changed, 107 insertions(+), 38 deletions(-) diff --git a/include/camera.h b/include/camera.h index 5207d3d..e6a49aa 100644 --- a/include/camera.h +++ b/include/camera.h @@ -19,7 +19,7 @@ public: const float h2 = height / 2.0f; const float w2 = width / 2.0f; - glm::vec3 ray_dir = position + (h2 / tan(glm::radians(fov) / 2)) * direction + (y - h2) * up + (float)(x - w2) * right; + const glm::vec3 ray_dir = position + (h2 / tan(glm::radians(fov) / 2)) * direction + (y - h2) * up + static_cast(x - w2) * right; return Ray(position, ray_dir); } diff --git a/include/scene.h b/include/scene.h index af66db6..88fe50d 100644 --- a/include/scene.h +++ b/include/scene.h @@ -6,6 +6,7 @@ struct Object { glm::vec3 position = glm::vec3(0); + glm::vec3 color = glm::vec3(1); tinyobj::attrib_t attrib; std::vector shapes; @@ -25,42 +26,42 @@ struct Scene { }; inline glm::vec3 fetch_position(const Object& object, const tinyobj::mesh_t& mesh, const int32_t index, const int32_t vertex) { - tinyobj::index_t idx = mesh.indices[(index * 3) +vertex]; + const tinyobj::index_t idx = mesh.indices[(index * 3) +vertex]; - tinyobj::real_t vx = object.attrib.vertices[3*idx.vertex_index+0]; - tinyobj::real_t vy = object.attrib.vertices[3*idx.vertex_index+1]; - tinyobj::real_t vz = object.attrib.vertices[3*idx.vertex_index+2]; + const auto vx = object.attrib.vertices[3*idx.vertex_index+0]; + const auto vy = object.attrib.vertices[3*idx.vertex_index+1]; + const auto vz = object.attrib.vertices[3*idx.vertex_index+2]; return glm::vec3(vx, vy, vz); } inline glm::vec3 fetch_normal(const Object& object, const tinyobj::mesh_t& mesh, const int32_t index, const int32_t vertex) { - tinyobj::index_t idx = mesh.indices[(index * 3) + vertex]; + const tinyobj::index_t idx = mesh.indices[(index * 3) + vertex]; - tinyobj::real_t nx = object.attrib.normals[3*idx.normal_index+0]; - tinyobj::real_t ny = object.attrib.normals[3*idx.normal_index+1]; - tinyobj::real_t nz = object.attrib.normals[3*idx.normal_index+2]; + const auto nx = object.attrib.normals[3*idx.normal_index+0]; + const auto ny = object.attrib.normals[3*idx.normal_index+1]; + const auto nz = object.attrib.normals[3*idx.normal_index+2]; return glm::vec3(nx, ny, nz); } struct HitResult { glm::vec3 position, normal; - tinyobj::mesh_t* mesh = nullptr; + Object object; }; std::optional test_mesh(const Ray ray, const Object& object, const tinyobj::mesh_t& mesh, float& tClosest) { bool intersection = false; HitResult result = {}; - for (size_t i = 0; i < mesh.num_face_vertices.size(); i++) { + for(size_t i = 0; i < mesh.num_face_vertices.size(); i++) { const glm::vec3 v0 = fetch_position(object, mesh, i, 0) + object.position; const glm::vec3 v1 = fetch_position(object, mesh, i, 1) + object.position; const glm::vec3 v2 = fetch_position(object, mesh, i, 2) + object.position; float t = std::numeric_limits::infinity(), u, v; - if (intersections::ray_triangle(ray, v0, v1, v2, t, u, v)) { - if (t < tClosest && t > epsilon) { + if(intersections::ray_triangle(ray, v0, v1, v2, t, u, v)) { + if(t < tClosest && t > epsilon) { const glm::vec3 n0 = fetch_normal(object, mesh, i, 0); const glm::vec3 n1 = fetch_normal(object, mesh, i, 1); const glm::vec3 n2 = fetch_normal(object, mesh, i, 2); @@ -86,13 +87,13 @@ std::optional test_scene(const Ray ray, const Scene& scene, float tCl HitResult result = {}; for(auto& object : scene.objects) { - for (uint32_t i = 0; i < object.shapes.size(); i++) { + for(uint32_t i = 0; i < object.shapes.size(); i++) { auto mesh = object.shapes[i].mesh; - if(auto hit = test_mesh(ray, object, mesh, tClosest)) { + if(const auto hit = test_mesh(ray, object, mesh, tClosest)) { intersection = true; result = hit.value(); - result.mesh = &mesh; + result.object = object; } } } @@ -102,3 +103,86 @@ std::optional test_scene(const Ray ray, const Scene& scene, float tCl else return {}; } + +constexpr glm::vec3 light_position = glm::vec3(5); +constexpr float light_bias = 0.01f; +constexpr int max_depth = 2; +constexpr int num_indirect_samples = 4; + +struct SceneResult { + HitResult hit; + glm::vec3 color, indirect; +}; + +// methods adapated from https://users.cg.tuwien.ac.at/zsolnai/gfx/smallpaint/ +inline std::tuple orthogonal_system(const glm::vec3& v1) { + glm::vec3 v2; + if(glm::abs(v1.x) > glm::abs(v1.y)) { + // project to the y = 0 plane and construct a normalized orthogonal vector in this plane + const float inverse_length = 1.0f / sqrtf(v1.x * v1.x + v1.z * v1.z); + v2 = glm::vec3(-v1.z * inverse_length, 0.0f, v1.x * inverse_length); + } else { + // project to the x = 0 plane and construct a normalized orthogonal vector in this plane + const float inverse_length = 1.0f / sqrtf(v1.y * v1.y + v1.z * v1.z); + v2 = glm::vec3(0.0f, v1.z * inverse_length, -v1.y * inverse_length); + } + + return {v2, glm::cross(v1, v2)}; +} + +glm::vec3 hemisphere(const double u1, const double u2) { + const double r = sqrt(1.0 - u1 * u1); + const double phi = 2 * M_PI * u2; + + return glm::vec3(cos(phi) * r, sin(phi) * r, u1); +} + +std::optional cast_scene(const Ray ray, const Scene& scene, const int depth = 0) { + if(depth > max_depth) + return {}; + + if(auto hit = test_scene(ray, scene)) { + const float diffuse = lighting::point_light(hit->position, light_position, hit->normal); + + //shadow calculation + glm::vec3 direct(0); + if(glm::dot(light_position - hit->position, hit->normal) > 0) { + const glm::vec3 light_dir = glm::normalize(light_position - hit->position); + + const Ray shadow_ray(hit->position + (hit->normal * light_bias), light_dir); + + const float shadow = test_scene(shadow_ray, scene) ? 0.0f : 1.0f; + + direct = diffuse * shadow * glm::vec3(1); + } + + glm::vec3 indirect(0); + for(int i = 0; i < num_indirect_samples; i++) { + const float theta = drand48() * M_PI; + const float cos_theta = cos(theta); + const float sin_theta = sin(theta); + + const auto [rotX, rotY] = orthogonal_system(hit->normal); + + const glm::vec3 sampled_dir = hemisphere(cos_theta, sin_theta); + const glm::vec3 rotated_dir = { + glm::dot({rotX.x, rotY.x, hit->normal.x}, sampled_dir), + glm::dot({rotX.y, rotY.y, hit->normal.y}, sampled_dir), + glm::dot({rotX.z, rotY.z, hit->normal.z}, sampled_dir) + }; + + if(const auto indirect_result = cast_scene(Ray(ray.origin, rotated_dir), scene, depth + 1)) + indirect += indirect_result->color * cos_theta; + } + indirect /= num_indirect_samples; + + SceneResult result = {}; + result.hit = *hit; + result.color = (indirect + direct) * hit->object.color; + result.indirect = indirect; + + return result; + } else { + return {}; + } +} diff --git a/misc/output.png b/misc/output.png index aaf44626e88cd274d651ba0d6a80f7fe10957091..45058c8e4dda714d9a046a51c8b9f9007c571602 100644 GIT binary patch literal 36635 zcmeGEWmr_-8$SwDN(urZNJ|J(Bi$t>ASodY0@B?ulr#uPiFAn!jdTtrk^<7*AvyF6 zeKy~pir4d8=e#{H&fjZBHfyi7?zKPbUUzT8loe&}VUc1XAtBw9eIcoegoNUagoHeU zaTjRGnI%p(pN!0>lm8M9KUUTYFB~4Cgg95 z@5-Y6Mg!6KQ73u*to>KsOJ+WL5Aw54qodn*rsEmWzrS$opowveiRp*~cXps((2o_D zwUojPb?pa1SbAO#Fsj(21*;akGt)0mk9rs5AA^jF%Gmd~Ky)4{gg%D^{dtktd;iuq zca`@ZKWCx*6|&=qgLC1H!OorOd#90v1b3JD1&dsupx-{3yhHL={J0e)8!%u+!*Z`oQ9WC|?WJnnaMhbO<`osXR8m6yh-zq2|F#*>YNXQ`; zNNB(nGVmn@zDP)@vB5~_z)u3;E18M%=PrtOChDJS})Rp0=c=lvAJ=w**Thl*!lVSLC-iq92~4b4^}4+TW2G8R$C|9|4s5|9!XOtV@C^n zXA3)9>YI6u-q^V~3)9ft5c>P?f9o`Lx45Nb>-77vfCmKK+ySw(Jp=un8yG5d(<-2B z;cjaETGGM>fCr!zpqnTE2Z{f|{9h}8vj~~A<0ULtGOd@H=);3 zjCvf4KF^%Hzxn)E0m}2|&;1|-6#h>g-YZlPcCtDwiMqb;UH=Gkdc)wl%@>BPxV`Yr z^?fAv!gJoHFeW-NE?IjOJ3ld^$DgkoIjw%M=tX_baU5t`pW`0LnS}Yk8{pfgKT-?5 z$F_y@+JF7bsd+N@vIXt$XNt?;d+KQNbmeagaKV8>d2}lM44Lrv$KO?~B>?JbALAYV z#1Q58XOJZTTIaN`K}UAAlb~K?n1}hv@6V@2|M8%aCb6R$X=UUi&M%w&l9zg6rS(SW z$$z`}VOl4)K&M$J#r@H31pSt2{t!bZG!H^^wHmC+Im{%eEkuP+1+KoC}=D6+h z%%5(uSbRR}t~tBm@PQ?@Oe5}5@>-!qJNxYd4N;~U%5(xmC^BuDH}se%NBx&ds&>t9 zCo!MDp)*e2m26BsNq*^^aywQz8ZCJ>fz=DEtzbT#z}fqD(8NcvLglmMe$>j%njI;} z{#z(d;#=67^X!!Hex2P;WQbD5Fvvs&8>0+}Hva>iA&O0kAG){A`Ptd_E$-B`3*s4e zXt$)y(a}yQIM?=E?UO~M{%M{^6Zo9hT;)x>H<|JmPqAr+h0X?>YtnNZg}?hty`MS2 z>;Gq0{4gs~ft{@ih}eF`^>=fT@y@__w_7JBNWCC#AXwY=FUh^k0r+1^{~wyh-#hXz zmYE`$&f6obkDhH0ex6@Yk)8LEh)Wmt99a*m9p`>L_*l4SESbC;o&6866IN*TN2KvD z`7ga?*ZcKi@7X=sXfEy!{-G0Bd}ZKW%5H0Q&tq_WtOPR9`5zNy{vcfN18q#uYt`Ax zr-&M4EX+M#;P>_l$u?6v8B7VP`-d)i@# zu+8^ltDBQfDt7YtH(wgs;s2VxZZWZ`H_zGNIm`6#X1HGJ`?5=OU3^_fKlw8gbk}aC z`b(iWt{_~#Pr!y2?ZUk#Qujqh@PBm0&Z!4;yx`Uew!;;dr3Uk}BUK7lGR<{nDd60f zjIR537aqQeeRWrb3D36+jREEy-S2Q3{~rTSG5GH^eOzs8zVwlzhFu|uh%Tp{f``VP z7l`Gkuepn5nhS#Pb5J{RDFm$Jq8*FJD{bSwrW=3-xWNvbt^SCqH)!d}4SZS^w#Gvh zUWwUwh2up^>FLd%yI@iHs2piE<6O--=$MP}4B79V6UHbtb8t1swXo&5lwA+U=;=48 z1#3UoE1?+fiU!_#Ao$pCVc{ybVAp&S!Ls)18hos1%zWqDMMK`zUcyevLe-{bnD!Q2 zYs2btyi54^DfQQTvgh0EG|M)=Xjrnrtn+-;Sc_{)?RZ*Wi{_?0B7XJt*R5m~!f9HBK_yp5^aQq3VP^srum{!v-h|gCG zrE>mR%rk!;S%5WpJhZ%3Z^xFg0^+NBbuslH87F%qs}Aup7=T)+ww+CW&wsewk@TH<5VaXa zrhy$;7H{GdgXM1>lYj{!fCPvi%P6o$fQJwE9ELfHdEsL)I^#TFny|_Z!+4i89z0;- z$svV0-2VgFzn=Pj04GH}_Yb?$B8ybq1Ez$pX~5~C8<;=X+5TkIxuB%pRqv;fmv)p{ zst8JLu=!1FlpwS<0k?+_$=I7U$4+T@rz(Fleag#IXndX@AmQ5Ih5s8u<#9B=+U)YN zBa>uYl$4J!MJWH&Oqx%vqHIg4^;4~h-&^L-qd<9zeNN+GVTRUuEPD8(zjOHN?Tm4h1Ci+?I&{#gO6<-x904|SpQlaTQWy@rh~PSE03M|(*F{3g7-K6ShO%EZ9- z7e@51DE^)HQ%gGjUZ&juqOSUOt4Ho2m(CUc(@)F=tr00(Kyin?N6x^jaZ|+X&yn$W zmASF4+`7Hn{?gfr0jz_a{ettLcPx}YBLC!_1H0YM(Gc2WWtFXgJ1_)Nb@%f0F2=8`4}(& znslGShyRQ<3_)AF+;70V=DvsHn``5>pYUdDc73$r*yqly?;q)h>Hh^a{im63bsXsr z9rDY`Y3~WGlxabIM9P81T!mfTnD8$v{u7b%-zbd)wu}|)#Ic+CH1du0-+dvK8ObAc zbHH8ry*Yj(QRalAR>Nh=ii@Fs`6d;YvPx)Ey065#sMJQ<`>egBT4Bs+s&ek+!r?uI zO%XA>!t{(v)0p;}xPes@$8O?pLY2>uah>1n5xR!pQpDEP_~a?y)1sU;d0C}5R$nw+ z8TrNIJGVkkF-1ptqeTI0;^r|Asn4_N*W>F=X9RaXK!`(w$MfsVi6 zl;T4^OYc^F*U5a`T%LO;^Zdi_7EJCvWV<3;CfC+Aqov_B2&p6)5ZpNze=>5X6_pYphZvQ?82uapLn`D4kv ztE_~LeKM!jkZXzYdZREn*7zR**bhit&2{3z*?(4H2{5JRJ^Idntj#pSz0A^nP-cVO z?ZF$p544fWMg29Up7{$f06dvyAm%pz2lf`Uf*U^Njwd(19qFP7Jf=Xi-!Ala;c5~< znwaiSj+5tsrZK0=Dhu}PVKK!3~Ho}d}?Cs)xI^*$= z5Qy?ifNt{f114-{66VDyFI0ux$PqS|fH63^Y++ zwI||o_#;V}B-}t{@LR1{cWmF`7xEm@H*50N4Dp4Iwf9%;gs$B2Jz6Kth^z125QESI z;>S{Ux|747M{c24Q#U4Ul9}U~0NVQ5faryh!&o!o3eI_6&=yA*lGU%h&+5Gt#^Tn9 z@NCs*f(jaD&_HVpMQNc9Wd?-vG!u5AFt@Vv&{FhmTGN&ZWba)j2Vs@|az^c_14_N# zt_B!X@Q^2)C6?I8*M6$9ZQ69Tr%zwSJ=TOeYPwl8Bu&-)KNG?Ac}ujL8%kHlt(Y8q z2xtT=Y|WqRhA6D!nNI6V5cqTdWL@{zl@MhFPk40Cj8{izE)iasT}C_JfTQtGTN6t0 z(+Xu|+G#xKofowHxF-;-o|!jcWO(O>`#S*wy(_gc*%umNDM%^Nv9w-W6$5YQL{#Bo z-+qXZc3V#Lg!jDB+&DzOw0AAkAgY4NoL=zCc{|4IhR_WD=ZdOP8|IdxJZShwMHST%J1yAy z;uWAZM#7QSJ~*)Hlb;MLBgW*ZNR5;T=5;4l-&fK-!lhd8m-^U~I=0#7A>{CgGX^=)!^2W6I3V(&ABWh@l5#o}QdmyaJw%e!6gv<1^)QO2UqS6o ze1Un+h%kD={21>%OJj{~pP54XWUl;Th0%?cO}NqXk{u$q>oYe-Tk1U<<8f6Kp#bcR zHM+t4S7V+74&ZaW*rL{bwWO3g^HLOo51TduiAoAE^c|;dv`zO}8NavlmF2lKr5pt=QFUDEb;HFE z-^3UE3D7(4HAW9qPQly$=;2-StbNC_qcB82G!`6dJyn?xk;sWq7tJ=0+o-e{j?=1e zR&Y-dQpix_ybtU;j`Hm1TSZ^VgCdZYTXp>75->T;jZo6qeWT^noXu!7ir7AQn8uy- zx|HSZGZWyuZDfka&z28 z>#dBOe9|A-7+;}@HdnuHw6^m@@Odeo_bpv?E`92KbvYWXIDf9c*5_-0=HT8rN20R) zFw1Rs?enF#qb2%QOxy6Wv*@e^aTsjEN4Zg@$Rmkc)-CLS*}MB&Q2&)xPV z`-xPyS$#sxxWqAYRT*8~o!0GFCehz}rW8I!5JSID%b)U$z`RHpbr8BvZ)Km2` z$FoZh7m6I`)AaHOj`y>9@u7fW#tjzE43)yUX893wC?9Ji_9LX%#g3OjDS^>2E+Ld~ z1H^Z+_XNU-6 zdu`+@kSbh`01As{_M=^K_*VR!wEM-xx_aH4!~!#o zdzN$b=CrY4-r3pCFOGZkyWdhUlsng?_TO$PAYO8a)E&+ zv(NLMFPN1ez}TxQ-P)<(_P4E&nprlfgM4U}FVy^BZW^BjAHI>T;fKxQr96`_idBR_{V!I7dPh>&yHS zGD6t>qqr_-IR{Mm)l();dI>sZpn4r}E^86($Zb!=5&JXUX*#nd6_~G{i~1rJN(8nn z&G}fb2k3|-GIScxg08bi9@3GPbk_5cT^VydyxtX$NhnkkB3TX6&pGgG3_V3GM-R{_ z$$;r}Gxv)SS4du|h+PAyP_OV~P%Ct;Shw_t{DC1J9mKE&!g z=OO^%QPZW5HE-50N~Liu3!5ugx6y$e^n&KcV%FFm;t?Au*S*gc6*~Paxw1yU=r7aT z8(-Q&-fN7G%d*5DqGDhtaeU2AXeq#F*);3C~krqC4IQYs*&6V#YKGKlhXj}*{LxjI0suPmK;k* zGgK9MleIvL_?v^sYm-wai~6(p%@j)siY#TDg3P1*0~eH$dTDZIf|99GyIgQbH&>V- z2H?IkB^DaP1a~TF4n$3_bQfp*Rb*#h-4%prH=fYHf%I|91^HMVQiX3ZmcGi$=GR*4 zza!e8_&)mw<2thqO#>3N^#yGb+WFmmn{SOx(;aS{BckeOJQVg~4;|2ZXq*bxFEF`N zo+vk?9obo4rU!Zb@l9_SvP=R{kFKGeK~DzHFr5k2O92N?t^P+sdcD9$EGo@@X#~y4 zPxw$1+8vwhN*VP6vpe%omzMjgeqJ9b1;H~!_QU!p)!m2ceBTV4G&@Hvym+9x6Tba) z_VBp&T5}Dx9Pf-^Nh!@iT0?Mt{hn|vgDn5@{U|PvonJYRe zEGqPoPHpIJHpK1Bd>MequpFn3tF895S52eEn+xUk;nB zZ8AUSq0f@RHBqi?>;R5@?0W95;Za00E`ICf&ue+My3Y_Vk|Kp523ZJuJ_j%5YV*Tf znBhg=gtsbOa^ig3#CGZf;b9kjdH9L*NYjo{iHf4H6q+2>`fzs^K^j%3+jbLAvhy(f zXs5yMp@ z_EB?VG)%IPy-?;l+$1;etHYpk!`IAG$B&TaIaJO{f?(|gyyTb7Ip(agSMqA24rXsf z9X&sN| zfGAz`M?|^sdf=r#xK~k_yLY3e-AFm5{>6-$=y5)aTbEI4WFlR_{TlmM{G4_en-?`B zHeiu)df$Txg9me2WzD+c`@^G9&T!IPb|S2~%UotH+@MXgeU|`7cq-y-JF!N@Qmqc^ zjsiX{om^{O`6@dyJnis4Kl|wGMr4HCto1N<-CV8buI@tyP(Z?F1nhJuvD}f8nL`Mk z(c|EY?c&Hf6iT6oLHl*33hi z^qf>MdU8f6rN(t&umT~30$Fsfn8J#x8|{S2AJ6E%TO1D3-B#XL;Pv*rXd8a_S{cs~ zeAGrq5Aj$W>C5gPMh_+?g zCE;+e)&I&aq8IUb-}lwrOL*u7pZU+$djpyVd|*=jeeM`HU#1J`t&nMwxE z7hHF}L*(?>aJ1~clFlyNGLO9oEaM$kNVo=vVDNX(h=A46yg^H<{d*qkPO0BtiEX+7^A zWNILx7}E}rIp$lt|9u6^8@`E z?<2L%a9Ixg)#lh*xix|rw*mp>T(-oTco3pwB-k5(uR&2v)Tu##n)}xCZb938hZN*r z|Embdw-hI}2(m|m&fM_?1l09g8gLHJalc=%3MVEd=Np!W*u}&|Jg4@;dc2^Bv_gqLdnvVCPX2=GTOC!icuR*R^0 zw$-G}K{->WkOmS9x{SMpy@B%#?9I`o1z~(8R;=UkPh>?3S@dL?m;><^W_of*=3-Z> z%&BMVvonmMe+;F;c<;i<2ia>3E455BgugYq+fQGJ-CxNve7 zmuoxi{rrm5x(OO>#vLcA*(4H>P#*H8-#G9{@;W1#8=G5|2={Q?hf!|#KEx+wg<%nk zzRC@jy{lB(EK(urWt%TJ7p&eOdUoCnTACPF1XQz67%>kOi%7ZZ>hYvm#t)kMZrx6W zL#N_O*cCX<{fx${G6&8F^WqOw0K9J|Krt2)#JArfotcigtuv73Hm{J$eZO|QytmwT zkHR#DADyDXoyLrxzI)@-c&;VMy5q4Fn6B5zsl&pAzZqK!Fw{e1d8n9FOUPD@tZKsg zIj{G=Mw@;w)YcGRG~U-xY1eNl_z_cX8F!X+CB6~fb5FGfzc9En9QK{eu8#)KOD5k! z#lNR2qw%rh)>tIxGVwCV4(4=NE5rF*fsA~-3V z`X+Ujs_LJ!LWk>&oYwlf8oax>Bn0s#Ore4~UQnF^P8GA2RbLSAH11R8 z$zAy5&Y=i>>#j1wlSoDOfCVVl90!F{esD}q#p8P)#buK!EZEzGL(jz#$DtHE^S;hI zMtHY&nWMCz0W<2nc0?H4i6P%UJD+8ePSl3?uG8^acatm4J9#}eS@%nW_~5(kK8UZK zSg;YO$AEzMQBF|wp}5SA7(qUXah$Pg*%1p{wr+L&qJO$YokFKbq+8F>&RD8_7QyT& z^qn674RRYO{Zm@AnG6Ij>Y?CWusr^P5Ojy)dZ@iFz3P3YTx_XM-=&)5k+756$0)YK zCu)+;L0hXK6d$FOS>NMS6$b|g7qPf1^)RUj2rlrxy*_Hg-eB@c6CZ6tHHDI)=2z|$ zbF_(46&NTbt@GA7T}cZF8x&{=jK8;>OeV8kcpR(4KE91yQm-Iy+pt?-bivwp8Q#ZL z^hW)d30uyMP-=8pw_;uE)0fnWF-DR8X&oBNAwGzvo7@a_Jcv+AIUM`Y;WZV}=(gr3 z%?S!Qo4{13K6b5@`$Srg`)4|z z)f`F!j9J4D$m+mnwRf36#bGsHsaW=G$eE4&G#0Tz1zJY`p$<~UlN!srJVeEblIr>QKQ=07rDA3Da|<4gg1t-o z@8ytIYmt5luM}JRsn8)f;VCzx!Du`+N64rdw4UakL8ZAb-4&+HF#iqqH5m5Y4on*> znUL$YOw!yfcQC8XXns$)Cn6wHOQL)V+tBepICY#+DXJh$NHDqyP00ZPodg!^B(YI64Rr)& zxs{S&F=T-Fit;Qb`T^APp10nMVS&zwfKu6?{y*gzeO+U4X>(Nxoj$RQEG)MQ(!G6r zm)LlP0m?_6%;a#mS3avx;Kuq8Jrx9!og=>XDD_xN%05|y9M*}G?>^~{#)rpVbc%Qy ziF_sr_E+M1hF5Gq_-Hbc1VTw45JE|^T`U2nv)bcWHs$!WoHOJ=&}sZDGaB{a2LYT6 zho%a2`T-;hy*e%>j-i4c4fU=0F>~}fq=y)05<_eDIL!iR19nuN@dZY4>AjbtNgEI- z+?!(^ud;6=p^0|03sFKh;9O)5>6CT!9+n=uXskOOPjxwXWe02V__ciE?_T-i4#m%r zGndnZPj#lf)7n1bLS`*jR31P2;3f4;hmL+v7jJ^suFnlK(&8H?ZnLZ}Gwpwll;T=qcQzTz?B{$@lh|0z zKaPGb+k(V0NHX=+cu|;S?7HhTwl~FnhV*gV7o`CjO&Spb5!C^zyX$w{axU5r9JhY% z?O#3Tkzb3@1~THk9;ztP%j+{^y=|n>Y>3JdpWed8`7U!KY)$^ls*8l1#HFz8Zse)5 zRid$qGFKUikZ1R$CYNsE${z zgMrLKpznPb+mH2DDsJT?tKe!`0+}l7d`8>6Xo?i68GEx+n#9MD3dv1MES=G2gX>Mr zB)C&~t?|PLrL2zcrG63fOXqqV+G{9Jw$-2<@(u`{+yv8jvs>_gd$KR}R=MB#4uCc2Mzm zH2R}vvh;VP_U$?D_m}z{iJ8oN5oPO!u`vBUZ$Q zEX}a>S3H|nB;xIVoI+hnUbn!R(QUcI5I&7ld3dN}$Eq!KjacS9U+t8om4#@}YDnga z<_5d6-Jb^;`9239KJ$&Tk^HHtoVZRX!sH$OhSC6`-@0YqAB9tG<@=%3KaEy2=KJ^u zi0T>F62BR!{8fwC`E#j5WtF|P99!bgF?*B(c?SIQ&#uZkzc3qVI}7>keG)b!*z7#;{H3gN8v`deQ|nE_2GuT+sOzG2c8 zLpdpobBU!$ibxSwf(6a{CQ~J|zT_~vh7mT65oGrc0ok-L_>8bw%U{w8PQ-roHJqlO zg3QmucrgWudpq5#G}5{{@_SDo@2?lb1HOkTTDyA64Kz;751?Ps?Su7WS%Mth8HYks zf-(+=+-51M_TToKT-Cm|jgvGu=fo197>;=BspX3UF$`GCY2YRGgHj`ykDE!w z&O7Fkt|5uNSfknsNiBz5_EH113lK>vb3#9Iw5fZZ-UDwKwm}ySbg$p-VN8mlu(JEm zq5FVWxh`*km&L9_qs#{oVKh=ni?`TXr_1*`x8QnWheoIXI_#A31@G#(up50&zYw8D zEO`ZWo`_7;{%gR=V>T)f=vHll9bX2sxB>Nc$`pX^9d&SwzYQ(_%@Ch@(mW$b+j)|v z|Agm9{KSf`RtTDzR%gp)tDGUnT|~v!3;fK z<6~JR)iqb|z$dfteM%@s-F>Wi`OxT<2NT#GZU^*aGsz18MbT#4a>XN_fW)K^w@q4!`$J2w3Jp4|7G=oTGs-vn5Be!y5o0dH^BycaER_ zL5LG*ItCxlz%}Ik3ex+PR8uHKalSJN48>y^WC`SoFuf~)k_QMBsC|8uCLwK5^>n>V zN=OrKX>jEi{6)=t&vm~E&k1(cxTP1A=!5}7bo#P*8(dnxZO#ECTCi$ z_~FBx1^)QCSCYBmWFyTwSqLc=)Ccrw1J$CNkmN3>A)@@ltWAeqUA3GZZq<>(V{;|- zm$k72Js|U=ki&778AVSapU9;}tkrqF^3QudmxA-%+r6OX#=Xe%MBnc1=5OKaU44OV zG6}3;HFVy+OW%ALl|ipByE~yzDc=&4jam^ycf)y?+hd4gUydqNWeZVKV^Z#A@4@||V` zvcJo#9y(8?;ys*{StRpQi$kS5#MyRO@*=8cGRax+QkbK1d%B&NyQ_{c4GA+#RdJsT zACDsMym49741wVw$`BI5N`uT+ju`;gCzKa# z);JMtsX}#oSE3itU8U>IQmlFIPs5$(%vk+`u*U4hCQ=_I1Fxn7FP}M|#)fsA*>^W@ zlZdO9i&-bP8wn}MB(o7Wkj9}>MXnkz@6EnLxg1CeprbhYdWA)5(Q~zmcX5Csay2UA zq}+iB6~c;k6I>ZBzZ@pvo25rBM{W-`H6{Ng6&ziG-kl?a>y1l5Ma6Ky?mV*Ur$B{z z!0>}d*V7`DA0hDWRcy*1O3O8TI3A2nx%J*C@9}i z0RDYbmv)CK+8BM|r~N#e-bz^7qIjw;z+M?KAoAMvkQ- z-r-Y`Wz{`(!l5!lg+B){>M%qzYE;#lN+5#h7IX}48vT)b$LW0d8fRD}5SK=~Y(Fz7 zsc6MRs5Ij{7>TlFodMskOh!48)SW{;y9?)Ozt!BaCL))!3~;&R6ks$==%Ji%+e(e! zR+|HkDisR*Y_P%mt-SHwe9TIGlo1hU%Go)-D)2|$IRc`T=U?S!>-uBq1jN(B$qk+o zRB5g$(4o^t2A0b5<8A6A_;|}IUiRVnT2~y>O-K7R$*Mh7JQ5XOay8Ls5gmW%+ww+` zOR4;lpz;SaB+jXQO!&ec--B7-B|CiDtQpZ!q?;h2v2an-1@B~*Su+%QgJAn6RNa}* z#NF$lj502|CkAlfGO_-rT;j)6nCq`k2&fF+z9f1UUj1e_Baq&X+9{sT7wDc|XmTU6`T zJu+_NETaH@PG5de?e?`&j$U59$xONAaQW={;;VV;Z#xV-D(q?<#h>t>0BsSQ45OS* zVSEQ#0UMU;`GQm~`Kr+ z54%8XrxocW>cVs=SM0R?%&_R5f7>+Kj&f4eJ8nLuCg^q{$IjhcyW&0xa)0BC=RTgW zAv|vgU;2%yx%RlF`SQnb{hy-w|HamcZer`$Fd3ym&6tSmsg8sGVBMhq0;uO$9TR@R79|5C6ck8C@?h8DR0Hp^n159dYzS;N9oH z2vS4zoIlg`!c_VxYeYoS|vt00+JA<(+li#6HU?(8?JqiLs2uq-ZhOe3Oj+hkFy&S@68 zdA-nzdi48>FEgcq=N`qV#QUcPmsM7*nY`LW6l@Jt3Ef|~VCy%+cFUzdxxBBm%2=+p z3t0$^X4cK$4T_$2;TnoRJRtoh6SPmdud=voImnoN@7Qk7X2df#@UY>trQ_K~o)u38 z|G0fFqq45bw8F@jIf!frs9d+|+;2n}4F-8->hx?AO1IOR@C#%-2q%c-x)f1sjxb3# zK%L5Re6*+rBL4C8_}iR2Z+gjH{RSh6F;CEiwu}j6;d0qRKnH{^&$BLDy|bQDh(2LZ zPMecn5NISG$SI4vbr_bBeHHqf*u^nem(hx!K z88bQD-j`_`j4<9iQD1lPSt86}M70Lqm8lc}((u}|^bR4nab`mpVd#d)1C$e=E!&?! zI7;C@pHBZf%U2is3(}(wI20CVblb)qo$8h7q0xtU>ObGGYc5HrJ7Ic#eWs8feDzC4 zl)%n5>cgp5q#d(Dtnc~EIuMbx$H_T(=ur?>5ao0AQKx*+YQOM7%%b2?6cAaWsADYT zRaWF?D?e}5+zbXX5KzGn(j4R`MjUx|+~5$}$Q4o3x%Ao^t1CeuT84CfF)9z5wQa=K z{^;i$lVf^1e)to3bA<#a?V?d zqn~SHptb?w>x-hXBvrV^1m_C((~HTPfQM`>G>P5I@&ea>8S=y88;RdnBqj|w7!|Ic zxmbQ2?o7{+Ivt=diJsu%FC%*{lk6IF`2oQ?)Pn{;IxKvVTXyM zGeu1ACWBYsXuVr`YbtM(0!htTZv7}8Kv7Ad5X)Z>Oq>ntsWn!=(51CjpAl%y3m;om zKD#;&CJUdMZ`%Lfr$MxP!P(yhwqpZPtx<}60y#b{c+yE8Cz^VhmvLESe{iR_`zja8 zbL`h>#%b2ivh+l$pPQe}FbqXx_eLmT-{jV}*4`IO?J zE}v)-%e2ufQ_Em!?>g@F)g}!|`fl?H4LDl(kDVL$UyqAz;wB0zh`jRVpZY{>v=bX_ zhD9g9^nu`^xaFj%RnzEfMBiVBtE<9~UaDiN`A&p{8`F=}GnY1&@0|p+!IOGHAn*l$ zWekUJw5Xk{FMa}DbI>LGeur_~gb(6ZPF>7yw7@2$PoxOYK-v?Ya~cS=4>$Rjx3mBh zlY{j}|IimkJL-MAwUOWj_(6kTFd^j~9zJIT>(Z&h1`isAN#xlRVFo3&*%%&_W5Yn| zVh;11v=2z_;m;n_+?hL0gFT25MIbskQx0)x+uiP-G+v(2*p3!7n$fb?fUtJK+h2=x z&xMe<4;}@1NUyVHPlVkt&d7~RpKN#{etSYQO)-IjirxeGPle1`LJ};Lh(bE?W0tnl zVe@;cZZqG)w02+a&tje{?7IZb0>`&;DwlrKagvGzC4w-q3aEEQ%t|KZ4oH>JM6-@|E8^0U;f zY*GJOuUdnwVCTO?JUPC&#jrVV&jXKuq$?MgIYzo1!xeA;t45Zs#h=kK!!neDp^ehUbSbC z4Q_{{0Cfm0LqYdwb5q|kkkof&Gk{Y_;=h3V3ZhBOueAYV^PrJ7SobKVbV_0R^eYb9 zfG`bJx=y<()> z1_rqHV@v}OAKTVEWIh%hK^b1@Cx$N16V0_RZc#NjH?RW+v)Y7r2b}e*O|n=q#;+#r zLgO>O+rX6}3ip#TyU6JE_9QWJzaGMbXhxDSRrO;?CB>_em$40oRCFRf0T%b?CCc!K z=jqGr2&v99!>7|2sXz`FUrLxTMuRp8WTcGZ5tM<#lHewz!r0d8^B3gm_taT!#ZU1G zWP%(b5M3{(tt9IT-l{RG*<^bFw&9XKvyz+c5x3nY&7}6POLfSmD_C7NaP)=V_f-Iu4dB3lC4r}Q(Jd9D(!j`cF zz!HYyBKMRci_AI2%;Hd~Pj;zpc;lMJq@tu`!j5 zfzhcW13SIc!D@m^52? z1d)B@zYq}NU+^g8(ty>7aU*f6@n6{G(JDj-HHm}OSjQrw3+}G(NaCvp7`&J{HxgwN zsm>{A>1OoRTY@Mb5m23r>Vw_deWDQ$+w^Hf`Y}_OMVKBH5Qsz`_!G#u_-`6Nh?Mp~ z4Qd2d(?h;&rlpjom*tu>GDX7yGm=;`pO=I(Lug-fXU-c|i4Kf#B zd#B7S9A-YjpC)vO1ul4d2u*qHG7$9R)FWo~c>OdG_F*EIY_zrv7OGco(;a6$FtC|J z1Sb5}>6%V7Pg`~x|G3;FAC5dK%~Xaj6QmEzItBEuP-mIJd%gNqP5v5>NW^Jh(_D(! z&W$lC>_i2aSAP!NGSaoVcSRuwbtd-%ueNpnChtN9Qx1enD8#7 zOXnx@s1>(VA9(<||2-Z4_2s~5%K_Aw*6+(3yo^i?1?2kS?vXjqGYfhwzom7ce%^RK zQE+DMr!)Z6ixx;82tmlDx|)bKPeMwWhh9jxX|Of&sCm+?xPSW!i@CJELp7Qtq5QBr z;0>%xEvVEYwZF;pPWbeC^L`}FwiLv-XSMZ5-I`Q2z7Qt2barGH6r+K73d6v7d#L#F z^m;>LMt9YKODBbrQ(FnSq=b5xUcpq!m zjb24Yu)vH9%oZD%T{n0{0QQzB3ki$Pkf#(4pBR^?v%O=jj=7P-A}e2s9ogU8lK7)9e7h)xtJx(2}BhUGBzlrt^~m*9L32a3ra zAzxnSy+uFv{|h*9VJR=xyf<>vC8FKHV9$rqNKXfmQy`vqDsy4`;fR1dlsqpqeH(>TsxGRSGlFs14AhVs(5~O?0YL>o)X~r;l>V zghfv&| zzOpk>eQr%#dQ$A8Q8wNy!v(`E`mPI=M_Od=MyNd zHOge$&Na~SvvExHOZ8Y$O*Xo%x?oameb7RjePf$Fs#W_*ye>6)g)^asOxs(Vz!K&^%ZK_4X;B?;WEqHlyk#(B0uoWDFMzAyq3cqc~vcqrq>Rk zBs&{m#2addyDh!HKS%iln$ZrG1jluJ={|G^N;y{f74B0JahY~p&C@v8wX6vfYn|yQ z@>O@93xt2nPW5G`X`lk<0S^ASL4ra$dWN#(%mpBe&L5rFy-Bp~TmjtPb?|2dfUx}i zg?az~Cm~<(Fcn6CuT}~95E$JPP=L|s;1Y#1D*91smKm6eY9P*9l)U=;ehME^D8?eM zmpaXATK+txwNm@5nIZXgb2nTtTeXtSTOD{&BERVS=X`nzA~?D@WZji zO0#j>-g~yAEfk5^picaD@4JKfmY!HF;q7y`Py0}v99<=QH2(^=@%tfnYeB`a$qJIR zs{fS)y%c!Vs(DYQK&4~vCO-AzAvGTVEh~Nas>Vr0JN|Kx?R7Z`48RP8be9(J2WoLO znAQfNKk@CrO-xJaj+F70^fVmx=JL|kL*kZxIwW}S@~Q9pgr#oLpjm9~ zG(Dik4!*m%Yu#dgIQUmD}YZ>S$)Tl#>BK?uDRC4c&@X0>zbB&aGa60;#wprUyvVX5HaAj|X|8l%3fC zf9)=XhDO_jxrkCO=LFPrY*k0kAsNJ&nH86cyNiF`I_E8 z_YFcPIb2Wk5Ay3g?yLZ`v;Nu@3@lbo7Kyl6CW&}Wy>~p8Gno#U9Siv(43GC^=0euL zazz?gK)!=J=69r3SETMgQT5d=Pz+8_@5NtJ9^x&HV>!%oFSv!U={+PE{zRv@EG|7L zmr!3oHIX77!sU&Ruc0rq;6}UB$XKMsV;0^7H?&o&ulCe{qSiX{CY->RSj zx)bE+1vvgwti)YUPEfPlt{aj083Xz0<76HrXK61hc>fAqn`1+BY+^}T5hApB8_27? zZ#)+f-NV*<8oEQxYtu);R{B!v5k`+;;m)!p-ub$qHVkCp^6<7? zswUcaj@a=khbZ!pg-wdmY%z?V#o%5Tnm;-_#k7h|{0g!bXrm}fH*fwyt~ za0?j(&?cY01Gf!juXXlAE|_=Iyr&GLNuCU6e*CCKX8!zJcA9dSF>KXr74m@&qCh5H zXs~CRlWHuKr<$DBmn3AaS15|U7~b?*{y!aoe_AonWBEIw>j^ALs&YheMwm`4M_D## z&STc*t5f``NsC^$Tt~Ln=L3h~Yir|*JI+jCSs##mT&~PSM!8!Qkyx`vfd|{B`FaOZQLl+gppmbL-zZ`O` zo?F^QfC9lf$Iz|rdyn@JcusH{%0*Xk=s_teG+LWX=RuB^oX~^Tf<7jG_wgp9H+@%c zW;8Uly9a!K!q!`Nr~+F3O3gCdEjO3#?UzAxAzA3{&(0U`0k^Ol@9aDW#g%uJ+e^t) zu+VG0HO;Sx3O#41Q&7MaT+iK;3%Gi#F&zf>`WsRRXbh)xIR)kiu*N1$r3Duq;E}?# zZ)HdpOzUs1y{GzXT*}#+4K@JEsSv+uwF8N}!c*||%0khYUXIXDL14L$b4*F<14(gl z(QR3gT~impjsS=PviZU){aeW6MZ8?q<5*-_`7JEP(fowX=b_OHJ=1n!*<#{- z)!vRYmy-=z%KIv$8s)WT(Y*%>sZ}_%0Ift(So$uQyf5Lwv{Qd-2lQe8@z{p=`bjo>((R%%VCb| zsz_7x=$*Oz;$>Mft}h6+^3xuF!qtL1^3Vo#A^7@zs7tQ$ZFh(<eESaq4ziu;=YXxcIa1%ROwi&jsIpI`{Xz)!&`IZN>twoAi7m%% z(r6QkN(CwdEf6)Zk(+Nkx-$sWV=lic{33j&aECIF}^hR*?j_AQNdam##&D$?}^3 z%wj>O90=SFk7=o5UJi5n^1z4Cj)FM936EBuzk=6f)#l@QgJDleXF=G_W-~kyel#XR zujWIVX~z)w)9pGyJ(rsGOuDx!)e3Vq02=t4?eH$_EHR{adK0gi*=PvMYnIZ1r3iNs zV%UIQCvB3WNsXbv1G9hD1DG1e31}Eq4L%i(FZ?kTo_XUo!;<#NSAq`ga6Tk@*-EJw zgyMS=`>G4Se2|Q)i^wrtYVnnU^$INE)_i)U1FN6SGIDce>O6RHGH)=e7=`~mI^?Qi zZ1X!2RyF!ytzKsa)a+D73Wy@ouSr!>SIr8;+XtGh!ff9ctzdMB#R)Y^rS##^>&p_A zdYb+FzA-+`QsAHY84KRl%ug`|q0#ScvJqhtd#qUzqZb)mB`zKRiMw9csCuO|UCNN;*gNT*G5)1dZ4#8@=Kff)Y#8M(V{!_xInRAT@? z*JM^@LFZm-WMJ8Sm=`l+YO|Af%x?&ODS@@4~Y4(avnDiv?Lkf!s25mWp z7&##Pc%{u5&eJRE$p_Q9*84e33GW(=P{uPN%X79wr5IW}v6>xM_LS~x=R~ihr;&pB z(#&Cct@FMEPC~ilEMu4;pfIe08c1h`%r_4Ty$`O<$piS{Fb1Gd zN3NciH15y-r==ELRA5$ePI7!VV zJVm}S{h9q`ZHF-dfoP=?jB9us=9*CfF3LXfE`_9Km!ud9>n!f`2F{Hrs4XhxLypn+ z-#A2dAdLGl;hQ=6&p7$Zb!PJ$f}(BaXe09Fa@4+V_{ha}nMX@LY5jC*TnfWPYFP5) z@~_)FW9D-6AK9b()}U9^Yai(^6)Y$yew^gkNG%m@0vN*1*_&MXB?JT`7z3bOBfVgM zE}1O3kL^%_xP6kvRnRl)8#;8NX}ua&uE_Vk(Fmr)h@;1lmx7hBLI(GpOWH;TxDF5A z28pDp-_TUOo4$#6KzvbiQL}0o5fFC0@Naz@MYY=Yxf#ux zficLJUrUWIbd&=JuGk8xe<_}^OJo041wQex2f4StCwCMV87>-2s0^_RIrKDY-#EpSo}#Ez;Nk z9uz5(n%uRT>vKCy1T4_KAQLMp5D?Fnv1g;Q(}EHTn7&(@)05<#jq7gCr-h?VVTBS6 zZHPM$x3-5cH;40DpQ;DG#5zG(w`hs_l@}IrdSMmgs+UdK1xlfpFEqZbj)_tMv8WXL zZYjlgk_lFGZalB3&X44}>?7@ifSFCPM2NY~be=4;TT2BqajxS}hV-%oGmLPy@zL>h z1I>$O_sb7kQLd48o@&*5N8E;44*>0L^TL`iy%uIRWLl|cbEF+Vu@2CkrqXCJFUQ2l?p3?fycq(L zXyqr@)SZ9ayou5tt*@~nh{kx_hxRJ8Y^2d?E|T`2tbUp%YEk%z50Z%v}+5$3<^6u zX9qZZNlGdE5^>n$5ArS?Yoi^gLzDf~NEaWAZd7XBSn$fkYwPG!{BNxGqnwr7vulA> z3JZk0){c+X5;{=WA{v%eU=)T;Hecu4r?qeE$ysO#zM&tW)WS4?>Ot^A&n5%)HQ2J& z6UbV_XCRyS8;V|+Js z#ne))9^p@^uh~y&7;$&B_uUod1@iniG16CE_t63$9yflRXTC_8P^XhoY--T2GbtgG z9wU@Ok@p~ut*DoL--mN!SdXCZP?+Y2+yn}mNBws(O)vqJMIXIUBqW$x!fm|#YyVo7 z)klqmtk-mMqnWVqc1_El&<(oSPo5S9T`}fFzzcjFQ6~@UvWO7+SU)lipC|`i(R_0AfZ5BZA~I{<~nn0d>;NQ3v-*~DC_4Vg*{DG zGb(bO!j1LWSGzVl)0+48Y)EZ>B_cFcsg#B}j&w!^gAc|vJ}Zo#?@2BGl@q?5ud_H+ zsPJWj-AAbE)Mqgq zK4i9kE_-R~Ha_M9mxJ`PeQTQ0bIF7WHkC`Nhr(pe-s^8#Jn#Hee7kpp1rn=wUx`v~ z9~74Dtz4xkcyU2Tfn7zH=PKq45M-G{KCTydX!%@QB8gR3U?3lmZ2GiCviliN1M~{m zC_j}J7LqKbvihf2;I4)^$&rgeJ^O*;-NDObzZ{c8|Sza|@`E-jsVM!M5pe`fGO+(90Q~OAm}ofTLu9GLOd^M6aW_ zW;;#Ch9mvK*}ats1mUICmULPnyy?TH%{Of!^r)QI?Qvf;OIehAcN&yh)8V~u4j0Zh z$xoFjvS-TnK;F)Z3j-1#P$(lge0QfvX8#!t>f~4v29yzy$p3f|Ynv|Kvd0F{ROpHy zPXmS}zJ}e5iWVb3){~)O&j}~2tKGo(wMogts@rsTr)Rb4KE24XX+^F;Hfwq^xVd6H zE$CZ4fh0%_y)jbz=UX&(;EM%Q1#Cp&PBGNwl2?j{BtX6EN4qf@?cSB7E1WO zwYEFSFKwPCY@VE}W8lU&YIi?CCHZn5#OEFmk^Ok&=lIYr)%4|klj$CD@5jHIhTD{j z5G?RK#4j=;^C#r?yCR#HoGb%j%KAF&ZxAnMq4zzO<87mBzc(VZ{7CX1c`+e5zkbMN zGCS3PJ$t22XL`X7jM8gC36>|%La$hJaCCcOfF`CR9rv|cmzF&g(ku>X%~l1xcv<2_ zOhQ=au$YwEIqXu1jqMGe8w=HnAlwBoErb~tQ&ZScWld7a27rz37a!2Sz((e*KH|DB zRNC#rxuaBnBF7pa&rlsc$Kwqvd?)h^oEzFTS!)zvIv^dUEEk}TpDq@oV%!;42>zUN zc?40nQ`HZ;&&(zN>G^c_LFX!H_Q-ta2wCybg8POr*MpyHPZpogTZMZDjR_WzZ4qbv zE(IAaGwAmltBCvm)G9~_~zEcy`@13+SVj2U3VnKqH^p7@$!1ZdG$^aE>7!Uh`K6_c6|z zGsff`V69ve^%nWJu zG{)`}3AD8N4+6GI-l$To27Z3}(MiL-wt2?yGAbfE@LSv2n2_UV#{xv=4>fY7H1L5*B_4<0w-mt{nyFA(DFCN7Qb$8 zJOAv)_S1qioZKcbdy1U&GzETL3XSD#8=E z&IBqirmSfSs5=NUy9g8WI=%q&HmXTU1W@X?r18*&!~YH$*_-+ED#f#+ElBP>6^e|8 zx2gtZQ47R;4J^W>6eMpt8@(@;1YaWZ`jJh9&g+g1b)X!j0m<3smoA=(BDv><#s2s7 z<7=iEz=K3@0S>s5_?al*l6F^$OTd)Y)KCBuK&#Jx&yC)$k?Q4F8%m#hveOYqJ{rfq zQS^^OaOdv(NS`bUvnSiL_e%<^=s9v#=B%be`3S~GEmVs#%V|Ah7$X;@S#IXr{mFX7 z;vmW2(>Okuph?=}5UY~kji=d+ zli=}$8hO|nrn+6>l4`X0`Gsf|kp82ntU%4;^x=|bVOndBl9mlt>T4|Xgu+58z7I2^KSB<1r+htb6C92 z{z~xHGR@vYyMFrcwTR7SXK>L|yotJ(qz>=+r$ErV9+jM!+ zW_*lWz_B4dm9oBx*xAfCkR^cu(+D@of`Il)wT~>)D9tEkFH>vW&9UqbPZB%u>`T32 zHD-0`CY@#G*j=^YqI7m&WOSSem)8pP+`=1W(7qHa(z7{@8_6HqSh)Ddj4rD+8zGasd$qDs!kekz2w^$&d86J%(Ezo&R-6Xea(^&J_JiGk*?gU`E zxU+KG_o~Aj<-feup6hd@82(a+O~3k<9<$)=UVQQJX$PQM$*wWpwiCWHjMQ-dCBhX_ zXY*-_^0m430omG_l@tjrlK?YAax4n6<6PTJ5(xPgF6f2ZT8fKeEFZ4?x^b3`#>XrO zNxzuWVfu1t)?lYkXAqzIf?bt<4$Pa{QGM}ATz=Py5UjzJy?3?ukQLT|dwEl8D?6M{ z%Gc`h^UI9Gyp1UF%ooyz5~hzLt}_RQgNeR$KwhN(i0Ai`Czx6HD>IxY?t3~Q`%|@; z@F9iG3hO-X!Fs|+RX(RhiY&AqUXs(_QnCmRB?yisw+oZ(+TbP61I=%EgC-8ClkYzU zwhwb)daB$$^~!yCj*L_FA4|Xfp)@ZtqNqdptqdo}MEBiR-ZxkO7?4)>t3{||hC7Bm z4|p5TyXPxE2c(+=)nM27ZA0PV=#4YY=e;j2OYj!)gA`Nrv>E#{6=xJB_z~cSH`CFyZWt0QHJ~;um1)9s zJTWvZIPz3Rd3oN^wrCb>lAbTL&6Eq>L%1ag`wdeHy)e*4O;Ey#f>QWUtTA|9;|O zBb7R$HbY7$ra0`c{Pg`)L`@)P8m4{UUMf7FjQOtfUb6|i6c=-3bXNEMrRtNea(*fR zdVIyxS&_b_s4&O7cB!~_F?toyQrY*LEW=c(lNAgLz<{;_1JHeUdSFtCRpX2~gFZq* zJ)4In4Rt)1EtZ{fD%0a>;UU9H_mQdNiRXB|(>ZY4Zh-n{#N5P`k9Rf5-?i&@K0U#8? z1s_x6i~NgD%e2CDavSdD*bL{!ArYFQrR3*Nrfugu{xwYfMFubRAV1iCxdF!K{?uPt zK1b9brI$8OM(ACSCNV9{xNiA~1;IGFAUE#IWCy-NR6Vi_!&Yxu&Sk51+zDUIIHCxH zGCi4$vST5N0T?#$%9D--{17M%$mh#{^oZQuZR0xK6)@s=HsaPWrJOO>IFXSm9kO-WRSAk$Ug01CDGD#03py-)FkOuuaw878i%7-PzG#6XJn9v86Ma~+~~ zvxYQhIZ%7p2G_5JE;Lm-n!f=Dc0al?=K!Ra2Ez8Vh+e1ow5yn@vwSV{lfyjq3tnoC zZ09CZ71guYRny-|8o?Sy^unTDPuw{18nFZh#TuYs;cR-IP{(@U9|P^r>hz!XULWN5 z;T^ibQaMeNQ75EJrg8g6tyPMtYh=4~@xWVr(R)ebvoa?G**G=2`^@GszZR-p!Pfa^ z8gZdczJ$?zv6QxNx)a%rFJY1F5%;sQl!EwRolAB|{kmh-#%-*sYDvRA! z5bxQB5c}mBx}TNC4J&O^|$*ySNqx@b@_ZyioI^ zsC;~Q!j?Fl^AV4HJOXiB`1{C=P|}^i#8p5XW^trU*^XK9Zg+l4t50dLL;dS%yS*F(`Fh&i z>J`J&XB-!NjD*RZ#m?QLz}&TtMkaTlPW=aHF$`k|EYpfax8@;oWZ{<$!7)4G@-^xG z_l^)CK{@W~lr416c^>@Z;GhoOMq9tMzNe|&=H58AbB z9Ts@-U#zQ=6UdQQN+P1INFD^JJPoihvM4}AD(G`)o1MOZ9gQ645;sDMl&?0G71}u8 zn?rNE7wl?;g|i_zu^jLowx(GH>cfncPMpS)tJWUx79Zoka`<;x?gK%OO zFuNkVP6m80+>03oqL-4|0Nnt(EglkYaZdrso!fxQ@S028-ESm$EhbH?3v@oDJb=rL5H)nndPMyaN zo_-MFD&`M$Wg7(5g?$Yx>o(d4w9td|CichF^}cFShaJ7Z@c*&a{|~VpNI*md96E6ZteR=DhOK!K zbt-3$9>mL$(NS|*&O(8a74ntbcAW)}WWnLCxhJQ){ervS5DnP2YY%xYT#MjgdwA^- z*~M30!^&n*sg+=(O>3T1RiK2~wp@)s+9l=MN7^Ul7R8O^K>Yx()BrgLP4q-!F)5{nvNUerQX<8@LYhu?T{zaT>E=Nv0jf*i)lJ z>nH5O{4f~8FTt`|Y`$;!(Y!rHvY2Lyqm-O{Q@n!Qu|-AYDGAL7|BD=V&Xe2Ok%;*) zCYLVxX_Dl5^dh=uqK=aWohrOsOL86E#2vK2(Ql(1Z4fca}bej9n-oUsZ5V`!N(@HDb)yAFYqNnqhh!yW8IcLgMpyS z)hOBQrp{GDR^jK<|v@T6ouwH2^QXTzq96Y1p6XKK#%=x(~3APVd!0 zqIjv}+e3Gl@7sE}6l^c%V@J%J`vIylPxBnLHTIJJT4hDE&Wk@w6Y)8XQ@<}3JDzi- zy#Aug?cE?{Si_-MKQ0xGnV^fQuEUN71!FrHAwsi=X$HvqWoFRCYv1S&VJF8q|AO`c z<$IQz)p^h$><0#T-?}q0+O0wEtq7%XkcSnDD(G^dk8B_+C$q5*J0E!=j&guJwVDTR zJR|@rJm?>}6^L*cW-!+P7grlsg99#nE*{^VKCzf*8pA)%TXapp`|G2TSa-Lgh$E9PviQ+N>4ZaOMB7gU& zX0Je9-hhuu0{H81;(Dg@K#j++n`8Ck%ixX}^A{?Uz~00UFphpdX+5`B4BBw%*sQCpW{4P10oRCb|Pe(v5;7$~BLaBE%f? zY*K76_j7#)9_KRUwm1W=IP^@)k;7V*k5ZCy;$m6f1*1ger4tue)7X;e*IurZO7nx4 z;MY?%Kluu#D;ADh(wqxC7AFe8%l1utP4I_tA_1|(?+amW^UnO9?}NX!Kh{-^#Bs); zsLt`(2>CQkQiU}PiJ`eG?mfvco}PfmpkT^*`#&6{1-6{{of!(PjjJ)YA=1ASef4&t z4OH%>h{kS6nx8l=>9riSFY{4c4$;dI-grgzzM!4L_yz;&?$DdMRA{){GxEOJb4|}4 zH|Ep-dzE?5n`~P_!6kPC!p=FgFUVl?m@qU9#luZO!Gz7HZ{Mqs<#y6RI|6&CvWJqw6{}*MOhqd(MV!*bP#wUExnoCXn341l1-BIQ z_q3lT%u^FKdIgFEcEKG!O1mNg%l^z5)ZN1L%3xZ9Vc}}vH@G(o)ja={dC>~^;|ina9N^>C-t4A1|Kp2fV5GcIh%*@xl!{ zU92XH5?*y1-3arLO-Xd~dfQ7wZ;^a`ZiJuabYy!c(T$$Cp^?gX^7h zf>^Hlo>Q(z09b=6pXv6Cud|o3KR(U3XZ}QWFCwF9jJuQt+EG${Uz^Q2^UNmV19*MjrhRt(U5M&6%;l#{VMwwF{U_H zTO3!+S2&gj?4J2iI@!7k)3+G}mroDGU43c69WygcS-OI2ZD#^X>&?-;VMtN=r;47P>2n5UIo3%hoqwQwBV%;t30cBBom? zhqCig&NKU8Z}cY&+#F!HJliz*8gZLEF$@Nh= z^ed)Q9>Lc}%{F3XlX?p1CrpoX!HwmW=5=35s@H}yolPN8O{=@l*rWYMdXdHx>qi88 zu;^W;M<=5D+Rn&P_XfkaQ?81ur^_38tZ0mLKdVu$TS($SHL9%UMX#(ma>huPc4Ja0 zW^WztNggFIVE*}8X_1@njja<(904ZWU;Wj*UlW{C)mUG2#i+kwgD`!v(`8<~fVq&w z!k*Ye5LZK`thVN9Iqi6*DYq5%ine1YjIce2-+(48mNSaENSqk-;)8e~mWd8;&^mD^ zE=6i(ADa8fe{X*W)zZiQ?cKiJYgU02xP5i#Hj<}4Yu94dM};`N0Ev}LlIoXPldnJ)j%fSD`K3lA;{lEp2T{1 z0tY7(Fxvrv<-5fzyU(6{2St@nhYd!?&_pXq^(t^%^&%UP4yD%SofX-e&d*@ne^ zryv)YDCWGohGT-;XNUeDMe7(#Iu&uXYTCW^iayB00<|oL9-W|#+1r3i(=!;k zIHXLkkDD&Gc+QPI7F(1m3}=knJ38n$m(q!Y-fa?Gw3E8pXWy?0>2sb?Zj-6c;c7gt zQ8~~aW;C3v?&b2TDrcFxYPsMX)n}+hF(mKDW#zj8umwpO&pvi zmm)SMCXxY*L$RllGJmyY$9;h>n}b=bd2zRw=I0y=N%AhdDHNPaaI=tlNilT!TR1L% zy2AL0Y2SMFYND&oPRa=Jav=f~@kwjKp)&c25j?zhX$i6QE(+J8ELAgE-V`a+$7PA? z?}c`@7!KKkXLyWh88E?(Tot44DQXY;e_~@44%0H7Pxp;)6BeGugwS^F6fS2uVA!@y zrkxkprwqh2`aacTUlN%aCYYF(s;wdnRdfd`cFjP&lG4{1)0IfW{1A8tZ(Y&a*Bg^WOZwhJmzdZN?Dd`O#DxvaYoTTG~1ES_wLx0tPKa>EA^ut z6I0xL;-mf6af6tgIqLcjy4d2@%EQIQ&{7pcVrn6FU|VT;gSlAebRpN?yJY=|Hemav zzJ(6}`ztWYEmZ-;qeC!(>JZWfmG)OJ*2|?9vjKD3`MGX!bjrS!ST6z@-mY>OIAI={ zkOE$K+#!;%YXqFhnzJ)$G{sg?B&J4sThI5^{PYNZBNM+j=bFhhE3k1VfX| zPvUG6pS;w88L#Ks_wKhgUVL&p0LJ`eT-ECp`F|Gt3_t>+RLlrbQ11c00Q!5I*$#8{ zSqMJcDB&Z-T*k~p_a37dN8Sc|3@tfsg}6K@vbQyeoW?6<9;>4Etxji0oU{<$`nKW# z`(J8dePE9PXaS#Y$Govg92&k(qmYeYv9<>TE_x0oR`Ek;Pn%h5I;BYB5V> zHx$l7Md2B-4_1v70;yn`eE|+l_o+xLDu1cijokF&q*WM3(zgU(?%r8j#EQW5Ap_)^G4^LCQ|kn3+c~agqnw{=!@|w+SG*A(8PHH=uF|6^V+E2 z74dWO*qAvKhy)y#m5(bX2SO!k=BpJSD({68Ix<&JJ!j1{?HRqf=MQV#kZQkai~49i zU~X?k?k`u&#Lv9f6?0(o;aSg}Xf!idlel@1%7mkvc*c}|i^04-QI~el(|cYZVs3Gc}*+!~>osl)V)>OY7CY%hp7xz1c`Jy0Au3&F-hsU{`B`Z}awjtG>FTruH zuJE5TF)uzdR)CpZ&F#V7SmbZdZehLTvVcor+WG^HaGPxDF`VP2MTZE3kO`@j+q;Adm>Vqo-8b)*)x_pPWg> z`hwH(L@&70@W?U~|9!CTOwmahME-KFyE#x<Etq0zverB_N1K%}ZiN)}^Bx z^2GX`+sIAnAV&O54R7j>o4e`@%{KsctzQgg*h^S*UPWq>H{y>LzilQt^hzv_jetbr zHeXVo?ex{CCZ)br8?mg({ba4-Q@ii7B;Pnb_|aNHj7vBJc1}l)g)c_LF|pj3xXH96 z`>JP6xnPpC5 z5`s7F6hb^)Q9LUMZ*5xzcl}GQ=IMiJYa&aMSDV2xD1x)@Tb^5l+ZM=sg_S-p`lm&r zfRIn#pFZic@!-{e6OXiW{I=hk%Jo2L&1h9K@Q3E_3e7H*=gwUfRC+F>Q_CTU{!K+r zk>_8%V$&)!yIx;03EUIvOngGSZKcPX46lnk03ScMedDQrNp0eBrZF0SA#>JkGuTv> z%JWd1o$3v(@RuYfpZhBHIY2`p!jVgm}bA=}3_i0w`51pJGza0#hFJpmOBrPRn|q zz#EDFaDqU(Zit60szwRiSR(|gL~NNRDc*~MY>xDoki1!*8T7yrGX|Y@oT?DZA05>5 zR>X^PE_8@|U8&+qBrWA##{#xda`s${JRlW`#>r2FYJaI`LEH?1~iA1cV7|r5lIu!cQX!URH&5Uxd;I ziVYOa7B3Q^;)JVEnSVjZIJM$4GY`ETWtv2?P5Bf)n*OdBnb7JZ*t6Q~NoNv7kD+HB z|Dgw(!dTZ?8MS}Y?~Uyq;04wCx-+N8@IMEcf8R>TM)*w_h`p1rGhM6Va=P)Bn_`qd zmDDIjfh$w^R`b_+<9Z6cJcN2xaIfyLz2Tv30+?qtaaC^zKjI>BtHjO0se}@D#6`J5 z{4rQ_I`r&N1|^C#byy$kGH-CQMJ%73sW=-e#Kl3WDZFK-z@qK5$!u&BRg_ffjfr)p z$GhMh$y6;Q^}In`$TuPtz}@=zTq$Q;C4u<)QSfN+E)wnvXu)}MXmciPIXKRDiV+ei zI-o7&d^!cS27M~#P zQHHXIlkkD7QKI$cZ~KNC_^{~?bHSj_`a_8nVKv+P0iOX;?%U(W(*Kf+m;$_&dK0q8 zjmNqFGW<Iqy#TO$rlorIFS#`GS+g8Q#N1w;6Hutnc+9Ot z{|ICNDW>=@SNo9iJiQM#vQjec&k)JXjD+vtGBd26?~f}!G>cp`+KzfWva9o_#1ard zUh|vLYjeHsFFuOB?({>r|0Pgi{3lnse0L`6e>d{K75Sfy{O{EK|Kdo41UZkPNLyp~u=CV_9qUXAA&pB)wJv>?9$fL8y7KhUPRH?$cWEiJ}-P~~@f zx~%#@i*+Uom-C1Q9r6c0&FJ0Hh(NAa4J{wiX?)%y0r1V_Tsz{=7js@@-1M;>m1;CA zX^d}*bsU01$!VN^?9qU3I4b>tc$=>;rum)hU*gs^sy8EiuTH$_d)W9gsqUh0ShLlq ztt0+|D}MoQ!xwTMgNnB;uR@sW&G2(YHzoGxlP;-Clvx!URXa?p93UHORTThG&Nauy z{RzrV)Iitlq+QF;9P#hRZ$g+n3`&o8Rs6CEkWKDn0Iv0Ri4)>~AuGp2g=WWt6tcfQ zP|@t%8D8JAsK5UwUi$-ZElPTplKev{I0yVq@vzH7^KXT`=C>>5KSAwzG62oZKCEZ` zh33H1FMQ`<9yJ(p~=%g|0mX z9`{_J9sOTE=!1WR)Y9LA9L+6%;2F?iZgU-Gk)jQ Xk$H>{8Jy(K0Y6G|YR`*h&EEYVIWtvI literal 23617 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 AhX4Qo diff --git a/src/main.cpp b/src/main.cpp index e0ee502..23d5a5b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,18 +23,16 @@ #include // scene information -constexpr int32_t width = 512, height = 512; -constexpr glm::vec3 light_position = glm::vec3(5); +constexpr int32_t width = 128, height = 128; + const Camera camera = [] { Camera camera; camera.look_at(glm::vec3(0, 0, 4), glm::vec3(0)); return camera; }(); -constexpr glm::vec3 model_color = glm::vec3(1.0f, 1.0f, 1.0f); // internal variables -constexpr float light_bias = 0.01f; constexpr int32_t tile_size = 32; constexpr int32_t num_tiles_x = width / tile_size; constexpr int32_t num_tiles_y = height / tile_size; @@ -49,22 +47,8 @@ bool calculate_tile(const int32_t from_x, const int32_t to_width, const int32_t for (int32_t x = from_x; x < (from_x + to_width); x++) { Ray ray_camera = camera.get_ray(x, y, width, height); - if (auto hit = test_scene(ray_camera, scene)) { - const float diffuse = lighting::point_light(hit->position, light_position, hit->normal); - - //shadow calculation - float shadow = 0.0f; - if(glm::dot(light_position - hit->position, hit->normal) > 0) { - const glm::vec3 light_dir = glm::normalize(light_position - hit->position); - - const Ray shadow_ray(hit->position + (hit->normal * light_bias), light_dir); - - if(test_scene(shadow_ray, scene)) - shadow = 1.0f; - } - - const glm::vec3 finalColor = model_color * diffuse * (1.0f - shadow); - colors.get(x, y) = glm::vec4(finalColor, 1.0f); + if(auto result = cast_scene(ray_camera, scene)) { + colors.get(x, y) = glm::vec4(result->color, 1.0f); image_dirty = true; } @@ -182,8 +166,8 @@ void render() { void dump_to_file() { uint8_t pixels[width * height * 3] = {}; int i = 0; - for (int32_t y = height - 1; y >= 0; y--) { - for (int32_t x = 0; x < width; x++) { + for(int32_t y = height - 1; y >= 0; y--) { + for(int32_t x = 0; x < width; x++) { const glm::ivec4 c = colors.get(x, y); pixels[i++] = c.r; pixels[i++] = c.g; @@ -239,6 +223,7 @@ int main(int, char*[]) { auto& plane = scene.load_from_file("plane.obj"); plane.position.y = -1; + plane.color = {1, 0, 0}; } ImGui::EndMenu();