DIRECTORY Atom USING [ GetPropFromList ], Checksum USING [ ComputeChecksum ], Real USING [ Fix, RoundC ], RealFns USING [ Sin, Cos, Power ], ThreeDBasics USING [ VertexInfo, VtxToRealSeqProc, RGB ], TextureMaps USING [ GetTxtrAt ], Tilers USING [ AddHighlight ], ScanConvert USING [ RealSequence, GetColorProc, Spot, Extend ]; ShadingProcs: CEDAR PROGRAM IMPORTS Atom, Checksum, Real, RealFns, ScanConvert, TextureMaps, Tilers ~ BEGIN RealSequence: TYPE ~ ScanConvert.RealSequence; RGB: TYPE ~ ThreeDBasics.RGB; GetLerpedVals: ThreeDBasics.VtxToRealSeqProc ~ { IF dest = NIL OR dest.maxLength < dest.length+3 THEN dest _ ScanConvert.Extend[ dest, dest.length+3]; dest[dest.length ] _ source.coord.x; dest[dest.length+1] _ source.coord.y; dest[dest.length+2] _ source.coord.z; dest.length _ dest.length+3; RETURN [dest]; }; Spots: ScanConvert.GetColorProc ~ { RETURN RecoverColor[spot, AddSpots]; }; Wurlitzer: ScanConvert.GetColorProc ~ { RETURN RecoverColor[spot, AddWurlitzer]; }; TwistedStripes: ScanConvert.GetColorProc ~ { RETURN RecoverColor[spot, AddTwistedStripes]; }; BurlWood: ScanConvert.GetColorProc ~ { RETURN RecoverColor[spot, AddBurlWood]; }; ZebraBurl: ScanConvert.GetColorProc ~ { RETURN RecoverColor[spot, AddZebraBurl]; }; Marble: ScanConvert.GetColorProc ~ { RETURN RecoverColor[spot, AddMarble]; }; RecoverColor: PROC[spot: ScanConvert.Spot, proc: PROC[spot: ScanConvert.Spot] RETURNS[ScanConvert.Spot] ] RETURNS[RGB, REAL] ~ { IF Atom.GetPropFromList[spot.props, $TextureMap] # NIL THEN spot _ TextureMaps.GetTxtrAt[spot]; -- modify with mapped texture spot _ proc[spot]; -- modify with solid texture spot _ Tilers.AddHighlight[spot]; -- get shading RETURN[ [ R: spot.val[0], G: spot.val[1], B: spot.val[2] ], spot.val[3] ]; }; AddSpots: PROC[spot: ScanConvert.Spot] RETURNS[ScanConvert.Spot] ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; intensity: REAL _ RealFns.Sin[10.0 * spot.val[x] ] * RealFns.Sin[14.0 * spot.val[y] ] * RealFns.Sin[20.0 * spot.val[z] ]; intensity _ (intensity + 1.0) / 2.0; spot.val[r] _ spot.val[r] * intensity; spot.val[g] _ spot.val[g] * intensity; spot.val[b] _ spot.val[b] * intensity; spot.val[t] _ spot.val[t] * intensity; RETURN[spot]; }; AddWurlitzer: PROC[spot: ScanConvert.Spot] RETURNS[ScanConvert.Spot] ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; intensity: REAL _ RealFns.Sin[10.0 * spot.val[x] ] * RealFns.Sin[14.0 * spot.val[y] ] * RealFns.Sin[20.0 * spot.val[z] ]; intensity _ (intensity + 1.0) / 2.0; spot.val[r] _ spot.val[r] * (RealFns.Sin[10.0*spot.val[x]] +1.0) / 2.0; spot.val[g] _ spot.val[g] * (RealFns.Sin[14.0*spot.val[y]] +1.0) / 2.0; spot.val[b] _ spot.val[b] * (RealFns.Sin[20.0*spot.val[z]] +1.0) / 2.0; spot.val[t] _ spot.val[t] * intensity; RETURN[spot]; }; AddStripes: PROC[spot: ScanConvert.Spot] RETURNS[ScanConvert.Spot] ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; intensity: REAL _ RealFns.Sin[40.0 * spot.val[x] ]; -- stripes vary in x intensity _ (intensity + 1.0) / 2.0; spot.val[r] _ spot.val[r] * intensity; spot.val[g] _ spot.val[g] * (1.0 - intensity); spot.val[b] _ spot.val[b] * intensity; spot.val[t] _ spot.val[t] * (1.0 - intensity); RETURN[spot]; }; AddTwistedStripes: PROC[spot: ScanConvert.Spot] RETURNS[ScanConvert.Spot] ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; angle: REAL _ 3.1416 * spot.val[z]; -- rotation varies with z cosAngle: REAL _ RealFns.Cos[angle]; sinAngle: REAL _ RealFns.Sin[angle]; intensity: REAL _ RealFns.Sin[40.0 * -- x component of rotated x-y vector (cosAngle * spot.val[x] + sinAngle * spot.val[y]) ]; intensity _ (intensity + 1.0) / 2.0; spot.val[r] _ spot.val[r] * intensity; spot.val[g] _ spot.val[g] * (1.0 - intensity); spot.val[2] _ spot.val[b] * intensity; spot.val[t] _ spot.val[t] * (1.0 - intensity); RETURN[spot]; }; AddNoise: ScanConvert.GetColorProc ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; intensity: REAL _ Noise[ 2*spot.val[x], 2*spot.val[y], 2*spot.val[z] ]; intensity _ (intensity + 1.0) / 2.0; IF intensity > 1. THEN intensity _ 1.; IF intensity < 0. THEN intensity _ 0.; intensity _ 255.0 * intensity; RETURN[ [ R: Real.RoundC[spot.val[r] * intensity], G: Real.RoundC[spot.val[g] * intensity], B: Real.RoundC[spot.val[b] * intensity] ], Real.RoundC[spot.val[t] * 255.0] ]; }; AddSwirl: ScanConvert.GetColorProc ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; intensity: REAL _ RealFns.Sin[Swirl[ spot.val[x], spot.val[y], spot.val[z] ]*30 + 10*spot.val[z]]; intensity _ (intensity + 1.0) / 2.0; intensity _ 255.0 * RealFns.Power[intensity, 0.77]; RETURN[ [ R: Real.RoundC[spot.val[r] * intensity], G: Real.RoundC[spot.val[g] * intensity], B: Real.RoundC[spot.val[b] * intensity] ], Real.RoundC[spot.val[t] * 255.0] ]; }; AddSegue: ScanConvert.GetColorProc ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; intensity: REAL _ RealFns.Sin[SCVary[ spot.val[x], spot.val[y], spot.val[z], (spot.val[z] + 1.) / 2]*30 + 10*spot.val[x] ]; intensity _ (intensity + 1.0) / 2.0; intensity _ 255.0 * RealFns.Power[intensity, 0.77]; RETURN[ [ R: Real.RoundC[spot.val[r] * intensity], G: Real.RoundC[spot.val[g] * intensity], B: Real.RoundC[spot.val[b] * intensity] ], Real.RoundC[spot.val[t] * 255.0] ]; }; AddCrack: ScanConvert.GetColorProc ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; intensity: REAL; IF RealFns.Cos[ SimpleChaos[spot.val[x], spot.val[y], spot.val[z] ]*10 + 3*spot.val[z] ] > 0. THEN intensity _ 0. ELSE intensity _ 1.; intensity _ 255.0 * intensity; RETURN[ [ R: Real.RoundC[spot.val[r] * intensity], G: Real.RoundC[spot.val[g] * intensity], B: Real.RoundC[spot.val[b] * intensity] ], Real.RoundC[spot.val[t] * 255.0] ]; }; AddBurlWood: PROC[spot: ScanConvert.Spot] RETURNS[ScanConvert.Spot] ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; red, grn, blu: REAL; chaos: REAL _ Chaos[ spot.val[x], spot.val[y], spot.val[z] ]; midBrown: REAL _ RealFns.Sin[ chaos*8 + 7*spot.val[x] + 3* spot.val[y] ]; brownLayer: REAL _ ABS[ RealFns.Sin[midBrown] ]; greenLayer: REAL _ - brownLayer; perturb: REAL _ IF brownLayer > 0.0 THEN ABS[RealFns.Sin[40 * chaos + 50*spot.val[z] ]] ELSE ABS[RealFns.Sin[30 * chaos + 30*spot.val[x] ]]; brownPerturb: REAL _ perturb * .6 + .3; -- perturb up to .6 greenPerturb: REAL _ perturb * .2 + .8; -- perturb up to .2 grnPerturb: REAL _ perturb * .15 + .85; -- perturb up to .15 grn _ .5 * RealFns.Power[ABS[brownLayer], 0.3]; -- makes seams brownLayer _ RealFns.Power[(brownLayer + 1.0) / 2.0, 0.6] * brownPerturb; greenLayer _ RealFns.Power[(greenLayer + 1.0) / 2.0, 0.6] * greenPerturb; red _ (.6 * brownLayer + .35 * greenLayer) * 2 * grn; blu _ (.25 * brownLayer + .35 * greenLayer) * 2 * grn; grn _ grn * MAX[brownLayer, greenLayer] * grnPerturb; spot.val[r] _ spot.val[r] * red; spot.val[g] _ spot.val[g] * grn; spot.val[b] _ spot.val[b] * blu; RETURN[spot]; }; AddZebraBurl: PROC[spot: ScanConvert.Spot] RETURNS[ScanConvert.Spot] ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; red, grn, blu: REAL; chaos: REAL _ Chaos[ spot.val[x], spot.val[y], spot.val[z] ]; midBrown: REAL _ RealFns.Sin[ chaos*8 + 7*spot.val[x] + 3* spot.val[y] ]; brownLayer: REAL _ RealFns.Sin[midBrown]; greenLayer: REAL _ - brownLayer; perturb: REAL _ IF brownLayer > 0.0 THEN ABS[RealFns.Sin[40 * chaos + 50*spot.val[z] ]] ELSE ABS[RealFns.Sin[24 * chaos + 30*spot.val[x] ]]; brownPerturb: REAL _ perturb * .6 + .3; -- perturb up to .6 greenPerturb: REAL _ perturb * .2 + .8; -- perturb up to .2 grnPerturb: REAL _ perturb * .15 + .85; -- perturb up to .15 grn _ .5 * RealFns.Power[ABS[brownLayer], 0.3]; -- makes seams brownLayer _ RealFns.Power[(brownLayer + 1.0) / 2.0, 0.6] * brownPerturb; greenLayer _ RealFns.Power[(greenLayer + 1.0) / 2.0, 0.6] * greenPerturb; red _ (.6 * brownLayer + .35 * greenLayer) * 2 * grn; blu _ (.25 * brownLayer + .35 * greenLayer) * 2 * grn; grn _ grn * MAX[brownLayer, greenLayer] * grnPerturb; spot.val[r] _ spot.val[r] * red; spot.val[g] _ spot.val[g] * grn; spot.val[b] _ spot.val[b] * blu; RETURN[spot]; }; AddMarble: PROC[spot: ScanConvert.Spot] RETURNS[ScanConvert.Spot] ~ { x: NAT _ spot.val.length-3; y: NAT _ x+1; z: NAT _ x+2; -- object space coordinate r: NAT ~ 0; g: NAT ~ 1; b: NAT ~ 2; t: NAT ~ 3; intensity: REAL _ RealFns.Sin[Chaos[ spot.val[x], spot.val[y], spot.val[z] ]*8 + 7*spot.val[z]]; intensity _ (intensity + 1.0) / 2.0; intensity _ RealFns.Power[intensity, 0.77]; spot.val[r] _ spot.val[r] * intensity; spot.val[g] _ spot.val[g] * intensity; spot.val[b] _ spot.val[b] * intensity; RETURN[spot]; }; SCVary: PUBLIC PROC[x, y, z, p: REAL] RETURNS [REAL] ~ { f: REAL _ 1.; s, t: REAL _ 0.; FOR n: INT IN [0..7) DO s _ Noise[x * f, y * f, z * f]; s _ RealFns.Power[s * s, (p + 1.) / 2]; t _ t + s / f; f _ 2 * f; ENDLOOP; RETURN [t]; }; Swirl: PUBLIC PROC[x, y, z: REAL] RETURNS [REAL] ~ { f: REAL _ 1.; s, t: REAL _ 0.; FOR n: INT IN [0..7) DO s _ Noise[x * f, y * f, z * f]; t _ t + s * s / f; f _ 2 * f; ENDLOOP; RETURN [t]; }; SimpleChaos: PUBLIC PROC[x, y, z: REAL] RETURNS [REAL] ~ { f: REAL _ 1.; s, t: REAL _ 0.; FOR n: INT IN [0..7) DO s _ SimpleNoise[x * f, y * f, z * f]; t _ t + ABS[s] / f; f _ 2 * f; ENDLOOP; RETURN [t]; }; Chaos: PUBLIC PROC[x, y, z: REAL] RETURNS [REAL] ~ { f: REAL _ 1.; s, t: REAL _ 0.; FOR n: INT IN [0..7) DO s _ Noise[x * f, y * f, z * f]; t _ t + ABS[s] / f; f _ 2 * f; ENDLOOP; RETURN [t]; }; realScale: REAL _ 2.0 / LAST[CARDINAL]; RTable: TYPE ~ RECORD[SEQUENCE length: NAT OF REAL]; rTable: REF RTable _ NIL; SimpleNoise: PUBLIC PROC[vx, vy, vz: REAL] RETURNS [REAL] ~ { R: PROC[i, j, k: REAL] RETURNS [CARDINAL] ~ TRUSTED { A: TYPE ~ ARRAY [0..3) OF REAL; a: A _ [i * .12345 , j * .12345 , k * .12345 ]; aPointer: LONG POINTER ~ @a; h: CARDINAL _ Checksum.ComputeChecksum[nWords: SIZE[A], p: aPointer]; RETURN [h]; }; SCurve: PROC[x: REAL] RETURNS [REAL] ~ { RETURN [x * x * (3 - 2 * x)]; }; ix, iy, iz: INT; x, y, z, jx, jy, jz, sx, sy, sz, tx, ty, tz, s, f: REAL; x _ vx + 1000.; y _ vy + 1000.; z _ vz + 1000.; ix _ Real.Fix[x]; iy _ Real.Fix[y]; iz _ Real.Fix[z]; sx _ SCurve[x - ix]; sy _ SCurve[y - iy]; sz _ SCurve[z - iz]; tx _ 1. - sx; ty _ 1. - sy; tz _ 1. - sz; f _ 0.; -- initialize sum to zero. FOR n: INT IN [0..8) DO -- sum together 8 local fields from neighboring lattice pts. SELECT n FROM -- each of 8 corners of the surrounding unit cube. 0 => {jx _ ix ; jy _ iy ; jz _ iz ; s _ tx * ty * tz }; 1 => {jx _ ix+1 ; s _ sx * ty * tz }; 2 => {jx _ ix ; jy _ iy+1 ; s _ tx * sy * tz }; 3 => {jx _ ix+1 ; s _ sx * sy * tz }; 4 => {jx _ ix ; jy _ iy ; jz _ iz+1 ; s _ tx * ty * sz }; 5 => {jx _ ix+1 ; s _ sx * ty * sz }; 6 => {jx _ ix ; jy _ iy+1 ; s _ tx * sy * sz }; 7 => {jx _ ix+1 ; s _ sx * sy * sz }; ENDCASE; f _ f + s * (R[jx, jy, jz] * realScale - 1.0); ENDLOOP; RETURN [f]; }; Noise: PUBLIC PROC[vx, vy, vz: REAL] RETURNS [REAL] ~ { R: PROC[i, j, k: REAL] RETURNS [CARDINAL] ~ TRUSTED { A: TYPE ~ ARRAY [0..3) OF REAL; a: A _ [i * .12345 , j * .12345 , k * .12345 ]; aPointer: LONG POINTER ~ @a; h: CARDINAL _ Checksum.ComputeChecksum[nWords: SIZE[A], p: aPointer]; RETURN [h]; }; SCurve: PROC[x: REAL] RETURNS [REAL] ~ { RETURN [x * x * (3 - 2 * x)]; }; m: NAT; ix, iy, iz: INT; x, y, z, jx, jy, jz, sx, sy, sz, tx, ty, tz, s, f: REAL; IF rTable = NIL THEN { rTable _ NEW[RTable[259]]; FOR n:INT IN [0..259) DO r:REAL _ n; rTable[n] _ R[r, r, r] * realScale - 1.; ENDLOOP; }; x _ vx + 1000.; y _ vy + 1000.; z _ vz + 1000.; ix _ Real.Fix[x]; iy _ Real.Fix[y]; iz _ Real.Fix[z]; sx _ SCurve[x - ix]; sy _ SCurve[y - iy]; sz _ SCurve[z - iz]; tx _ 1. - sx; ty _ 1. - sy; tz _ 1. - sz; f _ 0.; -- initialize sum to zero. FOR n: INT IN [0..8) DO -- sum together 8 local fields from neighboring lattice pts. SELECT n FROM -- each of 8 corners of the surrounding unit cube. 0 => {jx _ ix ; jy _ iy ; jz _ iz ; s _ tx * ty * tz }; 1 => {jx _ ix+1 ; s _ sx * ty * tz }; 2 => {jx _ ix ; jy _ iy+1 ; s _ tx * sy * tz }; 3 => {jx _ ix+1 ; s _ sx * sy * tz }; 4 => {jx _ ix ; jy _ iy ; jz _ iz+1 ; s _ tx * ty * sz }; 5 => {jx _ ix+1 ; s _ sx * ty * sz }; 6 => {jx _ ix ; jy _ iy+1 ; s _ tx * sy * sz }; 7 => {jx _ ix+1 ; s _ sx * sy * sz }; ENDCASE; m _ R[jx, jy, jz] MOD 256; f _ f + s * ( rTable[m]/2 + rTable[m+1]*(x-jx) + rTable[m+2]*(y-jy) + rTable[m+3]*(z-jz) ); ENDLOOP; RETURN [f]; }; END. VShadingProcs.mesa Last Edited by: Crow, October 2, 1986 6:16:05 pm PDT Perlin, August 5, 1985 0:23:18 am PDT PROC[dest: REF RealSequence, source: VertexInfo] RETURNS[REF RealSequence]; Regular array of dark spots Wurlitzer colors, stripes in 3-d Rotating stripes (barber pole) PROC[spot: Spot] RETURNS[RGB, REAL] PROC[spot: Spot] RETURNS[RGB, REAL] PROC[spot: Spot] RETURNS[RGB, REAL] PROC[spot: Spot] RETURNS[RGB, REAL] Perlin's marble texture returns band limited noise over R3. map the unit interval into an "S shaped" cubic f[x] | f[0]=0, f'[0]=0, f[1]=1, f'[1]=0. declare local variables. Force everything to be positive ixyz _ the integer lattice point "just below" v (identifies the surrounding unit cube). sxyz _ the vector difference v - ixyz biased with an S-Curve in each dimension. txyz _ the complementary set of S-Curves in each dimension. Add in each weighted component returns band limited noise over R3. map the unit interval into an "S shaped" cubic f[x] | f[0]=0, f'[0]=0, f[1]=1, f'[1]=0. declare local variables. initialize random gradient table Force everything to be positive ixyz _ the integer lattice point "just below" v (identifies the surrounding unit cube). sxyz _ the vector difference v - ixyz biased with an S-Curve in each dimension. txyz _ the complementary set of S-Curves in each dimension. Add in each weighted component Κ+˜headšœ™Jšœ4™4Icode™%defaultšΟk ˜ Jšœ œ˜#Jšœ œ˜%Jšœ œ˜Jšœ œ˜%Jšœœ!œ˜:Jšœœ˜"Jšœ œ˜"Jšœœ.˜A——head2šœœ˜Jšœ@˜GJ˜Jšœ˜J˜Mšœœ˜.Jšœœœ˜J˜šΟb œ$˜1Jšœœ"œœ™Kšœœœ ˜0Jšœ3˜7—Jšœ&˜&Jšœ%˜%Jšœ%˜%Jšœ˜Jšœ˜J˜J˜—šžœ ˜%Jšžœ˜&Jšœ˜—šž œ ˜)Jšžœ#˜*Jšœ˜—šžœ ˜.Jšžœ'˜.Jšœ˜—šžœ ˜(Jšžœ"˜)Jšœ˜—šž œ ˜)Jšžœ#˜*Jšœ˜—šžœ ˜&Jšžœ ˜'Jšœ˜—J˜JšΠbn œœ˜+š œ œœœœœ˜bšœ1œ˜7Jšœ'Οc˜H—Jšœ ˜;Jšœ* ˜8šœ˜Jšœ3˜3Jšœ ˜ Jšœ˜—Jšœ˜—šžœœœ˜DJš ™Jšœœœœ ˜XJš œœ œ œ œ˜8Jšœ œw˜†Jšœ$˜$Jšœ&˜&Jšœ&˜&Jšœ&˜&Jšœ&˜&Jšœ˜ J˜J˜—šž œœœ˜JJš  ™ Jšœœœœ ˜XJš œœ œ œ œ˜8Jšœ œw˜†Jšœ$˜$JšœG˜GJšœG˜GJšœG˜GJšœ&˜&Jšœ˜ J˜J˜—šž œœœ˜FJšœœœœ ˜XJš œœ œ œ œ˜8Jšœ œ& ˜IJšœ$˜$Jšœ&˜&Jšœ.˜.Jšœ&˜&Jšœ.˜.Jšœ˜ Jšœ˜—šžœœœ˜MJš ™Jšœœœœ ˜XJš œœ œ œ œ˜8Jšœœ ˜AJšœ œ˜$Jšœ œ˜$Jšœ œ $œ>˜‹Jšœ$˜$Jšœ&˜&Jšœ.˜.Jšœ&˜&Jšœ.˜.Jšœ˜ Jšœ˜—šžœ˜&Jšœ œœœ™#Jšœœœœ ˜XJš œœ œ œ œ˜8Jšœ œF˜UJšœ$˜$Jšœœ˜&Jšœœ˜&Jšœ˜šœ˜šœ,˜,Jšœ)˜)Jšœ(˜(Jšœ˜—Jšœ ˜ Jšœ˜—J˜J˜—šžœ˜&Jšœ œœœ™#Jšœœœœ ˜XJš œœ œ œ œ˜8Jšœ œj˜yJšœ$˜$Jšœ3˜3šœ˜šœ,˜,Jšœ)˜)Jšœ(˜(Jšœ˜—Jšœ ˜ Jšœ˜—Jšœ˜—šžœ˜&Jšœ œœœ™#Jšœœœœ ˜XJš œœ œ œ œ˜8šœ œ˜%Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ+˜+Jšœ˜—Jšœ$˜$Jšœ3˜3šœ˜šœ,˜,Jšœ)˜)Jšœ(˜(Jšœ˜—Jšœ ˜ Jšœ˜—Jšœ˜—šžœ˜&Jšœ œœœ™#Jšœœœœ ˜XJš œœ œ œ œ˜8Jšœ œ˜šœ˜JšœF˜FJšœ ˜ J˜#—Jšœ˜šœ˜šœ,˜,Jšœ)˜)Jšœ(˜(Jšœ˜—Jšœ ˜ Jšœ˜—Jšœ˜—šΟn œœœ˜GJšœœœœ ˜XJš œœ œ œ œ˜8Jšœœ˜Jšœœ3˜>Jšœ œ<˜JJšœ œœ˜0Jšœ œ˜ J˜šœ œœ˜$Jšœ+˜3Jšœœ,˜4—Jšœœ ˜Jšœœ ˜?JšœI˜IJšœI˜IJšœ6˜6Jšœ7˜7Jšœ œ'˜6Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜ Jšœ˜—š‘ œœœ˜HJšœœœœ ˜XJš œœ œ œ œ˜8Jšœœ˜Jšœœ3˜>Jšœ œ<˜JJšœ œ˜)Jšœ œ˜ J˜šœ œœ˜$Jšœ+˜3Jšœœ,˜4—Jšœœ ˜Jšœœ ˜?JšœI˜IJšœI˜IJšœ6˜6Jšœ7˜7Jšœ œ'˜6Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜ Jšœ˜—šž œœœ˜EJ™Jšœœœœ ˜XJš œœ œ œ œ˜8Jšœ œh˜wJšœ$˜$Jšœ+˜+Jšœ&˜&Jšœ&˜&Jšœ&˜&Jšœ˜ Jšœ˜—š ‘œœœ œœœ˜8Jšœœ˜ Jšœœ˜šœœœ˜Jšœ ˜ J˜'J˜J˜ Jšœ˜—Jšœ˜ J˜—š ‘œœœ œœœ˜4Jšœœ˜ Jšœœ˜šœœœ˜Jšœ ˜ J˜J˜ Jšœ˜—Jšœ˜ J˜—š ‘ œœœ œœœ˜:Jšœœ˜ Jšœœ˜šœœœ˜Jšœ&˜&J˜J˜ Jšœ˜—Jšœ˜ J˜—š ‘œœœ œœœ˜4Jšœœ˜ Jšœœ˜šœœœ˜Jšœ ˜ J˜J˜ Jšœ˜—Jšœ˜ J˜—J˜Lšœ œ œœ˜'L˜4˜L˜—š ‘ œΟsœœœ˜=šœ#™#J˜š ‘œœ œœœœ˜5Jš œœœœœ˜Lšœ/˜/Lšœ œœ˜Lšœœ$œ˜ELšœ˜ Jšœ˜—š ‘œœœœœ˜(šœW™WJ˜Jšœ˜—˜J˜——šœ™Jšœ œ˜Jšœ3œ˜8—™Jšœ˜Jšœ˜Jšœ˜—šœΟdœS™WJšœ˜Jšœ˜Jšœ˜—šœ£œ£œ*™OJ˜J˜J˜—šœ£œ7™;J˜ J˜ J˜ —Jšœ ˜"š œœœœ <˜Tšœœ 2˜@Jšœ:˜:Jšœ.˜.Jšœ5˜5Jšœ.˜.Jšœ;˜;Jšœ.˜.Jšœ4˜4Jšœ-˜-Jšœ˜—šœ™J˜.—Jšœ˜—Jšœ˜ —Jšœ˜—š ‘œ’œœœ˜7šœ#™#J˜š ‘œœ œœœœ˜5Jš œœœœœ˜Lšœ/˜/Lšœ œœ˜Lšœœ$œ˜ELšœ˜ Jšœ˜—š ‘œœœœœ˜(šœW™WJ˜Jšœ˜—˜J˜——šœ™Jšœ˜Jšœ œ˜Jšœ3œ˜8—šœ ™ šœ œœ˜Jšœ œ˜šœœœ ˜J˜ J˜(Jšœ˜—J˜——™Jšœ˜Jšœ˜Jšœ˜—šœ£œS™WJšœ˜Jšœ˜Jšœ˜—šœ£œ£œ*™OJ˜J˜J˜—šœ£œ7™;J˜ J˜ J˜ —Jšœ ˜"š œœœœ <˜Tšœœ 2˜@Jšœ:˜:Jšœ.˜.Jšœ5˜5Jšœ.˜.Jšœ;˜;Jšœ.˜.Jšœ4˜4Jšœ-˜-Jšœ˜—šœ™J˜Jšœ_˜_—Jšœ˜—Jšœ˜ —Jšœ˜—Jšœ˜M˜——…—5&J§