From 886e25cd1493c598b1e8d61f3e2ace59542e287b Mon Sep 17 00:00:00 2001 From: Erik Onarheim Date: Fri, 6 Dec 2024 20:57:50 -0600 Subject: [PATCH] fix: GPU particles color and transform now match CPU version --- sandbox/tests/gpu-particles/index.ts | 52 ++++++++++++++++-- .../particle-renderer/particle-fragment.glsl | 6 +- .../particle-renderer/particle-renderer.ts | 12 ++-- src/engine/Particles/GpuParticleEmitter.ts | 9 ++- src/engine/Particles/GpuParticleRenderer.ts | 21 ++++--- .../GpuParticlesSpec/particles-wrapped.png | Bin 10310 -> 12624 bytes .../images/GpuParticlesSpec/particles.png | Bin 7533 -> 7698 bytes 7 files changed, 74 insertions(+), 26 deletions(-) diff --git a/sandbox/tests/gpu-particles/index.ts b/sandbox/tests/gpu-particles/index.ts index 7ea00e7b4..62f4bd48f 100644 --- a/sandbox/tests/gpu-particles/index.ts +++ b/sandbox/tests/gpu-particles/index.ts @@ -7,11 +7,12 @@ var game = new ex.Engine({ var swordImg = new ex.ImageSource('https://cdn.rawgit.com/excaliburjs/Excalibur/7dd48128/assets/sword.png'); var particles = new ex.GpuParticleEmitter({ - pos: ex.vec(500, 500), + pos: ex.vec(100, 0), z: 1, emitterType: ex.EmitterType.Circle, maxParticles: 1000, particle: { + // transform: ex.ParticleTransform.Local, minSpeed: 1, maxSpeed: 10, minAngle: 3.4, @@ -26,17 +27,56 @@ var particles = new ex.GpuParticleEmitter({ endColor: ex.Color.Transparent }, radius: 1, - emitRate: 1, + emitRate: 100, isEmitting: true }); -game.input.pointers.primary.on('move', (evt) => { - particles.pos.x = evt.worldPos.x; - particles.pos.y = evt.worldPos.y; +var cpuParticles = new ex.ParticleEmitter({ + pos: ex.vec(-100, 0), + z: 1, + emitterType: ex.EmitterType.Circle, + particle: { + minSpeed: 1, + maxSpeed: 10, + minAngle: 3.4, + maxAngle: 6, + opacity: 0.7, + life: 2000, + maxSize: 5, + minSize: 5, + startSize: 5, + endSize: 1, + beginColor: ex.Color.fromRGB(23, 106, 170, 0.1), + endColor: ex.Color.Transparent + }, + radius: 1, + emitRate: 100, + isEmitting: true }); particles.isEmitting = true; -game.add(particles); +// game.add(particles); + +var particleParent = new ex.Actor({ + pos: ex.vec(400, 400), + width: 10, + height: 10, + color: ex.Color.Red +}); +game.add(particleParent); + +game.input.pointers.primary.on('move', (evt) => { + particleParent.pos.x = evt.worldPos.x; + particleParent.pos.y = evt.worldPos.y; +}); + +game.input.pointers.primary.on('wheel', (ev) => { + game.currentScene.camera.zoom += ev.deltaY / 1000; + game.currentScene.camera.zoom = ex.clamp(game.currentScene.camera.zoom, 0.05, 100); +}); + +particleParent.addChild(particles); +particleParent.addChild(cpuParticles); game.add( new ex.Actor({ diff --git a/src/engine/Graphics/Context/particle-renderer/particle-fragment.glsl b/src/engine/Graphics/Context/particle-renderer/particle-fragment.glsl index 62bcca1fb..c672166e8 100644 --- a/src/engine/Graphics/Context/particle-renderer/particle-fragment.glsl +++ b/src/engine/Graphics/Context/particle-renderer/particle-fragment.glsl @@ -35,7 +35,9 @@ void main(){ float dist = 1.0 - length(uv); float edge = fwidth(dot(uv, uv)); float circle = smoothstep(-edge/2.0, edge/2.0, dist); - vec4 color = mix(beginColor, endColor, 1.0 - lifePct) * startOpacity; - fragColor = color * (fade ? lifePct : 1.0) * circle; + vec3 color = mix(beginColor.rgb, endColor.rgb, 1.0 - lifePct); + fragColor.rgb = color; + fragColor.a = startOpacity * circle * (fade ? lifePct : 1.0);// * mix(beginColor.a, endColor.a, 1.0 - lifePct); + fragColor.rgb *= fragColor.a; } } \ No newline at end of file diff --git a/src/engine/Graphics/Context/particle-renderer/particle-renderer.ts b/src/engine/Graphics/Context/particle-renderer/particle-renderer.ts index a74718882..101cf6de0 100644 --- a/src/engine/Graphics/Context/particle-renderer/particle-renderer.ts +++ b/src/engine/Graphics/Context/particle-renderer/particle-renderer.ts @@ -10,7 +10,6 @@ import { HTMLImageSource } from '../ExcaliburGraphicsContext'; import { ImageSourceAttributeConstants } from '../../ImageSource'; import { parseImageWrapping } from '../../Wrapping'; import { parseImageFiltering } from '../../Filtering'; -import { AffineMatrix } from '../../../Math/affine-matrix'; import { ParticleTransform } from '../../../Particles/Particles'; export class ParticleRenderer implements RendererPlugin { @@ -65,7 +64,10 @@ export class ParticleRenderer implements RendererPlugin { this._shader.use(); this._shader.setUniformMatrix('u_matrix', this._context.ortho); - const transform = renderer.particle.transform === ParticleTransform.Local ? this._context.getTransform() : AffineMatrix.identity(); + const transform = + renderer.particle.transform === ParticleTransform.Local + ? this._context.getTransform() + : this._context.getTransform().multiply(renderer.emitter.transform.get().inverse); this._shader.setUniformAffineMatrix('u_transform', transform); this._shader.setUniformBoolean('fade', renderer.particle.fade ? true : false); this._shader.setUniformBoolean('useTexture', renderer.particle.graphic ? true : false); @@ -108,12 +110,6 @@ export class ParticleRenderer implements RendererPlugin { // gl.bindTexture(gl.TEXTURE_2D, obstacleTex); // gl.uniform1i(u_obstacle, 1); - // Blending wont work because ex doesn't have a depth attachment - // gl.enable(gl.DEPTH_TEST); - // gl.enable(gl.BLEND); - // gl.blendEquation(gl.FUNC_ADD); - // gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - renderer.draw(gl); } hasPendingDraws(): boolean { diff --git a/src/engine/Particles/GpuParticleEmitter.ts b/src/engine/Particles/GpuParticleEmitter.ts index f37912813..1a1fa965a 100644 --- a/src/engine/Particles/GpuParticleEmitter.ts +++ b/src/engine/Particles/GpuParticleEmitter.ts @@ -1,7 +1,14 @@ -import { Actor, clamp, Engine, ExcaliburGraphicsContextWebGL, GraphicsComponent, ParticleRenderer, Random, vec, Vector } from '../'; +import { Engine } from '../Engine'; +import { Actor } from '../Actor'; import { EmitterType } from './EmitterType'; import { ParticleEmitterArgs, ParticleTransform } from './Particles'; import { GpuParticleConfig, GpuParticleRenderer } from './GpuParticleRenderer'; +import { GraphicsComponent } from '../Graphics/GraphicsComponent'; +import { Random } from '../Math/Random'; +import { vec, Vector } from '../Math/vector'; +import { clamp } from '../Math'; +import { ExcaliburGraphicsContextWebGL } from '../Graphics/Context/ExcaliburGraphicsContextWebGL'; +import { ParticleRenderer } from '../Graphics/Context/particle-renderer/particle-renderer'; export class GpuParticleEmitter extends Actor { public particle: GpuParticleConfig = { diff --git a/src/engine/Particles/GpuParticleRenderer.ts b/src/engine/Particles/GpuParticleRenderer.ts index dc3a47b58..cc7974ee0 100644 --- a/src/engine/Particles/GpuParticleRenderer.ts +++ b/src/engine/Particles/GpuParticleRenderer.ts @@ -1,4 +1,4 @@ -import { TwoPI } from '../Math/util'; +import { randomInRange, TwoPI } from '../Math/util'; import { ExcaliburGraphicsContextWebGL } from '../Graphics/Context/ExcaliburGraphicsContextWebGL'; import { GpuParticleEmitter } from './GpuParticleEmitter'; import { ParticleConfig, ParticleTransform } from './Particles'; @@ -6,6 +6,7 @@ import { Random } from '../Math/Random'; import { Sprite } from '../Graphics/Sprite'; import { EmitterType } from './EmitterType'; import { assert } from '../Util/Assert'; +import { vec } from '../Math/vector'; export interface GpuParticleConfig extends ParticleConfig { /** @@ -164,6 +165,10 @@ export class GpuParticleRenderer { let countParticle = 0; for (let i = startIndex; i < endIndex; i += this._numInputFloats) { const angle = this._random.floating(this.particle.minAngle || 0, this.particle.maxAngle || TwoPI); + const speedX = this._random.floating(this.particle.minSpeed || 0, this.particle.maxSpeed || 0); + const speedY = this._random.floating(this.particle.minSpeed || 0, this.particle.maxSpeed || 0); + const dx = speedX * Math.cos(angle); + const dy = speedY * Math.sin(angle); let ranX: number = 0; let ranY: number = 0; if (this.emitter.emitterType === EmitterType.Rectangle) { @@ -174,15 +179,13 @@ export class GpuParticleRenderer { ranX = radius * Math.cos(angle); ranY = radius * Math.sin(angle); } - + const tx = this.emitter.transform.apply(vec(ranX, ranY)); const data = [ - this.particle.transform === ParticleTransform.Local ? ranX : this.emitter.transform.pos.x + ranX, - this.particle.transform === ParticleTransform.Local ? ranY : this.emitter.transform.pos.y + ranY, // pos in world space - this._random.floating(this.particle.minSpeed || 0, this.particle.maxSpeed || 0), - this._random.floating(this.particle.minSpeed || 0, this.particle.maxSpeed || 0), // velocity - this.particle.randomRotation - ? this._random.floating(this.particle.minAngle || 0, this.particle.maxAngle || TwoPI) - : this.particle.rotation || 0, // rotation + this.particle.transform === ParticleTransform.Local ? ranX : tx.x, + this.particle.transform === ParticleTransform.Local ? ranY : tx.y, // pos in world space + dx, + dy, // velocity + this.particle.randomRotation ? randomInRange(0, TwoPI, this._random) : this.particle.rotation || 0, // rotation this.particle.angularVelocity || 0, // angular velocity this._particleLife // life ]; diff --git a/src/spec/images/GpuParticlesSpec/particles-wrapped.png b/src/spec/images/GpuParticlesSpec/particles-wrapped.png index 7c7761942a4ed0592ffbd5bf99e23dbcbf94fff3..b6aa65c5bd26f30dcecaf96c6f0152593b639f6b 100644 GIT binary patch literal 12624 zcmeHuc|4T=yZ#`IZDuN4!i;EPMA|IbB}+mwhO#6{C|SeU3!@DQr9vXhjIB*}WoUd< z2t&#?82d6}!r0FH@j2gfKIeCS|DON8{|wJ~J@4(l?(4qq>wddqX>KIMFToFk!GuhV zPg=oXTo~|s6PyQpq7q^xzz+^TDx42FT3oYb=pa-8YAa9^%FY+&9Aw=}Kv z7bD4D>9O!!j-u7elW8{oZUq|p*P1O%=futj&DQh!Z`l*@q#1jKCC_RaMeG)gGFIq&E^13FCzS=ZCHf=eESp`90hJ>l^Sllx{ii|CmsPgVWfha~l3%O8`T` zF}+;>8U-4!?Foz{N5$i2^nVWyHmn*Qx{|M%P!^$o>TPW>Y1fSo`vDsgFEf&*@qR_#6}Mk8(}S|%l??AJU5^Y&qd zMG7WZdXu6`UJ$umPaq66({>qP~iUTp-E8?N?6Jbix z*;fnz@Qh6 z_uXaMi_ou`!|17bmCcFSIRRG%ITnSA37w&?ozuDbT2N5=F}*>Ls`n}{N>WfV+_6Jf zOfJ0}6Y7NI4*&XzUYL`I8*lWDK&a%UOnERWt?bl3_#?6})>sfxyoqks@R+znXL!kw$a}@U?r+u>1z4A zJN+>HI#%FQBTj_KPfQNhkH#t@q;;&a_IE1Z7Sg-S_hH|SJ1|bHf-cPNy8y)*3P)3z z!RF7;k|%CYj`ubD-xF5gL`WA5(O=LH;xs>VC#*le!GAy{u6)mqDS4H|hRCEc;geRj z^KN)k$y4^be3rdqC>ArW#0&!W9V zc+VdU|D|==Q(S*iPcAm4{MC!3SpVRwsl>~{<*8Vy4ILti_|RXQraPRtok$Q`^sqat zE*9%iQ8`rmaCyPxb-i;VEpd*7u8$+jUITGc_Zc@FbG^3m`EC&7OSf@s4wdVr&Ej$s zq8$^=_NPoFy_uvtpMH%{SreE3>|1ZdI=aO3@T|zg8tTJX@5cTlMQin;F>x*X*T%G+ z$O=;@s)Fe>)@N^{a|5~{xG$=~;Jv+j+PezX5oeYGD%iPL&*5}=Q}teGvXdN~O*?#o zJpl$@T<6?4*GnI!G_zEbCtBK~iw?=A5bamS-1BL(eoo=c{0r1rmh+L2YnCP5DmUv$ z68i0)tFD*=MBiPJN6XX80oOb%wDuKz@1rHCop`*vr!RWe*~aHd>h04tT|TE`q^+C= z_C>#&$wZ9ZhH;93l;i^!lo5UW$|-$?CF9EG4$z;Y-f2!GcV5+Ie|w6=s7Ov{oFT)7 zraBT{X)JV=?%Cm~!HQk*coZTi^V%wjecE2ihea`XH)LJ?de4x|`3-MI4m$%OGhpq6 zETDQ9rp=jU!~sCb0d(b&8(;4MRwW)7G^IM7D^4J1e@ONulutfXKo4&gW^V9q9=7nb z93iW|`K~1RYJmFG6Do^rI6B zHnO4j`K4C*WN4#*mNWV<;pBLp_dS@9j%RT1sA-JZ?gF2eMM%jAHQMVY-x3m2es+ZT~!iN~gu=hM6%Eq+KL((!p;0#w>L!yW}z zXmE^RWaPLXOomvuo;bs}P!zkY!iz#Sntqot?>P~wX#Q(=h_2O(c^Aa)4DK%iQk4q6 znFNAmO?q<^r}B{-F~A8W@4`4nEPwRKL->5kDeb|C*;b{e8Vrd;f_eUDIbKSW8cY_1BKzwX8(sa7MlNXPaXqMv=;d@r22jF%;BLrU*Ng zEfa0YZTBtWh@=Q7{HwAqEN$RE9!k=Sb~2T@RMQ3u%|2iS&dsn_vB@!pJme#e-$V~y z39;!&WWnAHWZ4djs+v8RbT_t{=DlN3X!WSFo8QFX_1Y0+&F{oQ4{}9ape);u!9U^j z{pM9;H;he3px~+jEXoxm`>9#YArSmLfX}N-@9Hb<0fu9#U4eM$KG~X_NPXu2OVE7KNOdcf}8{d+MO|INi?id7IwI)K3Hs zrSlnLuEHu9$K}2f3^f5dLEXW_CLa_8$Z01+bL0b*&*eUQb*QhH=&XL<%uB6Ax`EA| z=o9tQ{DPBfm~dF3zhK_XnR~*y;iw3wqFX`BDS1PzHZtMKyuzeKY=9nt?Q(re-UGv1 z{wo;Rq!5_rGOl{h#c{J9#_#9X^zA0Z1D?k4uwx1AGwJ(pDK2Xd&H!Qv24(BQ==64A zA2nf)CEs%TnpU&HE6PCC7^P#bwpj9JK&Vp+GP8vcgGBq(+*PsQma7Rr4>M^!jYCCb z=F$U>)l@A>v1OSGK#Wvxmb{SWp@H zmt0?ND4w#i@v>pV@fek^%qXB~CkAsF7hW}UGU>x5{@~s5KoV^~<2}e^quu>nD)V}! zK4_6^H{Q2Qo%kC4J~<>x)esgn3X-62c5n9slMl9S(|k~To4T4p6lu{KP7y;dveAxX zl!S^sZ|cNf*WslkPPtNf`7mz_`I2rj*30>aiZp~u^7_v_t7FrnVZNtgHfma?rm`OW z4P7SyUAE(icu8iRB?7=-?i88u%B{a2zsU^{A>DQ#H1POpG()tl1h3JUd_&!sZAZ=sf0 zW`iM5qVUO6={D0`6VuyJOCdoTj>u1@rv)_P)~r&}L)88BMCWu&FpAT1Qw{I!;bm6rc%#*gu- z^Vz%D89j?h>Vo^ExO9$+w4-rZyzh#XQMy;^j5T+1Y_qWfd3Ms{nA?!vA&Ov$$!Y(@~xf(Fq5gMASqO99AmEL^U7Nn z&L(vc!pRtE8;d#vnBBAvq8~7jgcy)O%v%uKbpckmwTt45A1|JA&DzyB6}eoulrXn` z^#)Ts_7+`TX-{MhQ-vg!BcZ!iEv#n0?hW^`Xu?X2e~k-hsexx(ECaP*ORe?5r)~HJ^e!V1M2`r7^T{0oaEbiL z=3hG(P=9wU0vBw{T5I|-y6}w;O}lG&4V5|9OXW^ntff`${dOxw+K;<|E^DKI=?GiE z_1NX5DIS8&ZOe6U)JkO;Yrh$#s&*5l4$uJyijx;GsP09sZ5tIDgpi)NaKnmOYCj#n zu+GuXQ`V_A%imP}tNi0(5_C@1A!fbN8L2y`-BBcTt0yYfS?KXT|A5OV(fy&I98qv; zFWa~k10Sog)&wkX1JtWGm&Bqedcd5iGEDO1_*nAP83q%J*ZuQZh_k8s&szkA#Dn6! zZ_P2kA*t)wrR%t}A+zs(hIGWKm<*-ev>FtBv#Tr|HQIIwD#W_*V8q()cv&Oxa7A=E zAb_>qwbIVcR^YN{D^^uG^vOru9W_mlTKS-z1B$>2=F3`Tb-J}k^c%;-3&HB^>)5;_NNKq6T0?GVa!FZOWOWyNcg;>}OXL{4w` zg&d(6@naCY3+A6rIKk$bWM{uhG8#m%>5FvtAcqy>PYuouDafU;^2zPpg1g4GS^jkd z=L4eun*p;w)>#?Vy@)qAIWZL>=u}z3A$KfO`AB5vs!ltTEUebj{j}9#o_UCD)H$## zo}v5OHP-1{(1(Si0A2xri%3o~@kj`3ksoj5lbx(VIx1*OX?k5jm&NJ+Il|RdD3Zu# zlFM6vM9wy!suM&P%ux(V9Bs0w*3l`g4j|PYj(WqUUkTWvi#~`h!nxJMp*{0NMHIw` z+ohv)Z?-PI>*0_)sH-+7T)i*TRkV=6qLkb-AYEGaMu8l9Aml2I%vh3+O}SFXe#mB@ zW9j1>=rR8*)<4l3bjr_e&Ce!}Z~l12fW2wrSrj&Fx2~r3C%kjvMd6QI?Ug&0k*RDD z7cr|r?NC^hVg+QD8E`j*?b#}+b_1JSFTeX7DlrZje&iUzcYaS{ELOdqeceMt61Odd zE6PUZ462YmG|=LOb*nkqb|NzN%kv%$YIyUiRbr*MM0*bqKBLM&_V&|vuR0Ri=&g?> zik`= z#CMiS_b^^p_c|GoYrnF#baS+RXckfve#(Gxr~xC2&^UKEGx7KcrxkP9UzE41fp8m% z@D%OVkk$L1x(NoAvG)*Nw_~znx#Glj`LihJW^KBU1u{TPW7Efi6#4;;j@D>y`JFxR zk|D7;3gj}PGR)wB#XF|la!M!5(>QV@G(>ml4&9y1#wrwiekjqJiO(AIn2HFpDHPW3 z6&uPxEk&&vRh-+3dsh>HMy=JIbOdtX&-|gqg^~7-Ew@szzuK0!hv-;wXR}#_A6oNk z5yT4Xb#az94K{R<9>cv(4@cd|xYbR0W6$!2nebdHn<0;~&Tdeh1ZeLN+M; zSW-Z?kVl>wzmRnNSY#&`RgcS9Q1tbHOK%%ihthiQ-VOr1OV=VrOS+g4^bMqKonlrq zaQUNcV|_PSP^P`;bYfnEKrA+N?4k*#6yw-gwdM4GFo-M7g z52y2|#W$doN&oD}i&`QC5ge4YmkmVNAl@~UtX$_buDW5>f`}3l#zbBlG#pFbu6uD| zn|7i7rlnMvu7i~F=CiP0&)Nc!=|98DhDqqRF$roT9;wYnlk46vA0|lZ5F!@&CDi)o zwvSXTXselayq6_*>KMVIj)AU4VGsAPHx#qi;k{)0%(Hm3;JxjiDvk-`{i@Ge(b|`oap+k_&^!CfZ5$2fn1thnCeNG} zaI8gI={}ABA7s=67JWcu3J7>}_{O;l&%TejYohT7cfIeTDt@pH`2Oj~rV9Laz9y^K zbC=^xuXDqhiATp($q{zHjCSZz?4!_`^XKh2f^A|lghUcI8iI>>B%+V$*XCxdNkCBxNL)b1a5&on9hSHZ z)9(62&f)dy%1VcJ8#uw0+RZkt%wsk^Yu2U)e88piTLR5|K_Ifev=(LgytE}#Q_Li!- zIxifTnWTxoLmH$KR+FCZ1S4DSTsHdIj%%(r9S_8IySj4A{fR8!v4hAibb%Kj$P(RL zhe@1PB~Pc9TGxfO*Lvubj%h*{x%2X@B|Sh#I{h%K*lAUY#S&uGn@+51NqcR@aT=I` z93G>l4G|*;XXf|R;DFx|S=oYo!fO;ueSpq~()Ab8pe)xg6ruP3*E_>o*Iy^fJLyYHcZ4y1Q@lP`@aBFhk=0iOX(kww0+ zf>^=Ua0W|9TD}{$E8tpq5ms)%N;w*}^q_Q0gA)ZB+{&b{7bJ6plJj`#5r(?%46xs4I@}`0>K=ib_{eq7r7$>LTo8 zYRTbO_0jKxAE1akTM3LY_OUH{{DSOJSN|Lh?17o!njFv8c=@aIJFD5hhDYPPId!)I zwRA_4ev<;uz^c)uchBt(r8iDv%(Kyaamcb)+&pBChEEjdJvbfvMrIp%E+z|~y%bbt zzrC+@e%hAC^evSgp+O$!0g`!}RkpW3^q{}3zob~ZK$eiMQEA$KondC%XDT9B%%$BM z>#&1&{ZUv%-XRjzrJrQ<^DP-&gVO$^Gp!)6cG;Tfq<*dZdoK`-W)))deg?Qw-a67e zP2`^k*(jF8hhJ&%`?LQu8H%d`S1QGyc-TRdt()Vu zvfo!LGKg3pU$e2I%X@_0SYRQ`9mBS+Tt}v=4_1s)-&K_&6OXYDLzX@8%60RW`yN#Y*LW}&L zTzYy%1U{VMk5!6oQl(aaj>t@?6E>e(d2kJzk`I0q4G$UZ3oW*DY;PV zl9O6NIn3Aj9!Be=)iABKNeqV^_jcr4(;8_n-6d}Yyk>^A4B*y3_iYduFU=)ITLeZq zm4;wzE~|pp2fQJ}V6v{44+82J?r=vVmS})~wyy)(OqIMd_L6$EWCsS6@cOxDJG=SQ z%5FB5HyizI4d4AGPs)v5ahqCJ`BpouTe)#j;IL4IZ)A|6AzZ5XQqU(o;=RpRGo@Wb zw`yMt-a1>i(NRb|hyuPRR6YLuFbLckANL2Cbz{5bT>-)N=XfnETRy&uvN2pru0~*t zMsSCp{z{e7zSJ7Ks#85Zv{)n|d5RTMo=2e+Y34LLLqY8-EuxKEt2jLW=9bmqX29*d ziIAeY8^d&$>Y%xDu>+bHm9EF={M9GoQ@|q=rxu-45S)iQCaPC9&7`~B@0k0{vuIal zJ;C(T3c)?~?M?_8Pucxf-vZsP7|1bL8EG%pGeU~HzZ=J>I&?_tGbc7HVlQw&LAm0i zTYwopIU+jKG8Y7SYD$a;@pc@SF`LOh;f`B$Ewv8OLL5Fg`_ARGXXTOs7kjbNoF6^$ z_$9^2LoM(X<%oU7>t3K4i+0T(&=;Q{&g@=sCsJAg?m4!ZawuSW`5~9%fv??-pJ+ZD zSuV;9ha!d)wzW^Dp$4=6C_J;nH|(C{{n9%mqr%Xjdqz56*y!wf;_jAJh8Z5Q%j-bk zSMTA9?q%<{!G*~v-Q$Cqs65b;5CB<^BI?lxNVBlP4L$ZuN>B}xQC%)H>m1(F$ zndi6NDLo!X##D84^vsnO8kS6`d{c`_5J&tzw9V71K!-)J78Cbxq^wILWHx@%DKtdH z+_y0FfO5B1pz(^TwQjD1Xm~sT*fez4WEbSvLa62P_}H|P_CGuU^)I6z8_Prool@M? z_eM5}Fx-%hB!oQ)Z?KO$>8xky(NFe5=#9!J?VAtliDU@`M&(_3^Y#$!YW1LHO2=&O zw=?4dN>23m+Tr(L?F|f9G;o|9z;RA1$>l-Hu-T5~XBsb6@wqQ+^n#xxEg9Q!%>TrI zmP5+-8r`gJUY~R9cklIVOll;wFC{kVb6;);8QpG#C}MYk=}=Em`*}2Ck7Fyvpp=A5 zMw8o|QaKuQHm`FwDfID63IG+l9B8MF$|xcc%%!M581}Q>f>;pfa%R}nwQ{fGDRH#= z4vFtI###OqJQ~sj{oWTD676C>!e2rX2+MJx08E&tlnnV@`e95H!t2=!%`buG5#`L- z>t8PAEAza~9CjJpQ#vssdQklVWP|OP$geLO{Gd}jCKhzBl5KZAhHlfZIWoC*l))=c z9#1X|XY8Hw5b|Fsc1(2EX;QGV=DpV#>xKCFFx_qF6N%rYjvjO@$M?oyoh>sT;VZEwN`k*UuixFk#bk4#_V)g5> zIv=%AD6aDX3fTMNcPa#J5?@e0?F5ZxQ9w4g6Jesr-SWt{F0ZKVKC5o3CcY>i*9Oqd zNw#&eeQ@1+Iqn`Z_s6>>wT?Eju!iOr+$7ih(JF+rqqn#HGV?^n*(_q`F|K6H|YU- zAg6PNt5?g|u_kVwlk;89FMj8!mFcl;ybhq~{?q}l)9zhpk_ral6Y-s+W)|da<~im+ z`J3y$f_g^=R965$Bl2v+L+H z$MfeL?X;vP6jP8u;|~c6qG6L-NO0`)JdrlHnnPpO;}<5UEZ!B}$QQdM2vsDJAEyB{ zdWwSfL8&JA?fQfT!VhrYAB?lP!-`Ln2@{se2jc|R$0P3x)ryKi#Q&muLOCETY6X-L z3&Hc(AVkh^OYRHTPq*ariIF{M{zMyBXd+9jW@Xir&l7fPH)-wEVZq+$htxu8d{qAgF~2*ZE&Fy%6Chq5j(5ylF zTnGOc=tU0FF+)^M`)0a}&Zkeb1S9Klq`%5y_;T3aL@^5V;;%P8W1%hDz=N7n44ND! zn*>C1MZSmm7AGx_Ar9oxzQ4+1({UX&N^!)?Li!@WgcOsoK%+Px&lqd${*HYMQpb8p z8fyv;al+i~iC7|{)r;}sAxWm#Q7tj(Kv(!n%7TLa02MvCr(?Ek$O*O|5H1mDOX`Zj zf9?T3ER2jK;)8R^z_Aa$w<`?|x?#Ovu;cfF5?-2wE{;}^u}IC>vY% zbGPifgV2=mRXws zRDE@zciOsvic`Z$D_#mJKO-ZtySQ&LyfR{GTr6%qsouB$EJLi5<<_LsMSpEqu+NvhD1)LsKSUP!F48A^L2 zZS541bC2!EibF5Je%nKsi3Yb7e{q6IburPrOJQn}y`&cNg%x>5C1`Iw?XEl2djjZE zybpgo(SH6$m1n!o@j^Rm_w}!xzoqkL`f6}kX%@}UYLGd0^tu;|B_9baBPFIk9!IA* zt-cOcMbdnimmSp^N&<)$Y|{di34e!fS_*D~S1QV-S%0AdyQe_mw`f2hX%9mDaWXkO z6Q1(0?*hLlLe}SLFMTt?plqnEXnDKAnY)MF&pXt))YLx=w|ganD=3lGJ|aLVZZ{qC zLIir3TiWQ4rXT3`j9J!l?9@#tC@Cor>snR&P|~v9OKEGuO6YFp)^0B*L=tV)F9yN8 zR^Pn}X^s()QUhIYeNF2xw8YNn4E?Ch!N8Q4PfDAdB#TA3?u3|XA|LCVNY2T8b^C5z z{#pb=LdCaXZg_M(81S27yCPot*0G{bHH7x?l0||=#}sTqmc@!>v&-0os3`mz7EUcW4Lh>p~X@*Xj~nUG5tFf zDw+Z<@_*a>Ao!Ep=JtXr z0z#v$k14M*u*8essw{K{jv?w=hbO1LTXM+PhrESi0$kA%>>}t~Khzq%njT5U=)5ZK zCwYl?S@-o;(RaNoJ||iqcRPxxbvDht8;??ZKyqWpM_S*dIb7Mr}lwd}Ekhy~wMR6$Bj(RObd9T5E8}vTP?R^$Rq~k!l2Hl$#$9C5XaA7iSuf)RO0IBj&w47M(y8Xq>6E-tS4c%i z*;)W{Bsi+ZOMnM8e-7ovzdk7wAJ z2Qs~#KF1u647x%h(gecLj#HF%Nl0)2H<_@&5eGb}54UtOr9plo{$w34y%dvGceB*C z;g9bV=?^7F&GNol45f}?CH>STD0xNTBVoSf8`BU)UyT9uQ6b+au%ka;6SToI?MgLE zCtsDmtia37O%WC9L7&a=?{oYgT?PX&rm`^a!$-{lMQ_?(%yRSh#m&m#(^XQoBR^<3 znLk(!-KAZvM8rxLo(dm-oWcdoE2;!mt0sQ~)H`s@U@b!RdB|r)i@qtOYF3rPP-bIV zQLLw5&M|fH-tMovJQ}sO_ysJsz2Eao+LjM(K>$2k6GFrAq~Iepc_>8 x|L2$=n*kbZW|O>i|Md;{+q?gRC2r`z$}vMG(sxgQf02Nh7@D6f*1ve`KLCK3LXZFe literal 10310 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 NiGjr_GUn{H{{_sdtKN4F9$no8EGYH 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 literal 7533 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