DIRECTORY CastRays, CoordSys, CSG, CSGGraphics, DisplayList3d, DisplayList3dPrivate, Graphics, GraphicsColor, Matrix3d, PriorityQueue, Rope, Shading, SV2d, SVPolygon3d, SVTransforms, SVVector3d; DisplayList3dImplB: PROGRAM IMPORTS CastRays, CoordSys, CSGGraphics, Graphics, GraphicsColor, DisplayList3d, DisplayList3dPrivate, Matrix3d, PriorityQueue, Rope, SVTransforms EXPORTS DisplayList3d, DisplayList3dPrivate = BEGIN Camera: TYPE = REF CameraObj; CameraObj: TYPE = CSGGraphics.CameraObj; Classification: TYPE = REF ClassificationObj; ClassificationObj: TYPE = CSG.ClassificationObj; Color: TYPE = GraphicsColor.Color; CoordSysList: TYPE = CoordSys.CoordSysList; CoordSysObj: TYPE = CoordSys.CoordSysObj; CoordSystem: TYPE = REF CoordSysObj; CSGTree: TYPE = REF CSGTreeObj; CSGTreeObj: TYPE = CSG.CSGTreeObj; DrawStyle: TYPE = CSGGraphics.DrawStyle; FileCamera: TYPE = REF FileCameraObj; FileCameraObj: TYPE = DisplayList3d.FileCameraObj; FileCameraList: TYPE = DisplayList3d.FileCameraList; FrameBox: TYPE = REF FrameBoxObj; FrameBoxObj: TYPE = CSGGraphics.FrameBoxObj; Matrix4by4: TYPE = Matrix3d.Matrix4by4; Plane: TYPE = SVPolygon3d.Plane; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = Matrix3d.Point3d; PointSetOp: TYPE = CSG.PointSetOp; -- {union, intersection, difference} Poly3d: TYPE = SVPolygon3d.Poly3d; Primitive: TYPE = REF PrimitiveObj; PrimitiveObj: TYPE = CSG.PrimitiveObj; Ray: TYPE = REF RayObj; RayObj: TYPE = CSG.RayObj; Vector: TYPE = SVVector3d.Vector; Database: TYPE = REF DatabaseObj; DatabaseObj: TYPE = DisplayList3d.DatabaseObj; Scene: TYPE = REF SceneObj; SceneObj: TYPE = DisplayList3d.SceneObj; Assembly: TYPE = REF AssemblyObj; AssemblyObj: TYPE = DisplayList3d.AssemblyObj; AssemblyList: TYPE = REF AssemblyListObj; AssemblyListObj: TYPE = DisplayList3d.AssemblyListObj; LightSource: TYPE = REF LightSourceObj; LightSourceObj: TYPE = Shading.LightSourceObj; LightSourceList: TYPE = Shading.LightSourceList; MasterObjectClass: TYPE = REF MasterObjectClassObj; MasterObjectClassObj: TYPE = DisplayList3d.MasterObjectClassObj; MasterObjectClassList: TYPE = DisplayList3d.MasterObjectClassList; FileoutProc: TYPE = DisplayList3d.FileoutProc; FileinProc: TYPE = DisplayList3d.FileinProc; MasterObject: TYPE = REF MasterObjectRec; MasterObjectRec: TYPE = DisplayList3d.MasterObjectRec; MasterObjectList: TYPE = DisplayList3d.MasterObjectList; RayCastProc: TYPE = CSG.RayCastProc; RayCastNoBBoxesProc: TYPE = CSG.RayCastNoBBoxesProc; PreprocessProc: TYPE = DisplayList3d.PreprocessProc; LineDrawProc: TYPE = DisplayList3d.LineDrawProc; NormalsDrawProc: TYPE = DisplayList3d.NormalsDrawProc; CountPlanarSurfacesProc: TYPE = DisplayList3d.CountPlanarSurfacesProc; GetPlanarSurfacesProc: TYPE = DisplayList3d.GetPlanarSurfacesProc; PlanarSurface: TYPE = REF PlanarSurfaceObj; PlanarSurfaceObj: TYPE = DisplayList3d.PlanarSurfaceObj; PlanarSurfaceList: TYPE = DisplayList3d.PlanarSurfaceList; DrawPlanarSurfaceProc: TYPE = DisplayList3d.DrawPlanarSurfaceProc; DrawSubBoxesProc: TYPE = DisplayList3d.DrawSubBoxesProc; NoOpRayCast: PUBLIC RayCastProc = { class _ CastRays.GetClassFromPool[]; CastRays.MakeClassAMiss[class]; }; NoOpRayCastNoBBoxes: PUBLIC RayCastNoBBoxesProc = { class _ CastRays.GetClassFromPool[]; CastRays.MakeClassAMiss[class]; }; NoOpPreprocess: PUBLIC PreprocessProc = {}; -- don't preprocess anything NoOpLineDraw: PUBLIC LineDrawProc = {}; -- don't draw anything NoOpNormalsDraw: PUBLIC NormalsDrawProc = {}; -- don't draw anything NoOpCountPlanarSurfaces: PUBLIC CountPlanarSurfacesProc = {RETURN[0]}; NoOpGetPlanarSurfaces: PUBLIC GetPlanarSurfacesProc = {RETURN[NIL]}; NoOpDrawPlanarSurface: PUBLIC DrawPlanarSurfaceProc = {}; -- don't draw anything NoOpDrawSubBoxes: PUBLIC DrawSubBoxesProc = {}; -- don't draw anything DeleteMasterObjectNamed: PUBLIC PROC [moName: Rope.ROPE, scene: Scene] RETURNS [found: BOOL] = { mo, beforeMo, afterMo: MasterObjectList; [beforeMo, mo, afterMo, found] _ DisplayList3dPrivate.FindMasterObjectAndNeighborsFromName[moName, scene.masterObjects]; IF NOT found THEN RETURN; IF beforeMo = NIL THEN scene.masterObjects _ afterMo ELSE beforeMo.rest _ afterMo; }; -- end of DeleteMasterObjectNamed DeleteMasterObjectIfUnused: PUBLIC PROC [mo: MasterObject, scene: Scene] RETURNS [found: BOOL] = { IF Rope.Equal[mo.class.name, "sphere"] OR Rope.Equal[mo.class.name, "block"] OR Rope.Equal[mo.class.name, "cylinder"] OR Rope.Equal[mo.class.name, "cone"] THEN RETURN[TRUE]; FOR primitiveAssemblies: LIST OF Assembly _ DisplayList3d.ListOfPrimAssemblies[scene.assembly, scene], primitiveAssemblies.rest UNTIL primitiveAssemblies = NIL DO IF primitiveAssemblies.first.object = mo THEN RETURN[TRUE]; ENDLOOP; found _ DeleteMasterObjectNamed[mo.name, scene]; }; -- end of DeleteMasterObjectIfUnused DeleteCoordSysNamed: PUBLIC PROC [csName: Rope.ROPE, scene: Scene] = { cs, beforeCS, afterCS: CoordSysList; notFound: BOOL _ FALSE; [beforeCS, cs, afterCS] _ CoordSys.FindCoordSysAndNeighborsFromName[csName, scene.coordSystems !CoordSys.CoordSysNotFound => {notFound _ TRUE; CONTINUE}]; IF notFound THEN RETURN; IF beforeCS = NIL THEN scene.coordSystems _ afterCS ELSE beforeCS.rest _ afterCS; }; -- end of DeleteCoordSysNamed DeleteLightSourceNamed: PUBLIC PROC [lsName: Rope.ROPE, scene: Scene] = { ls, beforeLS, afterLS: LightSourceList; notFound: BOOL _ FALSE; [beforeLS, ls, afterLS] _ DisplayList3dPrivate.FindLightSourceAndNeighborsFromName[lsName, scene.lightSources !DisplayList3dPrivate.LightSourceNotFound => {notFound _ TRUE; CONTINUE}]; IF notFound THEN RETURN; IF beforeLS = NIL THEN scene.lightSources _ afterLS ELSE beforeLS.rest _ afterLS; }; -- end of DeleteLightSourceNamed ClearScene: PUBLIC PROC [scene: Scene] = { scene.assembly.object _ NEW[AssemblyListObj _ [NIL, union] ]; ClearCoordSystems[scene]; ClearMasterObjects[scene]; }; ClearCoordSystems: PUBLIC PROC [scene: Scene] = { z: CoordSysList _ scene.coordSystems; -- WORLD z _ z.rest;-- SCREEN z _ z.rest;-- sceneAssembly z.rest _ NIL;-- cut off the rest }; ClearMasterObjects: PUBLIC PROC [scene: Scene] = { z: MasterObjectList _ scene.masterObjects; -- "sphere" z _ z.rest;-- "block" z _ z.rest;-- "cone" z _ z.rest;-- "cylinder" z.rest _ NIL;-- cut off the rest }; DeleteSubassemblyFromAssembly: PUBLIC PROC [subassembly: Assembly, assembly: Assembly, scene: Scene] RETURNS [success: BOOL] = { IF ISTYPE[assembly.object,AssemblyList] THEN [assembly.object, success] _ RemoveFromAssemblyList[subassembly, NARROW[assembly.object,AssemblyList], scene] ELSE ERROR; }; RemoveFromAssemblyList: PRIVATE PROC [a: Assembly, al: AssemblyList, scene: Scene] RETURNS [newAl: AssemblyList, success: BOOL] = { lastAssemblyList: LIST OF Assembly _ al.list; IF lastAssemblyList.first = a THEN {-- first item on the list DeleteAssemblyAndSons[a, scene]; al.list _ lastAssemblyList.rest; RETURN[al, TRUE] }; FOR l: LIST OF Assembly _ lastAssemblyList.rest, l.rest UNTIL l = NIL DO IF l.first = a THEN { DeleteAssemblyAndSons[a, scene]; success _ TRUE; lastAssemblyList.rest _ l.rest; -- splice out a newAl _ al; RETURN; } ELSE lastAssemblyList _ lastAssemblyList.rest; ENDLOOP; success _ FALSE; }; TemporaryRemoveFromAssemblyList: PUBLIC PROC [a: Assembly, al: AssemblyList, scene: Scene] RETURNS [newAl: AssemblyList, success: BOOL] = { lastAssemblyList: LIST OF Assembly _ al.list; IF lastAssemblyList.first = a THEN {-- first item on the list al.list _ lastAssemblyList.rest; RETURN[al, TRUE] }; FOR l: LIST OF Assembly _ lastAssemblyList.rest, l.rest UNTIL l = NIL DO IF l.first = a THEN { success _ TRUE; lastAssemblyList.rest _ l.rest; -- splice out a newAl _ al; RETURN; } ELSE lastAssemblyList _ lastAssemblyList.rest; ENDLOOP; success _ FALSE; }; DeleteAssemblyAndSons: PRIVATE PROC [a: Assembly, scene: Scene] = { DeleteCoordSysNamed[a.coordSys.name, scene]; WITH a.object SELECT FROM alist: AssemblyList => DeleteAssemblyListAndSons[alist, scene]; mo: MasterObject => RETURN; ENDCASE => ERROR; }; DeleteAssemblyListAndSons: PRIVATE PROC [alist: AssemblyList, scene: Scene] = { FOR list: LIST OF Assembly _ alist.list, list.rest UNTIL list = NIL DO DeleteAssemblyAndSons[list.first, scene]; ENDLOOP; }; RemoveDuplicateMOs: PUBLIC PROC [moList: MasterObjectList] RETURNS [uniqueList: MasterObjectList] = { thisMO: MasterObject; uniqueList _ NIL; FOR list: MasterObjectList _ moList, list.rest UNTIL list = NIL DO thisMO _ list.first; IF NOT ObjectNameInList[thisMO.name, uniqueList] THEN uniqueList _ CONS[thisMO, uniqueList]; ENDLOOP; }; ObjectNameInList: PRIVATE PROC [moName: Rope.ROPE, moList: MasterObjectList] RETURNS [BOOL]= { FOR list: MasterObjectList _ moList, list.rest UNTIL list = NIL DO IF Rope.Equal[list.first.name, moName, TRUE] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; MoListMinusMoList: PUBLIC PROC [moList1, moList2: MasterObjectList] RETURNS [moList1MinusmoList2: MasterObjectList] = { moList1MinusmoList2 _ NIL; FOR list: MasterObjectList _ moList1, list.rest UNTIL list = NIL DO IF NOT ObjectNameInList[list.first.name, moList2] THEN moList1MinusmoList2 _ CONS[list.first, moList1MinusmoList2]; ENDLOOP; }; CopyMasterObjectList: PUBLIC PROC [moList: MasterObjectList] RETURNS [copy: MasterObjectList] = { copy _ NIL; FOR list: MasterObjectList _ moList, list.rest UNTIL list = NIL DO copy _ DisplayList3dPrivate.AppendToMasterObjects[list.first, copy]; ENDLOOP; }; DrawScene: PUBLIC PROC [dc: Graphics.Context, scene: Scene, camera: Camera] = { mark: Graphics.Mark; SVTransforms.TellAboutCameraAndWorld[scene.assembly, camera, scene]; mark _ Graphics.Save[dc]; IF NOT camera.frame.fullScreen THEN { SetColor[dc, camera, GraphicsColor.black]; CSGGraphics.DrawFrame[dc, camera]; }; SELECT camera.style FROM wire => DrawWireAssemblies[dc, scene, camera]; shaded => DrawShadedAssemblies[dc, scene, camera]; normals => DrawNormalsAssemblies[dc, scene, camera]; ENDCASE => SIGNAL NotYetImplemented; Graphics.Restore[dc, mark]; }; NotYetImplemented: PUBLIC SIGNAL = CODE; DrawWireAssemblies: PRIVATE PROC [dc: Graphics.Context, scene: Scene, camera: Camera] = { assemblyName: Rope.ROPE; found: BOOL; assembly: Assembly; FOR list: LIST OF Rope.ROPE _ camera.visibleAssemblies, list.rest UNTIL list = NIL DO assemblyName _ list.first; found _ TRUE; [assembly, ----] _ DisplayList3d.FindAssemblyFromName[assemblyName, scene !DisplayList3d.AssemblyNotFound => {found _ FALSE; CONTINUE}]; IF found THEN DrawWireAssembly[dc, assembly, scene, camera]; ENDLOOP; }; DrawShadedAssemblies: PRIVATE PROC [dc: Graphics.Context, scene: Scene, camera: Camera] = { assemblyName: Rope.ROPE; assembly: Assembly; found: BOOL; FOR list: LIST OF Rope.ROPE _ camera.visibleAssemblies, list.rest UNTIL list = NIL DO assemblyName _ list.first; found _ TRUE; [assembly, ----] _ DisplayList3d.FindAssemblyFromName[assemblyName, scene !DisplayList3d.AssemblyNotFound => {found _ FALSE; CONTINUE}]; IF found THEN DrawShadedAssembly[dc, assembly, scene, camera]; ENDLOOP; }; DrawNormalsAssemblies: PRIVATE PROC [dc: Graphics.Context, scene: Scene, camera: Camera] = { assemblyName: Rope.ROPE; assembly: Assembly; found: BOOL; FOR list: LIST OF Rope.ROPE _ camera.visibleAssemblies, list.rest UNTIL list = NIL DO assemblyName _ list.first; found _ TRUE; [assembly, ----] _ DisplayList3d.FindAssemblyFromName[assemblyName, scene !DisplayList3d.AssemblyNotFound => {found _ FALSE; CONTINUE}]; IF found THEN DrawNormalsAssembly[dc, assembly, scene, camera]; ENDLOOP; }; DrawAssembly: PUBLIC PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { SVTransforms.TellAboutCameraAndWorld[assembly, camera, scene]; SELECT camera.style FROM wire => DrawWireAssembly[dc, assembly, scene, camera]; shaded => DrawShadedAssembly[dc, assembly, scene, camera]; normals => DrawNormalsAssembly[dc, assembly, scene, camera]; ENDCASE => SIGNAL NotYetImplemented; }; SetColor: PRIVATE PROC [dc: Graphics.Context, camera: Camera, color: Color] = { IF camera.colorFilm THEN Graphics.SetColor[dc, color] ELSE { intensity: REAL _ GraphicsColor.ColorToIntensity[color]; Graphics.SetColor[dc, GraphicsColor.IntensityToColor[intensity]]}; }; DrawWireAssembly: PRIVATE PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { Graphics.SetColor[dc, GraphicsColor.black]; IF NOT camera.frame.fullScreen THEN { CSGGraphics.DrawFrame[dc, camera]; }; DrawWireAssembly2[dc, assembly, scene, camera]; }; DrawWireAssembly2: PRIVATE PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { lightSources: LightSourceList _ scene.lightSources; WITH assembly.object SELECT FROM assems: AssemblyList => { FOR subassemblies: LIST OF Assembly _ assems.list, subassemblies.rest UNTIL subassemblies = NIL DO DrawWireAssembly2[dc: dc, assembly: subassemblies.first, scene: scene, camera: camera]; ENDLOOP; }; mo: MasterObject => { mo.class.lineDraw[dc, mo.lineBody, camera, assembly.coordSys]; }; ENDCASE => ERROR; }; CountSurfacesInAssemblyList: PRIVATE PROC [asl: AssemblyList] RETURNS [surfCount: NAT] = { surfCount _ 0; FOR list: LIST OF Assembly _ asl.list, list.rest UNTIL list = NIL DO surfCount _ surfCount + CountSurfacesInAssembly[list.first]; ENDLOOP; }; CountSurfacesInAssembly: PRIVATE PROC [assembly: Assembly] RETURNS [surfCount: NAT] = { WITH assembly.object SELECT FROM assems: AssemblyList => surfCount _ CountSurfacesInAssemblyList[assems]; mo: MasterObject => surfCount _ mo.class.countSurf[mo]; ENDCASE => ERROR; }; PutAssemblyListOnQueue: PRIVATE PROC [asl: AssemblyList, q: PriorityQueue.Ref, cameraCS: CoordSystem] = { FOR list: LIST OF Assembly _ asl.list, list.rest UNTIL list = NIL DO PutAssemblyOnQueue[list.first, q, cameraCS]; ENDLOOP; }; PutAssemblyOnQueue: PRIVATE PROC [assembly: Assembly, q: PriorityQueue.Ref, cameraCS: CoordSystem] = { thisSurf: PlanarSurface; cameraNormal: Vector; WITH assembly.object SELECT FROM assems: AssemblyList => PutAssemblyListOnQueue[assems, q, cameraCS]; mo: MasterObject => { surfList: PlanarSurfaceList _ mo.class.getSurf[assembly, cameraCS]; FOR surfList _ surfList, surfList.rest UNTIL surfList = NIL DO thisSurf _ surfList.first; cameraNormal _ Matrix3d.UpdateVectorWithInverse[thisSurf.assembly.coordSys.cameraWRTlocal, thisSurf.normal]; thisSurf.normal _ cameraNormal; IF thisSurf.normal[3] >0 THEN PriorityQueue.Insert[q,thisSurf]; ENDLOOP; }; ENDCASE => ERROR; }; -- end of PutAssemblyOnQueue DeeperPlanarSurface: SAFE PROC [x,y: PriorityQueue.Item, data: REF _ NIL] RETURNS [BOOL] = TRUSTED { xS: PlanarSurface _ NARROW[x]; yS: PlanarSurface _ NARROW[y]; RETURN[xS.depth < yS.depth]; }; DrawShadedAssembly: PRIVATE PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { predictedQueueSize: NAT _ CountSurfacesInAssembly[assembly]; surfaceQueue: PriorityQueue.Ref _ PriorityQueue.Predict[predictedQueueSize, DeeperPlanarSurface]; mo: MasterObject; thisPlanarSurf: PlanarSurface; box: Graphics.Box; mark: Graphics.Mark _ Graphics.Save[dc]; PutAssemblyOnQueue[assembly, surfaceQueue, camera.coordSys]; box _ Graphics.GetBounds[dc]; SetColor[dc, camera, scene.backgroundColor]; Graphics.DrawBox[dc, box]; IF NOT camera.frame.fullScreen THEN { SetColor[dc, camera, GraphicsColor.black]; CSGGraphics.DrawFrame[dc, camera]; }; FOR i: NAT IN[1..PriorityQueue.Size[surfaceQueue]] DO thisPlanarSurf _ NARROW[PriorityQueue.Remove[surfaceQueue]]; mo _ thisPlanarSurf.mo; mo.class.drawSurf[dc, thisPlanarSurf, scene.lightSources, camera]; ENDLOOP; Graphics.Restore[dc, mark]; }; DrawNormalsAssembly: PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { Graphics.SetColor[dc, GraphicsColor.black]; IF NOT camera.frame.fullScreen THEN { CSGGraphics.DrawFrame[dc, camera]; }; DrawNormalsAssembly2[dc, assembly, scene, camera]; }; DrawNormalsAssembly2: PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { lightSources: LightSourceList _ scene.lightSources; WITH assembly.object SELECT FROM assems: AssemblyList => { FOR subassemblies: LIST OF Assembly _ assems.list, subassemblies.rest UNTIL subassemblies = NIL DO DrawNormalsAssembly2[dc: dc, assembly: subassemblies.first, scene: scene, camera: camera]; ENDLOOP; }; mo: MasterObject => { mo.class.normalsDraw[dc, mo.shadeBody, camera, assembly.coordSys]; }; ENDCASE => ERROR; }; END. DisplayList3dImplB.mesa Last edited by Bier on December 22, 1982 12:01 am Author: Eric Bier on August 18, 1983 1:49 pm (when DisplayList3dImpl overflowed) Imported Types DisplayList Types Databases, Scenes, Assemblies, and Lightsources Master Object Class Types Master Object Types Noop Procedures A master object can use these entries if it doesn't implement one of these procedures Say you don't have any Return the empty list Delete Parts of the Scene Tree For now, we won't delete the built-in instances. Removes all but WORLD, SCREEN and sceneAssembly. Assumes for now that WORLD, and SCREEN are the first 2 coordsystems on the list. Removes all but "block", "sphere", "cone", and "cylinder" from current scene. Assumes for now that "sphere","cone", and "cylinder", and "block" are the first five master objects. Tree walk through the assembly deleting all of its coordinate systems. Then, cut the assembly loose and feed it to the garbage collector. A simple list remove operation. Not break up the assembly and its sons, nor does it delete their coordinate systems. This routine is called by MoveToFrontOfAssembly to splice an assembly out of an AssemblyList Other List Auxiliaries Removing Duplicates **** Naive algorithm for now. Go through moList. Add anything to uniqueList which it doesn't already have Find all elements of moList1 which are not in moList2 Currently this has O[n2] behavior. Since moList typically has 4 elements, this is alright. Improve if moList grows. Draw Parts of the Scene Tree Clip the picture to the camera's frame CSGGraphics.Clip[dc, camera]; Draw the current bounding frame if there is one. Clip the picture to the camera's frame CSGGraphics.Clip[dc, camera]; Draw the current bounding frame if there is one. Graphics.SetColor[dc, assembly.color]; Eliminate most back-facing surfaces at this point by a simple test. Get a list of surfaces from each subassembly of "assembly" and draw them with the Painter's Algorithm (back to front) Count the total number of surfaces and make a priority queue of the appropriate size. Now put the surfaces on the queue Draw a background color. Draw the current bounding frame if there is one. Take the surfaces off the queue in order and draw them Draw the current bounding frame if there is one. Graphics.SetColor[dc, assembly.color]; ΚP˜Ihead1šœ™Iproc– "Cedar" stylešœ1™1šœQ™QL– "Cedar" stylešΟk œœ˜CL– "Cedar" stylešœS˜S– "Cedar" stylešœPœœœ(˜œLš˜——šœ™Jšœœœ ˜Jšœ œ˜(Jšœœœ˜-Jšœœœ˜0Jšœœ˜"Jšœœ˜+Jšœ œ˜)Jšœ œœ ˜$Jšœ œœ ˜Jšœ œœ ˜"Jšœ œ˜(Jšœ œœ˜%Jšœœ˜2Jšœœ ˜4Jšœ œœ ˜!Jšœ œ˜,Jšœ œ˜'Jšœœ˜ Jšœ œ˜Jšœ œ˜!Jšœ œœ1˜GJšœœ˜"Jšœ œœ˜#Jšœœœ˜&Jšœœœ˜Jšœœœ˜Jšœœ˜!—šœ™Ihead2šœ/™/Jšœ œœ ˜!Jšœ œ˜/Jšœœœ ˜Jšœ œ˜)Jšœ œœ ˜!Jšœ œ˜.Jšœœœ˜)Jšœœ"˜7Jšœ œœ˜'Jšœœ˜.Jšœœ˜0Mšœ™Jšœœœ˜3Jšœœ&˜@Jšœœ(˜CJšœ œ˜.Jšœ œ˜,Mšœ™Jšœœœ˜)Jšœœ!˜6Jšœœ#˜9Jšœ œœ ˜$Jšœœœ˜4Jšœœ ˜4Jšœœ˜0Jšœœ!˜6Jšœœ)˜Fšœœ'˜BJšœœœ˜+Jšœœ"˜8Jšœœ#˜:—Jšœœ'˜BJšœœ"˜8šœ™J– "Cedar" stylešœU™U—J˜šΟb œœ˜#Jšœ$˜$Jšœ˜Jšœ˜—šžœœ˜3Jšœ$˜$Jšœ˜Jšœ˜—Jšžœœ2˜HJšœœ*˜>Jšžœœ-˜Dšžœœœ˜FJšœ™—šžœœœœ˜DJ™—Jšžœœ3˜PJšžœœ/˜G—šœ™š Οnœœœœœ œ˜`Jšœ(˜(Jšœx˜xJšœœœœ˜Jšœ œœ˜4Jšœ˜Jšœ$˜$—J˜š Ÿœœœ"œ œ˜bJšœ%œ$œ'œ#œœœ˜­J™0š œœœ`œœ˜’Jšœ'œœœ˜;—Jšœ˜Jšœ0˜0Jšœ'˜'J˜—šŸœœœœ˜FJšœ$˜$Jšœ œœ˜šœ^˜^Jšœ*œœ˜;—Jšœ œœ˜Jšœ œœ˜3Jšœ˜Jšœ ˜ —J˜šŸœœœœ˜IJšœ'˜'Jšœ œœ˜šœm˜mJšœ9œœ˜J—Jšœ œœ˜Jšœ œœ˜3Jšœ˜Jšœ#˜#—J˜šŸ œœœ˜*Jšœœœ ˜=Jšœ˜Jšœ˜Jšœ˜—J˜šŸœœœ˜1Jšœ1™1JšœQ™QJšœ/˜/Jšœ˜Jšœ˜Jšœ œ˜"Jšœ˜—Jšœ˜šŸœœœ˜2JšœM™MJšœd™dJšœ6˜6Jšœ˜Jšœ˜Jšœ˜Jšœ œ˜ Jšœ˜J˜—š Ÿœœœ;œ œ˜€Jšœœ˜,Jšœ@˜@Jšœœ&˜/Jšœœ˜ Jšœ˜—J˜š Ÿœœœ/œ œ˜ƒJšœŠ™ŠJšœœœ˜-šœœ˜=J˜ Jšœ"œœ˜5—š œœœ*œœ˜Hšœ œ˜J˜ Jšœ œ˜Jšœ/˜/Jšœ ˜ Jšœ˜Jšœ˜—Jšœ*˜.—Jšœ˜Jšœ œ˜Jšœ˜J˜—š Ÿœœœ/œ œ˜‹JšœΣ™ΣJšœœœ˜-šœœ˜=Jšœ"œœ˜5—š œœœ*œœ˜Hšœ œ˜Jšœ œ˜Jšœ/˜/Jšœ ˜ Jšœ˜Jšœ˜—Jšœ*˜.—Jšœ˜Jšœ œ˜Jšœ˜J˜—šŸœœœ ˜CJšœ,˜,šœ œ˜Jšœ?˜?Jšœœ˜—Jšœœ˜Jšœ˜J˜—šŸœœœ(˜Oš œœœ"œœ˜FJšœ)˜)—Jšœ˜Jšœ˜——™™šŸœœœœ#˜eJ™kJšœ˜Jšœ œ˜šœ,œœ˜BJšœ˜šœœ,˜6Jšœ œ˜&——Jšœ˜J˜J˜—š Ÿœœœœœœ˜^šœ,œœ˜BJš œ%œœœœ˜?—Jšœ˜Jšœœ˜Jšœ˜J˜—šŸœœœ&œ,˜wJšœ5™5Jšœœ˜šœ-œœ˜Cšœœ,˜6Jšœœ"˜<——Jšœ˜J˜J˜—šŸœœœœ˜aJšœu™uJšœœ˜ šœ,œœ˜BJšœD˜D—Jšœ˜J˜———šœ™šŸ œœœ9˜OJ˜šœD˜DJšœ&™&—J˜Jšœ™J™0šœœœ˜%Jšœ*˜*Jšœ"˜"Jšœ˜—Jšœ˜Jšœ.˜.Jšœ2˜2Jšœ4˜4Jšœœ˜$J˜Jšœ˜Jšžœœœœ˜)—šŸœœœ9˜YJšœœ˜Jšœœ˜ Jšœ˜š œœœœ'œœ˜UJšœ˜Jšœœ˜ šœI˜ILšœ,œœ˜>—Lšœœ/˜<—Jšœ˜J˜—šŸœœœ9˜[Jšœœ˜Jšœ˜Jšœœ˜ š œœœœ'œœ˜UJšœ˜Jšœœ˜ šœI˜ILšœ,œœ˜>—Lšœœ1˜>—Jšœ˜J˜—šŸœœœ9˜\Jšœœ˜Jšœ˜Jšœœ˜ š œœœœ'œœ˜UJšœ˜Jšœœ˜ šœI˜ILšœ,œœ˜>—Lšœœ2˜?—Jšœ˜J˜J˜—šŸ œœœM˜fšœ>˜>Jšœ&™&—Jšœ™Jšœ˜Jšœ6˜6Jšœ:˜:Jšœ<˜˜>Jšœ˜—Jšœœ˜Jšœ˜—Jšœ˜š Ÿœœœœ œ˜ZJšœ˜š œœœ œœ˜DJšœ<˜<—Jšœ˜Jšœ˜—Jšœ˜š Ÿœœœœ œ˜Wšœœ˜ JšœH˜HJšœ7˜7Jšœœ˜—Jšœ˜—Jšœ˜šŸœœœE˜iš œœœ œœ˜DJšœ,˜,—Jšœ˜Jšœ˜—Jšœ˜šŸœœœF˜fJšœ˜Jšœ˜šœœ˜ JšœD˜Dšœ˜JšœC˜Cšœ$œ œ˜>Jšœ˜Jšœl˜lJšœ˜JšœC™CJšœœ"˜?—Jšœ˜Jšœ˜—Jšœœ˜—Jšœ˜—Jšœ˜šŸœœœ!œœœœœ˜dJšœœ˜Jšœœ˜Jšœ˜Jšœ˜—J˜šŸœœœM˜mJšœu™uJšœU™UJšœœ%˜