From dfc465ca6d5a22abe558c15af97376a955dc1954 Mon Sep 17 00:00:00 2001 From: procfxgen Date: Sat, 4 Sep 2021 19:55:09 +0200 Subject: [PATCH] new models_magicavoxel_loading example (#1940) * new models_magicavoxel_loading example * Portable header-only file "magicavoxel_loader.h" for MagicaVoxel loader example. * models_magicavoxel_loading example added to CMakeLists.txt and Makefile * fix models_magicavoxel_loading example for linux. * * vox_loader into "src/external/vox_loader.h" * vox file support for "models.c" * updated example "models/models_magicavoxel_loading.c" * * Fix Vox_FreeArrays (removed memory leak) * * removed magicavoxel_loader.h * * Revert vs2019 solution --- examples/CMakeLists.txt | 2 + examples/Makefile | 3 +- examples/models/models_magicavoxel_loading.c | 153 ++++ examples/models/resources/vox/chr_knight.vox | Bin 0 -> 31031 bytes examples/models/resources/vox/chr_sword.vox | Bin 0 -> 30775 bytes examples/models/resources/vox/monu9.vox | Bin 0 -> 160767 bytes .../models_mesh_magicavoxel_loading.vcxproj | 387 +++++++++ projects/VS2019/raylib.sln | 19 + src/config.h | 1 + src/external/vox_loader.h | 771 ++++++++++++++++++ src/models.c | 110 +++ 11 files changed, 1445 insertions(+), 1 deletion(-) create mode 100644 examples/models/models_magicavoxel_loading.c create mode 100644 examples/models/resources/vox/chr_knight.vox create mode 100644 examples/models/resources/vox/chr_sword.vox create mode 100644 examples/models/resources/vox/monu9.vox create mode 100644 projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj create mode 100644 src/external/vox_loader.h diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index ad391edd4..d102eb4cb 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -86,7 +86,9 @@ if (${PLATFORM} MATCHES "Android") list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_obj_viewer.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_animation.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_first_person_maze.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_magicavoxel_loading.c) + list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_custom_uniform.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_model_shader.c) list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_postprocessing.c) diff --git a/examples/Makefile b/examples/Makefile index 5abf0c708..f5cb2175b 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -466,7 +466,8 @@ MODELS = \ models/models_skybox \ models/models_yaw_pitch_roll \ models/models_heightmap \ - models/models_waving_cubes + models/models_waving_cubes \ + models/models_magicavoxel_loading SHADERS = \ shaders/shaders_model_shader \ diff --git a/examples/models/models_magicavoxel_loading.c b/examples/models/models_magicavoxel_loading.c new file mode 100644 index 000000000..bb1389d6c --- /dev/null +++ b/examples/models/models_magicavoxel_loading.c @@ -0,0 +1,153 @@ +/******************************************************************************************* +* +* raylib [models] example - magicavoxel loader and viewer +* +* This example has been created using raylib 3.8 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by Johann Nadalutti +* +* Copyright (c) 2021 Johann Nadalutti +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +#include + + +// VOX Files to load and view + +#define NUM_VOX_FILES 3 + +const char* szVoxFiles[] = { + "resources/vox/chr_knight.vox", + "resources/vox/chr_sword.vox", + "resources/vox/monu9.vox" +}; + + +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - magicavoxel loading"); + + // Load MagicaVoxel files + Model models[NUM_VOX_FILES] = { 0 }; + + for (int i = 0; i < NUM_VOX_FILES; i++) + { + // Load MagicaVoxel File and build model + double t0, t1; + t0 = GetTime() * 1000.0; + + models[i] = LoadModel(szVoxFiles[i]); + + t1 = GetTime() * 1000.0; + TraceLog(LOG_INFO, TextFormat("Vox <%s> loaded in %f ms", GetFileName(szVoxFiles[i]), t1 - t0)); + + //Compute model matrix + BoundingBox bb = GetModelBoundingBox(models[i]); + Vector3 center; + center.x = -(((bb.max.x - bb.min.x) / 2)); + center.y = -(((bb.max.y - bb.min.y) / 2)); + center.z = -(((bb.max.z - bb.min.z) / 2)); + + Matrix matP = MatrixTranslate(center.x, center.z, 0); + Matrix matR = MatrixRotateX(90 * DEG2RAD); + models[i].transform = MatrixMultiply(matP, matR); + + + } + + + // Define the camera to look into our 3d world + Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 }; + + // Model drawing position + Vector3 position = { 0.0f, 0.0f, 0.0f }; + + int currentModel = 0; + + + + SetCameraMode(camera, CAMERA_ORBITAL); // Set a orbital camera mode + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + + //-------------------------------------------------------------------------------------- + // Main game loop + //-------------------------------------------------------------------------------------- + while (!WindowShouldClose()) // Detect window close button or ESC key + { + //-------------------------------------------------------------------------------------- + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update internal camera and our camera + + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) + { + currentModel = (currentModel + 1) % NUM_VOX_FILES; // Cycle between models + } + + if (IsKeyPressed(KEY_RIGHT)) + { + currentModel++; + if (currentModel >= NUM_VOX_FILES) currentModel = 0; + } + else if (IsKeyPressed(KEY_LEFT)) + { + currentModel--; + if (currentModel < 0) currentModel = NUM_VOX_FILES - 1; + } + + //---------------------------------------------------------------------------------- + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + //Display model + BeginMode3D(camera); + + Vector3 rotAxis = { 1,0,0 }; + Vector3 scale = { 1,1,1 }; + + + DrawModelEx(models[currentModel], position, rotAxis, 0, scale, WHITE); + //DrawModelWiresEx(models[currentModel], position, rotAxis, -90.0f, scale, BLACK); + + DrawGrid(10, 1.0); + + EndMode3D(); + + //Display debug infos + DrawRectangle(30, 400, 310, 30, Fade(SKYBLUE, 0.5f)); + DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f)); + DrawText("MOUSE LEFT BUTTON to CYCLE VOX MODELS", 40, 410, 10, BLUE); + + DrawText(GetFileName(szVoxFiles[currentModel]), 100, 10, 20, DARKBLUE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + // Unload models data (GPU VRAM) + for (int i = 0; i < NUM_VOX_FILES; i++) UnloadModel(models[i]); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + + diff --git a/examples/models/resources/vox/chr_knight.vox b/examples/models/resources/vox/chr_knight.vox new file mode 100644 index 0000000000000000000000000000000000000000..c921bf5c7a68dc58850152862931d7a59b931d75 GIT binary patch literal 31031 zcmchgXM7xI5rq7!#V(FGeWIU~pp%gwP{EUhl!tGjq{?tt;88e<`ZwvXKn zv8&9-iEUS$ZI@k-jg76w&b7K+d@#1Y6`PpxJ#!To+Of5RHu3G?Lp$-IWn5IZp;E25 z(sjYHAA08E5Lc~@SHy-f_)5;KDYAW# z8lNyP->P`i4&{`%NU&Es}(aUZg(&UhHqk98ScUChn;@_bAktgT!dxCR0o zOCQF*Qtfh;g_7&8TY9DBdg`$)S0iT+7|t)bQr+5wzVE8X^u`HEPc@(?re-n64RxXu z$XQ@5HRzf1#Br>H^mSk^E|9Yx(u9w?S#l8QnLytf8<>yi;(X_-3GprKIQVL>DF}zI7#P zO^#g|A11w3jFq{`ar&&d_Ix#Ft`>&DJaZ42r5_9ysD(+SRx*Zd%)&C%DsU~t!j<#c z_Vl4ApPuW_lOso6JbE1Y@#MwPo1W{zkrz)tIr_@G(wsx9r&k>J7Eez)%)9b+4&C0f zrk{K$U+I~*XAaI*IL;dLXm+AIRQeqGbkxvWW`ue4JItfmVIIv6^ISKc{&h5!N4FF0 z^o_$jb#+`vp6k+6PltJGYtmt!zIB+FdnM+%M>}ld!j0$NzIYe8 z@kQQFI!lXe%QCTk z!XM#B4jxQ?axBAA3_k~&yfo3%L{AevP4pD<(9=Xu6Fp7zG|^K?Mo$wxP4qO;(?m}( z4fHh8(?m}bJx%n;)SBpNqNjVd*{yG zI~s*hTg-RjZ4$rgt>9F76M?4W>Re zIkmW(9tk>h^E&Pzxr3|BNG7QQlB}wL4nbsHKc3AXjdTchTtU*oDj>ORR6te> zflk%}-Cqmz04>ldTA)+4Ko8Ucou&nPkQV5{TA;OBpwqQL577eg-yL<{_|DJ*JyZ*{ zUJG=l7HESO=qxSJ!?ZwWYk|(u0?D5et9;@+PYZOu7UkhTA-I|fnKHsx<(81 zaxKs+v_QEQ=#^TaIW5q&TA){HfnKczdW{z7IxWy^wLq`a0=-@f^ad@^8?``h(gM9% z3-lH(&|9@Yd$d4r(*nI+3-k^x&^xt2@6rOjTMP6aEzoVp%&;zTA&|mfqtR|+NTBjsTSyGTA-h6fqtO{`lS}=S6ZN7Yk_{F1^TTP=yzJ6 z-)n*XpauG)7U)k}pg(JY{-OoiuLb(67U*wUpucN@{-Fi>rxxg6TA+Vxfv(pA9nb>Z zpaojc0=2Y2Z7tA2Ezp0oK>yVOb&e-!>b%p>x)gvcROmkQskySiG zt0sl1@7y-knBF!yJ|c|O!Z?i$StQ6|Mse;a&)b?9DWYzj9G{#Li6__ki{E8AEFvAV z9asj(v_cvxCdjOiW2TgN7f>McHgtiXseF0sL4$jI3Aj`88$MZK1T{|8eT>pB1c literal 0 HcmV?d00001 diff --git a/examples/models/resources/vox/chr_sword.vox b/examples/models/resources/vox/chr_sword.vox new file mode 100644 index 0000000000000000000000000000000000000000..05fc4826b188f52fd1b59ec34208fcd4b9b4b6c0 GIT binary patch literal 30775 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 z zzPFdM=U4O@@%)UmIo9)x&N=57RpRk7d5hjVqw+kZ-;J~d&9)vp#+6O!neY(VBYcCq znY$+o_LdB-nOLWuF{gZ!KAj(8F8%!q`HLdlPdr2cL1|$H3v=>6*}!y@@W{)oCQ_)q_E_x2Uup6o^s($cT3&wslW- z`)q%Y#|auGmXn@f%QrL6Kaw?f!FR-mVBbDTg4lU@e@WlG!tPKypNH^$%e?aPH@;_h zdw5aNG2P*rH{s71p3U*?6+e;YANNwQx39zTnfxtRalCM#pqtCcs+lqL;Mc1BiLJU7 z+wd)XU1vw>o7XNocgwf&oW3KVl~-b)bMPza!x}j9(f+UaSR8<852JZT`(!!R`mYwxhjE9|L_1^fA!K zKp*oz!8F<^^fA!KKpz8r^vGoUXl2Q!Jti21-AA{By#0NB^!3r#M^UnqI%D_I(Y`+V zu@8EO12}X_Kh@Lze&pr#)zfY-j-Bpr-}$o-FM9g!>AR=zo_2TO^}u`%?4_Rmd;0Ii zImWi{UcEY4e&e^kPw6Xq`rGn;%ePy`wB`Ah_O_fGTfW)S=T@wvtu13n%;7-a2V{pW zW82dImcF<6ZJZkS7C-$hW8Bj3Dm~A>7@=+B&Ef1dd*Ug7kOQ=OKk^;mbt>;o>Dg(_ zEkxIx!m+^LvQYn2+(?OjoXVSVVE=A`Yw1~vhL)bq=r}Sun_0}GgJzWUo2N<|pG6+Z z-&79AgE(gAUasv~)cNVFv^V<3%$bj#lfA?DC+KIcByv!FPoH`KW~atc(ghBzYl1fz z`<9AZ_dy8ioH8HYi``TeKVvl=eJrEDgB_a z%iA$xgZj+xH^`^7$!0Y7e4DR-rp}z+bsvAZYG2l9(6#*U6!G#( zVJlsA-mc5nes3P@=<*%C<2Nw*23FtT&=$UPh0M1_b_sG%9m1my{$*ZzZ~uIw^Zy2? zzQLg+;O+RWlQY=oud5hAnR9Jl&@E80%vsm+K)uF&8UX#5=Ii`Hr*r zknUkY2fNCaa>cH7PENgYw%@W_^ugqitXBKIQokDBqT83^=Gx}*=-hgishs8T@5%de zd<35S5}gkr=72(vkLXfw#RLr0*%rgGjep+&cm*UON8Gx&51*k#t9BUx5GL=w-jjZ}`o= zK3I-d9%KAV%0`qd$b9_S((y+&l&FtaR}A$by1a`n%nJE~wAa$tAHu7O?)#qZ`CCv| z?!-elzH6Um@)XbHu8QYLOJLQLb%h#tjeKkBp>kr&dl;KP7BM)car1o%T z&y3jt%SJo||EYns@1w1UWX5g2YAN1qZFwfr39)z7aQ#~D>iIu?cHh^-fjZmpben#6 zAKvXoU5Yy#hVXW1u08FQbTWPQ2I>veJ8&)^p%FR$r$aVw(cl^T=QSGCQ?IXHKh~ow z*dlih$WMWfTY_#3$#8xA&z5>U^?I>h^a0Jfe8Tu1;kgt0{2WdMd`N?b+){6ASugUN z^y1n}vxJ{uw5@JkT!}5H>Eq|dF{h8+iaa*lm|5QhPrP71=z+)F{%O@~)N9mhl{>hd zxWj7b9CYb{wl~-!V+?>81Mlbhua(VcKa!{68=Fi*=6ZuR?JMi_7+3BnJ48o2__ZRCqk{Zl9dz;8!4OE7~J>i$8O~I9xm7S zgE7kO;9N=q*(u6t(>?n)^4aha&yu2bm*~_9o_d4qp7X7!hp%6i4?kQSEOEgZJ0FvI z(M32nL1Pc$@!97N-5&oIx|9PvLf<~$GRKy`-!^`Agzm0KzV%VRe0o>yvjg;Hpx#jZ zB>%{M_WIR;Ei$Rb>{M(rlkbOjbfbsPiV|N{@>jVLyS@PrF7c*^<`%#wsQb;D9m2`J zeK|D87wcEz<$Ly7;;yOS{mdB6k|XoJ?~A$%BU zui-DVMNSFsZy51+UhuOi|zJEo&67Vp7xW_Jx6GUmoYnhmQHRdST#VQ~-=3Sd;(-2%u`%*%^HDlL8&>e> zLu*^}`@D2kg_u7a9D3}vo9s6SV&x9t)WDfnpi6J?H)m|YLo(NHd?r5bapm=^p8b3P zmj~8pT>SWDozG)$oxFywW!VpM8t@gD_*=UFBf#s#JP*jnJNCoB?6I!%_dDZH*m%d}!7F}QIeSjU zj(UKe^vGf<`gcvwFpN4^vUk7-Z_-5+VwTp?!UKB862E;-N3f4K$<1q*j9cMn*WC5c zh5uJ@_t4z8Bah72V+{@7hRb_=_IBtl7x?P2H7n8ELv$?%>z|Bo1s`{bZ~lp$bq~JQ z`0zP7VeaoC{r;}=V`dF@)$PQX?3dRUKdZa&zGiQoD~IHS9cS4gy!{528G76i$GL-7 zY5%hB>eTu_jQVUc!awfz8nL@%@HS`9|0U9*iMxE|&l=hX|B3$g&iKZ@ZSlyJeV)>l zR)5-qbXhZW{tRyt%rC&Lb9qnB(V@Bese2WgNEdcr4~q=VcFv|^7JKC9HSkWrHqS@y ziK5TJpRIeAIx7=&{2Xr<@EHZ0ONTt4gLi7J5AZ9c?}q5$V9ohxAAX$t=uR+rAr>(u z^B+Xr3E#|K^y{$}`{o+t4Lx)oT=8LDCEFFw-2?C&J7adiWX6}HaraBle%?a=j>wT` z=yyhcbBMPcfMw6x6!@)z-s|o|^gZYALI+V=w^DnDLouEe8hs?T`5aHbO`kQ3@*Q|q;GW16S%6WFFS}x!-?JaKop~ky zk8kRIQ?F64RW`{?H_pzSj^oNXF_T}kXC7tLfp{PEKT}TGWh-&@HQWgHTacG_A8r*f zevFJfgf~ZElsTglcA9?VIkee=DdA@7!ozmO&z-tJ`efu{xhC(^e=Cw8! zVnO%q`B~J}71q-px~JP&eb@PV03WuUtGyC!!soB>t=^(7FG z6ES|qF5l;0|2Ti`p~|`VSVY;WkAHQ>q0OggYZCAw?n0Xx+Z$)?2L7sxS4hzOb8Q|* zI|Luc0Xb#`eD>q|t-1e%K5~I3U%MAD1mPnq@E!ZW1eOGC{0s$QecLK%`td-mTOXIW*h&G?)p@`M-epuHW!D}C3> z(0O=V+0!#QU1$8%W?*&CZ*#^+Z^oZx25-;f z{U!0+$m^=#`u_|LfA{UXl(0Q*!`bqwsk*jk)9j$lgWQ{U;{bfc^ zkjUjTD;|!{KI^B@KKh)wm$Zuda(4J{>ev3i;;XU>&pP^b)nYnR9S@Z14^Ek^X3taVK`I<|hTIL;06-6b44=eL#V`<~o$FP7q%9G2jP z&gsSP;QBc^E#=3!%2%)wS6qMXh%MnG<;*`2TYV%R{hz&+;T8NT$op5ZFW-##4JGJe zgU;W&kG6v!Id<+X#B|@_0Wal+Oyd1kVtrOTPvn?u#X!vIe#UG*$%8l-en^SEd9(9f z@-_0nU4Ay;l!&W4M-Mx1I$tyQ1fCm1;m+0;J;}w#E!eB_dW7DJTYeS~te^cS_v6uZ zC1~9`I#QA!l1V%tqpzmBeBB*%&rXp9yt%tnFWJbi@R*srUA6e_TrBa3UVJQP-!;B* zm293&*6~+tYj~?Oet28*BW#M5snC$Cch=4sR=UUe48O2y4;A)kPF}c?1LX?O_Tx*u z`@ue=tIEh_H6G%eU(}d=>&WjNe(js=ItP3uk^2@oS5&oRfnYLhe56^bt!Y#S( zM|&*67pLO(SHK{1F5X+4&uHgoc>u1&0ylK*4S21<{dMb@k*A;G-R*lii5Q!XKflB? zos+e%@Y*>XAJO5SqopHl-_QxHzU>@6_~s04PsP2T)8}@?IFBQ)#JfYu5}&Q#CBM`K zdU6@%TKNjj*}ytvjF$h+(TV%L=pcjj%-o%DhE5+_k0ZK_fAzu6Jx}L+7sg`5&dleS zKlZ(KOYNt1=g}(OzLop*oZa${kH|XRa*dbDtzU->x$gYii}o(OcHkRX8SfSS#Tnbl zihFpk=q;0IlZoes*qAH18}9kUb>s?2#2H+^r#IrWnXoUW?%d4CZk0VyvG-NxThV7% z=voB_D|k{_qY6G$c$A9YRh24q+?8=vbljDgqlyl@qT8;(uA<+r@a$Ep;C(7MQ;lPu zPO)gd555iB4ZaEb2)+;63i=7!2*we78;mJvC+H(Yos+hM@da%LV+r~R#u~IAj5p|G zrtO)2X4;!+Z>GJOK42Id3nYL!ynrUmMt(h^*jA5qVnSN*5o@slg?U}Y`#xXOF znLcLvc+vigHedAhqTLtmzG&k`8!!5O(eI0XU$pn4y%*oV`2I!TFZzDb_lv$?^!=i* z7k$0x>qTEL`gqaDvp$~n@vM($eLU;qSs%~(c-F_WKA!dQtdD1XJnQ3GAJ6)D*2l9x zp7rspk7s>6>*HA;&-!@Q$Fn}3^zo#RCw)BW<4GS+`gqdElRlpG@uZI@eLU&oNgq%8 zc+$s{KA!aPq>m?kJn7>}A5Z#t(#MlNp7b%*_EbMp?M<~e)!tN}Q~gc#H`UfuTT^XK zwKdh&)EK75FxBr=zf)~bwLR7LRNGVIm>S1aA5(oy^fA%LL?07ibb&kNT?d)N^H_G)k+~ z&d#~AP#UFG>Vi!|StyOtDz$TZt}K*BX_cC8X|61kMrq^!_`wBwx1igY`@dQK)~{#H z^0{xkYn0l%R+*#AjZ%BxDs#L@qtxoO%X-GTe6NrA?ljV2?TIy9_`hBLHZRZG<#Xfk zu2tsVEu6WnGWTxb>}-{}ceQtO&uh=;p4H1|@we|k`;N@E5c4(nf3y6p4bPh8b8UFn zD7AO3GLQc4O6`5C%<0n_rBl?Ax>=Jj9-vJ=KgP%zxCl+vwW@(?;54{ zu2tsFlt!t&Z~^;me2L!U8B_AwaWYteJHi}tup^Z zA4;uGyR4^=<$Ha2{$P(k*w+vC`-8pxU~fOz%MbSQgT4G<|3BFO5BC3qef?lxKiJO? z_Va`N{9r#npalFG;`*!)g`CXWwckS}M`S_jv74MFse{kqKNhA783r|HfR(sb(|F;<%7=QdJ-NGY%diD}^CA;hkd*TP!oB1lQ zL_INoxHoh`GxBo9K9u})vv5i9(Qb)1mPvMR1OA7y^UxqB3j$+~0kcqn}r zW3p>ww$1~-d2{~BEqJs)zkZd+yybMQGy3PY7~#?4I>&nK#n!o2PhxC-;_`i4*H(W? z8+pJev-10;6A5sr0gpR6@0{QNuXI>*xqf!Y!7p@orS`YjRD!;1y0?_>D_z2kpQT(g zxtv4`a7)d*TIMH)oAf)M#1rQ+Muk0LArDS!odcVCVx9Zw*BV{YM87v=w6WaHZ|Rcq zjNicjvZaDY9{s}D`Nw?uYq_Rw#KL9E9M5}l{_vT#ze?~Jvzz9P`w7D@e9h&;rlTKQ z`y^#|i7_#BV>A2uJsVH~2Qwux_icLf$GEo9W@g={;8UPwz33C_|7SRvfWbDLee^r8 z#3aD|!u(gn5d(VPLQ1^Iz@3xV|6g>iH$1%o4v?yWv$=Qg-`V}@%^gYc4Io)_u!qk z?jdeI+k5c*v48Q7Jusu^Sc6}ebUYJtpU`8ivDc3IyFbxEWvxEYqbXf;_CgoUZj_5{ znJnLlmj$;P-k;;S0{G?V!5+VY)*jmAmz+)Lu*E&(V{sbVze6_zJRP%{_QA8ZW-Xn> zy?ZTkF)I1^gZ;uER1T{a91^f@$i9ua)L@agFFNCE{wCUI)GNSjF2_@`-0#lHNdNe< zC+?Li!0-({yab8v*05eNFI3cz)9KZb{_({g(C=h1N4|0Ap>)rNcIChtt2dTYa2ngQ zkG?v?3NZZDcyjjEOrEIh$(Z5Nx;0DZ?pJ}c$umD)@g#52-9nzEm6)d)KJ?L|Couig zc{R+%RlJQhAo|!cqoa=SgbQh1Uc5s$*U0j%7|Jo7#x;3=E;e!(47&VOb9#k!`j;2F zl6Cw_5_6u33#<9=oy2$aLbrqHqbT3Av#J$iGNOY@>D0bw8=U{+y}WrXKRW@67wdd) z&e5OwpW>yXT<~A{TVlRD_gx>62eLZmK=?r(O1flu|5EnPHTt!Ev4%-{H=_fbw zK0`LrjNZ0SA9aRTTBQ@-v?h0KXX{HkCjTD)tRrX27XOP5+`Q)lR?%?4l{Bc~g!Vy-*;Wrh7k(o=h1 zZWDWcL>JbHIVt3!YOQ5Dakj{Hb;k!~-PwF)Ju5i_H|el0&1HjbX`StDJ&L1F!UsuLa(rYCx{s3P;c85k{9Rgp~jNY$ntYa`Pb+zPO}5I*6D8NbayNCj~zC)j4e&FS9@qf&VRAu_|b+QwG-nst?8VdbcKyQ!9OI6 zW9NJ1nL22tJP7RInf%J9acpuSeiYvxz~eOLwDj#!)JK6wA%EfGtGh?6Ww6#Ic_&!o zYr3)k9u=K)0FN{BQUH&NFHZoE&aa)X0X$MT9?T(mX6vS>3&weFUI9Ed*+WKa-w#hB zet<{CuCa?`BHtdIjK63sKK9K#sh0Cpd($LGEiG}a-6R5;Y ztmE;UpV?tH=}yI5kMQz|xXB=Xq!nX-4{md@+9mkZVnP%1Iz!t|=wsK7t7CjMf0U2n z7=wFocIAb?b#KRKa9tS3YFvl#*G2LK-}x(U7HpFAqq%&m*YZst;5jepTi3}PyYS-( z{rb#ymdP(WqSG$;WHxC2h+eNk3%Z}+3pjN6(Vx)4rt(i= z-jBpKU(1V;p=Tu+cdT7w9K%^>cqz}^rTtXen;E_CNL=6*82!3!9?fY*z)djX4=xR=Oxt$lXQ@1hYKzM!jL zqw6lv$i+W={j}AOILMZFVoYboRM}4(_?Z=BZTJ(OS+AS!55pUNAU%A-Ihl5opUD+F zdJxOMiN7e&h&i3~m`?sY(t9?H-ksdT{6Q9YMFHLyS6lJj#>ENzJ=O0G-S;h7Z51uO ziuuaq5gvfSnel%%?=kvXqIY-hsJTby%IVt0YxuMFYllq8#u)W3>aT%q639Kx5t_gG zW%VTL>BSv3zsTXkE{h-OkPSDjT~^2`0e1%Gd=GYoGvhVA`W;zp6R(((O?&u&n?Yx| z;_i{IIFc1Mn`h&BHs%t|J43^t!RQ$bo~?U_PW~Bep0)oB2G7?18El@x<{50B!Q|PT zp24G*LpYhp?`&`PoP%?*{LP=}qny1f&V@fVU%zV6r9{4&OEhqu-1*siH}SI9Y;BGBy)J%i{OJ5;7kOQy(PEb8&iwD5&<|(DJ^z#PaYf8#q;2aLKfE{# z`5*;(gRk)qmoY{b{Xcb1b|a0iKEN5a8toSk_B9;d1@l6jPx6HBkrR*DM9=9;dSt{~ z_L^LL(lMPv2mLI?cZ~Sqw(wy^UcYs;uwai$@KlG!w62eWo+@*$Cokd`v_C@2@A(s) zM_+DyRv|~hy7k<|n{Cpgbm&wzBhLtS3EBAxJf6T~on2%VPCbFg6L>s<$0xaipTOhE z_fO#Q1RhV|@dO@E;PC_=PvG$c9;^7ELZ00cojND)?|K%{nX9eW!2XJ1_5UACUTOJ2e04ei~;yy87D8JHLO`O^RG-*NAO7aP$L{nHhGZNwD)OXlJZ{-3=?_gBnE{7Q^rNz)?F)4BK#+`IpuZ}B6WbXDhQ!2NrE$#Nwh zfmdlS+&eQ0aH+pWUJswahPFv|9m92U^KP%yWpI_rQ2QmpD$FAbib_P zvF@x{;rY;7tg{Q=l2NaIwdP`nlkf@5*wWZT|L+ig5cAngtS8?oN#8u*B|FI@B}eK8 zT)Re30$;3g+!H6xcJ|>e-~D5AtmX1LWRo6|OU}srHQsxbKWLYo_;wR)Pn>CN`e){L z&8IuSiF-8c#ThfVhmXl*K^sXR+mU5bb7w||o-cNC_mrjlY}oW`y!1Z*$U-iiWbuxTnjeS#QOX009l)cC({L6aw{wiLvB>(i$^9&x=#@wvm%{$Pwtvp-+p}n=!OM=}Yzp^|(B~_1 zR%4BijBk7K{V{wl?|Tm3bMn^-+xb(ZPka{Aa_!3{I`$eZshsPN z_S34d-mqPd@SoRg{3AG0vojyDt=y9@PVA$C4^<$SuA}h-^4^v8y4#TF%Dx$s8QyEs2Xa6RC z;s}qs=KLPJL$v-cf2@}kbZS=~%$Uc1o$l|uC)PJRZO!lm91M;4APNnLB&3_TTuSor|w~KMs4&hIKvxEBukR z$+oJTi2H zSBp!}&+3g!RB9}30R#qUZ+cF3Az>l=Mq zN7ga=pY45lklW>6c~tI{iE^tcKa1X_ zU*!b&$_6+-arSrdP4-*CKK6x=5}(bST`>JB@6iSRSB~#C-dW;K+MB4i`YLDr-@9Lq z>6A-$frKw;YONOM@}J?4+dufHqJvGmJ6KNgM1J*bhFTA`a6 z%R^qPmo@a<=*ft$@Q9u{{YNac{wwWdFZ{;v1~WSLJvxBOx|hb^SjXzKJY-MW{Yq!- zo0Q%>Dc|86y^B70zsp^qzbX1ZVlQd%v)PQkn2+*IohxgdJ@d1c13z<*Py!}%zG27W zMGAAw#K|S_Gm-oMm_4N^-(TeV&SrAV!jU8A@j~0V9Q*%=mu|?c0k2Zwk6QRN2LFHa zp)KXAUl?zzoRY5};~cE@F&jey&#DWu0C;DfHSj4#Yjbc&*bv5Wv(aWS*S8b!l~ZJF z{JAj~a^WA-^QY|}#vJwZ_}41>62Z$jE@ON&jsR~?@edEqu(5UOI&bHv^ve26~ zTTbEiiSeY-4q`nQ*6ujQNL2BDgOR(5@It;B!_CatPS}EW@J%O6|L!Q4#5=a-ae&X? z(^DL?k@VQ|GxZa;vBKR3>EGLMT1*GKSmwL@D}QA;(;DBxn8)g+=*Ek4xzb+Vxck9c zX6j`x^4z#*;KcX;xCgV0cMMe4k&ZuSD@cv`gq5FH1R_Eljmj*ahGZl%_M=1YxR#~9Du#Qg5OH?HBP}i}Q9? z6m*Ljx>5PP4xejquY9*K{u4NrR&+yn`H{7(?7eY3bDH1PGk$dv&o{w!z$THzeTLpt z_CbNpt=Zd+|HIcUI0*(3m!i$@CE@|PiPnwXYm&;>a~Ji6@NcY*v3iZZg0ZINvPXsr zac@7tch8cTkHMTq?Dqw^sz8_Wc7&j2m=8dqtrjfC;5}0J zDZ&d4IEG8X+%L%n3pi0(!yJuWprbovu#^wU7%qGhKX=U5nfO0JLrVK%7o1Mef-XL| zwRXq$?+qR9N%R@ePH7L1=#5gbw}mzv?eD1j9PvjxBj-oz?)l7GByjWCoJM@$@;E2{ zK_xr)$R5j{$QJZ=PxeM-&$QO#0qrW#mXbX&d!qLcL)th;M|iuGKJvsIcgR{Zuo}Ua z1)R^U@j|YF29C|)Okpo)#+Bl=#>Q~M-d~U-@1iX*oW9L_g&NZ=5 zt4M$9Q+uP24#%8P@h%U0G|EI3S&N?alJ8enzMU2F>0JC=I%Rhddr`YK9Qk*^}YN&(T-fxgVOzW zt?!6jSjk0_^PN8;(|5^gNBlUuWbv;3bBXUt7a7_)5+6BGVoqQ72socs8QRgO<00#l z$J2InaVwv9hh9Ei9MjQ}`{>2GY{UtfuFD4Bp)>2^vC8rdTOoOv?Ak@E?&$^Z#T1lD zl&jzHnc=4*E^d|0plcs=!L}=AID61GelKTx>e5MF@%h?`HXD3(>a5QA7OaamPvL!? z#+(OuZ*d}f^l@qEUu@9dr_boVIo#6Cr})H-U(_j`N?N^#kL z2R#RRowo0+ku`kU1q-qwJzyr!XSzuA@BFIW2UmZj(-9{_-|z$ao7JDJr908_GF|>Z znHZK1okdyx?6*B*-q+#|yXZg8bGq0E7dByhahJUy7iZn&Bhrn$`r-o}x;pJ4{a@eudrtS?rK|0dcQP zjHkC2Q39fF{DZ<})DY!YbViwoBhWz=_uQ=@e7Baa(6zNiR_1j~?LU ziSueB>aCiQ`%B1!_`+=QURytFcO6}G{)DLK&Mxk)-K{z)J~l+241ZENbCalNh&=I> z{fJLNf#(hKp>>_pJJxJ$e`d`gm_?coo{#Q+ayRD8*b6*d>by?zM_cI5$HyOsT`}K9 z)Gx80wP<;lyp&dQ=FpFI*&^oug%{0xc!sV`jjuk&7sR;fF8@5by16xqXP`6LZDBmMf(xX>^<&ulIyGn$yO^JZ<~e`A~<;vwSxi~6mf=r`d=%wq|zd(M-t zGku-?=I@`tK73#UMU&k_RHPsID!4NR4QRnAafWw`b@jx(Ie*gXqkY_GtB|9d-ZYE) zQ1||I(e!i?d9tX-a=!+6K7!4b^+{4Ro$V!S_q{{c_~7jty9*!SC|$fbhDHvo(X(`6PvCj(B5f)E zMc)+f{gEHE=2ITmdy&Ei_oRE@g%>H@I|zZ{NyQ(ZqWy?e|n( z?KH?8XFacf{pl!U``WSAx9{9R+&X((aGiglD;Kw34(Tq~iz7{b5-%6|3VUJT+YNS# zv2SyF^9*m1hN$cAm+j&XHu&7!vstCBb9>ItMlMX7ajXS?O8n*%!}#_lz8;ZmZ1I zYm{2OR++2QD78ARGQu<0-fzg|(k|K}=ffjLz_TXiO)9dB7!#rp|?T-Z$|X-mZ=H zJZt=I5{hs{htToo)cOA=e+}1$-Mf~5m>p1p5)Qj`< zy!L;P|E(I+L$hgC`0F5dMrHj&%ppW)9vaWVG{{9$jT3t2cz2`URjilLefVAaEssP6 z)_awyQ~Ap%fd5zLcMlb51y;LP#Sexb^nFF*5%kU`$FAT z-MVyFoYJV*s#nALa(?3X*zee$J>lIG-{2arQqtA5%Xet6eGsC|FyrrA<`*Byj=6oX zuwU9TgWH*BJ6}FV{nVfIT-L3Kc8TR)$Syw7Yqi$yiA}t)wqy01^4Pa0d<-`({@8l; zYQ=fe;00RGpZJG8qs95+ke>(K^E_`3$k=@RW3gXaIr9&L=`d1~*1ZztYOm+gI^OVyt8qTciJ+xPTf@Jah~b)P(M z>D?RkEC1L2hGo6CXbxOduZ`pJe_N7oVtwx`eaz!KGG*=E-1CKR>t%aGwgtb{Tc|Tr zx5ZyBVmtnysb6{DviHu^5B{&>n7nVOHCVvaI(X^vwV2JS^M##rRLqwOIe( z+Crzwe;I%L`?KGClt-8{cX#wD`l-EZQ*mxw4~&i(Phcefa;m*aatfQ#@zJXC-(3*I(px zw=V1adKUVa`}QH$=M!I@8i%n|XEDdh9z2QP{4Dl~AKGVQu(lK52J|TSZsNO~oVqZ! znf_|uHTbcK@6Pf5n_v=*aps$xU3(E}s_{;J*SN2Df+4?J(J$H?F2v%H(Wc~nwx%*hg;VtdwLqNMTMNBeTN^E35p z^ZPC4OZ;Mfc=TW`Q*g}XiT`9TR}sgSdko(R4|4YZPvqX#c#A)soy+fz?TbBoIobxz z!yK!)ht2I{)Zy3r7h`qj#yTgDFMh{UI6I$xll;k!u!#QII~Skmx#zwa{~7g;)=Awt zTzEkT+H>tkn-80KfsW(>zN%ARL>-&D?l*a~-cNX?+Bd;B;lkZuv2Mk$JD%I%{H&i! zyTSP|Q731gNStR?j@Fq=OV^XrXDsl5vp5fYa)>xV#;?%zYCQH#$jzu*a~bj)7E z|6nF}0^LUy`3N?NYFwzR!LO-)K}*4D4lW~*qZ&Wg_&wL&-2b(6s?lbM&#ZTy zdM2OWV%d-L+gUY_@4&52GIWryRP>jkKdHoyS9s!zUb3R!uE=7Qn3jsKX2nmf;;U5A zS62M2EAjUgAF7H!SH*X@5{F*VzgBb$m6+#>zh#A&uEdg8;?yfT`U;(?#41-}qboi! z6W3dQWed+4Ggy-b#FOB~H2$lU<4V zuE=f`f7^2ugNt>VjEYT0cX~&knf}tV_f~A z&KGrlmyaYRcSaw4K9Kiv^duFXm7G=8g*tzz^M${ryg&y}o#C38g@XUm4ZrKrv79CH zl2jMUAN0)hVhP{sJj%Eq7H|8jqSYR6T0Kh^SS)~H{0J2ulOJyYwMh> zT>nGg>|W;Zw>#(Di@VPU>Q;W4N=(B4xg&E#FH(r{?U22W=(@Mrs5YaXf}HlZ{6q_} zCgVr?baLDg{mBvdxBT}u=w@!{2d~WMjt}gWyl`h^#B2RFWbBpb7v1uYc3=hl3|4`7vCe#sxT6gN^w`+$6Q3IDea-{1Nlu|w8;lgxW$-(1t} zrgSwa|Hu*D&KZ3FY;0E_(AvM@2tVKvz0WZEYsx#<<>Pg|{d(9HchTy9WIq*r^6$ap z+L#~Iy)(XZ`r?szha5i6#f>e*m(2M(f41k&JUft|H}n5O%utt(DtV%Z6pwVrhj%sN z3j56}9=D*U%&VaoDD!&LIokDZgN`R>JIKk+37vh#7ydr-9dt!G{ajAR7NXvQp5{F2 z2Kc9r(1L(3{KTII;WEe344jWh6OxY2a88%VNN#{@Rp(cfIs-p#Sxh*r}IlD*3|kp7x<=x z?^(hpFUAV7A><7{CO*f12E1?1?hyEm{Cy$!)xvkV`=~#vpVMQ1jCm5-X97N^$oYkmwWr$sMD_^y z;Sl*4HmE@E&iNL8WJk=SKO1=^(9eeCm>pbwcFAOBjrmUod`!Wg?;~B{1OBPJU@G$g_Js_dW~Y z=WoET1pG?CuLOF`nf3#ICE)AN==|zf2fq^JPY?K&fL{stm4Igr_?3WP3HaWCU#XUL z{g%T$;8y~ECE!;=qZ!LJ1TN}z)a_?3WP31pFg zU#aAo2>6w%iFMV%uLS%`pkEC5m4IIf)-~W)DmgJj)EBvLBj8s8ekI^n0{cP0uLS%` zAkzf=O2}eea`m#VI{1~q#uV@?0lyN+JORH_$M;c}6#vpq2K-7O2ZhM5c(#!DHQ*lu z*tK$+)lK}(&&j#ic-M-t59oRzBenAUx1J^ZoL1?D8@^)wb#|zjyBt3f@FM|T4fv6O z9|_LYfFB9?kq~JRek9;W0)8amM*{j8@FM{~641jCW2^Ba0Y4J(BLP1W@FM{~67VAd zeGd4MfFB9?k$@iw_>tgT4fv6O9|`!8fFB9?k$@iw_>tf&4KZF5KN9dG0qr>8mmcsV z0Y4J(BLP1WoJRpa67VAdKT^mWSUF1rek9;W0)8amM*@B%;70;}WJSzKBA&5uXJ^2V z1pG+Aj|BWkKhe9iAMPx|13yxU+uCFYxfCOF?r*~9ArU{YN-w)` z{^#sJ3A()*_q;RilC9)A=9qTw-LQL>;mY~q9+{ALOD$RdaoL7A5->~hwTYY3)-ADtzvVS?xFXKJ;?h)Bw$LgSi z3qJh|cMR-CTLhlw)Vca>jUM$8@By{Bg0lin<7-m)!zLB`3f=z+e)CRg#9^+>!Px#| z?EKP(*6WO2_Y6L!eCUgq8&}*~9c>W&dhXmcbYxH5%Bh;f9G&{R6gzS+SM^+s+e(am z*3WMAPl4Zi>^_%xwn`4hbMa0IyU`In<;`2XnjF8qDO)DL{Y8N%5tE*X=jhl237bY6 zW8UFN$+xrNv;94L`VAhZ^N}BeJzv7vgdbOz?%-OyTfzof%58bZrg}pspT{^_@mpv3 zfztY(!pk21<=j53@ecuyc`mkdgdZyLOLP3{EN$|pXG8*EFZyg@bp#v^_uJM-^{Q+^WJl<)e+55qE!ak5J8rvqU3I9mGQ z;CZUz;<5AU)ic^FDF4eR&lCO=h5lCAa2MJr_&}w>-eDVEMEfIO|0DcwnexYFhb)cn zfgkh=et67>B_jhKp=aa&anGK8^XOfNUVR>YO<%;oE#bqL%$HMAJDCMuUR~s$T`V0#@+6G>Dd$SqCa9Cb=G43_{Xe*N$F0*gul`|`k|EV zsB%BxT%Lj1Yn%O52T)R*o{NMRK+_2f?6kK`dvyF2e{O0TF_b}2t zutr?Vm-xiSn0?08a_ty708hj*M{K%l>v{R2xcDk|SbF}^cRixl(c9oN#p*dfvfKoD z?=v_%%eZgf{L9xhxigE}wnU2HMQ)0^6}66~|x zuv;$qSW7vHvoG#1=g59Ja%RalY9PxEcP+a18Gc9CmgZ{;FRXL9UW@r5*KPJ0rpl+d zHD7L=qcfAc@tGY`$Um8F@)>Dzrs+;^=kf-#t?c`<-db!l??W^nr(1SbK7TvsQp;Dq z^ehT-|1#%^S}#83v6XYsbKR4T=c>5ikxxU9y@qX*UHGD4p{u`f7#mdJyuaSLs zW$n9ysZ)N)z~5P1sS~8H6Zy(FJ}+_SDcqdh=~E74xt1Rc-w)-Bly47VshDEP_Jdsu z`$Vr@8;fbgd@Vl*Hp|qQJYp-1)$f?X)tC6nJ}!4@PJLxhuH~DIb4~?Je<_#qD#zH@ z;{34uWzHvd4#6hBPq;eBbx3&1OMRwyu-sh!#a_eYtc4`U>5*|V^?YybC7Fl?{m6cb z>Q&5Ez9aARHBP2W_$qdP1s`Xg-DK+5Z?CKaJNzxn zeCDfldgCnR>B@7>Z8qZQ&S7}3o^zC+wSl#BTsb&v`6hn{zw=B!PiOD*tsIZ{etUB5 zx%WNt9^*>BaDI>LU+ss65zfwhp6B`6d2MXoF=%?D^Z=KPjbpmv>VtkQ#m%%-<`ScS+-+-8hS^b{g-HOh1viS*8a!4D(r>4 zg~7+h-U^wll_p=ThUaclJ6K>R;0`-ZR<1R$9Er_FJu0pnR&I(X5GA&JE|Vp z2A+lL$?KX8TUvJ`o;j0~75NcPV0Kd9sW7JQ#69kEtZOE|#n-zP58L`|D~_@)r-a{l znm_Y@ZMNcJTlc;V{x6Qaq2h&idJ}%%8mFW8U&RZ`mMQ{^)J?Pfz_l%Q04e z^KWnYySE`<_wO`+?%$aI&j07Xb}t+EvT-jP_p)&>8~3ttFB|u=aW5P9vT-jP_p)&> z8~3ttFB|u=aW5P9vT-jP_p)&>8~3ttFB|u=aW5P9vT-jP_p)&>8~3ttFB|u=aW5P9 zvT-kK_p){`YxlBtFKhR*b}wu9vUV?P_p){`YxlBtFKhR*b}wu9GEs+NP?u&OC)>eG z_pPC|Jd0y{I!^gU-+f?3wGPfM?Xze5M)@jJdr5ma(=Ge>5pMDs&-|Af0YN>2 zy%+3sn6k$vDCB%@?JGac`=jM(&0*r5echk&)=N5H$Szy2u%?vuo)>KMHNR`i{#jXr z>Sy-+!k#(KdTh=8Y%E{W{X#y`y&@xZkLKoSfs4%X=t5r2Qazx6Z$@WG)b=sgIX_3e zw9m%jr9QrpPx`nbU-ePigFd$g-0}xTb8i=yZJqtr^XZoU9^_#j8~dN}_Dg+yA)oYd zMZW6eS|7c6->~ua)u@}>t6wf;Ofq>n4|RUg;-xY5Tc z|LZL0Ny#_g7oRKHn;l>12G=Y27C+;=m-_fZKI!9%eAUObK5q2U^SL+n@_xqkW*hgg z{uW9>3Bh z{V(Jb{VVd7{x$s@`o%RHS#A9Se=F1sYdy2V-oEu)@kMnQKGC}(U+G=byP-GYf0&%+ zvwnV<1aXX$jHy0L;>2@x=)Y=zt^JMmkMPiiF}ap28iM*(INH8vHu225=V~)(d!ub5 z7yqkkEA`no_RdxO#F6i5%MWm)jl&z&F8YUDInPV3@6_J$(!TU4pL3G?lT&wN>~)XT zf3v35dC!RZI*$D5YOFl6_Kd6tb6jNC`M57GR}k zef3|mkJcJr$VZ;Aedg?#`j;Or_H%s=K8Zc|Jz>x8Kij!jdv^u@^`K_U7e1WNbgxLU zeJ*c5pGlyOf$>%1YX1-`eIz%mz?=81`N!tioi%fhk9_KEsV{s)pY?G?F7@%1%&ix@ zVlv0<*+uqm`+Fs)tdJXf$Tm&l62q@z>}myku@-;U#}&EM$5--6AJ=3@JbW+v==s~% z;vpmU)hqX~D~=zKk?AJ_x z68QW`9ATHf+TQxOBA5F3N8#y?%}`vcA$iHRRwt#+H8SKUcYN7j_})J2 z6;2t(=XI;|!N)`Uz{}x`C5}G5<;XYjUIgDCgX3 zH#3J9@|TM{=K;#oF2uri;rxwu2e|3xty&#^lSxJ$M*94P0ZxLTwKdXJ%&@`Z2!gI&iAZ~V?MY_4VAI_ zOqDgcl%L(INi?>fdd&U`V(Me-^*$^f!?LY)bL?!BJN1jk?DF*ap;}3D%*i;PZ^rj9 zw)bYt-i?9($#Z?gpE8CgTl??EV!B)BNR8#Fr!V|*pZQEatAjy5d5+^;`|uMx+rEx5 zd|TrzV|gc=9Q)+2ZGL^CPdPZws~Kmz`6|}~)5jOM`j@aVoTeZc+1&ofrPX>84n zGc_$Xc*XR)*JHWhOFsFry**nTu690TG7i&~zOMB3MPFa= zOZDA1`m(vW~hFZ$%ONuS}`XXm2h zSV?~USPiShUpSV-llTTZYhDR!U#f?F3~!Q}2@~%x-RSe$zt+?A)#qRJd8JQ&#`Hy> zU!JH{WYcjVh;kZs^n4PdEC!*5|c8zv?sZ zHNVp5mGe=r9z085p7OzXcb^ZPb({OnIsW>W`&setrd$0i^|RE^jec(Q!v~bE^<#dg zueqj?9Q~`O#$6r*elxz7K07Bze`7XUv30LFa^iPR_HCr4ewO+%*VB!DuJr@Yd$mu} zS8-JP7t)n}%+6nRe%D-0d>_dkfrRg-TWxRkwba*AUpM-?dE)F;e%otj z@fatGpCVo9>q=ktM_Vl+W-a8SmOMD$^t-rPY><3BqNTpl-*?XUs`ddDcLr(Wb zj*(b!lK-Fh6%$NJSNh}ANuR9&*8iPcV?Zu;!l@ISN*jIJo08V_R{C7&Gw(;?BkFSf zHa_A<>Qbc}eO~MHTA%i9r7PE9V6s1HC(lK(hcO>Vk_(XFbh1Yw!M&7yKlWNAex76> za#}gRCV$th^D3`K&(c!AH~PKNFCT4EmnGTrmA>S6o@=G)`?{(&66aDJ}vdT%+H1HwSK?q_bQJ8@5r8jaqb&VjjeC#PM_*4 zr>#EutdqSCY2#km>uLS;{2TjU60V$X^=Y3;TIv&4ryKoV>-VdEuk_33n5^}q+_zk^ zF&>-l^r?n%+UnC-YuSTIjHP!jPFm}8rO%ZYL3JHbe+dX9>4l!$F|~1 zH^#<3pXi*=KB;As*m-+=wrOksm0XD=r!TGjoBcQTW+ZtS=~kb)j`>ob%YW)yzxH1y zd4nn2Ys){`PVxfvU5cIWvjJv#?%%ONX8PklN%HX0MxSea%8N`ZeXjI*tIu0~F7+wz zF5T!?Y$UOdi!B@!>uT+n==A;TknKO6KYN$^)#p~98-1#Ol-Bx`KbiP-k~J{h z>Qk;^TIy4tW4h7rwK2?A+jC##m&^;&y_yqtS33`X=&Un<$j3g*6?R0SD;b*?u+?<%RXxIIN`4uvmKLs z_#_`b*~63MZ>Eht<;thEKG*tOX|vKN8#~E+|6ln@N&fx5^>WX=PU=}L^*1Wj3bSq< z<-X-Sj>Xgy-(kAbr}vTUvq|<6rHwxMG1FR~e3nTb=Eiwx$$rbo&zj^2%-Lh5`fr8# zuxtHYsk?A%Eqt2$X1k5$W9@18yaygQ`k|ZXS@P-|nBFSMm$m2-9NV@??I(?UQ_#gNjV=U*XxuA(-;d=KDb+ZXbX7v*N-_?>5OT8C+p@~9%hm!ljOK0_DYf`vdhj+ z@@P);xW^&(#V(UvoK5!m$>B)y(9-f}{`_1Y6Fys;K=RI4{MK7Gg(Jdwf&& zFUs?&A6moYpYQU&CpqZ{?7t)zrT^7@m8;X@=*iyZLwlFfQmll{zYvFN546j^KzpZm z*;G5uf3M_NjeXaCzF&K5p74<*F_6(qy10EIMxNI0Q*0rve)g`scl&Ja)CW$>U)hi5 z3|pqK{#3rdQ(N_jpJIJ;E(f*V+*W=Z1i)W-e z^|*4(aQlmAnb$M-mj4#3o0@A$Jao!OkZzyL1M_~DVj_OyPjc0Fr{Bx*%4ZR(naZxc zQ?o0H<>=%e)rBjPPb}@@SCUQvETQtvlG>o_W6<6ND}u= zaw8Lez(kH;!gHGJFH^&>lQWoblpXvp-5!g}yXWP}`H38k5u0|aE^Wep9^a4Ud>-m| z-W|WM+71K1Mg5EChEu)57n2;%kgqT0kHXLbrX>3s&-jy)nEW`;i_HXQcw~<;yqf0m zbYgs14{qsrhG|(COS|HzYImw-n6?w=4*Feu`LE=TO!+g#_yVN&*Xgd zw2ap3Y;U+`?`7gYN%lP^JT{4$r)6@@=l1C)drFgdSz7rV7f#Dl*L=S9xfo(v`&_&< zsU47T=yd0EF|ni$M&hqZE1&ZnB{BAdSEsGdH$JzwHm!Uv&XvU8lKrv?w@zwnC2^~y zW_?mWEG>U`&FA8GY2$PIyOSCVNv)l!!b@oW5z9W=#%M>+QF+#iQ*y2kIpKk&rdT>o`${fEECTjAdJtt}g4cr4d&UmsWg zPU~Gc$i7Q`hkbKA;=xDOrvX+iU{Yyp?dCWy3}~K=o{i;P^DN@Q=@O=zYrA|ZV}7GOxxNqmo|QezM|^}QJ{wzaA|4#^ z;D`rDJUHUP1)DowI$JvDH{-#jaX8NFvizig2OqOnck#9;=YQAtPRr+Vi?zjrBOV;_ z;D`rDJUHUP5f45J{?Ct7sf!#l50*DMU9z2WZCE_`*50`>+hHrOr_$HM{Cn`=hzCbJ zIO4$(4~}?n#DinbUBH85=E2c5Joqs?EM^`ow;|%eBY&6tg*(=mBJ*rKxV5%KJUHUP z5f6@daKwWn9vt!DhzCbJcq0cX;=xB^x)BfFwWh|*gYD1l`Gj})RU;l;%Jpche-RIk zcyPpnBOV;_;D`rDJUHUP5f9#BXGM6k%Xbp-;Lq&nhzIZBhht-)z^5Y~9P!|Y2S+?O z-slGpj(BjygCiciWD7++c%N@1;=vIQj(G6Y+B4!WA6t_m9vt!DhzCbJIO4$(4~}?n z#DgOqJYs)FJosDoUA)o{9vt!DhzB3S;1N4+%zln|aKwWn9vt!DhzCbJIO4$(5031R z?oj?V9(8oHrkL7wqJUHUP5f6@daKud`9vt!DhzCbJ_%z3D z@Zk6A?MFN~;=vIQj(BjygCias@!*Hnuu|RB!uk~P;D`rDJUHUP5f6@daKwWn9vt!D zMl3$!!3*)+hzCbJIO4$(4~}?n#DgOq9P!{Id*t_X{-M0LhzCbJIO4$(4~}?n#DgOq z9P!|-{OpJacWSc4JSXwshzCbJIO4$(4~}?n%<)`2_%jUIwMU`AUn3qI^EpF!aLl<| z?EaW}u=OY6!G(Df@!*IDM?5&Xw zK@lIRRtgWck*fG?ARmm_3r>~=DyL`kE4~}?n#DgOq9P!|Y2S+?O;=vIQ zj(Bj)IAk6d_xGObso-S%c}eW!*|oD2{Dwn0m?f@qEUp~oeMLMt;=wWdCGg;g2S+?O z;=vIQj(BjygTKA+8@E=sA>zTox;Rsdd#g_884l9hhm!0!np)S!?CFENPT|234~}?n z#DgOq9P!|oaS{&>_V`3L>r^gn#DgE^GXU`5?>yTi=J%sBt2fTWzGJ6V30gCiasVRyuX2j{;qHsZlcdDamR9`P|mJox<&{>6hIvU}3> z@8W9w5Asy@S9bL*V1lxs|g|3^G{k=GDB_?4XAn0fHb zcjLkBW442NU1VIxgBRA~%?CNA?xmpLh`E;d$e2AawhoTi5Vy{^hD&oOgc74Qyw`!V2Jb1(R81dls2lK-kG!ma#^9PTo2j~Cru8x8nl=UmVdgnRf zh7k{*s3R8f;9dMU;=z3$Yk2S$4~}^7uzi$4fez4z$2Y+L39;>}o;>}a} z4neH#KpgCdFJqpcAs+n0$iH~-vELK%;61ix#Dn+vmSX0?Up)^zcBOZL1?I%3=0N;vu@S{G* z4CMnDlmF#j9#{ij<@tmM-^neHc<}tpzj$yEYdi7|Ch{jD9=uhjCgQ<|(KEt>8}Z!E z84j~Kd)qzVIr}H#!CQIi5f4u4Jw&*Cx-ie#vKKk03=jTJEHGMY3N~59g9}{r*!}JB z$?WEsJ|6r^EIs1E-80V%4=&8}74Cl^UpwN#-(_1f^Wd|5FDLdpnxEF9(fwF{Zm#)! z`$Arfc6jjF!Wt)UDe@CUJop%9Mm%_t?ICu?DCP6{{BAsW>wJ)i2d~6WBObh9YaSVE zgY$+W9z4(YfCmTr6eC_xWE%z#Uf{hE4?fOg8V_!~lfgWj^Cv|-xbWU1&JuInGsscK zgZJ@(2+RLve`Umj|LL8S@z|ctjB(oH!4VH`ok0}w;DsE9hzF1G-)KHZdvB-mJR=?) z@!*IDAB#&xJa}c#V8nxW#0?`JTuyU4ZSdg84k^61hzCD%jzz?SBOY9oxsB_1aKwWP zc2LAWA|4#^;D`rDJUHUP5f6@daKwWn9vt!DhzCbJIO4$(4~}?n#DgOq9P!|Y2S+?O z;=vIQj(BjygCias@!*IDM?5&YW-hy;$l3XPnxPHjVr0cVzn=Zxo{#_*!Og@GpC@6F`hpNF|~z4*Qgyr{JQqhMRysFjj@9x@M>({#k= zJ<5De-;b^NV|={kLmj_@<@QC5*%g&_?burQNUU_sUJ7_{z=H!GT$+mk58lDCLXHQ+ z(y{gIfA~YkZ0|ki@`Y>T5=M^8NBqg+(PDi84-R;6z=H!G9Pr@M7!G)F?;Nv`dW6~7-3-jiPv@Zf+42Ru07!2u5rcyPdj10Edk;E5P= zz=KOz74YCG-+91;3*)(9OD)dmZb<}cKCM#9vtxCfCq<-e(~Ud2M0Vj;K2b8Zsp_#Ja~uyCE&pU4-R;6z=H!G z9Pr?P2M0Vjc@C92()<6bCs4-R;6z=H!G9Pr?P2M72+l5-L8;3<1I;K2b84tQ|D zg99EM@Zf+42Ru07!G-&7)e|`USMFP%cyPdj10Edk;D873z_5S^e=mj*@Zf+42Ru07 z!2u5rcyPdj10Edk;D84QJa|y6H5jL3dC>t64tQ{Ya{&+Din#?m_(ZN>z=H!G9Pr?P z2M0Vj;K2b84tQ|Dg99EM@Zi7(D!jK(ISyiP#F*V0@Zf+4@37MX9=r!90v;Uj;D84Q zJUHON0S^v%aA11`JUHON0S^v%aKM8{Y}1#{=i2{e=VHtUcm(qb>wUn3qx}d04-R;6 zz=H!G9Pr?P2M0Vj;K2b84tQ|Dg99EM@Zi998?n95;LIuC{=n`Yi{Fje%I|*|Jqvhn zz=H!!40v$Bg99EM@Zf+42Ru07!2u5rcyPdj10EdM!cokv5QBIqHgPNl5plCIp6%dO z_pDDmIN-qn4-R;6z=H!G9Pr?P2M0Vj;K2cx40v$Bg99GChlicG-(%e3B=5t(ArHiB zmvX&|+!r1k@Zf+42Ru07!2u5rcyPdjgS9H)!2u5rcyM5AhisoaE8uT%W1>F9On&h3 zY4(#mbf%j#9p!LzVx|EP4tQ|Dg99EM@Zf+42Rt}r48wy19vpDhka=*%N%7!kaQ-uM~P3~iZ|Yhl?FUG;K2b84tQ|Dg99EM@Zf+4kL2$J zJa~@{8Q8}QYk$CllYHnc{#eOPUf`)aIUnnT7&9BY@P2mlJ>kIt4-R;6z=H#B74YD~ z8W`~4ed8g@tf{BOhl>`0V;y5!LbatETlFFen zk3#MX4=&`a2RwM6pCaJFQ~AjO51!?mOFVd+Yh2^O4>G>t!FTqQ?y&z0SiAh7uBJ0< zkG~VY)c3Qm@>2cw#<{5hk3Hbe40v#%Zbra^%Y{Di;M#uJfCq2YbPjlMoADkGo-FK_ zU~?Su>ztnDxjE*O)7HD(V*`xs)jfzA2ju~v04s6`p@;NBTg0S{i|903pR>}d&j zaBGiBz=JC}nuqp!6zsFXXRpMxuZ)>lUUP8a+Wy0-yw7kS56*r6+jH~I@ZhEMy#gLw z%DoAA@R%Pi;K4=4c|7=59Dh$7bWs1Kz*{CTbupKdAV+e{kGU^*AmG83JpF(NALD@m z51!-r0T2G4OZEdE{A%HI@!+*{Wda_&d}my+fg9ZGC%opA{*|%W;6f+(alnIbozoQX zp~N>9@ZdwXWWa;}`YDeMF<4j}aLQlgxCA`7=HqXi6V|BLath!7`>}in_VJzb-NHQ& z_Aeg1_T2#wzRmj^@ZjQpeataxf8)XZ{Tz9zuYA_JJ>ofbIrl8_%paW*8}Q&0&p6=0 zdoiz9zsWQD=GoCy{<%1Oz=JFPg@6Z7*@*!U4mlT$FY8Rar+t;@Zyx{uG3N5x@f*7> zKQ}c$%*$47_e;+u;K8%YJhvutOxznDJn;RD<+Bv*oT)wo9{kYS6!73G*RIBc58cOP zYTp3+G~mGvUv|KQdmJyYy-W9A;8I)Xj0W-GM|u3?!QaB)fCn#e+FO`VI0rnKyR$hx zwq+|PKH$N3r*cSwcY_C?lv($sIF9j;2bVa>QFNAB{u~cp_^kmC-f`an4?ZmOyH#t1 zzbY6{mE4hl2mfd-IWmT4{0;#R9*JEAJUHON6Z1RZ!Ijv2ur4lwXU~32&dZ+RtL2g% zhX;qe{@}p_pI*R&Kjd|ey*dK6sHb&@agIk`#?N6 zxbX6v&6WT5|2zN3i$kutk)J<)T&T}6^>@INOaG>< zk1wC%y0iRw=FR?%{th{g{MRS-I((jaG~Kjy5BPMU&S_G=WR~0cJWQYSWj^O;a-P9& zdEXsB8eX>2|06cU7_S@~-@72sIwltx)~;e z{Ex?M#=?4Yic63A^kzvedd_qA?-Bej;rBt-BaishO7o@?3mwC~l|2FDSNTl3BR;a6 zhwonS!&f)`WPlYVeqG|%C4ODeFLS>24A;i5*Y*pJv;R}uG49^V85-kbPZM9Y-#Jx- zXe>9W#IH;Iy2P(b{JO-izrXJbN9R*2@!=uolUt{rT7RSUk_{%@#_-5F7fNf_kCs`hQIOaop@vn=?i9;Y>UEJ8H;0mk7M@u^{jkx zUgFm!eqG|%C4ODv*Cl>k;@2g9UErab%|e>_;rb2zhncH_;tlcT;_ahv9J=q9`19}Ug%qY z`1Ps1j8CWf#IH;Iy2P(b{JO-i%j{3VuS<4giC=Hznw9wVh5XbKzi#jQ=Km058~7*x zT6L2Wzb^6X62C6->k_{%@#_-5F7fLUzrHnQOZ>W)-&(Q}OZ>XTuScHoPOfQ^pBsK% z;@2g9UEqqRT62C6->k_{%@#|fE{Uo<&r1nB--6`?w z62C6->k_{%@#_-5F7fLUzusD3OZ<9wmhVwt_;rb2m-uywU-y3NV|MB6zLu8$@aq!4 zF7fLUzb^6X62C6->k_}7l&<5~$83`lzb^6X62C6->k_{%@#{vPyXNYcf2YLLO8mOS zuS@*8#IH;Iy2P(b{JO-ir`D+wzn-#RO8mNH^Og8@iC>rab%|e>_;sz{u{vhsnLhFB z62C6->k_{%@#_-5F4+$yeqG|%BfPrAuXkgk;@2g9UEnOZ>XTuS@*8#INV_dQ1FzhaaoNuS@*8#IMU6{o>apeqG|%C4ODv z*E`k;@2g9U9k~M{JMa_C4ODv*Cl>k;@2g9UEk_{%@#_-5F4-`%Pw+$EqnUAQOqcj|iC@pfr5br+M{LVmxp0GV75N7j#>0Srw&HRt z@tL9Ab8UyPwPDY|o*2Yv2e!}@@7v|)9D>i-AOkymVCxV1914HS_Zrwu1KWEScPiZb z;2jP)-N0`;uoH$-TlY5P@8xqHVD!N58SwwYJ095agSf{KwfB4m&wlU@2Jd(9o(E%S z$o|JX$6?3-qXy4ufP(`J9pLH!X9rk3z~=#W4RCvaMj){y}(8t}LQCm*ai1AoO}eh>Ul1Hab5S2pmy4SbD*b!^}>9r#xVeun{; z4ScZ!>>b3q1~@-tUoxNafHMzbb_3tma^4SPup<@c|AFIMN_? zGRRLEqV`dH7(AFGgY|1Do%zf@ANWm%!rz5G9k|RO7i-AxN}kq$TMumP0ag$4ymtAR z2f1Gh`Idux)PLZqgSc3MQw~$_OpffpXE0bxhN$jRenvqaPVTonJWtMo-pRim{w%Uz z#2Pq=ht748cg|BS@#=rDJr0exs3y{c-9Hg`@8#lFYCo;qj4ax2dJy?E17KJkoC{m`7*sHHSA?pJ)-(;IxkdcXDAXST$aA7IaZu$b#;;xVNd zQ1E^`?`q#YT<+ji#{E=0t#wB5Lpiwboy$B^yRj9k@A(ww=0W2ugyfv(i=)3ktL%sA zaL5vO+?cDUIj+RkFZ|xQoU2{?xEAg)u!jm9EX0SeFP!I5W!@v+dMmE^;RyD?zttQ! zfxD+LaW);l-jRP-@KY7mpMrm=$Y)Dh;Y1H7de5te6Fr>h;l%f1@~z+9!-*bF^l+kw6Fr>h z;Y1H7dN|R0X1(Xt!-hjiVk;^l+kw6Fr>h;Y1H7dN|R;i5^b$aH5A3J)G#_#7qpchZ8-V z=;6f3yX)aZ4<~v!(Zh)zPV{i1hZ75a#2!veot@OfiCuox9!~7z@I9R9;Y4p<_Hd$y z6Du}+4=47-s(Lu_jrAyf&SS%T&NWHlL=PtlYgi8_4uUzh2}q1t(he)WlgzeJ>yONn4V>7#&$a5pam#=5(^oYfu6Lf@ z%DH^$OrRY;wz;@n^_$u#c-_MI3gyT?)y%!+hF;}!1f5-L?pAW=XJYC-f65WxMd$OM z)XnYX1$<(IOkhEs@74cz%!A54j)LvgtN+_Ndu{?}W^#5~&!^0o!Kb%4m6Oiyt3CUI zUA%x>3-k5Xp8xlE4<1ByE5^po6c%srx8Y~=XJ5V99A~pvVaIbC@p&GYXC0il_Ir1Y z>kdv7%VXTmeZq+jPISiF$oT5uL(ZPuhPIPdhgA*N`=<<34CptLM!HEt|ba0}B6CIrB;6w)} zIylk6iO#$3;KY*8xq}lOoao@hztkA+;6w)}Iylkg_XsCCIMKn0g1@|j6PMl?%>46yzAgZ2PY+B#K}51@kp+C2PZ!9Ic}_Ro%$V}JdTa?Ru}m@;Kal;TNn%f&6k?w z$sBlRd)~pGvAUn1i+OeG-@;m0Td!}-uSR{O(s#^Y%iRS#;{5^tsQu9X-|-V}FWei9 znRwT0`J%h*m^Amj_K_6q{j|jA*#U>1_kvB{JpISBsQycW!&~`WQ*ql`Y~w8Fe~F_e z`>|R%u#<(_DQZJ6PSsk2QHPsvo^AMiZ`FwSm;E-s;tvz^sT7YW@Zpzyw`=#Z;oH77 zhfgzp@Hf7adt0h&QK&U@YR(^@@dt_pBsj8Xtd6YF$HwBEPh@0#7BG4*^BHwd9>B7x z_d7TL4!yU3u*GV2%EH{O4%lG!h<9>`3Vy)pqi-JkAJ4TCyKVWCN7_d|+ZI-AFJP)G#^TLr&b>s_~SqV>DN+TI^H(fY0yPK@|HOFq>WPPA~M zg%d5DXyHT)Ct5hsy3ZC){O^x&k8iDo6Rq*m!ig46v~Z$@6D^!*;Y153S~$_diRS6I z&st-ng%d5DXyHT)Ct5hs!ig46v~Z$@6D^!*;Y153S~$_di55<@aH92FS~$_di55<@ zaH541Eu3iKL~G2oaH93>TR73eiPqR@;Y153S~$^q4=tQ%;Y91*w8m%)Ct5hs!ig46 zv~Z$@6D^!*;Y153S~$_di55<@aH541tuf!ii55<@aH541Eu3iKL<=WcIMKq17EZKq zqJp zeBuZB-NT6)A9nli9oS;(24|L>wulcan_P_0W-YfVL<@=;dF%o=W z4TqQNp(J}5i}K;?^?SAE#c>W`)8Ea%ffFNZ!oquL;KY$z=_5G{$WM zCmJ}>7&{G|Xy8NxCmJ}>z=;M zc*l+L+rWtiPBd_$ffEg!Xy8O+yfnsb11B0d(ZGoYPBd_$ffJ26)WC_D+rfzjPBa-O z)Z}X5L<1)pIMKj~22M1_Xags9y!$5ej!W+wPSp0gHgID5!QXJA$>Re~G;pGU69u1V zy>Yk9|)qh!Kov$UJ{P zoR}L&lQVh$?*EvtbE40KJVxNeezu?3){Xi>C)V4N-9A;*C$f18b&mIpq1h+?eP?xy zJj11Z=-;#FTRGx~-pN+o>u+Gfj4d)1pPaL6I&1z)&7+lT``+b-AL7I_TfNV@)BGv? z)4lz^|NGN}XUEyrlwY=$t9#}<#@Q|uleoKJ+o=g~%MWqO{wZ*{_iCygz=s|4JlZE+ z@a?a1?l4TN%+ddn(^0EM7ww(c`(S%@M!}bOD+WKyeidVSZcg3dE^GUXn8F}y3pns>dksBV1v>~AsXf)Bm+t_ry-jb~G5-XW)_ z;5)A2L=7iuIC1FSYdBHEi5gDS;xEg0PtI%axAvQAI8l4IHJqr8ml{sgaH572BlBTT zJ&zhr)NrD9zqK(?!-?8EuHi%tCu%rR!-*PBY@Mf9!-*PB)NrDP6E&Qu;Y1B5YB*8D ziTeJ&{0%2+I8noi8cx)3qJ|SSoT%YM4JT?iQNxKEPSkLsh7&cMsNqCyEYxtKh7&cM zsNqBnCu%rR!-*PB)NrDP6E&Qujjb9^)NrDP6E&Qujma8L)NrDP6E&Qu;Y1B5YB*6F zUp1Vl;Y1B5YR{#H6E&Qu;Y4kW*KneS6E&Qu;Y1B5YB*7wKQ)}F;Y4lT)NrDP6E&Qu z;Y1B5YB&*$%^FVB#(bT5hdnVhoT%YM4JT?iQNxKEPSkLsVn5WzQQ$|cGw)z;*T&8r z9H`+$4JT?iQNxKEPFx&jJ=d*iHJljv{Rg>UII)+X9W1EfL}yK`;lw_FT5ZhzsIE_M z90u#^U>{eMQ(nV~z<*f7iAs*}9$UJV^Se>=ZviTm=kfyTj!^3_!gIPp+@j&o#&;oQ!LdDfEhns z!wt!qlMfg#rx0y zVXsXghv?3|9vWwb7)K%QJ^lW{gNd_np5Px#K7q%cLzU<8lbvV9@(+7xb|!cH8%3^h zoP98I|2ww&E+6NNZE?$fDdp~0zskW=*Z#yljS?R0%AXt5J8NKJ_rz!Z-t$hEav}m- z=a!FV4-Oo|n8YVrtGzYDV|sg0N_{kPuBUR_cEpMgjn`x2_E)y$uCZ3!@c;6S7WSL& z%W*2M?KKc9ugvv9jf9OleHCmdmVTpHcV%8z=5=LW9~(Do@z)BbRB)k!3lY{-=5l2& zSLSkME?4GqA%Ae6%~!#k3eHq;rh*F;jZq4VJT;$4puHaH-tW5Eu*Z24iU-7ejF&8U1v=BF_;84L%E;kcnoc%Ay z?G;|JrB}h7VE@wULL4CbH`x=DjOF&fBv^Rp9nAUE_VjU_xd{Af19QwR2z{Z)Fz_EIxx3BpKaFAE# z?^3%J|HUNlar~>F%=3NmSuEK>8}~D)Z_$|llZ?G^u$N_!Oyw`&*7}TV>!_SuT&T9EEhvseRx%GU_t(t=$B&GUv6GrKq$M5c$v`Up zx0*DhB^~L>Kq~%(nlz*(9qGwHDz)=#(vX&Pq$dMuyvtoSd@0u1sxx1(7iRW@PjT)& zb9Vdp+-uZcp~bzwXr8*tOnObUT>T ziY51?p*xV8Zbi3a3%2&9_oSgaklXi}x9&Xq^^y;jZciGz1F7j&bUW)~OSdNt-GS6} zXE6J6hu`=&Yor{{hVDRWx)t5-#F(JllZNgFw8x&x`{R&-CSA-8Pm1@8LdQoUg|-<+LU(d|x*CAvLn=nkZ&Tjl$<4jtQfdd%PV z5-wJ7r<{#m|Ha?jofv0yd(zMyNKLn*o7lg-T=Vxw=9d~#!TCvne=y!!=T3}4x;<&= z4y2}A(cQI2VrIW?ls_Ed|CzP1kw1Hcn{+3}C*7VjbO%z?t@3?8v#zm0Pw?`&-?X*{ zcjBL=*k5;I?9%N?Lw6uG-HPs1OkxR7Ywu!l>O4^P>l43m&SvaRtc`Sg($F19O}C<( z{En^I=DxM@llEiw@aEkiexHAvwUjjU22#_j=&kIz_)#3Aykz%VpKinhzPB!hPkDS; zdr7T*rF|#=)3PHE-NG}+F%{~I>=tRr)4PvcrgYS;Sv>+pb`)sb48p6t2r z;**+2cwnt?m${=QA4*QHQkGq_eJCJb69(2aa7>DfH{u}X)L%ekAT#JTYM{0UKspt*l6OJ>$odw+4H~&^2 zb1ar`hRt1T-;+xFfdu<$w&E=d^Y<{HODuQeRxO5oJg(AiATzO##(aJSPZscVSB}bS zHPVi8{z!Y~*DPVoDV*G}sIG8SV~pxJr2(ql{nnBTS9M zsWoHx`LSFwzQyeCR}ZJNH)wUn4qLy(8=N<|872?;S_*rLM&?S*Z#uFsE97%E-22k` z4ZG&-L5`QId0Z^jXUubhf4j}`7It*w|K0uHzQbo7X~bt6*E&+W*56-;Avjq_YHfOQ zp>9;Mv?hzW*4p-@(ssCS4?|#AM`}7fspt&EOpu4}Oi}Nous3nU4you4q!r6)U~ETf zx;?4r4y3hKHFP_&Yuz7N6Mo#si}1uY`+IV30IBKrq@p_zmDK3L5K`0avp$Y}{M|Rt zimz-~x?SdNbbC_K9Y~vVVd<)}P7j8Vita%6JkwqE;zrqiq1%&+?m*fJ458a)pA=m? z0q7auWEaQp)eN3wJo%ztQud$F9Y{NYA#^)Z)9pz`cOb$0o$I@FCS-tJ3tawy&t;di z6Bt6bBQ@QgRCEV&l-J8V?)b@DeuJ4BJrfu-X)PQrLg_^0RtB&Sg0EUU${>+xM>iX02!^FobSLYPvnC z=nkagFP)2N9-n$n@T#!4XP)yH&5w2hL+Ey-rrVQ>?m$-f>W3paQv7N=YT?&>cZEH* zr5H;)fgyA|Qq%28MRy?2?1S6lvU6B^A|GszU#7SraP^?0H5Vd6zdahVF;8bKYm&{pYx-YaOX`tmpo^xy@J9 zWq-Lg{e3$aWM522YHfQ`X*=AvH*VGR>qt$fCl#H6?8%91Ucx9+)9pz`cOXF=zIka* zlbUW%D!K#Nc?K`+k^YJ8QPb^7MRy=mYxOJZPsvwa)9pz`cOdOcbKaaQF0;)lZ$0~X z=?)~|&U<{Kk8^Jy76^;lmoSTNM{2q~spt-* zW%IB2X=-cpJ|FFyyk7DBPUUI0FJTtlj?{E}QqdjAQVq%(KU$~$W{o54I77Yq9(Lv$ z2QOh3-Hz0Bds5LI$b0)V3uCCT&${8u8N@y|Vt}Xoe(g(`MYkh0-JVo*2QuP=oo8RA zm}1Y5*_s!Fa{&I%SJ%FTS#)9pz`cOZxS!%Ou=H|jqvjQP9Y@ddbZlGmJr1KY;EUv{?Upkv; zpFOhtXrCINeftt-(d|f0ww&>vC6)?moSTNM{2q~ zspt-*wTF3O9W32zU}JstE?<0>XKkNNL$4z>y`EI`hODb@_yoTwt!MkNXV6DspW|9Q zrq;eEmG%Q^*+maL<615L1smklI(N*DoGtmmv>V7SU*om$Q~$DKzp1)axXFQcJQ4TU zVJGg3El=+4d;9&2nZJI-_ka08UDSi~zwfHONKbd5`@>GgnS?rrVN=Zby2$1KoI;^DxEp z`6qgN?B{te0>1EH`fFa8!*p9x(d|f2cc8oGd%2bGv|+!@1?S-Ii2zJJQn~=FEx1@5GHCne*+x#Xi|%xAHw} zH4*>L9;xZIq@vf6p58!j;Taa296NgW`k$VA`eZ)k{UvP5O8buV+7H^#_*QnCF%Gh;&*QV459i&BHynx+&axe=%?x*0zw>VKoQ<=SdiQsB z?*pJGMp)n^yP2=xMm4+R?nmniKr)FKW}1yBV9|IV>Qx zwmqq|9q!wkQ}*a|q^8r8iq1g3cV5F3j*L9dnr=@jx&vwDu{C&KM{2q~spt-*eQsaf z`nl&}-(bc|^=2x%L)QO~HI8maYPvnC=nkZP&Yqy#Wqthlk^H}r=e3J#?~6em<-X+M z*K~VQ(H%(p+_<9Kk(zE#cExpz%?>W(-k$w%aV)m{;>)+zlYB4UC260tC+K#hrrVQ> z?m&W?Wk+JbBWvIso-VA1CBN1~wd338>^yTX0mTjar-EQwc`(RJ3eC_)idL60h^`xRVkX!pX{-qAjTD*6|hUmpvJ8Mxx zYVCVcX+MzWmjga1=SRWu_?2ywIgx!Y&9nSYVF^(v$mh;L%=xSAjZT{dp4{S`$MV`c zzOx;1__^GQeRa1Eb6$lQ?=Bns*uA#SR4u-WEAzoEa?TY@++iaX>ciZ!!wY`&6+2|Z zU-Zme-P*Tzo9#nmsZ+Zo@TE+}g71FvtbUWnCto6N+>?3)tvUTK`-obx)5f)qy#D~( zm%i8D`$n6N?217j-~+9Eu}0gD)Y|r>P@`c-UPfzvHgq~t)9J|$|KEsTrWJ#0=ys&0 z+mnj!Kw4wwz485yT#)z1{(JtwxA`;wf9L-n@-_dz@c;Mt+P9J}2_osG$X!nP9AGP_Y?Fa2XXm_FAg?8`%hwv|)`p&cboxX4G`xd@$ z;ro8q&+qzqt)JKWd83~<`8)M-p1)H+Z}sy|KkxMOr*?m8_lI_WX!lW@kJ^6F?t^w0 z+FfY({=W%qOuqNj_n!K#XZgE*@0stP`|gGBUij|c_4&I#U+eR=KHuo`P5yrUo#*e@ z=UaWg)8{*VR{0*Z{ZrdNwEaWdkJ^3I{)4t3w7t;wLfiNMBz!W_eI)mh+{dZ=ICT$a z?q%*C&fLq~eJu35a38;JX>U+e#k{@>(#()W43C;h+G|2zG^(|<$1rdQ?rqVp%6Kj{2H=cD!?>3yK{ zfzAb;3p($`5K8wI+*fd4(S1etmE2cyU#ITt)IFW)d#>-Zd~f-_^#8m5U+e$1{@>{T zO};OEpXdA1|6BdP`+@k5mVQIOrd#EEqxUDhKj{5I?<1X$bU)DhK<|Ridu!v&y_N2* zbZ^1E1@{)+TXb*9y(RZ{s_#?xb*BHh{ulY)^#8m5U+e$1{@>{TO};mMpXYmXUvGWK zyCdRzI(@YC8~Qc<|4-I^^|rRR=X#$c)qA4~DX|yz-leJDN%hXE90WOvfdKhX$!X4W zm~UVh?l#=u?cTdR^BXhULE?993`pb{<9Y7uy8r9lYc9Wr&w_m3J@xL1cTc=~?7d^} zA9?T4I|u$uy(r(3d`t2z%eO4wihL{bt;)A5-S?%{npb#H?d;j?FtV=g|8H8?wqdFY|)Ti}EhX zyCm>{z#B!;Vcmwu1b2Y}>J8$BrGlcI?`*XUATUU*>(gj(mUU z^FhEc;IjMHj`%89|WVx~D+MX+WF73In=iHvNfW?keJ5J0xvE$ghV|$LwKQ!-P z3xgR8<}I2%i)jwiJf;Oqi+GmoTefS(o>hC+>{+*G!=6ohwgMh|w(Z%mXUCphdv*gJ zd-ehz`SvPF*Z~vYBce32tbt_ld zzB0y=ohAR7b7Swdy;t^L+IwN|xxHrrr=6#Eo|t`N=dt<6_8!@HX#T+tCNt;EpSNql zu4$|@SZA=#nm>zo4)1)xYxlCfD|W8hxn}3Oof~#;+PM|5+PQ7#j-5Mp?%KHM?7z1E%KpoM+3vG| z*WNSxPwhUj z%aR<+GOXCYYX6%3>-KNp-;`l1;Fn?B{vG>w?BBJ2H{iE_FW|?!FUOJZ4}Cre_Z{dQ@hW3IFsX4h7-F^ zWH`3(SdJt65A8eH!)nKjeKU5<+COLiyxj}-7R)c&RpevZ?rA<|_?QiR$g?ENvK%Wi ztje$^!#WomTx`m+6}XUPTZSDOc4XKMJlMY%c)-0c$B|rzJ|6@gx?OTT$?_=6qihfI zJji)3)4iN`cHhZ!YyYi$Wf{t{mgFeOdLzqq;3GH>_Mh5)!N)ltXR@5iabo9*EXVd9 z%X1{hp}hzDcQe`3x3Y|Ig{&DrW3nQ zH}$c`xIgJa_Wm%5*DlS+26YCD}?c-^h0@-$md{mMgw4 z`MTiioUbz(Pvtw2<3z?|S&rpAlI>8Ig99GyFUV4`zbMyetcHWaY@o zl#?SbV_uGe3`O3i{aI>J#wGcdWm}PJRjxJO)_L2IZ2RZL$zL)t)?f5GuA^D~Yoxu4{Fl>JfO2l*dlzsGPd`<;w;vfs*iD}PzmGKP}8B^)<0 zU(0+Y^QFueGM~wND&q~$*F0bGe97|#hI0&O7*6Fsk@Ez@v8=~9j$}WS_27s%8FRAc zWXyA2kiRJZwA?c?&&oR|>%5!`GNxtD$e)opizh2{PTst%1v!g+PtS3VV+q5u{427r z%DyK1y6hXWZwBXA{%!d;4$S>`g9lH4Uc zH?m*LekJ>*>=&}1%YG*NsjMabZ}`9F|BC-hJQsM*@tol~#d0F^37%uQkAt&=*%AJ)tr-MA60-hqCX$&*+&&ob0_q@yt@}_X4F{N>2FlKOMG34aW%U+PXsE6r! zUEo^6w2Ws3%PN*NEbCY{uxw)4!m^EJUG@#xH)Y?FeOvY&*>_~$m3vR_T?~6c7u@e- zIP&?>=L4U=xBBla%Ks++8fUSsa8p{lhSqyXX&&$3bcM?|$ zV+vOqa~f9$Qx;DSOCCo7Ls3W53wpx1gl`$!3a(XLYq-{Rw1I6C+ZMKMY-?E7v20-3 z#Il8D8_N!s9W1*z_HgWC+6#Kp%RZhXpAUUL@cDa-|1Kz&cP#I?-tfHQdBO96_Z{~e z=2zKYa6Dst#`J{q3DYCiM@$cRA8_4czQ=Zl;||{~mRpQvJY}3EOeL&0xUPe~@SNj0 z!*eS4t-i|oD(UM+U)LC~FkWK3z<7@F4C5)j6C5WPkFgx%Ji>OUtM9IZQ_f{iV@S)N z!Is6D!Mm%*0BmBWlN1vt`Ge0*x%%T#qxsb8S68qC%jLX9x*@SdcggF z?H>C*zB?>;7;o|1;w)n-V=dvj33|hFj^zx?sl0c3yVYA+Zza9m;Je0mh3^vI1-^59 zXZTLBonSb@cZ}m0;}Nbyoqcy5obfJuN_Q#w)7Ub)%i_#o%wsHIEMlC-GlOLo#~g-v z`4?oL!kWOGz?#IL#G1mH#+bpE#g@aB$5hZ?QGe4*I>ft#bs6Uh&Q<-b>2FYbp#<+uV2jecjJ$$=Z_jI-&ap64j`OxPBpTCFw?;iy{ z;(N#UhVK>M3%*Y-K6rS?@rLOY+Y7E|+|Rh4us>mY#Q%uzfrAH(_dML=yu);d^%mDH z-ZHilwi|4hm@Y7#V>-ihD)YTA?{s;q%d##@IB#%X8%xOl?($j2kr2TmUF-t%&g`3~P5?pusy zj3taW7_abM;=90ij_(ZLsq7CrzSr@cj&F5b#$3XDgZUcs73NFK7nsj6pJ6`5dxGl( z^D(yLQ=C{2&oR0VE_8z>q2~miq@GiHPGiqt&tlJE&torOFJhm@H-l{!*BqvKJPTOj z987XC$-@*cQ(Po?NOF+EpT?fSoyDBfbzav6T^Dsdy`pOlmN{7AU{%j+JgoDu!NVpG zTRd#@u!MUV_X_S++-tbkac|(>#Jz=k8}|(zhJKNRN?3o+Xv2fyl+@valYVu=Hwac6E9DAAGvwN{J_rx z?t6~zvES+Y7Hb)63F{5kYphpTFR@-=J;!>6^%TRS-XHXSulGB>-{LRhFX6wze~teN z|0Vtl{O9=3@SkEo!FY12cbvx@9N|8^!0S4=)D@;F-B004=sv0Y6c1@0GCX8?$nlWp zp}<3thiRNM7-#X#VVlRbfGNgDoR>H!lN?R*GQ~@RlO!K0F48~XNm$6m-e_~zo`$mc_!4}7lSui~%Z|HS`+{~iAu{#X1j_-njXIji9O z#QcH%9rqjNSIjS%pE-KQ{lwD~_D8NB@jvkOz`;FdcX)5{mhqPG-r&8)dxiHB?*-m- zyk~e%F+4d7kIuq_vvBV$+;MQrL79UR2R9sCb8yAMB?lKAoO5u-!72U|oF^O{V?E~K z2>aos^WZwT(jBfz=V21tl=F~q9+G^d_(=1S;UmjOj*mPa1wM*=OkxZvQNgEJ0J@t)e=|BT&-}m%GDZI z>s)PcwaL{MSKD08^RvLuB0o#~Ec3I%&niD_{H*h{!Otc?Tl{SEv%}90KfB!QakIQ0Jt^MU9^-9~C}6`S{@DosTy@Uio<8qrqpL&pMwq>{T8re0*~8!NWTb zZ#=y6@WR70f6rVzarnf?BaaU}-t%~e{T6!}dkOmu_G|1{*e|hPU_ZxxhW!-BlXLRu zoILPw&%+%Lw>*@2DDiN^!!-|AJY4c{!NWNZXFQy8aDw@ShhrX&I5@m^PFx2!y2KU3 z6~h(hVUm+6eiHm7xk>So<|V^RmX{nad0q;<6nUA(IfHQ)-yFVqd<*!-xEbeYoSzB4 zCOC?56z6D?qbZIO{3N+aIV)*rCF87Qot2!kl6O`L&Pvf)nfCX}B40~RpTH|P)qYaKWIojfAo1-0$b~xJQXpf_P zewsWqcxZ4^=c3L}jgKlH6+S-s_~7H6k2gME`FP=@$!UYr2B&rGH6E&bRJi!$;e&^F z9^QC(<>7^gXAYmac;fMq#|IwodA!4Yi@S`w)S+wa*VwPHUt+(&evbVN`zeMe=j4%t z2M+EzxZ~iKgE9vt4sJNO=HQBhOAanLIOpJugH!w`_>b`);Xk}_PFx2iJz|=`G=V9` zL!6UIex~?IaFgUE#Y>u(3@=$;a=heuDezL{Wg6oQzFB;8_~!8~;2Y&;jH5Ar#`zlO zXo8~{M{$lOIhx`q!B5gzNjWQNXC>pTWSy0qvyyjK3eHN=S(*0t%OYn>oGo*oIG>-#OWia51ig}dWZiOe;I!X{|)|Y{8#ud@n7IS$A5?eVtH*%vQg95uOV^3~v{&QFb>DnAu|KKc3J=bfK7eqQ-`;pdCzFP@t` zG&reqQ{$z|NrjV7PCht!=j4r(S5BTeed6?y(+5uPIlaSvi@k*V2KP1YE8Lg3FL0mZ ze!~2S`2q7i<~z){n9G<;m~Sv&W4^+CiTMKaIp#CWr;rL6I{fcmpCtzoJ{eN;3LULijOoO89uUnXgNjozcXC~{+w}*n>sf&ZmQf=xcTJfgPV75-ne`fjT zeAKz9@lfTV!ow#IA3VJC@W#V4k54>4^7z2xJ&$)-Z?TrKmayJny~cWl^%Cm^)+d~g zI3IA{VoFMTUzk7dbBSTokw{axsl>2Hz~cIehc@7Vr&o zGs4jbKT*D-9F1}`#?d%O6CA}jigPr%V5hT^a8{DeO3GPDJ1ZGyCF`u@oRz$@QgBv^ z&dRiNu*lyMf6M%>@VCm}8h`8jZSXh4-z6WSo(#Gm>*g^3F)X87Vp= z)6T#mhf5qTbGX9cDu-(vu5&oU;Vg%99L{s-55NnH94>LV%;5@$s~oOzxX$4QhnpO3 zak$Ol4u`uO?s2%!-xn`UUK+gAd8zSI<)y;QCodnoyz}zL%PTK0ynJ!c#NWVP$6mu; z#a_YwiTwlnGj~tiJ#zQJ-92}AxNdQkag}i0;JU_jh3g5^Bc=yT_n7W5-C`(h=xj{uf04r_ z4wpGx;c%71H4bMuoaJzi!+8$<;dfz?!zB)vIb7jzmBTd-*E!taaFfF=4!1en;c%D3 zJr4Kz`{Ja@NrRI*CpAv0oK!gZeMxF54_#;c8BK{PZ>`M&kdeyJWp62u{>b8$8v||7E2jR3Cj(ZYb;k-F0ou-ImdE_ zamSZeOSPq?q@2-PK{iJl`Obn;><4i=IiBV@_%$XQ>CMKMTm@^T_KZ$<|e*%9J ze+qvZe+GXRe-3{he*u3H|1`ciT=TdVa1G>~i>!;6p^S^0VQxmaiE=Z_%@{Z1+)OOk zyJ+u{z03AG6A5P`=}e@YiL^73aVE0PM9!JWI}-(GqUcOa>wb~LB@UN4T;Xt)!x;`| zIh^BgojM5aF@e94)^){;-kq&gO55N zH9o3*RQUMhQ5qFU(EM4a{}SHOy7a70l0_dhXCOXAhj+b9RU07DpLJ z3C9hNCk&4m9x&WvxWjOZp^Tw~;ReGshARx07%niJV>rWbis1yqF@_@yht9xv*TIus zQaW)KhSGX*7Dk+fsIxHYEQ~n|>TkQ-98R$hz|OW?Z}s@iNTI2rp4yMtK?IWqiTjMSGX*UAA|{US}cUEF_(U zl(Ud_7BbF4)>+6o3wdXu;4BoKg=xJna=66dGKVW1&Tu%(;T(ta9QqeU3yT~sak$Lk z3Wuv4u5q}|;Rc7B9By&A&EXD*yBzLuxX<4g7fmi2T-3R!aZ%->!o?>SA6&e1@y5j~ z7caX0!rR2#z+1;#!&}8$!Ta2y=XO1F_Q2UaXLlHGF_bZsFg(fsDF1`}_wwJ#e=C1k z{*wGR@?Xn;CI6-T7xJIWe}nAVANFdUo%XJFJB z7;^^3oq-8wAm$9jaZlo&!kxgK#GS&O#+|{P#ht^Q$6df(#662?4%0lQ1x$T8=OOFL z+nsS0?B-^On_+H7xQTKz%FP%zS-gBN|Ibm1Hfr1jw(3^@nG{_|kOS%^9dqt3#ZvoP)~OgIZM zXCaP#68jYP1okBM6!tXs4E8Mc9QHi+0`?;I8EmuI=CI9UTfo+vb1t&3yc`)~H|H9eC*}z%HS;JYyS;6_t*%N1v zoIP-M&)J>qx3WLU{V4Z?-1lqt3&a^DrKq2WKIUdlL5)?gZ{6 z?iB7c?hNiM?i}ts?gH*2?rCf@*k-ZKVVlRcfUP&{%FB^)733(&F)asALp%-hG{Vy; zM`Ij~FFOw_a;(a+CWo^ys)Sdxyj`gm)l(KaJkFn9+&$(esR&{qQOO-iy9YI zE-GAna`C~%I~Q+UymIlv#TT|Fwg$HPf_Ly$@m26W^Yp~iBTo-J-Sc!8oB??s<$aL% zUfw%-Z{;n^Tax!i-s_SxAoHcn7c!sAd?xd$%qKD*%X}pBq3*xC4&L~82Kt0jis~|^Fj%hh& z^q%FXZvfj#CmbE17O-c7<-OGF_^M%akGM~wO zD)WiV$1)$ue5mv9u7h{J_1>%ZKE3zreL(MndLPpJu--@X9@YD(-pBMluJ;MO$Mhb@ zK8bw_djfk3cN%vFcNTXJcOG{EcMN%z7w4O71&gwa*=e(W^dM@gDn!6e9X1SZ=Zk{{;vSwkC zyCv?Hxm)LJgRf1#w)ooSYlp90zV`Uq=jsb*6K4ZwUB@-7Rjd`PpIASzzGHpE`ik`h z>lcoujvI^KS@I61Dy9miXC9t-c;w-MhZi}Y<$RL!QO*ZB@8!Ic^H$EXoFyIKl=ZCR zE1554zL5D`<};a3Wj>MlSmq;{5B2-qb@0Kne*5&>uipXv4(fMEzr*?+(Qj10qxv1w z@3?*^hBzPO9QP#dDcmW%X}lS{S-d&CdAtR@MZD9PW-!fSnhUy}wsXeLSv&PQ81#yN z4F9-JCv+OqXOCYvp91&^EeAQi#VsT%wU-fdYrLm)*c-W1RdfX!#l3O3H`wf-^;h7g$jvl2Gu+H_Gsn$5H~z)Q!Xh{8JZ$i= z$-@>8+dS;>u*<_95BnT^;b`ivp}V^7YM82+DwsYoePDXW^oHpb(+j3A-8FUB&|O`3 zH7r#u6)ewqpYXoP_bT6ue9!Vd$@eJVgM9b$-N|>WyRz;|y1UWcweGHDzLfbw=5v|P zWImPoMCN0ek7Pdl)Ss(ce?9u^)nA|f`t>)Uzd`*C>2FwnBl?Su@IB1;5YM`cW1hsE z#G1mI#+t#J#hSyK$6CNz#5#>%=%$aXK=oz8A`R@PZbXE!>#*4dTJmoi_-d@l2u%%?J+$b2mGk<5n`y}7#d z)~&Z5z4hv?PjCHt8_?UJ-iGux9M#>3?uPjeded1P^Cad3-Xz`>-Zb6}-Yni6-aOs{ z-Xh-Vpf{cM1)bp>!#S?634O)%71!6KzNYk*&{tAlDSf5&mC;vLUpY?loD?`Iax%@y z3@5Xk%yBXw^o4r^_a^Qw+}pT!aPQ*Y!@ZCBOYWww8nV}AugPAOy(0Uk>>skf%l;<& ztL!hbf9a~JtA?)Xx~gHQVyIyFkn3HpH@RNrdXei{t|z%3<$93oURQUzy46)#S0!ED z=;~TmS2AD9d?E9>%x5y6%6ua8vCKy@AGi*yI&*dEtV?IzI_uF{Z;V%+_3LavXM>}9 zi|TDeZ#s+WY;=%oy~Xqv$3KaG3V#BB5`PMR8h-|V7Jm+Z9)AIUG3ZWjQOu*5$1soU zZ9;D`y~TIU)7zBZ5_(JOEv2`#-ZFa2@{{8y&rgA$B0tmo%>8z=rt);x$gCLr?*?ZmGxHA+l}6?^>!umrOX#HpUZqE z^Qp`yG9Sx)B=dpmu%s_ul zxnAXZk?UEmC%GQwdXVd0cXztG)m>S4CEeZV?pk+OGGEGkA@jM+XELA4d?NF)%ttaG zxDM<3bG7TQLw}u2Z->Tg(oBl?T#Z?vC#9ggd8LWeOO z#`&1!V~URiA4xt^e5Cov@R8*s$48!zVID?!i1IMX!x#_aI-Jm9Oo#D(vvfG6!-Ni# zI!x&>%~gi0ELS~_TDsnZ=)eKj&T+MMc&(%5~8+>f?vBk$WA3J>P^0CLoJ`Z0q zH)U?fT$i~fb5-Vw%%3uU$ow93sK2J%4Y})b*W|9sU6H#gS4F;xY@f1y$o4MVn{2PL zy~y?~+mmdMvOUOlug5z*-s-We$C4gz^mwhuE4eS_zL5J|?lZYh0 zUAo$I**>LDU3TiSOPAdf`W)Bim_A4K8P%sQ2X#55%VAxP=rXFyQC*Jda$J`ax{T>E z&dVe(Q@kX2N%E57CCy8Qmn<(iUWPas=46DEC?}(wjBzrq%L!e^bQ%9{mM*7snb2jD zs}yHxzA}7e`O5K?=c~Y1k*{gKX84-rYmTpZzScR};AE4NEl##M+2LfDlRZB6x%iT~ zDRV>Sy3941t1?$){*?J6=u+mU%nh0AGS_6T%3P7TCRbIys%#ZmEAoBH_aWcAd~fo- z%J(AQvwTnTJ<9hW-@QKX^m(h#vOY`tywT^iKCfiIl>I{XbJ@>iKb8GN_G8(PWIu2n zHg)Q1P3Tpp?KzH0g^{Uf;oet=9P^UvW9oFfHPNO;<)#;c{$8|cP z)0j@<{7mvQ#ZQ8tBtI#B()?uj$?`ME&k#Su{EYAu2!*x z1ZPR^QoN-(%W#(EEXP@%vjS&D&ZdJ-`I_Tvp09OIHaOYjWQ&t+PIfriUK!C!@3>OZB)0T zx*gN)xNawO8`Eu^t4Xe=xJq!9SMozQJe zw{e~(Ih*1y!DEuc6n|;%GTddk%W;?IuE1R}=$5lN&gMB==VgPJOo!?US63az4m;uiHD_-s-lj+mdc?bbGDaD-4$yE-;*9IKyy? z;RM4mh9e9Iu1G?+dTmMScG8v7Z(P4I{Z8n2T)(>Q)@_e&dv)8V+kV{+=yp)IL%JQ- z?TBupx*gT+m~O{)JE7Z{ZsUAS@-@X*g0CcBDZbL*%+l?EZU=cA;%%6>5#FM_jq*0e z+qiBg_=#~9KQfEMDJ~N{COJ&;m*y_RU6#8XcX{p#LAQL(@iouaIwu>PY;v;2$u=iD zoa}P4$H$k9O&J?9)@7{8Se5ZhuBKcKx$1J&r)3Q!WI=#{9wN9_(zm)$%{&V@y z!wH>Exsp1abft6}cct|j)9Zv@b=s-ZE}eGkv`44CI_(QO)#so-hx9qD z&k=n_^*O4~v7k>~#&j9yX_BWYo)SDIc}nrrr^|j_4(M`_vmwrgIUC_D%GoGqW1Nli zGQm-duQ+#;98U3<;4aBqinBCl8P2kt1%W1Ej1 zK6d%|lCddcL&my{H5tETYRc4*sV-AZrm9R|GBjmr%F&RkAxmAxx;!;`Ycf@3s>t*y z(}zs&GQG+4s>he0N4Xy5dXVd0hj%)>)nQqOB^}=A@LGpgGGEGkA@jM+XELA4d?Irw zp~op#Qje3alpf=*v>s!wj4t)quE!2NcIvT9kKKCg(POV3`v&!(%K=>u>T*bz!@3;N zWmK1=L6>@r=`qgHBu7&mB{)iQ)T_rnJ@)HyK#zl*4RJQi*$8J*&PF*K<7J$q3BF?7 z#W|ehZ;HDFZ%NKloTWL-aF*pP$621U0%y~@oZ)PivpLS@Ia}jqotq7AHo4j2W}BNG zZocGf%Gr>!F6Wm_O_>@p)n%&5^d-la3{9Duax~;?$WoWJE>BIKsyr2WKIQq4=UtvR zd0ut+BGa=>Pcl8q^dQr{9`E#ctH-h)OM1M~ajJePhGa_vO|}hy6nHo;#^k8uts z`J3V{!CR8I6mMzXGQ4GZ%kh@yt-xE6w`tyHc$?*Ij<wrkn0WV@8@Lbh|+&Sd*GehRd=m99qO-Le;xYk)L)nWy7kwizh3?I>91dZ1Ns}(-;n->^*5rwXb1N?oX}xR zhjCsed70v+TZcV5?A2kP4*PXDpu<7FhWHxhYlN>TKcifY@iwl*2_43C80T=3zbWn# z+$Fh7ahK*U6LiR1p0@&TMc$@)o8fJiw>jSCd0XLWm8UhH)_L0CX_Kcdp1$O4%K0Tr zQf0{c87%-OqME+5KqugWdN!yVKdN z&dNF~$#NshwJcY%T*`7G%egGyCS56g#a+4z>ng0Ph^`{KYSC4Tu3B}~n%9}W+V$0; zuTFh+>8o2`J^Jd^SD(K6^)(RmrK@3Gjp!=c&a=M8^);cdn7-mXO!CmBuWo(y=&M&> zefsLx*MPnTIU3?e(v;htDmynCA)9zzP9_y?n}Eb?Ea>gZ+Z#o zC8U?IUc!2b=p~|;7QM9SrByGj1^wuzT{j)N>C{b^Zn|~Tqnlpc^y#KQ=teKYdKuA6 zw2f2UjOk`vHxs&v=_Zc5Q#W0@>DEn;ZhCdor<;D=4CrQ%mmyw;c^T17^vEpTjOk`v zHxs&v=_bzEBxh5cB{)lRmf|eUS(dLHUwOU?d=>ec=4*zpS-$4@n&)eYr)8d2cv|IY zji+^V|@oLA59nW?=+3{${gB|xexzow5 zU1hsUcHP)@ZP%4umq91G_@;}HE<(Bp>msa+h%O?!XwgNBE?RZbTGWX?+V#<)k4}Ab z>7!d8J^JX?M_Eu)jOZe&i&0&S>0(?L6S|1$BF@z$S5sUixJq)B;wsHmhN~=BIj-_t6}T#L zHOEraW&7?B2P;^E%UU((<)DEJgoRsEZ+84C`V<7g1e|>S9b6EzAjOt=c7vs8^&_zraajqu0n&K+K zRg$X|S81*?TxGe+ah2z)z*Ui}X|86tn&oPat9h>cfqG$)t0k_Mxmw|Bm8-R&5A&Pm zH_We_Uo*dIe#QJx^FPdgH~-E2SMy)Ye>VTg{73U2%)dAP&iq^R%jTENzcK$h=t2kI zbP&=(NC#mZgmnEu)jOZe& zi&0&S>0(?L6S|1$BF@z$S5sUixJq)B;wsHmhN~=BIj-_t6}T#LHOEraW&7C zKMXG{a<#5&m2FZ{fd{|JGUlbkMGY4jpvrpi2kc zI_S|suMYY;`P0LI9tQO=q=#WWjOZb%hfzI@>7i8*ZF*?eLx&zZ_0Xk3|F&U&2cr)l|RfbEONEP)iPHrK@a9O&25-lH@9YP)!d4?pXPp;`)=-= zxv%EFnEPz*lev%PKA3xN?wz@}=9bMZ1s!nzjr$PyA@0N6hq;e%AK|`*`xfq7xo@50 zjsJH3JNWP9zl;BF{(JcE<-d>re*OpeALM_C|6%?|_>b~G%6|+0t!pkFwCSK-2OT=- z)IpaHx^>W_gI*o<>7ZW+13DPg!H^DybuglXs18PTFs6fX9ZcvTrh_A?t8fJ<-U*me(ndjALM?B`(f@!xQ}u_%KaGkF2N=Mc|fp2Ivxc#iPg!gCAHtvt6b zaKm*w*BxAUa^1ysH`hH}_j29GbwAewTn}^4q$|2gmIkcW~Uv zaTmwk9QSbC%W)sa{TvT)Jjn47$HN?lI1Y0h<~YJ}gyR;DTR3iAcJbWCb34x+Ja_Wk z#d9~$Jv{gF+{bf2&jUOU@;t=zFwY}AM|mFQd5q_Ao+rxAH`npNH8*K)GTdaj$#IkC zroc^+n`v%lxS8cJ)!=PAieikmby8E&%N< z4RadiG{R|w(-ux!Ic?*#ozo6ZJ2~y*w42i&PJ21+-IsC?9h{F(vVGhF_MmTKYu$99$4%<2G;INa!E)Kgn z?BTGN!#)oCIUL|{ki#JkhdCVKFv{U5hhrR$b2!0ajKeq=Q#>SiNb->4AR9cVX_r+(o!+;jWdtHtyQF>)@`FyDsj!x$EJsm%Bdh`U7{Ied8>|S%|YRXA#a? zIBVssjk9*nIymd(tc$a5&U!fO<*bjhe$ECs8{}+=vtiCgIE!*N%GnraZ=_5}7M_7wIs_6+tc_8j&+_5$`I_G#=hfj93pz1Q$w-Fr3fRlQg7-lz9Iy!YK3m+jq!hA&d zXyK!kk2XHq`RL%IlaDSwy7}ngqnD39KKcV6TnuqB%*6;7Q7%Tg7~^7`iwQ1bT*Prr z;+n#hz?H<6!j;CA!Ij08!^uX(=e`HJU1J^$hPchA3h{x$G` zKZHMwKZ3sne=Ghr{O$NV@OR?x!rzU*C*a2(!XCyR!QO(s6?+@@cI+M4JF$0R@5bJP zy%&2Q_I_t!0RJHVA^gMmNAO4SkK!N0KaPI_e++*d&m^8HJPABWJSjYBJQ+M$JUKjh zJcWSYvrW%7JX`l{&9ha{Ry_OZ*$>aYd-g40#~s2Q#vQ@kg1Z%W8}4@89k@Gjcj4|1 zxG{$?hcQPmw_t9?+=jUwa|h;5%w3qfG528Z#oULvAM*g_LCiy#hcS;}j$$6gJcfB3 z^91G?<~WW?98)+FIFdM0IMO&WII=i$IPw9r=bD~tc&_fbn&+yXt9b6yb04024|uVL zu!gZlu(n`r#oC6o9cu^HPOM!4E6xzkFwO|h7M!g(+icZ8Hs|Qyvu0CA-0T-rWOe2`0m_{*;VH(FYfhmS5F7KqgQ}QO{P0E{+H!W{Q-fY0+ ze$)Mi`*rtg?pNKfxc?dOU5qZ>yLj$Ryn0SAU*3?mq#7)CLSVHn3Sfgy$=F5{$(Q!*xGOv;#&F)d>zU~sSL zUcPvWH|3%N~)vMfO(N+hlJKvdbNkJ1loZ?iRUQ) z@2f#xSwpghWsS(%B5SLxZ9!H!Lvn`YjL6v{XRDlTa<x4`mW)-y6p7M3j{TT75lu8>?|xgv74$ki%W zn_TU3b;#8zSC?Gfa`nj7>+iFE*#=}Alx;}1;UJq_qjHVOH7?hLTrs)ga!krGB}XF2 z<@cuF8$l*{Lh^*=i3E9M3CR+cB_d0UEUmJ%$K^8xoK@J&0GK7N+_J`~b+aIyN#r{_N+w5<* zzr+4c`@8J#w!g>zUi}$8L!@f@Yy6o$=ugAV#`}*wbw{O6{L1$yc&ZwQEc8=LOZs&xZF+1bI zzF?Oku&2|WE_=G|>9MERo<4i}?HRCVP}jqDjo1~nYt*hW zyT&LF1bgfV*%7uQVn>S|t#-88(QZeF9i4V`+0kuBj~%^s^x4sG$ABG! zb`04uY{!TlQ9DNM7_(zM*kOLi{IK~E^IObsHNVaLcJn*T?=-*5{BHAm%X!elV!)A||9W{G2m~C#z+_1S3b6d=9HMh;&c5^$-?KHQ`+-`Gw%L_ z=jTu|*BbUYl$`7cho=0Dx69#P%;y2`WC`wvd>2aQ&5j3IWS_z^)!X6< zC8v7)?1>~3KYyC(_vFvtarcCiuf1)_kCssKqqWr)N`AIQlJDMqZ*$4`-Wo~1ne*nm zS3lod!^zK|&xJh`@ow0A!SjB$v?f2zdhZG5w0hRhV6NXk&HHR|dG^!H55K>6xB1RK z*K1FkpRIoSUH*63-h+L3K7u{wzxK4s5$u&mwoh5!gMDVcdhV5v_h6Sf@8*95S>=1R z=fjSVfCc;e&t1WMSGSq2*PlPb=F9UlLyKnvcDa6DW^(?42 z-}mmF{d}k0y$<&}-0O6&)4eYDg7*g98*p#Hy?*!l-RpC&*S$9P+TCk+ufx3#_d4C{ za&O4JLH7pT8*p#Hy?*!l+-r5O&Am4F+TCk+ufx4g_lDgYa&O4JLH7pT8*s1Ry%zUc z-D`EP&Am4F+TH7LZ^XS}_lDgYa&O4JLH7pSi@4X~UW|VsZhC zeUAD(;&Z?m@?6OGVc&;+AMt&#BkE_6C*=E(&tac~d%?RQKZDPqy-v?|`o7cb4!?K( z{2cas#P7lPZGLa{d+T1id)+_phkO_IUD$UK-$i_G^SRCER-aq<+C10e>ae5B)$ZAD zSDR;hTf4Y1{#WpO z@YgS0KKVZ#^8ftxpWg*P{WIRTV8;A^zZZNC{_@YCKW7BL2haWIv(5k2pESNLrIJ?*8b~L{<;4bpIZN~PX(!eVb;cfeJU{X3r}tS*Qflc z@)w`l3Z8npJURB~lAnJCpa0`O{^Q5L|NFoH__u%iw;%udumAevU;gD^e*E)4|MQQ3 z`lo;T@sI!bk3at5AO7LT-~avJ|M$iUE z$8Y}TZ~pj=-}sFmzy9mL{^Qqv?bm+%>aYIlkAM2#)_(lTul&l-IluhNzx?C>_`jZi z{NKIZcUTii9|!QW_uf19jv)|&q9`b$C}KeYQDY#R5J@wk+EDD+yJANad&e$%oUdos z*SB1Gd%1gi@AZ2#6ZAM9?oYq_kYs0f_V=0D-3(85XPmzU%2-MhGR=MHY)zKvVAZsF$5o49e~2CiSfj%(Mhp{%S7SFc{hl`B_p`SN94 zx^xK_FJ8oj3m0(y{CS)^cMfOIp2e9nXK?!TX`DKB3MWsVL}_U$PMkP_VE_L8C@Lz#zJ2?!ckf>8*|P_`ckjlo zUAwSz=T7X{u>;$;Z^yQ6+pu-(R&3d_1)Dc-#->f1uyNx?Y}l{?g@uJ!zkWT|ty_n+ zYu94Unl)IxdNo$9T7{J>SE8Vx04r9k!1CqGk)NNBWy_Xf>C&ZGvSbMsFJ6pAixwd- zFAur7xyZ@ML3VaFva+&}nVAWn&j+v9i-ijp!sGG4?RLZEa>40z!r^crBO?O~7A%0> zZby20I&3x@tX3;DO@qZ^L0VcGQd3i5Hk&bj{(P8BCd`{R4|C_v#hf{Fkdl&u*|TRO zIXM|gNl8ddOvJ2NvoLe!Oe7>EV8)CYm_B_vrcIlMsZ*ySK0Y2(rc6OxTpT7(o{UM8 zCLuO97855<#DobG5EB!F@#DuMIyxHT#*M?+v11Vx6@|#iNQ@aX2BSxhMnpseMvWSU zkt0VUJUkpDMvTDl;lmLY76zlyh|thb7z_r4goGeCI2d}p9zj7t(CKs-Hf$II0|PO1 z=uiw9G6aJM55}NDgD`O5Knxf#0R8*-N56jk(6?`2^y$+Fy?ggYuU@^-vu95P1O%W* zj~?jWy*s*f>xQmfyP`{%F6i93GdgwZgpM6MqCeZ`3iJk% zpQd+tGRPC@4fakUc?MG;`L&@y;sQPg5_ds3khrzPfyBK#4kT`pav*V+ngfZh0~|>H zj-Y&xM5i1MBzjeGAkjUJ1IgcIlw%}1uyP>LLzx4KuIL;{JbS=_!~-WBNdDTVoOR;S zG7coKtx#$t9z5kh;wfbg)Pn^Du%MnSs22!#Dv!L-TD24@1U_ldEP%I0Y#DXTXpg0yZg$2d4ps6fq z8Vj1vf@ZLw1Qs-t1~!h)8vpk*v5p9L*vK`U5L0Sj8mf>yDh)huWY3tG#9*0G@VEU1tL zZD2tgSdqwv!Ej^=qL*+WJ85VSw1)XC-=ULDN7IcvX zU1C9(SI*s@3Wu^7W4rN zdccCd!Ga#LpbuHlBNp_S1wCOwPg&427WAA2yD;D%?7W5ky^jjA6I~MeN7W4-e^hXx-Cl>T)7W5Yu^j8-2Hx~4F7W5Am^iLM_ zFBbG~7W5w$^j{YAKNj?V7KC>RdE=vEQv@KVdX+CV3Qb*+Fxg$!+Um28c-IAnszgQ; zkS@$We6^ljX8kWsEg4 zGDNrvP%T6wvC!l-=Q-ryOlnh$zqld(IE}@6qcI@J5G+e9!$enxk@#0j;AOQiRwwOmgvu~w(DX4`ElA@_^P=bu+AY-XoirVrFNl&ex5W{YNWsk~Jd zc+~<~sw9z1PO?OAOQlYLREOK`R56|QT>t(zs1?36b7i$uHO+E}EH#9dP97LjX1Z7N zrMn##X#`0lLd?iX26=0!ZEa$_Etf?_O>;ZkURlI2U4Z(lwhvXL8qYYj4^nMkMv;ab zXi--!giaPFR;-khtl8Vbs2R;-(`pE!7UkG2nU&*$>1&GWR59NZgUnZtYV+EwRPb%l l)WPt1%xQL)I(q)$#}p$=Cca_@mBnKBc^u|Eb-b#>UjVVd+(Q5W literal 0 HcmV?d00001 diff --git a/projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj b/projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj new file mode 100644 index 000000000..f2e86c8a6 --- /dev/null +++ b/projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj @@ -0,0 +1,387 @@ + + + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + Win32 + + + Release + x64 + + + + {2F1B955B-275E-4D8E-8864-06FEC44D7912} + Win32Proj + models_mesh_magicavoxel_loading + 10.0 + models_mesh_magicavoxel_loading + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + Application + false + $(DefaultPlatformToolset) + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + true + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\ + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\models + WindowsLocalDebugger + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + /FS %(AdditionalOptions) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + CompileAsC + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + Copy Debug DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) + CompileAsC + true + + + Console + true + true + true + raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\ + + + xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)" + + + Copy Release DLL to output directory + + + + + {e89d61ac-55de-4482-afd4-df7242ebc859} + + + + + + + + + \ No newline at end of file diff --git a/projects/VS2019/raylib.sln b/projects/VS2019/raylib.sln index 53d2a18ad..f5a4180f2 100644 --- a/projects/VS2019/raylib.sln +++ b/projects/VS2019/raylib.sln @@ -275,6 +275,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rlgl_standalone", "examples EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_split_screen", "examples\core_split_screen.vcxproj", "{946A1700-C7AA-46F0-AEF2-67C98B5722AC}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_mesh_magicavoxel_loading", "examples\models_mesh_magicavoxel_loading.vcxproj", "{2F1B955B-275E-4D8E-8864-06FEC44D7912}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|x64 = Debug.DLL|x64 @@ -2283,6 +2285,22 @@ Global {946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x64.Build.0 = Release|x64 {946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.ActiveCfg = Release|Win32 {946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.Build.0 = Release|Win32 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x64.ActiveCfg = Debug|x64 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x64.Build.0 = Debug|x64 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x86.ActiveCfg = Debug|Win32 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x86.Build.0 = Debug|Win32 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x64.ActiveCfg = Release|x64 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x64.Build.0 = Release|x64 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x86.ActiveCfg = Release|Win32 + {2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2422,6 +2440,7 @@ Global {6237BEDE-BAAA-4A06-9C5E-8089BAA14C8B} = {E9D708A5-9C1F-4B84-A795-C5F191801762} {C8765523-58F8-4C8E-9914-693396F6F0FF} = {E9D708A5-9C1F-4B84-A795-C5F191801762} {946A1700-C7AA-46F0-AEF2-67C98B5722AC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {2F1B955B-275E-4D8E-8864-06FEC44D7912} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} diff --git a/src/config.h b/src/config.h index b7358d7e7..b244add66 100644 --- a/src/config.h +++ b/src/config.h @@ -182,6 +182,7 @@ #define SUPPORT_FILEFORMAT_MTL 1 #define SUPPORT_FILEFORMAT_IQM 1 #define SUPPORT_FILEFORMAT_GLTF 1 +#define SUPPORT_FILEFORMAT_VOX 1 // Support procedural mesh generation functions, uses external par_shapes.h library // NOTE: Some generated meshes DO NOT include generated texture coordinates #define SUPPORT_MESH_GENERATION 1 diff --git a/src/external/vox_loader.h b/src/external/vox_loader.h new file mode 100644 index 000000000..63f2719f5 --- /dev/null +++ b/src/external/vox_loader.h @@ -0,0 +1,771 @@ +/* + The MIT License (MIT) + + Copyright (c) 2021 Johann Nadalutti. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + + vox_loader - v1.00 + no warranty implied; use at your own risk + + Do this: + #define VOX_LOADER_INCLUDE__H + before you include this file in* one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define VOX_LOADER_INCLUDE__H + #include "magicavoxel_loader.h" + +revision history: + 1.00 (2021-09-03) first released version + +*/ + + +#ifndef VOX_LOADER_H +#define VOX_LOADER_H + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#define VOX_SUCCESS (0) +#define VOX_ERROR_FILE_NOT_FOUND (-1) +#define VOX_ERROR_INVALID_FORMAT (-2) +#define VOX_ERROR_FILE_VERSION_TOO_OLD (-3) + + typedef struct + { + int* array; + int used, size; + } ArrayInt; + + typedef struct + { + Vector3* array; + int used, size; + } ArrayVector3; + + typedef struct + { + Color* array; + int used, size; + } ArrayColor; + + typedef struct + { + unsigned short* array; + int used, size; + } ArrayUShort; + + + // A chunk that contain voxels + typedef struct + { + unsigned char* m_array; //If Sparse != null + int arraySize; //Size for m_array in bytes (DEBUG ONLY) + } CubeChunk3D; + + // Array for voxels + // Array is divised into chunks of CHUNKSIZE*CHUNKSIZE*CHUNKSIZE voxels size + typedef struct + { + //Array size in voxels + int sizeX; + int sizeY; + int sizeZ; + + //Chunks size into array (array is divised into chunks) + int chunksSizeX; + int chunksSizeY; + int chunksSizeZ; + + //Chunks array + CubeChunk3D* m_arrayChunks; + int arrayChunksSize; //Size for m_arrayChunks in bytes (DEBUG ONLY) + + int ChunkFlattenOffset; + int chunksAllocated; + int chunksTotal; + + //Arrays for mesh build + ArrayVector3 vertices; + ArrayUShort indices; + ArrayColor colors; + + //Palette for voxels + Color palette[256]; + + } VoxArray3D; + + + // Functions + extern int Vox_LoadFileName(const char* pszfileName, VoxArray3D* voxarray); + extern void Vox_FreeArrays(VoxArray3D* voxarray); + + +#ifdef __cplusplus +} +#endif + + + +//// end header file ///////////////////////////////////////////////////// +#endif // VOX_LOADER_H + + + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +// Implementation +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef VOX_LOADER_IMPLEMENTATION + + + +///////////////////////////////////////////////////////////////////////////////////////////// +// ArrayInt helper +///////////////////////////////////////////////////////////////////////////////////////////// + +void initArrayInt(ArrayInt* a, int initialSize) +{ + a->array = MemAlloc(initialSize * sizeof(int)); + a->used = 0; + a->size = initialSize; +} + +void insertArrayInt(ArrayInt* a, int element) +{ + if (a->used == a->size) + { + a->size *= 2; + a->array = MemRealloc(a->array, a->size * sizeof(int)); + } + a->array[a->used++] = element; +} + +void freeArrayInt(ArrayInt* a) +{ + MemFree(a->array); + a->array = NULL; + a->used = a->size = 0; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// ArrayUShort helper +///////////////////////////////////////////////////////////////////////////////////////////// + +void initArrayUShort(ArrayUShort* a, int initialSize) +{ + a->array = MemAlloc(initialSize * sizeof(unsigned short)); + a->used = 0; + a->size = initialSize; +} + +void insertArrayUShort(ArrayUShort* a, unsigned short element) +{ + if (a->used == a->size) + { + a->size *= 2; + a->array = MemRealloc(a->array, a->size * sizeof(unsigned short)); + } + a->array[a->used++] = element; +} + +void freeArrayUShort(ArrayUShort* a) +{ + MemFree(a->array); + a->array = NULL; + a->used = a->size = 0; +} + + +///////////////////////////////////////////////////////////////////////////////////////////// +// ArrayVector3 helper +///////////////////////////////////////////////////////////////////////////////////////////// + +void initArrayVector3(ArrayVector3* a, int initialSize) +{ + a->array = MemAlloc(initialSize * sizeof(Vector3)); + a->used = 0; + a->size = initialSize; +} + +void insertArrayVector3(ArrayVector3* a, Vector3 element) +{ + if (a->used == a->size) + { + a->size *= 2; + a->array = MemRealloc(a->array, a->size * sizeof(Vector3)); + } + a->array[a->used++] = element; +} + +void freeArrayVector3(ArrayVector3* a) +{ + MemFree(a->array); + a->array = NULL; + a->used = a->size = 0; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// ArrayColor helper +///////////////////////////////////////////////////////////////////////////////////////////// + +void initArrayColor(ArrayColor* a, int initialSize) +{ + a->array = MemAlloc(initialSize * sizeof(Color)); + a->used = 0; + a->size = initialSize; +} + +void insertArrayColor(ArrayColor* a, Color element) +{ + if (a->used == a->size) + { + a->size *= 2; + a->array = MemRealloc(a->array, a->size * sizeof(Color)); + } + a->array[a->used++] = element; +} + +void freeArrayColor(ArrayColor* a) +{ + MemFree(a->array); + a->array = NULL; + a->used = a->size = 0; +} + + +///////////////////////////////////////////////////////////////////////////////////////////// +// Vox Loader +///////////////////////////////////////////////////////////////////////////////////////////// + +#define CHUNKSIZE 16 // chunk size (CHUNKSIZE*CHUNKSIZE*CHUNKSIZE) in voxels +#define CHUNKSIZE_OPSHIFT 4 // 1<<4=16 -> Warning depend of CHUNKSIZE +#define CHUNK_FLATTENOFFSET_OPSHIFT 8 //Warning depend of CHUNKSIZE + +// +// used right handed system and CCW face +// +// indexes for voxelcoords, per face orientation +// + +//# Y +//# | +//# o----X +//# / +//# Z 2------------3 +//# /| /| +//# 6------------7 | +//# | | | | +//# |0 ----------|- 1 +//# |/ |/ +//# 4------------5 + +// +// CCW +const int fv[6][4] = { + {0, 2, 6, 4 }, //-X + {5, 7, 3, 1 }, //+X + {0, 4, 5, 1 }, //-y + {6, 2, 3, 7 }, //+y + {1, 3, 2, 0 }, //-Z + {4, 6, 7, 5 } };//+Z + + +const Vector3 SolidVertex[] = { + {0, 0, 0}, //0 + {1, 0, 0}, //1 + {0, 1, 0}, //2 + {1, 1, 0}, //3 + {0, 0, 1}, //4 + {1, 0, 1}, //5 + {0, 1, 1}, //6 + {1, 1, 1} }; //7 + + + + + +// Allocated VoxArray3D size +void Vox_AllocArray(VoxArray3D* voxarray, int _sx, int _sy, int _sz) +{ + int sx = _sx + ((CHUNKSIZE - (_sx % CHUNKSIZE)) % CHUNKSIZE); + int sy = _sy + ((CHUNKSIZE - (_sy % CHUNKSIZE)) % CHUNKSIZE); + int sz = _sz + ((CHUNKSIZE - (_sz % CHUNKSIZE)) % CHUNKSIZE); + + int chx = sx >> CHUNKSIZE_OPSHIFT; //Chunks Count in X + int chy = sy >> CHUNKSIZE_OPSHIFT; //Chunks Count in Y + int chz = sz >> CHUNKSIZE_OPSHIFT; //Chunks Count in Z + + //VoxArray3D* parray = (VoxArray3D*)MemAlloc(sizeof(VoxArray3D)); + voxarray->sizeX = sx; + voxarray->sizeY = sy; + voxarray->sizeZ = sz; + + voxarray->chunksSizeX = chx; + voxarray->chunksSizeY = chy; + voxarray->chunksSizeZ = chz; + + voxarray->ChunkFlattenOffset = (chy * chz); //m_arrayChunks[(x * (sy*sz)) + (z * sy) + y] + + //Alloc chunks array + int size = sizeof(CubeChunk3D) * chx * chy * chz; + voxarray->m_arrayChunks = MemAlloc(size); + voxarray->arrayChunksSize = size; + + + //Init chunks array + size = chx * chy * chz; + voxarray->chunksTotal = size; + voxarray->chunksAllocated = 0; + + for (int i = 0; i < size; i++) + { + voxarray->m_arrayChunks[i].m_array = 0; + voxarray->m_arrayChunks[i].arraySize = 0; + } + + return voxarray; +} + +// Set voxel ID from its position into VoxArray3D +void Vox_SetVoxel(VoxArray3D* voxarray, int x, int y, int z, unsigned char id) +{ + //Get chunk from array pos + int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE; + int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE; + int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE; + int offset = (chX * voxarray->ChunkFlattenOffset) + (chZ * voxarray->chunksSizeY) + chY; + + //if (offset > voxarray->arrayChunksSize) + //{ + // TraceLog(LOG_ERROR, "Out of array"); + //} + + CubeChunk3D* chunk = &voxarray->m_arrayChunks[offset]; + + //Set Chunk + chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE); + chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE); + chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE); + + if (chunk->m_array == 0) + { + int size = CHUNKSIZE * CHUNKSIZE * CHUNKSIZE; + chunk->m_array = MemAlloc(size); + chunk->arraySize = size; + //memset(chunk->m_array, 0, size); + + voxarray->chunksAllocated++; + } + + offset = (chX << CHUNK_FLATTENOFFSET_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY; + + //if (offset > chunk->arraySize) + //{ + // TraceLog(LOG_ERROR, "Out of array"); + //} + + chunk->m_array[offset] = id; + +} + +// Get voxel ID from its position into VoxArray3D +unsigned char Vox_GetVoxel(VoxArray3D* voxarray, int x, int y, int z) +{ + if (x < 0 || y < 0 || z < 0) + return 0; + + if (x >= voxarray->sizeX || y >= voxarray->sizeY || z >= voxarray->sizeZ) + return 0; + + + //Get chunk from array pos + int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE; + int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE; + int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE; + int offset = (chX * voxarray->ChunkFlattenOffset) + (chZ * voxarray->chunksSizeY) + chY; + + //if (offset > voxarray->arrayChunksSize) + //{ + // TraceLog(LOG_ERROR, "Out of array"); + //} + + CubeChunk3D* chunk = &voxarray->m_arrayChunks[offset]; + + //Set Chunk + chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE); + chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE); + chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE); + + if (chunk->m_array == 0) + { + return 0; + } + + offset = (chX << CHUNK_FLATTENOFFSET_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY; + + //if (offset > chunk->arraySize) + //{ + // TraceLog(LOG_ERROR, "Out of array"); + //} + return chunk->m_array[offset]; + +} + +// Calc visibles faces from a voxel position +unsigned char Vox_CalcFacesVisible(VoxArray3D* pvoxArray, int cx, int cy, int cz) +{ + unsigned char idXm1 = Vox_GetVoxel(pvoxArray, cx - 1, cy, cz); + unsigned char idXp1 = Vox_GetVoxel(pvoxArray, cx + 1, cy, cz); + + unsigned char idYm1 = Vox_GetVoxel(pvoxArray, cx, cy - 1, cz); + unsigned char idYp1 = Vox_GetVoxel(pvoxArray, cx, cy + 1, cz); + + unsigned char idZm1 = Vox_GetVoxel(pvoxArray, cx, cy, cz - 1); + unsigned char idZp1 = Vox_GetVoxel(pvoxArray, cx, cy, cz + 1); + + unsigned char byVFMask = 0; + + //#-x + if (idXm1 == 0) + byVFMask |= (1 << 0); + + //#+x + if (idXp1 == 0) + byVFMask |= (1 << 1); + + //#-y + if (idYm1 == 0) + byVFMask |= (1 << 2); + + //#+y + if (idYp1 == 0) + byVFMask |= (1 << 3); + + //#-z + if (idZm1 == 0) + byVFMask |= (1 << 4); + + //#+z + if (idZp1 == 0) + byVFMask |= (1 << 5); + + return byVFMask; +} + +// Get a vertex position from a voxel's corner +Vector3 Vox_GetVertexPosition(int _wcx, int _wcy, int _wcz, int _nNumVertex) +{ + float scale = 0.25; + Vector3 vtx = SolidVertex[_nNumVertex]; + vtx.x = (vtx.x + _wcx) * scale; + vtx.y = (vtx.y + _wcy) * scale; + vtx.z = (vtx.z + _wcz) * scale; + return vtx; +} + +// Build a voxel vertices/colors/indices +void Vox_Build_Voxel(VoxArray3D* pvoxArray, int x, int y, int z, int matID) +{ + + unsigned char byVFMask = Vox_CalcFacesVisible(pvoxArray, x, y, z); + + if (byVFMask == 0) + return; + + int i, j; + Vector3 vertComputed[8]; + int bVertexComputed[8]; + memset(vertComputed, 0, sizeof(vertComputed)); + memset(bVertexComputed, 0, sizeof(bVertexComputed)); + + + //For each Cube's faces + for (i = 0; i < 6; i++) // 6 faces + { + if ((byVFMask & (1 << i)) != 0) //If face is visible + { + for (j = 0; j < 4; j++) // 4 corners + { + int nNumVertex = fv[i][j]; //Face,Corner + if (bVertexComputed[nNumVertex] == 0) //if never calc + { + bVertexComputed[nNumVertex] = 1; + vertComputed[nNumVertex] = Vox_GetVertexPosition(x, y, z, nNumVertex); + } + } + } + } + + //Add face + for (i = 0; i < 6; i++)// 6 faces + { + if ((byVFMask & (1 << i)) == 0) + continue; //Face invisible + + int v0 = fv[i][0]; //Face, Corner + int v1 = fv[i][1]; //Face, Corner + int v2 = fv[i][2]; //Face, Corner + int v3 = fv[i][3]; //Face, Corner + + //Arrays + int idx = pvoxArray->vertices.used; + insertArrayVector3(&pvoxArray->vertices, vertComputed[v0]); + insertArrayVector3(&pvoxArray->vertices, vertComputed[v1]); + insertArrayVector3(&pvoxArray->vertices, vertComputed[v2]); + insertArrayVector3(&pvoxArray->vertices, vertComputed[v3]); + + Color col = pvoxArray->palette[matID]; + + insertArrayColor(&pvoxArray->colors, col); + insertArrayColor(&pvoxArray->colors, col); + insertArrayColor(&pvoxArray->colors, col); + insertArrayColor(&pvoxArray->colors, col); + + + //v0 - v1 - v2, v0 - v2 - v3 + insertArrayUShort(&pvoxArray->indices, idx + 0); + insertArrayUShort(&pvoxArray->indices, idx + 2); + insertArrayUShort(&pvoxArray->indices, idx + 1); + + insertArrayUShort(&pvoxArray->indices, idx + 0); + insertArrayUShort(&pvoxArray->indices, idx + 3); + insertArrayUShort(&pvoxArray->indices, idx + 2); + + + + } + +} + +// MagicaVoxel *.vox file format Loader +int Vox_LoadFileName(const char* pszfileName, VoxArray3D* voxarray) +{ + + ////////////////////////////////////////////////// + //Read VOX file + //4 bytes: magic number ('V' 'O' 'X' 'space' ) + //4 bytes: version number (current version is 150 ) + + unsigned long signature; + + unsigned long readed = 0; + unsigned char* fileData; + fileData = LoadFileData(pszfileName, &readed); + if (fileData == 0) + { + return VOX_ERROR_FILE_NOT_FOUND; + } + + unsigned char* fileDataPtr = fileData; + unsigned char* endfileDataPtr = fileData + readed; + + signature = *((unsigned long*)fileDataPtr); + fileDataPtr += sizeof(unsigned long); + + if (signature != 0x20584F56) //56 4F 58 20 + { + //TraceLog(LOG_ERROR, "Not an MagicaVoxel File format"); + return VOX_ERROR_INVALID_FORMAT; + } + + unsigned long version; + + version = *((unsigned long*)fileDataPtr); + fileDataPtr += sizeof(unsigned long); + + if (version < 150) + { + //TraceLog(LOG_ERROR, "MagicaVoxel version too old"); + return VOX_ERROR_FILE_VERSION_TOO_OLD; + } + + + // header + //4 bytes: chunk id + //4 bytes: size of chunk contents (n) + //4 bytes: total size of children chunks(m) + + //// chunk content + //n bytes: chunk contents + + //// children chunks : m bytes + //{ child chunk 0 } + //{ child chunk 1 } + unsigned long sizeX, sizeY, sizeZ; + sizeX = sizeY = sizeZ = 0; + unsigned long numVoxels = 0; + int offsetX, offsetY, offsetZ; + offsetX = offsetY = offsetZ = 0; + + while (fileDataPtr < endfileDataPtr) + { + char szChunkName[5]; + memcpy(szChunkName, fileDataPtr, 4); + szChunkName[4] = 0; + fileDataPtr += 4; + + unsigned long chunkSize = *((unsigned long*)fileDataPtr); + fileDataPtr += sizeof(unsigned long); + + unsigned long chunkTotalChildSize = *((unsigned long*)fileDataPtr); + fileDataPtr += sizeof(unsigned long); + + + if (strcmp(szChunkName, "SIZE") == 0) + { + //(4 bytes x 3 : x, y, z ) + sizeX = *((unsigned long*)fileDataPtr); + fileDataPtr += sizeof(unsigned long); + + sizeY = *((unsigned long*)fileDataPtr); + fileDataPtr += sizeof(unsigned long); + + sizeZ = *((unsigned long*)fileDataPtr); + fileDataPtr += sizeof(unsigned long); + + //Alloc vox array + Vox_AllocArray(voxarray, sizeX, sizeY, sizeZ); + } + else if (strcmp(szChunkName, "XYZI") == 0) + { + unsigned char vx, vy, vz, vi; + + //(numVoxels : 4 bytes ) + //(each voxel: 1 byte x 4 : x, y, z, colorIndex ) x numVoxels + numVoxels = *((unsigned long*)fileDataPtr); + fileDataPtr += sizeof(unsigned long); + + while (numVoxels > 0) + { + vx = *((unsigned char*)fileDataPtr++); + vy = *((unsigned char*)fileDataPtr++); + vz = *((unsigned char*)fileDataPtr++); + vi = *((unsigned char*)fileDataPtr++); + + Vox_SetVoxel(voxarray, vx, vy, vz, vi); + + numVoxels--; + } + } + else if (strcmp(szChunkName, "RGBA") == 0) + { + Color col; + + //(each pixel: 1 byte x 4 : r, g, b, a ) x 256 + for (int i = 0; i < 256 - 1; i++) + { + col.r = *((unsigned char*)fileDataPtr++); + col.g = *((unsigned char*)fileDataPtr++); + col.b = *((unsigned char*)fileDataPtr++); + col.a = *((unsigned char*)fileDataPtr++); + + voxarray->palette[i + 1] = col; + } + + } + else + { + fileDataPtr += chunkSize; + } + } + + //TraceLog(LOG_INFO, TextFormat("Vox Size : %dx%dx%d", sizeX, sizeY, sizeZ)); + + //TraceLog(LOG_INFO, TextFormat("Vox Chunks Count : %d/%d", pvoxArray->chunksAllocated, pvoxArray->chunksTotal)); + + + ////////////////////////////////////////////////////////// + // Building Mesh + // TODO compute globals indices array + + //TraceLog(LOG_INFO, TextFormat("Building VOX Mesh : %s", pszfileName)); + + // Init Arrays + initArrayVector3(&voxarray->vertices, 3 * 1024); + initArrayUShort(&voxarray->indices, 3 * 1024); + initArrayColor(&voxarray->colors, 3 * 1024); + + // Create vertices and indices buffers + int x, y, z; + + for (x = 0; x <= voxarray->sizeX; x++) + { + for (z = 0; z <= voxarray->sizeZ; z++) + { + for (y = 0; y <= voxarray->sizeY; y++) + { + unsigned char matID = Vox_GetVoxel(voxarray, x, y, z); + if (matID != 0) + Vox_Build_Voxel(voxarray, x, y, z, matID); + } + } + } + + + + return VOX_SUCCESS; +} + +void Vox_FreeArrays(VoxArray3D* voxarray) +{ + //Free chunks + if (voxarray->m_arrayChunks != 0) + { + for (int i = 0; i < voxarray->chunksTotal; i++) + { + CubeChunk3D* chunk = &voxarray->m_arrayChunks[i]; + if (chunk->m_array != 0) + { + chunk->arraySize = 0; + MemFree(chunk->m_array); + } + } + + MemFree(voxarray->m_arrayChunks); + voxarray->m_arrayChunks = 0; + voxarray->arrayChunksSize = 0; + + voxarray->chunksSizeX = voxarray->chunksSizeY = voxarray->chunksSizeZ = 0; + voxarray->chunksTotal = 0; + voxarray->chunksAllocated = 0; + voxarray->ChunkFlattenOffset = 0; + voxarray->sizeX = voxarray->sizeY = voxarray->sizeZ = 0; + } + + //Free arrays + freeArrayVector3(&voxarray->vertices); + freeArrayUShort(&voxarray->indices); + freeArrayColor(&voxarray->colors); +} + +#endif //VOX_LOADER_IMPLEMENTATION diff --git a/src/models.c b/src/models.c index b233cf2af..168ac2c31 100644 --- a/src/models.c +++ b/src/models.c @@ -8,6 +8,8 @@ * #define SUPPORT_FILEFORMAT_MTL * #define SUPPORT_FILEFORMAT_IQM * #define SUPPORT_FILEFORMAT_GLTF +* #define SUPPORT_FILEFORMAT_VOX +* * Selected desired fileformats to be supported for model data loading. * * #define SUPPORT_MESH_GENERATION @@ -71,6 +73,11 @@ #include "external/stb_image.h" // glTF texture images loading #endif +#if defined(SUPPORT_FILEFORMAT_VOX) + #define VOX_LOADER_IMPLEMENTATION + #include "external/vox_loader.h" // vox file format loading +#endif + #if defined(SUPPORT_MESH_GENERATION) #define PAR_MALLOC(T, N) ((T*)RL_MALLOC(N*sizeof(T))) #define PAR_CALLOC(T, N) ((T*)RL_CALLOC(N*sizeof(T), 1)) @@ -131,6 +138,9 @@ static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount); static bool ReadGLTFValue(cgltf_accessor *acc, unsigned int index, void *variable); static void *ReadGLTFValuesAs(cgltf_accessor *acc, cgltf_component_type type, bool adjustOnDownCasting); #endif +#if defined(SUPPORT_FILEFORMAT_VOX) +static Model LoadVOX(const char* filename); //Load VOX mesh data +#endif //---------------------------------------------------------------------------------- // Module Functions Definition @@ -718,6 +728,9 @@ Model LoadModel(const char *fileName) #if defined(SUPPORT_FILEFORMAT_GLTF) if (IsFileExtension(fileName, ".gltf;.glb")) model = LoadGLTF(fileName); #endif +#if defined(SUPPORT_FILEFORMAT_VOX) + if (IsFileExtension(fileName, ".vox")) model = LoadVOX(fileName); +#endif // Make sure model transform is set to identity matrix! model.transform = MatrixIdentity(); @@ -5469,3 +5482,100 @@ static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount) } #endif + +#if defined(SUPPORT_FILEFORMAT_VOX) +// Load OBJ mesh data +static Model LoadVOX(const char* fileName) +{ + Model model = { 0 }; + int nbvertices = 0; + int meshescount = 0; + + ////////////////////////////////// + // Load MagicaVoxel fileformat + + VoxArray3D voxarray; + int ret = Vox_LoadFileName(fileName, &voxarray); + + if (ret != VOX_SUCCESS) + { + TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX data", fileName); + return model; + } + else + { + // Compute meshes count + nbvertices = voxarray.vertices.used; + meshescount = 1 + (nbvertices / 65536); + + TRACELOG(LOG_INFO, "MODEL: [%s] VOX data loaded successfully : %i vertices/%i meshes", fileName, nbvertices, meshescount); + } + + ////////////////////////////////// + // Build model + + // Build Models from meshes + model.transform = MatrixIdentity(); + + model.meshCount = meshescount; + model.meshes = (Mesh*)MemAlloc(model.meshCount * sizeof(Mesh)); + + model.meshMaterial = (int*)MemAlloc(model.meshCount * sizeof(int)); + + model.materialCount = 1; + model.materials = (Material*)MemAlloc(model.materialCount * sizeof(Material)); + model.materials[0] = LoadMaterialDefault(); + + + // Init model's meshes + int verticesRemain = voxarray.vertices.used; + int verticesMax = 65532; //5461 voxels x 12 vertices per voxel -> 65532 (must be inf 65536) + + Vector3* pvertices = voxarray.vertices.array; //6*4=12 vertices per voxel + Color* pcolors = voxarray.colors.array; + unsigned short* pindices = voxarray.indices.array; //5461 * 6 * 6 -> 196596 indices max per mesh + + int size; + + for (int idxMesh = 0; idxMesh < meshescount; idxMesh++) + { + Mesh* pmesh = &model.meshes[idxMesh]; + memset(pmesh, 0, sizeof(Mesh)); + + // Copy Vertices + pmesh->vertexCount = (int)fmin(verticesMax, verticesRemain); + + size = pmesh->vertexCount * sizeof(float) * 3; + pmesh->vertices = MemAlloc(size); + memcpy(pmesh->vertices, pvertices, size); + + //Copy Indices TODO compute globals indices array + size = voxarray.indices.used * sizeof(unsigned short); + pmesh->indices = MemAlloc(size); + memcpy(pmesh->indices, pindices, size); + + pmesh->triangleCount = (pmesh->vertexCount / 4) * 2; + + // Copy Colors + size = pmesh->vertexCount * sizeof(Color); + pmesh->colors = MemAlloc(size); + memcpy(pmesh->colors, pcolors, size); + + // First material index + model.meshMaterial[idxMesh] = 0; + + // Build GPU mesh + UploadMesh(pmesh, false); + + //Next + verticesRemain -= verticesMax; + pvertices += verticesMax; + pcolors += verticesMax; + } + + //Free arrays + Vox_FreeArrays(&voxarray); + + return model; +} +#endif \ No newline at end of file