From 5183dccab4ee003cea61aa1d756d16d0e8cd2a72 Mon Sep 17 00:00:00 2001 From: blobt Date: Thu, 11 Jun 2020 15:57:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAshader=E7=BC=96=E8=AF=91=E5=92=8C?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E6=B7=BB=E5=8A=A0=E9=94=99=E8=AF=AF=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vs/shader2/v14/.suo | Bin 35328 -> 36864 bytes main.cpp | 68 ---------------------------------------- misc.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++ misc.h | 4 ++- model.cpp | 2 +- shader2.VC.db | Bin 38440960 -> 38445056 bytes 6 files changed, 77 insertions(+), 70 deletions(-) diff --git a/.vs/shader2/v14/.suo b/.vs/shader2/v14/.suo index ae4de5622f49fd2c2b9b55803b5686ceb213bc3f..d9907acbc18f641a759232670b6caa0f62e04918 100644 GIT binary patch delta 3073 zcmdT`ZA@F|6~6DqCX8GNCXfUO#C*mu8VHbvI3e-1@8z4=1_J@w5XS*bFxaVWz=RHm zHZ)&S%RQO2AKS80O`FuJZMd2CBm2SD^h>Rl{iv!fOI1zkk5-fRNh)nqo1J6(5<)Yr z)qd^0dhYvm&ikJGob#UdMz8YGAMr07V!G=MRebsj*ZO|*=8+GXk>j`(6U^{4>^R)x zkHQ=LUi}^%+zXMUvuTakGA7{*OA0XE*12?SZ9{BFBqQ!)`4S;uyBomk>#G>;Ph4-bue*B3wax8IjP9QmUfr!x~$Us<3FL}V! z+w)l2yHJU;6n@$w zu)5Qg@=z?kh_iDLF_g1vDCG0OQd_tA2^* z{inD3D!K+mS;@=&8B++Yy5qWQmL>d}rTJB2MQk z@!dpw8lzs-x=}S`y~32twdjCQChD3{LQ5#5tFC4WOewIXal3J*e4Rdo3ha9J7>+!! zqTqHc>ys14)PGd9F@X{nCY1-ag!W!hN^S|1v?)+D8`aek+NU|?>utgM;oh#>|AB+r zD-VB`LwMv@Eoa$-1agUXm&C*8U{p_cn+TCZ?+L}&qH9C*9E4=lt*%s8Wr1I6 z)hQ*Ckc;zl-6Uj8uu`Fe*^=h3xE)r@Fl0&_ps?*(_1V^0wtS57kktIN`klskw(PjE z32qFwFS&SSIKU>=GsDlb<(?ai{SEdNHgNI3mV+3t z$8N`x8@zq;07RoEFpTeDo8gxi=2E9{O*^cv%(4eBY$Y-Ok}zz5b%mYdHu{~zq;~H)1N5I2Qt4)-zdz{$`A+ksK82`7#JMJKT#5_F-Y?_3 z8bMcKJpMRNWf#H>vd&!s|IEMibjBo%)2nLI{1+^?qk*!%R_L7S)ywD4^11OFIX`a?jyNfxF2gAhy2n_2~U(r>zRKbJg;tDv17U%FT)}3&9JFODlH+SZ>>lWPm8cdO;|X8BtM+lZ*C+GMQ~f z+K1_8+=B99OWfwtbnJiX`)cFN=DsaE&5!4K z&Uwyr&Uwy-SDaLf6YB9YroU94r;f3FP*qt`ag(L1P%^1s-Or}zUSz$H4OgH z=@3HxCi8PF-8BT?Vc-TM;7xE0jDoiSpQC~g_6aZsPJ(gZ2LV9f9q=~b{-`BnTL8aTf*8v}~8*;C#E4#U0whura1UhY%_}-}xR*1#-k@5InxydB zVD@#I&9G`GP`QWhuehp7g+^_?@pRU>l!7Z81bz+qOY(R;XJJEV5~i@qXnyHF zNnejKcHYYZmN|hxS$d#!mVy?6QKM%Gb=x)4vXmd#5@f#{zY+JDpR$KPZ}E-S{oK^u zW~cAHtFQp+*1n5uaaB&!rnMIQ2J%aa9qrbV^FB3+DNmvpr(z3=r@x3yy!GAPD_gRf zTFGd+9GZIg=oCyr68KZd-vwn(9hR zsO8r#_C*>t7=F~X|*HLNX=lx^v26t_6dFV+J@;m zhIYG&MDKdqwqvvOn>~urOskEi>r9eq(~l8Tww)3BSOkqnT#bqvM!a;r%fm*Axwp_o zN1m*;mgU7@!Hh4Om)$nF`tU#$2JGFeQ#xQj844VV*ZCyg{4ozb=WY2tmUN&Y%zIuVJyW0{>zMXufB{gUE&obbOy+@B8XsLm*ZK9|I9`C0TvesFv&e zHBqU$>5eCnL|-~hHf#JA&7--}sS_sZKaob;MF-Q-(C#K08LOjjhAQY|lb*gh9!Up1 h8>jqkHI^u~4X$Ohx$gp>zI1wYhDniPH>094&!7INcmn_c diff --git a/main.cpp b/main.cpp index 5a8843f..f0c9aed 100644 --- a/main.cpp +++ b/main.cpp @@ -22,75 +22,7 @@ LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) return DefWindowProc(hwnd, msg, wParam, lParam);//其他消息调用window默认处理函数 } -/** -* 创建一个GPU程序 -*/ -GLuint CreateGPUProgram(const char* vsShaderPath, const char* fsShaderPath) { - - //创建shader - GLuint vsShader = glCreateShader(GL_VERTEX_SHADER); - GLuint fsShader = glCreateShader(GL_FRAGMENT_SHADER); - - //读取shader代码 - const char* vsCode = LoadFileContent(vsShaderPath); - const char* fsCode = LoadFileContent(fsShaderPath); - - //把shader代码 从内存传到显存 - glShaderSource(vsShader, 1, &vsCode, nullptr); - glShaderSource(fsShader, 1, &fsCode, nullptr); - - //编译shader - glCompileShader(vsShader); - GLint compileResult = GL_TRUE; - glGetShaderiv(vsShader, GL_COMPILE_STATUS, &compileResult); - if (compileResult == GL_FALSE) { - char szLog[1024] = { 0 }; - GLsizei logLen = 0;//实际错误日志长度 - glGetShaderInfoLog(vsShader, 1024, &logLen, szLog); - printf("Compile shader fail error log is : %s \n shader code :\n %s \n ", szLog, vsCode); - glDeleteShader(vsShader); - } - - glCompileShader(fsShader); - compileResult = GL_TRUE; - glGetShaderiv(fsShader, GL_COMPILE_STATUS, &compileResult); - if (compileResult == GL_FALSE) { - char szLog[1024] = { 0 }; - GLsizei logLen = 0;//实际错误日志长度 - glGetShaderInfoLog(fsShader, 1024, &logLen, szLog); - printf("Compile shader fail error log is : %s \n shader code :\n %s \n ", szLog, fsCode); - glDeleteShader(fsShader); - } - //创建program - GLuint program = glCreateProgram(); - - //绑定shader - glAttachShader(program, vsShader); - glAttachShader(program, fsShader); - - //连接 - glLinkProgram(program); - - GLint nResult; - glGetProgramiv(program, GL_LINK_STATUS, &nResult); - if (nResult == GL_FALSE) { - char log[1024] = { 0 }; - GLsizei writed = 0; - glGetProgramInfoLog(program, 1024, &writed, log); - printf("Create CPU program fail error %s\n", log); - glDeleteProgram(program); - program = 0; - } - //解绑shader - glDetachShader(program, vsShader); - glDetachShader(program, fsShader); - //删除shader - glDeleteShader(vsShader); - glDeleteShader(fsShader); - - return program; -} /** * @hinstance 本应用程序启动实例 * @hPrevInstance 上一次应用程式的实例 diff --git a/misc.cpp b/misc.cpp index 62ace13..6b03036 100644 --- a/misc.cpp +++ b/misc.cpp @@ -36,3 +36,76 @@ char* LoadFileContent(const char *path) { fclose(pFile); return nullptr; } + +GLuint CompileShader(GLenum shaderType, const char * shaderPath) +{ + //创建shader + GLuint shader = glCreateShader(shaderType); + if (shader == 0) { + printf("glCreateShader false\n"); + return 0; + } + //读取shader代码 + const char* shaderCode = LoadFileContent(shaderPath); + if (shaderCode == nullptr) { + printf("load shader code from file: %s false\n", shaderPath); + return 0; + } + //把shader代码 从内存传到显存 + glShaderSource(shader, 1, &shaderCode, nullptr); + glCompileShader(shader); + + GLint compileResult = GL_TRUE; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult); + if (compileResult == GL_FALSE) { + char szLog[1024] = { 0 }; + GLsizei logLen = 0;//实际错误日志长度 + glGetShaderInfoLog(shader, 1024, &logLen, szLog); + printf("Compile shader fail error log is : %s \n shader code :\n %s \n ", szLog, shaderCode); + glDeleteShader(shader); + return 0; + } + + return shader; +} + +/** +* 创建一个GPU程序 +*/ +GLuint CreateGPUProgram(const char* vsShaderPath, const char* fsShaderPath) { + + GLuint vsShader = CompileShader(GL_VERTEX_SHADER,vsShaderPath); + GLuint fsShader = CompileShader(GL_FRAGMENT_SHADER,fsShaderPath); + + //创建program + GLuint program = glCreateProgram(); + + //绑定shader + glAttachShader(program, vsShader); + glAttachShader(program, fsShader); + + //连接 + glLinkProgram(program); + + //解绑shader + glDetachShader(program, vsShader); + glDetachShader(program, fsShader); + + //删除shader + glDeleteShader(vsShader); + glDeleteShader(fsShader); + + //检查错误 + GLint nResult; + glGetProgramiv(program, GL_LINK_STATUS, &nResult); + if (nResult == GL_FALSE) { + char log[1024] = { 0 }; + GLsizei writed = 0; + glGetProgramInfoLog(program, 1024, &writed, log); + printf("Create CPU program fail error %s\n", log); + glDeleteProgram(program); + program = 0; + } + + return program; +} \ No newline at end of file diff --git a/misc.h b/misc.h index 513e345..1c0bf57 100644 --- a/misc.h +++ b/misc.h @@ -2,4 +2,6 @@ #include "glew.h" GLuint CreateBufferObject(GLenum bufferType, GLsizeiptr size, GLenum usage, void* data = nullptr); -char* LoadFileContent(const char *path); \ No newline at end of file +char* LoadFileContent(const char *path); +GLuint CompileShader(GLenum shaderType, const char* shaderPath); +GLuint CreateGPUProgram(const char* vsShaderPath, const char* fsShaderPath); \ No newline at end of file diff --git a/model.cpp b/model.cpp index fc6f32a..f333716 100644 --- a/model.cpp +++ b/model.cpp @@ -33,7 +33,7 @@ VertexData * LoadObjModel(const char * filePath, unsigned int ** indexes, int & while (!ssObjFile.eof()) { memset(szOneLine, 0, 256); ssObjFile.getline(szOneLine, 256); - printf("%s \n", szOneLine); + //printf("%s \n", szOneLine); if (strlen(szOneLine) > 0) { std::stringstream ssOneLine(szOneLine); if (szOneLine[0] == 'v') { diff --git a/shader2.VC.db b/shader2.VC.db index 4617c986cceaa900a46b19da4159136320245f83..b61ba147e630502859baa1330ce8ac7c8da1499c 100644 GIT binary patch delta 7973 zcmZvh34GL49>?E%$xM=&9s@n0w4~5N%h__@9ZDIXrC1PAIoj#P4TVxzTwFUK2uN`X zi18#vckzG~5M{)JfES0yR#Zep7P0H1AVOUi1cCkiXIjDCO+Vjn{(0}^<>lq&Ws>^p zUTEpt_d?6s1lvi*QeIf6XYrFez1Ne(>ckD+wlN8-+e+zir4?o6MKh|(=PW2HomOMy>qQmjo*d45B$mFFE&;JibQUXk()Ut-(Jl<$<&%9qNg%7>~=4O6Zw zmm+^ro>Vp}?NdVTZo8{>?ftCQOp^|uYlSo!|2 zAs`F5!BCJ5hJhR~9C*M8FcORcxgZaW2KitNxD6D5v0xmy9gGKefC=DEa2L26Oazm_ zWH1F3f+FAr#h?U~f-+DJrh;i;I+y`wf>~fTm;>g53NR1M2bEv}r~(VYBJc;W7~BK? z2$q0*!Joi=pc?qVQm_o%50(esAGTshBJUh<6t9R=WA0?mvXa?F{G)1z6eE=tR~1X= z6f@yuwn&z7rzD$hgo!H`&sYH-04u>Nuo^rF)&v&MsHvGCZQ?bCvae>3zyT;Cb)@*b26Rzk(ORcCZ8N1TTSI z;N`$;`(Mf3BzF)`2qVKar^>k3yL+S@aXI3Lz&qaEH9RoBWcO*O`dVqloOwLun7OWp zjsG>CJE$iqO=>K?8G4QM@6L=`Il5vu2!L0?9`G7?9lQbF1bcx6_JRH2E$}vY2fPd3 z0|&rCa0na*?}HD(hu|adH&72g21mdr;8XA!I0`-o$G{ihIQSBr0AGQV;P2oR_!^uB z-+%`25AZGcCpZJX1K)$Q;2ih?oCiOG3*aJX1V4d)fuF&@!6k4R`~t3ktKe5~4O|B| z){L&;en1i=i6nDtbcKz-a?0sk%zKLEOdcd>8W%1MnP^Teu=DAva#*n>RoP^Hip|Hk zSuxJepB9Z1t*G1We2wf3UJeXKsd0+``8(|#Qb;OEf4q zDNYWBk-|w4q)3vB)PmHK6h(?A#gJl2ain-sD^hDx0;vrtk(5MgOVUZnq;{nCq!dyr zsROAaDUFm)>O|^H>O$&D>PG5L${=NudT=X$N>3gTypv_~_T+20hX(VYBDVLN-8qKYZbMtw{X5P=VxyJB2OfTHQ^1;U? z*)H>ZvoLxLU#Qp$*~mCaGwb{1@M!;eq(Qfl3P@u~<4CuY#*^+KO(5M#x{Gu-X(DM7 zX)4C8SbP8L6B!l{Aesom=OlXYklB<=3T;Sio0nOXt$t&cko&Uj7em zwEZSxs!?5<7Gpj9(+r-X@(63s)fqgmLFyn+Hj3ZMNDpMVZBA|t-Pu_raC5@bv-mXY z&C@gaY#UEAJDr)yThrX{utp+$!{FCUn{O7+3%Kf94&$b=bQWJAi;ZHVapGd@Hdcpa zv-mkKN7nNlR_yXw{4R>wc&l>7EWW7K+CqAk^c?AV(hJ-=x^*k>RwaKYJhG8-QFJr= z=-c?m(nH#2Q%&B+>&-Upw(%tEGUCySti8-~&5`NbxTk+hDHXTp?U>lgD+`LNaGOs4 z-=re#5{vq;Qsx2dpCO0;i$(dbB82`*dXco9w1Zn$(|2-hi&U)kHoM$Orv`?6G(SoWTVohtBmKO!5~hL4W;l|?P8TrjXv6P!<_d7+ns=2jE z+Bj{LQJ;Ih4yHt&5AE(n zpi$u|%~=!u)rXt{3L}M+B1n-W7pVoQB`Jy&O^PAKlHy45q*kQXqy$nMQX(lySk;Hx ziWQGYM})&tyt)|3RnbK_#9)zNW*6&XUye&k4*rU3p6tqRCXBylUb)m*b~7O~9hTfo z2$d-Ik15dwlq{?y23^md~TOi3B4@GvhkSpLMz(J4{doud0C;Yexa?*&{n6=R(otU)e>4! zEfJwS<+nUkB~hRi9q?s)cEaO+$`xQ#{l2bZ-MPzouP)PdBIltxM? zbs}{pbs=>nbt82rWsovSJxD!Cy-2-DeMo&t{Yd?VHMnemcvgxpUNOTVnqTn6CA{Ll zy}0Q4*{ZR>=b=O+qt_wXJT!BF=xmLgK0x&0O4i#kD=+o58}n1+6U@391H@DItal&p zl=_*G*u`OxxS=V7 zq~T>e@pEg(wp>0~3ciLkziP+h{W>N1s_my&ZD<%NM_BHY!^Jy8xv*@yM;x>Xd$RSn zRFCNGkjKg$nNjDp=a{22JmO@U{Ghy4UM%;QGvtoiDy>>uq|MRFv`G;yB2>9To+?j~ z$IE$gwlyHrBko2Qw9tkb=PQ*k>q-xg=)tQm;Y~)Bgd`A@H3y}^;4=E6IVf%pyv;#T zb5PhEObG_4XL55esX3S!41Si*KHVH_4h7cMULNsMtfCj{cLKBM^l;Hn(F^pEz}$o_ zx1wk1J%Raso<|H)^bUFwFuRWSh)hLi&xPqNb<_LJaPh?6e2?Hg73T@wNqUbN-p0fv zvxCngy11nJu)?tMVYv~F5xXO{g}Dvyj<#d09mvxq2fouu(mA_y_PTZaevc5U9Puq8#V-kMW`YanDi=N#r1q)cdsCs!KndX6JX3PuQ6bg;S`h#dYT zzehkLNF#-nb!G;6epk+Bg?iDiq;!N@*yXjcXN(W=W03p=c&<^-weeuU(-C&-B7jGz}9# zD4L2Z7K$+QO$tSL!JQb2N~OlTHOYG5{3vl>vAkXRfLR4Q#_*QhY&|wt42o2BHCk1b zUzH0=gK|s>jBR{<9uIz3y(D{`vcz#q&2gadx5Q;l@l2$b+!7Zz#nX^pbW2>=6qg}= z@-6WstIJ)v;+P`0v%eylsyA13iPO4hZ)o$?aP=v5obtZ=IrfmamYhzd zX$kJYu}1~nJaZfi%MVk#NSY6CQIE#e0Ag8rgFib+4LA0F}i&2 z!Z|vRP3w@B2%2^%4YjQ!we9ASsBLq^rC9O1U&|v#FPt&AO6MZYqozft(Z?sWwdDV_ zHG(l}>}-Midgjf>+K1SCgXYG1&7Efs@VJpEBQD4O|3lf`cGVtjr(+HEH%tk(R->K_ zEx~@F)=onW=D?USyj7$!T2Ylag}QQtzoE!1_Q#7jRcf3;t(j(4qfi@{lB;9^K_3b{ z{)WO}shBVgRZS0;b1X8KQguSRyjtfuq(-%hr7uqOiQWHkHM z0r2}y{%rt68gXZ;hTBoGhCfotK-J1)3W@>6S*92g@}#+SMvABQF(Dqx<_C z?l#7j+v2TuGjqjhn-oxw2Vc+)yr6eAs^|4RZD!5S6&)iqU5nMiG@)Kr&#MiV_v<#I zlL!vvLAHX>EsANNX=*^!G&RipZ9+iQG$G)YZ<+=WHBAG!(VK35M3bye_vDJ>cBd@t zOih(r2)o_j7vow5GJJba^480h^@TQ}tqK#DLl?Q(+2+pJg*?v4h)z_D&Np7xj2$<^ zqK)ZCheVi3o0sq;vldgHW_r^+BFqTum*gMI6VlNiZO~6{vp%} z6Rx>tZJcOnTtM+hDtBr|eRZ-!l9@1YJ~4*7o28nmojsy6=jK?flO;FP4SwIwXybyr zgWcFsxicccrL&fd`Ka>d#f3m;y2Hq<+1{F(Y&Snl_lQW-N?OZp)yr+`^KBYVlChrL z?xL@HY`Klew=uWGbd}j<=BA0CVctWdeXI*@)RNG0)h)6q@G%y@ipe+~mAP0l&Po>C z$J~@x=kQ@o&A|Rlmt8s8EC*qj%$duqU7jo2;+wpW>JZc?ZeJJFBbe@5st0R!!x;BI zy`AvcgIO+@{+?PVhjF%?Gas*W`Lt}^#j;&2gYgWz+bzzukyKH(L zKP8eK-Ed-hsvOQlftubzezZj@j)|60FL9k^uV?1o6}gy18M~k9K4czbEE@-36YL`w z3saeI6DW4RtpuU)h?V13@o$+3uiXRa%DrW&@jFfOp}{4vmI0bo2WTh zmIfrQKpl4n*Df|3YjiLj0}Dn1twM{>O$oFFtDu0IuTv_7B~3?p6mgry7~ZkwY}^gb zYRU`kM`f@`p%vMU0f7_Z%c0OF<0uOV@$c2FUGY@W%5X$&hSd+=3K%) z)3G&>R<<%Uclj`Rx#yIN1sbNtC zLojfy#k0yM7tOBd z-`_qsA+RQ=zAhptv?lw%_s=SI^&enQu z-d{=drf{oJ2RP1EP3#m`;6u+6A$Gr-$s@IZ%h(Q=*9Tl~;RXaXYvQa};C zr}`&$ma1DVg16No1}y5`3NK6BnEa!BNj@i^l8-8q;v?Ue-;_U>4f(eJ@A9kiNAeDN ztGvPgrnF6avqf}!x7LZ1xaR)!aHu!7UYsi?{Am)*f{=HkeQ^~YE?E2G=LZiL_uChF zZ4Vc%)kifElQ0t|V+v-*ESMGZ!F(}4%pbF19k2i_5DUVBu@I~y7K%NBb;821&fcS1 zc)vlS-wYUGNUaL5=UQ%^Pk?vpiSP=GUa)flEU#|(CLHU6MPMoxiFL)IuxKm>i^aNO z-LW_<9_xYi#Cl=9u|Aj`>x(5|iC90ZKQ;gxhz-I9V@cQ$Y^b;4o8+epVTRY@NLkL| zw6;1ev9R)S5(W?(b1S=el>6q|!RgOy?BSOqp0dlvf(HV=CadmeiMdl7pH zdl{?5+}M0<0k#mU@_sRVQA#-Ec`XHtIx4}1EW}kfb21#O#1De!;rOy1b|H;NiWVVQ z&>c92SI;Y1ge}IZu^Q|ZYzem1JFld+cD(QwY|!MU+TGfLrrIN#yCw7yt#*HHFweVD z{qg=~-u7>`m+~Yz?MkYq53MdTaysHues- z5!-}q#f`T zEr_#tro%g~aMvZP(o$49YYs%8(N`o$@NOtrzNK^2zR~i{|BqVSk5@9QvrBhjUhE@m zH}*013AP8@i|xY?ZaLb_@Fz`whE|-NAmx?qc__Kd?Ws``Ck}*`?sY2u=uu2u60P1Rq|s%4;Bj zS21y@*jH<9O_`ui$u+?=lc2~)WWzX(E2{xg_1R-gumP_&BXFzg%ju0z2bvf4xpPBsD`Mu`1RBLtr5@Gy~TS`ICA7h1<5V4Mh zlus?L;P+?ZXni=&Fq~tpkOka#ps{kC72Z)o@BMiJRyygEAvO4q>z=)8K70>a#CLvEjQPKmz(56LWB0uh z771Y6d(3qE!^YC|fiGR(29%|KsKE zfpp$_!rH9c@pYCNd)Lo^Yl>+7fpyW}+cpED+h5Rg8b@R%F^iZ@;Mc+FZF7ich%%y_ zs37JN&k}zj<`K^k&l4{YFA^^iFB6r7o0v~5AQlo;#3EubQBBkkuMkU!r9>^Uj95;1 zh&o~gv684K{z|+`yhdomDq=P9I`IbaCh-=rhR}(%#5!UsHv z{Sc0JF+hkBJoj)!-X-26wiAtD+>6@*=8eK+r9hWkcEAh9VsxiWf8BfPO@|y@^c0`j z0m%ErPT~XNLt+=gp>Z;^xT%7JV@(pAD6Drv5n+O#+1Hi!583`QI>EP9J1)Yi$&^% z$8JNER6b3}YxP_hd=`*%U|bk{9%84!VO?5#9#+C1#_PD`z^fCDH`kqqZoYx|eg{8W zRz9ulnaQ&!m-ijOtE=?y=iP%Ie&u7Q6}XDaatkWj59+`DJb3)Ke?wd#{y|(Mz9lXZ z-w~II?};CXe-c-SABmrcpNXr)HR3vPgJ>n%h?~SO#4X}i;y2;bD|{T^G|^Le*vb(f!k6$P{0SS;fe0W1i6A1F z2q8KWp~NFZCnAjKOoS6%xKVjHf-ibaIL1dCa=yxkfSy&L@+Qr0Pt5j=E>t-Z$&Jy4 zUHPs*#Rb9yrq$K;*~rDgdSiYR&;Ib@?hahvadQd;YqqjY0b1S3Xhk1d6vbVl=wK`L zgCo-Uax30?3BuJdT6mIOQ5=aTVu)Cx8_}JJBjSl3L{Fj@(VOT)*onSG0+C4cBl;5q zh=If)VlX$7T}gbC5Hi!kO#sT{5lRlfi$4Kvl`-Q7nYI0ihhy|<)023dkufca4**m0 z)Xgt0`9On`gwFcfk|h3?DJ3~#{e$Q9VK-ia&iZ70>~J}`q|e?ieN5UjF`;4YkCOCo ze0mShE!=I~nm&ZzoXQ!~ubdddOXNAl<-*BGe?9DA3Xk_JI5~tPL%FfwWHRr3!y9Q& zd*U7 z`s7O^_#oMp>&n3NHMr)GU8$}_O#f+=lMj_$v92zd-YeV5`^qkM)yEa!((}I?!Qa@I zK3>nlEm8WpF(df5%j=wc zdEH1XgYT=$S%^XKufi4+^sdX?H;H1zLd#F>-W)qMkCs6;UMbIU(4jn z^lko`{P8u`Ode%aUeDx<3dBuHPiEvcj)nlxJ3W@ghZ;N7<#5_$^n4a|T}0Q=iG= z-P(_LP&VS9%i?G8eTyBK5@YHlYWrW>q0+%F3n5j~%52GOuJK_k5llgV7bvTebl={1 zUW4m!1^tBkoBbD;CE zw+p%3#K6Is&8B{?G>AUHs^+r=ur}9iPE+kH%O=_x^j++5@MKYSm_pT^sv8*F$>#I; zXj=dQvXH9MexFd+w21t76K29E5xp16IWOb35%;7j}vC)6u z;yB&pWFmC(H_<7!Z@jVT$n&zPzoU6jSm8E$1E zQ{9Z&ni(r(YT8mpC&