<> <> <> DIRECTORY CoordSys, CGColor, CSGGraphics, DisplayList3d, Graphics, GraphicsBasic, GraphicsColor, Inline, Matrix3d, Shading, SVArtwork, SVPolygon3d, Real, Rope, SV2d, SVLines2d, SVVector3d; CSGGraphicsImpl: PROGRAM IMPORTS CoordSys, Graphics, GraphicsColor, Matrix3d, Rope, Shading, SVLines2d, SVPolygon3d, SVVector3d EXPORTS CSGGraphics = BEGIN Artwork: TYPE = REF ArtworkObj; ArtworkObj: TYPE = SVArtwork.ArtworkObj; Color: TYPE = GraphicsColor.Color; CoordSysObj: TYPE = CoordSys.CoordSysObj; CoordSystem: TYPE = REF CoordSysObj; DrawStyle: TYPE = CSGGraphics.DrawStyle;-- {wire, shaded, rayCast, normals}; LightSource: TYPE = REF LightSourceObj; LightSourceList: TYPE = Shading.LightSourceList; -- LIST OF LightSource; LightSourceObj: TYPE = Shading.LightSourceObj; Matrix4by4: TYPE = Matrix3d.Matrix4by4; Plane: TYPE = SVPolygon3d.Plane; Point2d: TYPE = Matrix3d.Point2d; Point3d: TYPE = Matrix3d.Point3d; Poly3d: TYPE = REF Poly3dObj; Poly3dObj: TYPE = SVPolygon3d.Poly3dObj; QualityMode: TYPE = CSGGraphics.QualityMode; Ray2d: TYPE = SV2d.Ray2d; StrokeEnds: TYPE = Graphics.StrokeEnds; Vector: TYPE = SVVector3d.Vector; Camera: TYPE = REF CameraObj; CameraObj: TYPE = CSGGraphics.CameraObj; FrameBox: TYPE = REF FrameBoxObj; FrameBoxObj: TYPE = CSGGraphics.FrameBoxObj; globalCPx, globalCPy: REAL _ 0; globalStrokeWidth: REAL _ 0; globalLine: Graphics.Path _ Graphics.NewPath[2]; lastCameraPoint: Point3d; CreateCamera: PUBLIC PROC [viewName: Rope.ROPE, coordSys: CoordSystem, screenCS: CoordSystem, resolution: REAL, focalLength: REAL, clippingPlanes: LIST OF Plane, visibleAssemblies: LIST OF Rope.ROPE, style: DrawStyle] RETURNS [camera: Camera] = { frameBox: FrameBox _ NEW[FrameBoxObj _ [[0,0], [0,0], TRUE]]; camera _ NEW[CameraObj _ [viewName, coordSys, screenCS, resolution, focalLength, frameBox, clippingPlanes, visibleAssemblies, style, TRUE, fast, FALSE]]; }; -- end of CreateCamera PlaceCamera: PUBLIC PROC [camera: Camera, focus: Point3d, origin: Point3d, slant: REAL] = { zAxis: Vector _ SVVector3d.Difference[origin, focus]; <> camera.coordSys.mat _ Matrix3d.MakeHorizontalMatFromZAxis[zAxis, origin]; <> camera.coordSys.mat _ Matrix3d.LocalRotateAboutZAxis[camera.coordSys.mat, slant]; }; SetFocalLengthCamera: PUBLIC PROC [camera: Camera, focalLength: REAL] = { camera.focalLength _ focalLength; }; SetQualityCamera: PUBLIC PROC [camera: Camera, qual: QualityMode] = { <> camera.quality _ qual; }; ColorFilmCamera: PUBLIC PROC [camera: Camera, colorFilm: BOOL] = { camera.colorFilm _ colorFilm; }; Clip: PUBLIC PROC [dc: Graphics.Context, camera: Camera] = { clipPath: Graphics.Path; downLeft, upRight: Point2d; IF camera.frame.fullScreen THEN RETURN; clipPath _ Graphics.NewPath[4]; downLeft _ CoordSys.CameraToScreen[camera.frame.downLeft, camera.screenCS]; <> upRight _ CoordSys.CameraToScreen[camera.frame.upRight, camera.screenCS]; Graphics.MoveTo[clipPath, downLeft[1], downLeft[2]]; Graphics.LineTo[clipPath, downLeft[1], upRight[2]]; Graphics.LineTo[clipPath, upRight[1], upRight[2]]; Graphics.LineTo[clipPath, upRight[1], downLeft[2]]; Graphics.ClipArea[dc, clipPath, FALSE, FALSE]; }; DrawFrame: PUBLIC PROC [dc: Graphics.Context, camera: Camera] = { downLeft, upRight: Point2d; IF camera.frame.fullScreen THEN RETURN; downLeft _ CoordSys.CameraToScreen[camera.frame.downLeft, camera.screenCS]; upRight _ CoordSys.CameraToScreen[camera.frame.upRight, camera.screenCS]; Graphics.SetCP[dc, downLeft[1], downLeft[2]]; Graphics.DrawTo[dc, downLeft[1], upRight[2]]; Graphics.DrawTo[dc, upRight[1], upRight[2]]; Graphics.DrawTo[dc, upRight[1], downLeft[2]]; Graphics.DrawTo[dc, downLeft[1], downLeft[2]]; }; -- fast, low quality GetPerspective: PUBLIC PROC [point3d: Point3d, camera: Camera] RETURNS [point2d: Point2d] = { point2d _ Matrix3d.GetPerspective[point3d, camera.focalLength]; }; -- assumes point3d expressed in CAMERA coordinate system. LocalToCamera: PUBLIC PROC [localPoint: Point3d, localCS: CoordSystem] RETURNS [cameraPoint: Point3d] = { cameraPoint _ Matrix3d.Update[localCS.wrtCamera,localPoint]; -- puts in CAMERA }; LocalToWorld: PUBLIC PROC [localPt: Point3d, localCS: CoordSystem] RETURNS [worldPt: Point3d] = { worldPt _ Matrix3d.Update[localCS.wrtWorld, localPt]; }; VectorToWorld: PUBLIC PROC [vector: Vector, localCS: CoordSystem] RETURNS [worldVector: Vector] = { worldVector _ Matrix3d.UpdateVectorWithInverse[localCS.worldWRTlocal,vector]; }; SetCP: PUBLIC PROC [dc: Graphics.Context, point3d: Point3d, camera: Camera, localCS: CoordSystem] = { lastCameraPoint _ LocalToCamera[point3d, localCS]; -- puts in CAMERA }; MoveTo: PUBLIC PROC [path: Graphics.Path, point3d: Point3d, camera: Camera, localCS: CoordSystem] = { objPoint: Point2d; point3d _ LocalToCamera[point3d, localCS]; -- puts in CAMERA objPoint _ Matrix3d.GetPerspective[point3d, camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.MoveTo[path, objPoint[1], objPoint[2]]; }; SetCPAbsolute: PUBLIC PROC [dc: Graphics.Context, point3d: Point3d, camera: Camera] = { lastCameraPoint _ point3d; }; MoveToAbsolute: PUBLIC PROC [path: Graphics.Path, point3d: Point3d, camera: Camera] = { objPoint: Point2d; objPoint _ Matrix3d.GetPerspective[point3d, camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.MoveTo[path, objPoint[1], objPoint[2]]; }; <> LineTo: PUBLIC PROC [path: Graphics.Path, point3d: Point3d, camera: Camera, localCS: CoordSystem] = { objPoint: Point2d; point3d _ LocalToCamera[point3d, localCS]; -- puts in CAMERA objPoint _ Matrix3d.GetPerspective[point3d, camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.LineTo[path, objPoint[1], objPoint[2]]; }; DrawTo: PUBLIC PROC [dc: Graphics.Context, point3d: Point3d, camera: Camera, localCS: CoordSystem] = { <> newP1, newP2, thisCameraPoint: Point3d; lastScreenPoint, thisScreenPoint: Point2d; newP1isP1, newP2isP2, nullSegment: BOOL; thisCameraPoint _ LocalToCamera[point3d, localCS]; -- puts in CAMERA [newP1, newP2, newP1isP1, newP2isP2, nullSegment] _ SVPolygon3d.ClipLineSegmentToPlanes[lastCameraPoint, thisCameraPoint, camera.clippingPlanes]; IF nullSegment THEN {lastCameraPoint _ thisCameraPoint; RETURN}; lastScreenPoint _ Matrix3d.GetPerspective[newP1, camera.focalLength]; lastScreenPoint _ CoordSys.CameraToScreen[lastScreenPoint, camera.screenCS]; -- puts into SCREEN coords thisScreenPoint _ Matrix3d.GetPerspective[newP2, camera.focalLength]; thisScreenPoint _ CoordSys.CameraToScreen[thisScreenPoint, camera.screenCS]; -- puts into SCREEN coords IF camera.quality = quality THEN { -- use round-ended strokes Graphics.MoveTo[globalLine, lastScreenPoint[1], lastScreenPoint[2]]; Graphics.LineTo[globalLine, thisScreenPoint[1], thisScreenPoint[2]]; Graphics.DrawStroke[dc, globalLine, 1, FALSE, round]; } ELSE { -- not a quality camera. Just draw line segment. Graphics.SetCP[dc, lastScreenPoint[1], lastScreenPoint[2]]; Graphics.DrawTo[dc, thisScreenPoint[1], thisScreenPoint[2]]; }; lastCameraPoint _ thisCameraPoint; }; -- end of DrawTo LineToAbsolute: PUBLIC PROC [path: Graphics.Path, point3d: Point3d, camera: Camera] = { objPoint: Point2d; objPoint _ Matrix3d.GetPerspective[point3d, camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.LineTo[path, objPoint[1], objPoint[2]]; }; DrawToAbsolute: PUBLIC PROC [dc: Graphics.Context, point3d: Point3d, camera: Camera] = { <> newP1, newP2, thisCameraPoint: Point3d; lastScreenPoint, thisScreenPoint: Point2d; newP1isP1, newP2isP2, nullSegment: BOOL; thisCameraPoint _ point3d; [newP1, newP2, newP1isP1, newP2isP2, nullSegment] _ SVPolygon3d.ClipLineSegmentToPlanes[lastCameraPoint, thisCameraPoint, camera.clippingPlanes]; IF nullSegment THEN {lastCameraPoint _ thisCameraPoint; RETURN}; lastScreenPoint _ Matrix3d.GetPerspective[newP1, camera.focalLength]; lastScreenPoint _ CoordSys.CameraToScreen[lastScreenPoint, camera.screenCS]; -- puts into SCREEN coords thisScreenPoint _ Matrix3d.GetPerspective[newP2, camera.focalLength]; thisScreenPoint _ CoordSys.CameraToScreen[thisScreenPoint, camera.screenCS]; -- puts into SCREEN coords IF camera.quality = quality THEN { -- use round-ended strokes Graphics.MoveTo[globalLine, lastScreenPoint[1], lastScreenPoint[2]]; Graphics.LineTo[globalLine, thisScreenPoint[1], thisScreenPoint[2]]; Graphics.DrawStroke[dc, globalLine, 1, FALSE, round]; } ELSE { -- not a quality camera. Just draw line segment. Graphics.SetCP[dc, lastScreenPoint[1], lastScreenPoint[2]]; Graphics.DrawTo[dc, thisScreenPoint[1], thisScreenPoint[2]]; }; lastCameraPoint _ thisCameraPoint; }; -- end of DrawToAbsolute DrawStroke: PUBLIC PROC [dc: Graphics.Context, path: Graphics.Path, width: REAL _ 1, closed: BOOLEAN _ FALSE, ends: StrokeEnds _ butt] = { Graphics.DrawStroke[dc, path, width, closed, ends]; }; DrawLine: PUBLIC PROC [dc: Graphics.Context, start: Point3d, end: Point3d, camera: Camera, localCS: CoordSystem] = { <> lastScreenPoint, thisScreenPoint: Point2d; newP1isP1, newP2isP2, nullSegment: BOOL; newP1, newP2: Point3d; start _ LocalToCamera[start, localCS]; -- puts in CAMERA end _ LocalToCamera[end, localCS]; -- puts in CAMERA [newP1, newP2, newP1isP1, newP2isP2, nullSegment] _ SVPolygon3d.ClipLineSegmentToPlanes[start, end, camera.clippingPlanes]; IF nullSegment THEN RETURN; lastScreenPoint _ Matrix3d.GetPerspective[newP1, camera.focalLength]; lastScreenPoint _ CoordSys.CameraToScreen[lastScreenPoint, camera.screenCS]; -- puts into SCREEN coords thisScreenPoint _ Matrix3d.GetPerspective[newP2, camera.focalLength]; thisScreenPoint _ CoordSys.CameraToScreen[thisScreenPoint, camera.screenCS]; -- puts into SCREEN coords IF camera.quality = quality THEN { -- use round-ended strokes Graphics.MoveTo[globalLine, lastScreenPoint[1], lastScreenPoint[2]]; Graphics.LineTo[globalLine, thisScreenPoint[1], thisScreenPoint[2]]; Graphics.DrawStroke[dc, globalLine, 1, FALSE, round]; } ELSE { -- not a quality camera. Just draw line segment. Graphics.SetCP[dc, lastScreenPoint[1], lastScreenPoint[2]]; Graphics.DrawTo[dc, thisScreenPoint[1], thisScreenPoint[2]]; }; }; -- end of DrawLine DrawOnScreen: PUBLIC PROC [dc: Graphics.Context, screenPoint1, screenPoint2: Point2d, camera: Camera] = { IF camera.quality = quality THEN { -- use round-ended strokes Graphics.MoveTo[globalLine, screenPoint1[1], screenPoint1[2]]; Graphics.LineTo[globalLine, screenPoint2[1], screenPoint2[2]]; Graphics.DrawStroke[dc, globalLine, 1, FALSE, round]; } ELSE { -- not a quality camera. Just draw line segment. Graphics.SetCP[dc, screenPoint1[1], screenPoint1[2]]; Graphics.DrawTo[dc, screenPoint2[1], screenPoint2[2]]; }; }; DrawHorizonOfPlane: PUBLIC PROC [dc: Graphics.Context, plane: Plane, camera: Camera, localCS: CoordSystem] = { <> plane _ Matrix3d.UpdatePlaneWithInverse[localCS.cameraWRTlocal, plane]; DrawHorizonOfPlaneAbsolute[dc, plane, camera]; }; -- end of DrawHorizonOfPlane DrawHorizonOfPlaneAbsolute: PUBLIC PROC [dc: Graphics.Context, plane: Plane, camera: Camera] = { <> <> almostZero: REAL _ 1.0e-12; t: REAL; vanishCamera1, vanishCamera2, vanishScreen1, vanishScreen2: Point2d; IF Abs[plane.A] <= almostZero AND Abs[plane.B] <= almostZero THEN RETURN; IF Abs[plane.B] > Abs[plane.A] THEN { y1, y2: REAL; <> <> <<-A + By -C = 0. y1 = (A+C)/B.>> <> y1 _ (plane.A+plane.C)/plane.B; y2 _ (plane.C-plane.A)/plane.B; <> t _ camera.focalLength; -- since we have chosen direction[3] to be -1 vanishCamera1[1] _ -t; vanishCamera1[2] _ t*y1; vanishScreen1 _ CoordSys.CameraToScreen[vanishCamera1, camera.screenCS]; <> vanishCamera2[1] _ t; vanishCamera2[2] _ t*y2; vanishScreen2 _ CoordSys.CameraToScreen[vanishCamera2, camera.screenCS]; } ELSE { x1, x2: REAL; <> <> <> x1 _ (plane.B+plane.C)/plane.A; x2 _ (plane.C-plane.B)/plane.A; <> t _ camera.focalLength; -- since we have chosen direction[3] to be -1 vanishCamera1[1] _ t*x1; vanishCamera1[2] _ -t; vanishScreen1 _ CoordSys.CameraToScreen[vanishCamera1, camera.screenCS]; <> vanishCamera2[1] _ t*x2; vanishCamera2[2] _ t; vanishScreen2 _ CoordSys.CameraToScreen[vanishCamera2, camera.screenCS]; }; DrawOnScreen[dc, vanishScreen1, vanishScreen2, camera]; }; -- end of DrawHorizonOfPlaneAbsolute DrawInfiniteLine: PUBLIC PROC [dc: Graphics.Context, p1, p2: Point3d, camera: Camera, localCS: CoordSystem] = { <> <> cameraP1, cameraP2: Point3d; screenP1, screenP2, vanishCamera, vanishScreen: Point2d; almostZero: REAL _ 1.0e-12; box: GraphicsBasic.Box _ Graphics.GetBounds[dc]; count: NAT; ray: Ray2d; params: ARRAY[1..2] OF REAL; cameraP1 _ LocalToCamera[p1, localCS]; cameraP2 _ LocalToCamera[p2, localCS]; screenP1 _ Matrix3d.GetPerspective[cameraP1, camera.focalLength]; screenP1 _ CoordSys.CameraToScreen[screenP1, camera.screenCS]; screenP2 _ Matrix3d.GetPerspective[cameraP2, camera.focalLength]; screenP2 _ CoordSys.CameraToScreen[screenP2, camera.screenCS]; <> IF Abs[cameraP2[3]-cameraP1[3]] > almostZero THEN { -- there is a vanishing point t: REAL; t _ -camera.focalLength/(cameraP2[3]-cameraP1[3]); vanishCamera[1] _ t*(cameraP2[1]-cameraP1[1]); vanishCamera[2] _ t*(cameraP2[2]-cameraP1[2]); vanishScreen _ CoordSys.CameraToScreen[vanishCamera, camera.screenCS]; <> IF cameraP2[3] > cameraP1[3] THEN ray _ SVLines2d.CreateRayFromPoints[vanishScreen, screenP2] ELSE ray _ SVLines2d.CreateRayFromPoints[vanishScreen, screenP1]; [count, params] _ SVLines2d.RayMeetsBox[ray, box.xmin, box.ymin, box.xmax, box.ymax]; IF count = 0 THEN RETURN; t _ params[count]; -- use the highest value of t. screenP2 _ SVLines2d.EvalRay[ray, t]; IF camera.quality = quality THEN { -- use round-ended strokes Graphics.MoveTo[globalLine, vanishScreen[1], vanishScreen[2]]; Graphics.LineTo[globalLine, screenP2[1], screenP2[2]]; Graphics.DrawStroke[dc, globalLine, 1, FALSE, round]; } ELSE { -- not a quality camera. Just draw line segment. Graphics.SetCP[dc, vanishScreen[1], vanishScreen[2]]; Graphics.DrawTo[dc, screenP2[1], screenP2[2]]; }; } ELSE { <> <> ray _ SVLines2d.CreateRayFromPoints[screenP1, screenP2]; [count, params] _ SVLines2d.LineRayMeetsBox[ray, box.xmin, box.ymin, box.xmax, box.ymax]; IF count = 2 THEN { screenP1 _ SVLines2d.EvalRay[ray, params[1]]; screenP2 _ SVLines2d.EvalRay[ray, params[2]]; IF camera.quality = quality THEN { -- use round-ended strokes Graphics.MoveTo[globalLine, screenP1[1], screenP1[2]]; Graphics.LineTo[globalLine, screenP2[1], screenP2[2]]; Graphics.DrawStroke[dc, globalLine, 1, FALSE, round]; } ELSE { -- not a quality camera. Just draw line segment. Graphics.SetCP[dc, screenP1[1], screenP1[2]]; Graphics.DrawTo[dc, screenP2[1], screenP2[2]]; }; }; }; }; -- end of DrawInfiniteLine Abs: PROC [r: REAL] RETURNS [REAL] = { RETURN[IF r >= 0 THEN r ELSE -r]; }; DrawInfiniteLineAbsolute: PUBLIC PROC [dc: Graphics.Context, p1, p2: Point3d, camera: Camera, localCS: CoordSystem] = {}; <> DrawInfinitePlaneWireFrame: PUBLIC PROC [dc: Graphics.Context, plane: Plane, camera: Camera, localCS: CoordSystem] = { <> }; DrawInfinitePlaneWireFrameAbsolute: PUBLIC PROC [dc: Graphics.Context, plane: Plane, camera: Camera, localCS: CoordSystem] = {}; <> DrawInfinitePlaneShaded: PUBLIC PROC [dc: Graphics.Context, plane: Plane, artwork: Artwork, lightSources: LightSourceList, camera: Camera, localCS: CoordSystem] = {}; <> DrawInfinitePlaneShadedAbsolute: PUBLIC PROC [dc: Graphics.Context, plane: Plane, artwork: Artwork, lightSources: LightSourceList, camera: Camera] = {}; <> 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]]}; }; DrawArea: PUBLIC PROC [dc: Graphics.Context, normal: Vector, poly3d: Poly3d, artwork: Artwork, lightSources: LightSourceList, camera: Camera, localCS: CoordSystem] = { <> worldPoint3d: Point3d; objPoint: Point2d; colorshade: Graphics.Color; cameraNormal: Vector; worldNormal: Vector; eyepoint: Point3d; cameraPolygon: Poly3d; outline: Graphics.Path _ Graphics.NewPath[poly3d.len]; <> cameraNormal _ Matrix3d.UpdateVectorWithInverse[localCS.cameraWRTlocal, normal]; worldNormal _ Matrix3d.UpdateVectorWithInverse[localCS.worldWRTlocal, normal]; <> <> IF cameraNormal[3]<=0 THEN RETURN; <> <> worldPoint3d _ Matrix3d.Update[localCS.wrtWorld, poly3d[0]]; <> eyepoint _ LocalToWorld[[0,0,camera.focalLength], camera.coordSys]; SELECT artwork.material FROM plastic => colorshade _ Shading.DiffuseAndSpecularReflectance[eyepoint, worldNormal, worldPoint3d, artwork.color, lightSources]; chalk => colorshade _ Shading.DiffuseReflectance[worldNormal, worldPoint3d, artwork.color, lightSources]; ENDCASE => ERROR; <> cameraPolygon _ CameraPolygon[poly3d, localCS]; <> cameraPolygon _ SVPolygon3d.ClipPolyToPlanes[cameraPolygon, camera.clippingPlanes]; <> objPoint _ Matrix3d.GetPerspective[cameraPolygon[0], camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.MoveTo[outline, objPoint[1], objPoint[2]]; <> FOR i: NAT IN[1..cameraPolygon.len) DO objPoint _ Matrix3d.GetPerspective[cameraPolygon[i], camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.LineTo[outline, objPoint[1], objPoint[2]]; ENDLOOP; SetColor[dc, camera, colorshade]; Graphics.DrawArea[dc, outline]; }; CameraPolygon: PRIVATE PROC [poly3d: Poly3d, localCS: CoordSystem] RETURNS [cameraPoly: Poly3d] = { <> cameraPoly _ SVPolygon3d.CreatePoly[poly3d.len]; FOR i: NAT IN [0..poly3d.len) DO cameraPoly _ SVPolygon3d.AddPolyPoint[cameraPoly, LocalToCamera[poly3d[i], localCS]]; ENDLOOP; }; DrawAreaNormalAbsolute: PUBLIC PROC [dc: Graphics.Context, normal: Vector, poly3d: Poly3d, artwork: Artwork, lightSources: LightSourceList, camera: Camera, localCS: CoordSystem] = { <> <> objPoint: Point2d; colorshade: Graphics.Color; worldNormal: Vector; eyepoint, worldPoint3d: Point3d; cameraPolygon: Poly3d; outline: Graphics.Path _ Graphics.NewPath[poly3d.len]; <> worldNormal _ Matrix3d.UpdateVectorWithInverse[camera.coordSys.worldWRTlocal, normal]; <> <> IF normal[3]<=0 THEN RETURN; <> worldPoint3d _ Matrix3d.Update[localCS.wrtWorld, poly3d[0]]; <> eyepoint _ LocalToWorld[[0,0,camera.focalLength], camera.coordSys]; SELECT artwork.material FROM plastic => colorshade _ Shading.DiffuseAndSpecularReflectance[eyepoint, worldNormal, worldPoint3d, artwork.color, lightSources]; chalk => colorshade _ Shading.DiffuseReflectance[worldNormal, worldPoint3d, artwork.color, lightSources]; ENDCASE => ERROR; <> cameraPolygon _ CameraPolygon[poly3d, localCS]; <> cameraPolygon _ SVPolygon3d.ClipPolyToPlanes[cameraPolygon, camera.clippingPlanes]; <> objPoint _ Matrix3d.GetPerspective[cameraPolygon[0], camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.MoveTo[outline, objPoint[1], objPoint[2]]; <> FOR i: NAT IN[1..cameraPolygon.len) DO objPoint _ Matrix3d.GetPerspective[cameraPolygon[i], camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.LineTo[outline, objPoint[1], objPoint[2]]; ENDLOOP; SetColor[dc, camera, colorshade]; Graphics.DrawArea[dc, outline]; }; DrawAreaAbsolute: PUBLIC PROC [dc: Graphics.Context, poly3d: Poly3d, camera: Camera] = { <> outline: Graphics.Path _ Graphics.NewPath[poly3d.len]; objPoint: Point2d; <> poly3d _ SVPolygon3d.ClipPolyToPlanes[poly3d, camera.clippingPlanes]; objPoint _ Matrix3d.GetPerspective[poly3d[0], camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.MoveTo[outline, objPoint[1], objPoint[2]]; FOR i: NAT IN[1..poly3d.len) DO objPoint _ Matrix3d.GetPerspective[poly3d[i], camera.focalLength]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords Graphics.LineTo[outline, objPoint[1], objPoint[2]]; ENDLOOP; Graphics.DrawArea[dc, outline]; }; -- end of DrawAreaAbsolute DrawStyleToRope: PUBLIC PROC [drawStyle: DrawStyle] RETURNS [rope: Rope.ROPE] = { SELECT drawStyle FROM wire => rope _ "wireframe"; shaded => rope _ "shaded"; rayCast => rope _ "rayCast"; normals => rope _ "normals"; ENDCASE => ERROR UpdateThisCode; }; RopeToDrawStyle: PUBLIC PROC [rope: Rope.ROPE] RETURNS [drawStyle: DrawStyle, success: BOOL] = { <> success _ TRUE; SELECT TRUE FROM Rope.Equal[rope, "wireframe", FALSE] => drawStyle _ wire; Rope.Equal[rope, "shaded", FALSE] => drawStyle _ shaded; Rope.Equal[rope, "rayCast", FALSE] => drawStyle _ rayCast; Rope.Equal[rope, "normals", FALSE] => drawStyle _ normals; ENDCASE => success _ FALSE; }; UpdateThisCode: PUBLIC ERROR = CODE; END.