<> <> <> DIRECTORY CoordSys, CSGGraphics, Imager, ImagerBackdoor, ImagerColor, ImagerColorPrivate, ImagerFont, ImagerPath, Matrix3d, Shading, SVPolygon3d, Real, Rope, SV2d, SV3d, SVDraw, SVLines2d, SVVector3d, SVModelTypes; CSGGraphicsImpl: CEDAR PROGRAM IMPORTS CoordSys, Imager, ImagerBackdoor, ImagerColor, ImagerColorPrivate, ImagerFont, ImagerPath, Matrix3d, Rope, Shading, SVDraw, SVLines2d, SVPolygon3d, SVVector3d EXPORTS CSGGraphics = BEGIN Artwork: TYPE = SVModelTypes.Artwork; Camera: TYPE = REF CameraObj; CameraObj: TYPE = SVModelTypes.CameraObj; Color: TYPE = Imager.Color; CoordSystem: TYPE = SVModelTypes.CoordSystem; DrawStyle: TYPE = SVModelTypes.DrawStyle; FrameBox: TYPE = SVModelTypes.FrameBox; LightSource: TYPE = SVModelTypes.LightSource; LightSourceList: TYPE = Shading.LightSourceList; Matrix4by4: TYPE = SV3d.Matrix4by4; Plane: TYPE = SV3d.Plane; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Poly3d: TYPE = SV3d.Poly3d; Projection: TYPE = SVModelTypes.Projection; -- {perspective, orthogonal} QualityMode: TYPE = SVModelTypes.QualityMode; Ray2d: TYPE = SV2d.Ray2d; StrokeEnd: TYPE = Imager.StrokeEnd; Vector3d: TYPE = SV3d.Vector3d; CreateCamera: PUBLIC PROC [viewName: Rope.ROPE, coordSys: CoordSystem, screenCS: CoordSystem, resolution: REAL, focalLength: REAL, projection: Projection, frame: FrameBox, clippingPlanes: LIST OF Plane, visibleAssemblies: LIST OF Rope.ROPE, style: DrawStyle, colorFilm: BOOL, useBoundBoxes: BOOL, useBoundSpheresForShadows: BOOL] RETURNS [camera: Camera] = { camera _ NEW[CameraObj _ [viewName, coordSys, screenCS, resolution, focalLength, projection, frame, clippingPlanes, visibleAssemblies, style, colorFilm, fast, FALSE, useBoundBoxes, useBoundSpheresForShadows, [0,0,0]]]; }; -- end of CreateCamera PlaceCamera: PUBLIC PROC [camera: Camera, focus: Point3d, origin: Point3d, slant: REAL] = { zAxis: Vector3d _ SVVector3d.Sub[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: Imager.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]; Imager.ClipRectangle[dc, [downLeft[1], downLeft[2], upRight[1] - downLeft[1], upRight[2] - downLeft[2]]]; }; DrawFrame: PUBLIC PROC [dc: Imager.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]; SVDraw.LineSandwich[dc, downLeft[1], downLeft[2], downLeft[1], upRight[2]]; SVDraw.LineSandwich[dc, downLeft[1], upRight[2], upRight[1], upRight[2]]; SVDraw.LineSandwich[dc, upRight[1], upRight[2], upRight[1], downLeft[2]]; SVDraw.LineSandwich[dc, upRight[1], downLeft[2], downLeft[1], downLeft[2]]; }; -- fast, low quality DoProjection: PUBLIC PROC [point3d: Point3d, camera: Camera] RETURNS [newPoint: Point2d] = { <> IF camera.projection = orthogonal THEN { newPoint[1] _ point3d[1]; newPoint[2] _ point3d[2]; RETURN; } ELSE RETURN[Matrix3d.PerspectiveTrans[point3d, camera.focalLength]]; }; LocalToCamera: PUBLIC PROC [localPoint: Point3d, localCS: CoordSystem] RETURNS [cameraPoint: Point3d] = { cameraPoint _ Matrix3d.Update[localPoint, localCS.wrtCamera]; -- puts in CAMERA }; LocalToWorld: PUBLIC PROC [localPt: Point3d, localCS: CoordSystem] RETURNS [worldPt: Point3d] = { worldPt _ Matrix3d.Update[localPt, localCS.wrtWorld]; }; VectorToWorld: PUBLIC PROC [vector: Vector3d, localCS: CoordSystem] RETURNS [worldVector: Vector3d] = { worldVector _ Matrix3d.UpdateVectorWithInverse[localCS.worldWRTlocal,vector]; }; SetCP: PUBLIC PROC [dc: Imager.Context, point3d: Point3d, camera: Camera, localCS: CoordSystem] = { camera.lastPoint _ LocalToCamera[point3d, localCS]; -- puts into CAMERA coords and stores in camera. }; SetCPAbsolute: PUBLIC PROC [dc: Imager.Context, point3d: Point3d, camera: Camera] = { camera.lastPoint _ point3d; }; DrawTo: PUBLIC PROC [dc: Imager.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[camera.lastPoint, thisCameraPoint, camera.clippingPlanes]; IF nullSegment THEN {camera.lastPoint _ thisCameraPoint; RETURN}; lastScreenPoint _ DoProjection[newP1, camera]; lastScreenPoint _ CoordSys.CameraToScreen[lastScreenPoint, camera.screenCS]; -- puts into SCREEN coords thisScreenPoint _ DoProjection[newP2, camera]; thisScreenPoint _ CoordSys.CameraToScreen[thisScreenPoint, camera.screenCS]; -- puts into SCREEN coords IF camera.quality = quality THEN { -- use round-ended strokes line: ImagerPath.Trajectory; line _ ImagerPath.MoveTo[[lastScreenPoint[1], lastScreenPoint[2]]]; line _ ImagerPath.LineTo[line, [thisScreenPoint[1], thisScreenPoint[2]]]; Imager.SetStrokeWidth[dc, 1]; Imager.SetStrokeEnd[dc, round]; Imager.MaskStrokeTrajectory[dc, line, FALSE]; } ELSE { -- not a quality camera. Just draw line segment. Imager.MaskVector[dc, [lastScreenPoint[1], lastScreenPoint[2]], [thisScreenPoint[1], thisScreenPoint[2]]]; }; camera.lastPoint _ thisCameraPoint; }; -- end of DrawTo DrawToAbsolute: PUBLIC PROC [dc: Imager.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[camera.lastPoint, thisCameraPoint, camera.clippingPlanes]; IF nullSegment THEN {camera.lastPoint _ thisCameraPoint; RETURN}; lastScreenPoint _ DoProjection[newP1, camera]; lastScreenPoint _ CoordSys.CameraToScreen[lastScreenPoint, camera.screenCS]; -- puts into SCREEN coords thisScreenPoint _ DoProjection[newP2, camera]; thisScreenPoint _ CoordSys.CameraToScreen[thisScreenPoint, camera.screenCS]; -- puts into SCREEN coords IF camera.quality = quality THEN { -- use round-ended strokes line: ImagerPath.Trajectory; line _ ImagerPath.MoveTo[[lastScreenPoint[1], lastScreenPoint[2]]]; line _ ImagerPath.LineTo[line, [thisScreenPoint[1], thisScreenPoint[2]]]; Imager.SetStrokeWidth[dc, 2]; Imager.SetStrokeEnd[dc, round]; Imager.MaskStrokeTrajectory[dc, line, FALSE]; } ELSE { -- not a quality camera. Just draw line segment. Imager.SetStrokeWidth[dc, 2]; Imager.MaskVector[dc, [lastScreenPoint[1], lastScreenPoint[2]], [thisScreenPoint[1], thisScreenPoint[2]]]; }; camera.lastPoint _ thisCameraPoint; }; -- end of DrawToAbsolute MoveTo: PUBLIC PROC [path: ImagerPath.Trajectory, point3d: Point3d, camera: Camera, localCS: CoordSystem] = { objPoint: Point2d; point3d _ LocalToCamera[point3d, localCS]; -- puts in CAMERA objPoint _ DoProjection[point3d, camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords path _ ImagerPath.MoveTo[[objPoint[1], objPoint[2]]]; }; MoveToAbsolute: PUBLIC PROC [path: ImagerPath.Trajectory, point3d: Point3d, camera: Camera] = { objPoint: Point2d; objPoint _ DoProjection[point3d, camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords path _ ImagerPath.MoveTo[[objPoint[1], objPoint[2]]]; }; <> LineTo: PUBLIC PROC [path: ImagerPath.Trajectory, point3d: Point3d, camera: Camera, localCS: CoordSystem] = { objPoint: Point2d; point3d _ LocalToCamera[point3d, localCS]; -- puts in CAMERA objPoint _ DoProjection[point3d, camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords path _ ImagerPath.LineTo[path, [objPoint[1], objPoint[2]]]; }; LineToAbsolute: PUBLIC PROC [path: ImagerPath.Trajectory, point3d: Point3d, camera: Camera] = { objPoint: Point2d; objPoint _ DoProjection[point3d, camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords path _ ImagerPath.LineTo[path, [objPoint[1], objPoint[2]]]; }; DrawStroke: PUBLIC PROC [dc: Imager.Context, path: ImagerPath.Trajectory, width: REAL _ 1, closed: BOOLEAN _ FALSE, ends: StrokeEnd _ butt] = { Imager.SetStrokeWidth[dc, width]; Imager.SetStrokeEnd[dc, ends]; Imager.MaskStrokeTrajectory[dc, path, closed]; }; DrawFilled: PUBLIC PROC[dc: Imager.Context, path: ImagerPath.Trajectory, parityFill: BOOLEAN _ FALSE] = { Imager.MaskFillTrajectory[dc, path, parityFill]; }; DrawPolygonAbsolute: PUBLIC PROC [dc: Imager.Context, poly: Poly3d, width: REAL _ 1, ends: StrokeEnd _ butt, camera: Camera] = { <> <> outline: ImagerPath.Trajectory; objPoint: Point2d; <> poly _ SVPolygon3d.ClipPolyToPlanes[poly, camera.clippingPlanes]; objPoint _ DoProjection[poly[0], camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords outline _ ImagerPath.MoveTo[[objPoint[1], objPoint[2]]]; FOR i: NAT IN[1..poly.len) DO objPoint _ DoProjection[poly[i], camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords outline _ ImagerPath.LineTo[outline, [objPoint[1], objPoint[2]]]; ENDLOOP; Imager.SetStrokeWidth[dc, width]; Imager.SetStrokeEnd[dc, ends]; Imager.MaskStrokeTrajectory[dc, outline, TRUE]; }; DrawLine: PUBLIC PROC [dc: Imager.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 _ DoProjection[newP1, camera]; lastScreenPoint _ CoordSys.CameraToScreen[lastScreenPoint, camera.screenCS]; -- puts into SCREEN coords thisScreenPoint _ DoProjection[newP2, camera]; thisScreenPoint _ CoordSys.CameraToScreen[thisScreenPoint, camera.screenCS]; -- puts into SCREEN coords IF camera.quality = quality THEN { -- use round-ended strokes line: ImagerPath.Trajectory; line _ ImagerPath.MoveTo[[lastScreenPoint[1], lastScreenPoint[2]]]; line _ ImagerPath.LineTo[line, [thisScreenPoint[1], thisScreenPoint[2]]]; Imager.SetStrokeWidth[dc, 1]; Imager.SetStrokeEnd[dc, round]; Imager.MaskStrokeTrajectory[dc, line, FALSE]; } ELSE { -- not a quality camera. Just draw line segment. Imager.MaskVector[dc, [lastScreenPoint[1], lastScreenPoint[2]], [thisScreenPoint[1], thisScreenPoint[2]]]; }; }; -- end of DrawLine DrawLineOnScreen: PUBLIC PROC [dc: Imager.Context, screenPoint1, screenPoint2: Point2d, camera: Camera] = { IF camera.quality = quality THEN { -- use round-ended strokes line: ImagerPath.Trajectory; line _ ImagerPath.MoveTo[[screenPoint1[1], screenPoint1[2]]]; line _ ImagerPath.LineTo[line, [screenPoint2[1], screenPoint2[2]]]; Imager.SetStrokeWidth[dc, 1]; Imager.SetStrokeEnd[dc, round]; Imager.MaskStrokeTrajectory[dc, line, FALSE]; } ELSE { -- not a quality camera. Just draw line segment. Imager.MaskVector[dc, [screenPoint1[1], screenPoint1[2]], [screenPoint2[1], screenPoint2[2]]]; }; }; DrawChar: PUBLIC PROC [dc: Imager.Context, c: CHARACTER, camera: Camera] = { screenPoint: Point2d; screenPoint _ DoProjection[camera.lastPoint, camera]; screenPoint _ CoordSys.CameraToScreen[screenPoint, camera.screenCS]; -- puts into SCREEN coords Imager.SetXY[dc, [screenPoint[1], screenPoint[2]]]; Imager.SetFont[dc, coordFont]; Imager.ShowChar[dc, c]; }; -- end of DrawChar DrawArea: PUBLIC PROC [dc: Imager.Context, localNormal: Vector3d, poly3d: Poly3d, artwork: Artwork, lightSources: LightSourceList, camera: Camera, localCS: CoordSystem] = { <> worldPoint3d: Point3d; objPoint: Point2d; colorshade: Imager.Color; r, g, b, scaleFactor: REAL; cameraNormal: Vector3d; worldNormal: Vector3d; eyepoint: Point3d; cameraPolygon: Poly3d; outline: ImagerPath.Trajectory; <> cameraNormal _ Matrix3d.UpdateVectorWithInverse[localCS.cameraWRTlocal, localNormal]; worldNormal _ Matrix3d.UpdateVectorWithInverse[localCS.worldWRTlocal, localNormal]; <> <> IF cameraNormal[3]<=0 THEN RETURN; <> <> worldPoint3d _ Matrix3d.Update[poly3d[0], localCS.wrtWorld]; <> eyepoint _ LocalToWorld[[0,0,camera.focalLength], camera.coordSys]; SELECT artwork.material FROM plastic => [r,g,b] _ Shading.DiffuseAndSpecularReflectance[eyepoint, worldNormal, worldPoint3d, artwork.color, lightSources]; chalk => [r,g,b] _ Shading.DiffuseReflectance[worldNormal, worldPoint3d, artwork.color, lightSources]; ENDCASE => ERROR; <> cameraPolygon _ CameraPolygon[poly3d, localCS]; <> cameraPolygon _ SVPolygon3d.ClipPolyToPlanes[cameraPolygon, camera.clippingPlanes]; <> objPoint _ DoProjection[cameraPolygon[0], camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords outline _ ImagerPath.MoveTo[[objPoint[1], objPoint[2]]]; <> FOR i: NAT IN[1..cameraPolygon.len) DO objPoint _ DoProjection[cameraPolygon[i], camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords outline _ ImagerPath.LineTo[outline, [objPoint[1], objPoint[2]]]; ENDLOOP; scaleFactor _ MAX[r,g,b]; IF scaleFactor > 1.0 THEN { r _ r/scaleFactor; g _ g/scaleFactor; b _ b/scaleFactor; }; colorshade _ ImagerColor.ColorFromRGB[[r,g,b]]; SetColor[dc, camera, colorshade]; Imager.MaskFillTrajectory[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: Imager.Context, cameraNormal: Vector3d, poly3d: Poly3d, artwork: Artwork, lightSources: LightSourceList, camera: Camera, localCS: CoordSystem] = { <> <> objPoint: Point2d; colorshade: Imager.Color; r, g, b, scaleFactor: REAL; worldNormal: Vector3d; eyepoint, worldPoint3d: Point3d; cameraPolygon: Poly3d; outline: ImagerPath.Trajectory; <> worldNormal _ Matrix3d.UpdateVectorWithInverse[camera.coordSys.worldWRTlocal, cameraNormal]; <> <> IF cameraNormal[3]<=0 THEN RETURN; <> worldPoint3d _ Matrix3d.Update[poly3d[0], localCS.wrtWorld]; <> eyepoint _ LocalToWorld[[0,0,camera.focalLength], camera.coordSys]; SELECT artwork.material FROM plastic => [r,g,b] _ Shading.DiffuseAndSpecularReflectance[eyepoint, worldNormal, worldPoint3d, artwork.color, lightSources]; chalk => [r,g,b] _ Shading.DiffuseReflectance[worldNormal, worldPoint3d, artwork.color, lightSources]; ENDCASE => ERROR; <> cameraPolygon _ CameraPolygon[poly3d, localCS]; <> cameraPolygon _ SVPolygon3d.ClipPolyToPlanes[cameraPolygon, camera.clippingPlanes]; <> objPoint _ DoProjection[cameraPolygon[0], camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords outline _ ImagerPath.MoveTo[[objPoint[1], objPoint[2]]]; <> FOR i: NAT IN[1..cameraPolygon.len) DO objPoint _ DoProjection[cameraPolygon[i], camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords outline _ ImagerPath.LineTo[outline, [objPoint[1], objPoint[2]]]; ENDLOOP; scaleFactor _ MAX[r,g,b]; IF scaleFactor > 1.0 THEN { r _ r/scaleFactor; g _ g/scaleFactor; b _ b/scaleFactor; }; colorshade _ ImagerColor.ColorFromRGB[[r,g,b]]; SetColor[dc, camera, colorshade]; Imager.MaskFillTrajectory[dc, outline]; }; DrawAreaAbsolute: PUBLIC PROC [dc: Imager.Context, poly3d: Poly3d, camera: Camera] = { <> outline: ImagerPath.Trajectory; objPoint: Point2d; <> poly3d _ SVPolygon3d.ClipPolyToPlanes[poly3d, camera.clippingPlanes]; objPoint _ DoProjection[poly3d[0], camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords outline _ ImagerPath.MoveTo[[objPoint[1], objPoint[2]]]; FOR i: NAT IN[1..poly3d.len) DO objPoint _ DoProjection[poly3d[i], camera]; objPoint _ CoordSys.CameraToScreen[objPoint, camera.screenCS]; -- puts into SCREEN coords outline _ ImagerPath.LineTo[outline, [objPoint[1], objPoint[2]]]; ENDLOOP; Imager.MaskFillTrajectory[dc, outline]; }; -- end of DrawAreaAbsolute DrawHorizonOfPlane: PUBLIC PROC [dc: Imager.Context, plane: Plane, camera: Camera, localCS: CoordSystem] = { <> plane _ Matrix3d.UpdatePlaneWithInverse[plane, localCS.cameraWRTlocal]; DrawHorizonOfPlaneAbsolute[dc, plane, camera]; }; -- end of DrawHorizonOfPlane DrawHorizonOfPlaneAbsolute: PUBLIC PROC [dc: Imager.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]; }; DrawLineOnScreen[dc, vanishScreen1, vanishScreen2, camera]; }; -- end of DrawHorizonOfPlaneAbsolute DrawInfiniteLine: PUBLIC PROC [dc: Imager.Context, p1, p2: Point3d, camera: Camera, localCS: CoordSystem] = { <> <> cameraP1, cameraP2: Point3d; screenP1, screenP2, vanishCamera, vanishScreen: Point2d; almostZero: REAL _ 1.0e-12; box: Imager.Rectangle _ ImagerBackdoor.GetBounds[dc]; count: NAT; ray: Ray2d; params: ARRAY[1..2] OF REAL; cameraP1 _ LocalToCamera[p1, localCS]; cameraP2 _ LocalToCamera[p2, localCS]; screenP1 _ DoProjection[cameraP1, camera]; screenP1 _ CoordSys.CameraToScreen[screenP1, camera.screenCS]; screenP2 _ DoProjection[cameraP2, camera]; 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.x, box.y, box.x + box.w, box.y + box.h]; 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 line: ImagerPath.Trajectory; line _ ImagerPath.MoveTo[[vanishScreen[1], vanishScreen[2]]]; line _ ImagerPath.LineTo[line, [screenP2[1], screenP2[2]]]; Imager.SetStrokeWidth[dc, 1]; Imager.SetStrokeEnd[dc, round]; Imager.MaskStrokeTrajectory[dc, line, FALSE]; } ELSE { -- not a quality camera. Just draw line segment. Imager.MaskVector[dc, [vanishScreen[1], vanishScreen[2]], [screenP2[1], screenP2[2]]]; }; } ELSE { <> <> ray _ SVLines2d.CreateRayFromPoints[screenP1, screenP2]; [count, params] _ SVLines2d.LineRayMeetsBox[ray, box.x, box.y, box.x + box.w, box.y + box.h]; 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 line: ImagerPath.Trajectory; line _ ImagerPath.MoveTo[[screenP1[1], screenP1[2]]]; line _ ImagerPath.LineTo[line, [screenP2[1], screenP2[2]]]; Imager.SetStrokeWidth[dc, 1]; Imager.SetStrokeEnd[dc, round]; Imager.MaskStrokeTrajectory[dc, line, FALSE]; } ELSE { -- not a quality camera. Just draw line segment. Imager.MaskVector[dc, [screenP1[1], screenP1[2]], [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: Imager.Context, p1, p2: Point3d, camera: Camera, localCS: CoordSystem] = {}; <> DrawInfinitePlaneWireFrame: PUBLIC PROC [dc: Imager.Context, plane: Plane, camera: Camera, localCS: CoordSystem] = { <> }; DrawInfinitePlaneWireFrameAbsolute: PUBLIC PROC [dc: Imager.Context, plane: Plane, camera: Camera, localCS: CoordSystem] = {}; <> DrawInfinitePlaneShaded: PUBLIC PROC [dc: Imager.Context, plane: Plane, artwork: Artwork, lightSources: LightSourceList, camera: Camera, localCS: CoordSystem] = {}; <> DrawInfinitePlaneShadedAbsolute: PUBLIC PROC [dc: Imager.Context, plane: Plane, artwork: Artwork, lightSources: LightSourceList, camera: Camera] = {}; <> SetColor: PRIVATE PROC [dc: Imager.Context, camera: Camera, color: Color] = { IF camera.colorFilm THEN Imager.SetColor [dc, color] ELSE { intensity: REAL _ ImagerColorPrivate.IntensityFromColor[NARROW[color]]; Imager.SetColor[dc, ImagerColor.ColorFromGray[1.0-intensity]] }; }; 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; }; ProjectionToRope: PUBLIC PROC [projection: Projection] RETURNS [rope: Rope.ROPE] = { SELECT projection FROM perspective => rope _ "perspect"; orthogonal => rope _ "ortho"; ENDCASE => ERROR UpdateThisCode; }; RopeToProjection: PUBLIC PROC [rope: Rope.ROPE] RETURNS [projection: Projection, success: BOOL] = { <> success _ TRUE; SELECT TRUE FROM Rope.Equal[rope, "perspect", FALSE] => projection _ perspective; Rope.Equal[rope, "ortho", FALSE] => projection _ orthogonal; ENDCASE => success _ FALSE; }; UpdateThisCode: PUBLIC ERROR = CODE; coordFont: ImagerFont.Font; Init: PROC [] = { coordFont _ ImagerFont.Scale[ImagerFont.Find["xerox/TiogaFonts/Helvetica14B"], 1.0]; }; Init[]; END.