<> <> <> DIRECTORY CoordSys, Imager, IO, RealFns, SV2d, SV3d, SVDraw3d, SVGraphics, SVModelTypes, SVPolygon2d, SVPolygon3d, SVSceneTypes, SVVector3d, SweepGeometry; SweepGeometryImpl: CEDAR PROGRAM IMPORTS CoordSys, IO, RealFns, SVDraw3d, SVGraphics, SVPolygon2d, SVPolygon3d, SVVector3d EXPORTS SweepGeometry = BEGIN Slice: TYPE = SVSceneTypes.Slice; Camera: TYPE = SVModelTypes.Camera; Matrix4by4: TYPE = SV3d.Matrix4by4; CoordSystem: TYPE = SVModelTypes.CoordSystem; LightSource: TYPE = SVModelTypes.LightSource; LightSourceList: TYPE = LIST OF LightSource; LinearMesh: TYPE = REF LinearMeshRecord; LinearMeshRecord: TYPE = SweepGeometry.LinearMeshRecord; MasterObject: TYPE = SVSceneTypes.MasterObject; Path: TYPE = SV2d.Path; PlanarSurface: TYPE = REF PlanarSurfaceObj; PlanarSurfaceObj: TYPE = SVSceneTypes.PlanarSurfaceObj; PlanarSurfaceList: TYPE = SVSceneTypes.PlanarSurfaceList; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Poly3d: TYPE = SV3d.Poly3d; Polygon: TYPE = SV2d.Polygon; RevoluteMesh: TYPE = REF RevoluteMeshRecord; RevoluteMeshRecord: TYPE = SweepGeometry.RevoluteMeshRecord; Shape: TYPE = SVSceneTypes.Shape; ToroidalMesh: TYPE = REF ToroidalMeshRecord; ToroidalMeshRecord: TYPE = SweepGeometry.ToroidalMeshRecord; Vector3d: TYPE = SV3d.Vector3d; globalImpatient: BOOL _ FALSE; TooFewPointsForShadedSweep: PUBLIC SIGNAL = CODE; LinearSweep: PUBLIC PROC [poly: Polygon, frontDepth: REAL _ 0.5, backDepth: REAL _ -0.5] RETURNS [meshRecord: LinearMesh] = { frontToBack, clockWise, thisNorm: Vector3d; iPlusOne: NAT; IF poly.len <=2 THEN SIGNAL TooFewPointsForShadedSweep; IF NOT SVPolygon2d.IsClockwisePoly[poly] THEN SVPolygon2d.InvertPolyInPlace[poly]; meshRecord _ NEW[LinearMeshRecord]; FOR i: NAT IN[1..poly.len] DO FOR j: NAT IN[1..2] DO meshRecord.array[i][j][1] _ poly[i-1][1]; meshRecord.array[i][j][2] _ poly[i-1][2]; ENDLOOP; meshRecord.array[i][1][3] _ frontDepth; meshRecord.array[i][2][3] _ backDepth; ENDLOOP; meshRecord.len _ poly.len; <> <> <> meshRecord.surfaces.front.normal _ [0,0,1]; meshRecord.surfaces.back.normal _ [0,0,-1]; <> <> <> FOR i: NAT IN[1..poly.len] DO iPlusOne _ IF i = poly.len THEN 1 ELSE i + 1; frontToBack _ SVVector3d.Sub[meshRecord.array[i][2],meshRecord.array[i][1]]; clockWise _ SVVector3d.Sub[meshRecord.array[iPlusOne][1],meshRecord.array[i][1]]; thisNorm _ SVVector3d.CrossProduct[clockWise,frontToBack]; meshRecord.surfaces.sides[i].normal _ thisNorm; ENDLOOP; }; -- end of ShadedLinearSweep RevoluteSweep: PUBLIC PROC [path: Path, linesOfLongitude: NAT _ 10] RETURNS [meshRecord: RevoluteMesh] = { leftToRight, rightToLeft, thisNorm: Vector3d; degreesPerLong: REAL; thisAngle: REAL; jPlusOne: NAT; poly: Polygon; <> poly _ SVPolygon2d.CreatePoly[path.len+2]; poly _ SVPolygon2d.PutPolyPoint[poly, 0 , [0, path[0][2]]]; poly _ SVPolygon2d.PutPolyPoint[poly, path.len + 1, [0, path[path.len -1][2]]]; poly _ SVPolygon2d.PartPolyGetsPartPath[path, 0, poly, 1, path.len]; <> FOR i: NAT IN[0..poly.len) DO IF poly[i][1] < 0 THEN poly[i][1] _ -poly[i][1]; ENDLOOP; IF NOT SVPolygon2d.IsClockwisePoly[poly] THEN SVPolygon2d.InvertPolyInPlace[poly]; path _ SVPolygon2d.SubPathOfPoly[poly, 1, path.len]; <> degreesPerLong _ 360.0/linesOfLongitude; meshRecord _ NEW[RevoluteMeshRecord]; FOR i: NAT IN[1..path.len] DO FOR j: NAT IN[1..linesOfLongitude] DO <> sin, cos: REAL; thisAngle _ j*degreesPerLong; sin _ RealFns.SinDeg[thisAngle]; cos _ RealFns.CosDeg[thisAngle]; meshRecord.array[i][j][1] _ path[i-1][1]*cos;-- assign new x from source x meshRecord.array[i][j][3] _ -path[i-1][1]*sin;-- assign new z from source x meshRecord.array[i][j][2] _ path[i-1][2];-- assign new y directly from source y ENDLOOP; -- next point of longitude ENDLOOP; -- next line of latitude meshRecord.linesOfLongitude _ linesOfLongitude; meshRecord.linesOfLatitude _ path.len; <> <> meshRecord.surfaces.top.normal _ [0,1,0]; meshRecord.surfaces.bottom.normal _ [0,-1,0]; <> <> <> <> FOR i: NAT IN[1..path.len-1] DO FOR j: NAT IN[1..linesOfLongitude] DO jPlusOne _ IF j = linesOfLongitude THEN 1 ELSE j + 1; leftToRight _ SVVector3d.Sub[meshRecord.array[i+1][jPlusOne], meshRecord.array[i][j]]; rightToLeft _ SVVector3d.Sub[meshRecord.array[i+1][j], meshRecord.array[i][jPlusOne]]; thisNorm _ SVVector3d.CrossProduct[rightToLeft,leftToRight]; meshRecord.surfaces.sides[i][j].normal _ thisNorm; ENDLOOP; ENDLOOP; }; -- end of ShadedRevoluteSweep ToroidalSweep: PUBLIC PROC [poly: Polygon, linesOfLongitude: NAT _ 10] RETURNS [meshRecord: ToroidalMesh] = { leftToRight, rightToLeft, thisNorm: Vector3d; degreesPerLong: REAL; thisAngle: REAL; iPlusOne, jPlusOne: NAT; <> FOR i: NAT IN[0..poly.len) DO IF poly[i][1] < 0 THEN poly[i][1] _ -poly[i][1]; ENDLOOP; IF NOT SVPolygon2d.IsClockwisePoly[poly] THEN SVPolygon2d.InvertPolyInPlace[poly]; <> degreesPerLong _ 360.0/linesOfLongitude; meshRecord _ NEW[ToroidalMeshRecord]; FOR i: NAT IN[1..poly.len] DO FOR j: NAT IN[1..linesOfLongitude] DO <> sin, cos: REAL; thisAngle _ j*degreesPerLong; sin _ RealFns.SinDeg[thisAngle]; cos _ RealFns.CosDeg[thisAngle]; meshRecord.array[i][j][1] _ poly[i-1][1]*cos; -- assign new x from source x meshRecord.array[i][j][3] _ -poly[i-1][1]*sin; -- assign new z from source x meshRecord.array[i][j][2] _ poly[i-1][2]; -- assign new y directly from source y ENDLOOP; -- next point of longitude ENDLOOP; -- next line of latitude meshRecord.linesOfLongitude _ linesOfLongitude; meshRecord.linesOfLatitude _ poly.len; <> <> <> <> <> FOR i: NAT IN[1..poly.len] DO iPlusOne _ IF i = poly.len THEN 1 ELSE i + 1; FOR j: NAT IN[1..linesOfLongitude] DO jPlusOne _ IF j = linesOfLongitude THEN 1 ELSE j + 1; leftToRight _ SVVector3d.Sub[meshRecord.array[iPlusOne][jPlusOne], meshRecord.array[i][j]]; rightToLeft _ SVVector3d.Sub[meshRecord.array[iPlusOne][j], meshRecord.array[i][jPlusOne]]; thisNorm _ SVVector3d.CrossProduct[rightToLeft,leftToRight]; meshRecord.surfaces.sides[i][j].normal _ thisNorm; ENDLOOP; ENDLOOP; }; -- end of ToroidalSweep GetLinearPoly: PUBLIC PROC [linMesh: LinearMesh] RETURNS [poly: Polygon] = { <> poly _ SVPolygon2d.CreatePoly[linMesh.len]; FOR i: NAT IN[1..linMesh.len] DO poly[i-1] _ [linMesh.array[i][1][1], linMesh.array[i][1][2]]; ENDLOOP; poly.len _ linMesh.len; }; -- end of GetLinearPoly GetRevolutePath: PUBLIC PROC [revMesh: RevoluteMesh] RETURNS [path: Path] = { <> path _ SVPolygon2d.CreatePath[revMesh.linesOfLatitude]; FOR i: NAT IN[1..revMesh.linesOfLatitude] DO path[i - 1] _ [revMesh.array[i][revMesh.linesOfLongitude][1], revMesh.array[i][revMesh.linesOfLongitude][2]]; ENDLOOP; path.len _ revMesh.linesOfLatitude; }; -- end of GetRevolutePath LineDrawLinearSweep: PUBLIC PROC [dc: Imager.Context, meshRecord: LinearMesh, camera: Camera, localCS: CoordSystem] = { <> localCamera: Matrix4by4 _ CoordSys.WRTCamera[localCS, camera.coordSys]; IF meshRecord.len <= 0 THEN RETURN; SVGraphics.SetCP[dc, meshRecord.array[1][1], camera, localCamera]; -- First Point of front plane FOR i: NAT IN[2..meshRecord.len] DO -- Draw front plane SVGraphics.DrawTo[dc, meshRecord.array[i][1], camera, localCamera]; ENDLOOP; SVGraphics.DrawTo[dc, meshRecord.array[1][1], camera, localCamera]; SVGraphics.SetCP[dc, meshRecord.array[1][2], camera, localCamera]; -- First point of rear plane FOR i: NAT IN[2..meshRecord.len] DO-- Draw rear plane SVGraphics.DrawTo[dc, meshRecord.array[i][2], camera, localCamera]; ENDLOOP; SVGraphics.DrawTo[dc, meshRecord.array[1][2], camera, localCamera]; FOR i: NAT IN[1..meshRecord.len] DO -- Draw Lines between Planes SVGraphics.SetCP[dc, meshRecord.array[i][1], camera, localCamera]; SVGraphics.DrawTo[dc, meshRecord.array[i][2], camera, localCamera]; ENDLOOP; }; LineDrawRevoluteSweep: PUBLIC PROC [dc: Imager.Context, meshRecord: RevoluteMesh, camera: Camera, localCS: CoordSystem] = { <> <> localCamera: Matrix4by4 _ CoordSys.WRTCamera[localCS, camera.coordSys]; IF globalImpatient THEN FOR lat: NAT _ 1, lat+(meshRecord.linesOfLatitude-1) UNTIL lat > meshRecord.linesOfLatitude DO <> SVGraphics.SetCP[dc, meshRecord.array[lat][1], camera, localCamera]; -- First point of this line of latitude FOR long: NAT IN[2..meshRecord.linesOfLongitude] DO SVGraphics.DrawTo[dc, meshRecord.array[lat][long], camera, localCamera]; ENDLOOP; <> SVGraphics.DrawTo[dc, meshRecord.array[lat][1], camera, localCamera]; ENDLOOP ELSE FOR lat: NAT IN [1..meshRecord.linesOfLatitude] DO <> SVGraphics.SetCP[dc, meshRecord.array[lat][1], camera, localCamera]; -- First point of this line of latitude FOR long: NAT IN[2..meshRecord.linesOfLongitude] DO SVGraphics.DrawTo[dc, meshRecord.array[lat][long], camera, localCamera]; ENDLOOP; <> SVGraphics.DrawTo[dc, meshRecord.array[lat][1], camera, localCamera]; ENDLOOP; <> FOR long: NAT IN[1..meshRecord.linesOfLongitude] DO SVGraphics.SetCP[dc, meshRecord.array[1][long], camera, localCamera]; -- First point of this line of longitude FOR lat: NAT IN[1..meshRecord.linesOfLatitude] DO SVGraphics.DrawTo[dc, meshRecord.array[lat][long], camera, localCamera]; ENDLOOP; <> ENDLOOP; }; LineDrawToroidalSweep: PUBLIC PROC [dc: Imager.Context, meshRecord: ToroidalMesh, camera: Camera, localCS: CoordSystem] = { <> localCamera: Matrix4by4 _ CoordSys.WRTCamera[localCS, camera.coordSys]; <> FOR lat: NAT IN [1..meshRecord.linesOfLatitude] DO SVGraphics.SetCP[dc, meshRecord.array[lat][1], camera, localCamera]; -- First point of this line of latitude FOR long: NAT IN[2..meshRecord.linesOfLongitude] DO SVGraphics.DrawTo[dc, meshRecord.array[lat][long], camera, localCamera]; ENDLOOP; <> SVGraphics.DrawTo[dc, meshRecord.array[lat][1], camera, localCamera]; ENDLOOP; <> FOR long: NAT IN[1..meshRecord.linesOfLongitude] DO SVGraphics.SetCP[dc, meshRecord.array[1][long], camera, localCamera]; -- First point of this line of longitude FOR lat: NAT IN[1..meshRecord.linesOfLatitude] DO SVGraphics.DrawTo[dc, meshRecord.array[lat][long], camera, localCamera]; ENDLOOP; SVGraphics.DrawTo[dc, meshRecord.array[1][long], camera, localCamera]; ENDLOOP; }; -- end of LineDrawToroidalSweep AverageVertex: PRIVATE PROC [meshRecord: LinearMesh] RETURNS [pt: Point2d] = { pt _ [meshRecord.array[1][1][1], meshRecord.array[1][1][2]]; FOR i: NAT IN [1..meshRecord.len] DO pt[1] _ pt[1] + meshRecord.array[i][1][1]; pt[2] _ pt[2] + meshRecord.array[i][1][2]; ENDLOOP; pt[1] _ pt[1]/meshRecord.len; pt[2] _ pt[2]/meshRecord.len; }; DrawNormalsLinearSweep: PUBLIC PROC [dc: Imager.Context, meshRecord: LinearMesh, camera: Camera, localCS: CoordSystem] = { thisNorm: Vector3d; upperLeftPoint, lowerRightPoint, midPoint: Point3d; iPlusOne: NAT; midPoint2d: Point2d; <> thisNorm _ meshRecord.surfaces.front.normal; midPoint2d _ AverageVertex[meshRecord]; midPoint _ [midPoint2d[1], midPoint2d[2], meshRecord.array[1][1][3]]; SVDraw3d.DrawLocalVector[dc,thisNorm,midPoint,camera,localCS]; <> thisNorm _ meshRecord.surfaces.back.normal; midPoint _ [midPoint2d[1], midPoint2d[2], meshRecord.array[1][2][3]]; SVDraw3d.DrawLocalVector[dc,thisNorm,midPoint,camera,localCS]; <> FOR i: NAT IN[1..meshRecord.len] DO iPlusOne _ IF i = meshRecord.len THEN 1 ELSE i + 1; thisNorm _ meshRecord.surfaces.sides[i].normal; upperLeftPoint _ meshRecord.array[iPlusOne][1]; lowerRightPoint _ meshRecord.array[i][2]; midPoint _ SVVector3d.Add[upperLeftPoint,lowerRightPoint]; midPoint _ SVVector3d.Scale[midPoint,0.5]; <> SVDraw3d.DrawLocalVector[dc,thisNorm,midPoint,camera,localCS]; ENDLOOP; }; -- end of DrawLinearNormals DrawNormalsRevoluteSweep: PUBLIC PROC [dc: Imager.Context, meshRecord: RevoluteMesh, camera: Camera, localCS: CoordSystem] = { thisNorm: Vector3d; upperLeftPoint, lowerRightPoint, midPoint: Point3d; iPlusOne, jPlusOne: NAT; <> thisNorm _ meshRecord.surfaces.top.normal; midPoint _ [0, meshRecord.array[1][1][2], 0]; SVDraw3d.DrawLocalVector[dc,thisNorm,midPoint,camera,localCS]; <> thisNorm _ meshRecord.surfaces.bottom.normal; midPoint _ [0, meshRecord.array[meshRecord.linesOfLatitude][1][2], 0]; SVDraw3d.DrawLocalVector[dc,thisNorm,midPoint,camera,localCS]; <> FOR i: NAT IN[1..meshRecord.linesOfLatitude-1] DO iPlusOne _ i + 1; FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO jPlusOne _ IF j = meshRecord.linesOfLongitude THEN 1 ELSE j + 1; thisNorm _ meshRecord.surfaces.sides[i][j].normal; upperLeftPoint _ meshRecord.array[i][j]; lowerRightPoint _ meshRecord.array[iPlusOne][jPlusOne]; midPoint _ SVVector3d.Add[upperLeftPoint,lowerRightPoint]; midPoint _ SVVector3d.Scale[midPoint,0.5]; <> SVDraw3d.DrawLocalVector[dc,thisNorm,midPoint,camera,localCS]; ENDLOOP; ENDLOOP; }; -- end of DrawNormalsRevoluteSweep DrawNormalsToroidalSweep: PUBLIC PROC [dc: Imager.Context, meshRecord: ToroidalMesh, camera: Camera, localCS: CoordSystem] = {thisNorm: Vector3d; upperLeftPoint, lowerRightPoint, midPoint: Point3d; iPlusOne, jPlusOne: NAT; FOR i: NAT IN[1..meshRecord.linesOfLatitude] DO iPlusOne _ IF i = meshRecord.linesOfLatitude THEN 1 ELSE i + 1; FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO jPlusOne _ IF j = meshRecord.linesOfLongitude THEN 1 ELSE j + 1; thisNorm _ meshRecord.surfaces.sides[i][j].normal; upperLeftPoint _ meshRecord.array[i][j]; lowerRightPoint _ meshRecord.array[iPlusOne][jPlusOne]; midPoint _ SVVector3d.Add[upperLeftPoint,lowerRightPoint]; midPoint _ SVVector3d.Scale[midPoint,0.5]; <> SVDraw3d.DrawLocalVector[dc,thisNorm,midPoint,camera,localCS]; ENDLOOP; ENDLOOP; }; -- end of DrawNormalsToroidalSweep PolyListLinear: PUBLIC PROC [f: IO.STREAM, meshRecord: LinearMesh] = { postPlusOne: NAT; <<>> <> <<>> f.PutF["vertices [%g]:\n", IO.int[2*meshRecord.len]]; FOR i: NAT IN[1..meshRecord.len] DO f.PutF[" %g %g %g\n", IO.real[meshRecord.array[i][1][1]], IO.real[meshRecord.array[i][1][2]], IO.real[meshRecord.array[i][1][3]] ]; <> <> <> <> ENDLOOP; FOR i: NAT IN[1..meshRecord.len] DO f.PutF[" %g %g %g\n", IO.real[meshRecord.array[i][2][1]], IO.real[meshRecord.array[i][2][2]], IO.real[meshRecord.array[i][2][3]] ]; <> <> <> <> ENDLOOP; f.PutChar[IO.CR]; <> f.PutF["faces [%g]:\n", IO.int[2+meshRecord.len]]; <> f.PutF["f ("]; FOR i: NAT IN[1..meshRecord.len] DO f.PutF["%g ", IO.int[i]]; ENDLOOP; f.PutF[")\n"]; <> f.PutF["f ("]; FOR i: NAT DECREASING IN[1..meshRecord.len] DO f.PutF["%g ", IO.int[i+meshRecord.len]]; ENDLOOP; f.PutF[")\n"]; <> FOR post: NAT IN[1..meshRecord.len] DO postPlusOne _ IF post = meshRecord.len THEN 1 ELSE post + 1; f.PutF["f (%g %g %g %g )\n", IO.int[postPlusOne], IO.int[postPlusOne+meshRecord.len], IO.int[post+meshRecord.len], IO.int[post]]; ENDLOOP; f.PutChar[IO.CR]; }; -- end of PolyListLinear PolyListRevolute: PUBLIC PROC [f: IO.STREAM, meshRecord: RevoluteMesh] = { longPlusOne: NAT; <> <<>> f.PutF["vertices [%g]:\n", IO.int[meshRecord.linesOfLatitude*meshRecord.linesOfLongitude]]; FOR lat: NAT IN[1..meshRecord.linesOfLatitude] DO FOR long: NAT IN[1..meshRecord.linesOfLongitude] DO f.PutF[" %g %g %g\n", IO.real[meshRecord.array[lat][long][1]], IO.real[meshRecord.array[lat][long][2]], IO.real[meshRecord.array[lat][long][3]] ]; <> <> ENDLOOP; ENDLOOP; f.PutChar[IO.CR]; <> <<>> f.PutF["faces [%g]:\n", IO.int[(meshRecord.linesOfLatitude-1)*meshRecord.linesOfLongitude+2]]; <> f.PutF["f ("]; FOR j: NAT DECREASING IN[1..meshRecord.linesOfLongitude] DO f.PutF["%g ", IO.int[j]]; <> ENDLOOP; f.PutF[")\n"]; <<>> <> f.PutF["f ("]; FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO f.PutF["%g ", IO.int[(meshRecord.linesOfLatitude-1)*meshRecord.linesOfLongitude + j]]; <> ENDLOOP; f.PutF[")\n"]; <> FOR lat: NAT IN[1..meshRecord.linesOfLatitude-1] DO FOR long: NAT IN[1..meshRecord.linesOfLongitude] DO longPlusOne _ IF long = meshRecord.linesOfLongitude THEN 1 ELSE long + 1; f.PutF["f (%g %g ", IO.int[lat*meshRecord.linesOfLongitude + long], IO.int[lat*meshRecord.linesOfLongitude + longPlusOne]]; f.PutF["%g %g )\n", IO.int[(lat-1)*meshRecord.linesOfLongitude + longPlusOne], IO.int[(lat-1)*meshRecord.linesOfLongitude + long]]; <> <> <> <> <> <> ENDLOOP; ENDLOOP; f.PutChar[IO.CR]; }; -- end of PolyListRevolute PolyListToroidal: PUBLIC PROC [f: IO.STREAM, meshRecord: ToroidalMesh] = { longPlusOne, latPlusOne: NAT; <> <<>> f.PutF["vertices [%g]:\n", IO.int[meshRecord.linesOfLatitude*meshRecord.linesOfLongitude]]; FOR lat: NAT IN[1..meshRecord.linesOfLatitude] DO FOR long: NAT IN[1..meshRecord.linesOfLongitude] DO f.PutF[" %g %g %g\n", IO.real[meshRecord.array[lat][long][1]], IO.real[meshRecord.array[lat][long][2]], IO.real[meshRecord.array[lat][long][3]] ]; <> ENDLOOP; ENDLOOP; f.PutChar[IO.CR]; <> <<>> <> f.PutF["faces [%g]:\n", IO.int[meshRecord.linesOfLatitude*meshRecord.linesOfLongitude]]; FOR lat: NAT IN[1..meshRecord.linesOfLatitude] DO FOR long: NAT IN[1..meshRecord.linesOfLongitude] DO latPlusOne _ IF lat = meshRecord.linesOfLatitude THEN 1 ELSE lat + 1; longPlusOne _ IF long = meshRecord.linesOfLongitude THEN 1 ELSE long + 1; f.PutF["f (%g %g ", IO.int[(latPlusOne-1)*meshRecord.linesOfLongitude + long], IO.int[(latPlusOne-1)*meshRecord.linesOfLongitude + longPlusOne]]; f.PutF["%g %g )\n", IO.int[(lat-1)*meshRecord.linesOfLongitude + longPlusOne], IO.int[(lat-1)*meshRecord.linesOfLongitude + long]]; <> <> <> <> <> <> ENDLOOP; ENDLOOP; }; -- end of PolyListToroidal CountPlanarSurfacesLinearSweep: PUBLIC PROC [meshRecord: LinearMesh] RETURNS [len: NAT] = { len _ meshRecord.len + 2; }; CountVerticesLinearSweep: PUBLIC PROC [meshRecord: LinearMesh] RETURNS [len: NAT] = { len _ 2*meshRecord.len; }; SortedLinearSurface: TYPE = REF SortedLinearSurfaceObj; SortedLinearSurfaceObj: TYPE = RECORD [ localWorld, localCamera: Matrix4by4, post: NAT, meshRecord: LinearMesh ]; PlanarSurfacesLinearSweep: PUBLIC PROC [meshRecord: LinearMesh, assembly: Slice, cameraCS: CoordSystem] RETURNS [psl: PlanarSurfaceList] = { poly: Poly3d _ SVPolygon3d.CreatePoly[meshRecord.len]; iPlusOne: NAT; avgDepth: REAL; shape: Shape _ NARROW[assembly.shape, Shape]; mo: MasterObject _ shape.mo; localCS: CoordSystem _ shape.coordSys; thisSortedSurface: PlanarSurface; <> <> FOR i: NAT IN[1..meshRecord.len] DO poly _ SVPolygon3d.AddPolyPoint[poly, meshRecord.array[i][1]]; ENDLOOP; avgDepth _ AverageDepthInCamera[poly, localCS, cameraCS]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [ whichSurface: NEW[SortedLinearSurfaceObj _ [CoordSys.WRTWorld[localCS], CoordSys.WRTCamera[localCS, cameraCS], 0, meshRecord]], assembly: assembly, normal: meshRecord.surfaces.front.normal, mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; <> SVPolygon3d.ClearPoly[poly]; FOR i: NAT IN[1..meshRecord.len] DO poly _ SVPolygon3d.AddPolyPoint[poly, meshRecord.array[i][2]]; ENDLOOP; avgDepth _ AverageDepthInCamera[poly, localCS, cameraCS]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [ whichSurface: NEW[SortedLinearSurfaceObj _ [CoordSys.WRTWorld[localCS], CoordSys.WRTCamera[localCS, cameraCS], meshRecord.len+1, meshRecord]], assembly: assembly, normal: meshRecord.surfaces.back.normal, mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; <> FOR i: NAT IN[1..meshRecord.len] DO SVPolygon3d.ClearPoly[poly]; iPlusOne _ IF i = meshRecord.len THEN 1 ELSE i + 1; poly _ SVPolygon3d.AddPolyPoint[poly, meshRecord.array[i][1]]; poly _ SVPolygon3d.AddPolyPoint[poly, meshRecord.array[i][2]]; poly _ SVPolygon3d.AddPolyPoint[poly, meshRecord.array[iPlusOne][2]]; poly _ SVPolygon3d.AddPolyPoint[poly, meshRecord.array[iPlusOne][1]]; avgDepth _ AverageDepthInCamera[poly, localCS, cameraCS]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [ whichSurface: NEW[SortedLinearSurfaceObj _ [CoordSys.WRTWorld[localCS], CoordSys.WRTCamera[localCS, cameraCS], i, meshRecord]], assembly: assembly, normal: meshRecord.surfaces.sides[i].normal, mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; ENDLOOP; }; -- end of PlanarSurfacesLinearSweep DrawPlanarSurfaceLinearSweep: PUBLIC PROC [dc: Imager.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = { hiddenLine: BOOL = FALSE; -- should be an argument poly3d: Poly3d; post, postPlusOne: NAT; avgDepth: REAL; meshRecord: LinearMesh; thisLinSurface: SortedLinearSurface; thisLinSurface _ NARROW[ps.whichSurface]; meshRecord _ thisLinSurface.meshRecord; post _ thisLinSurface.post; avgDepth _ ps.depth; SELECT post FROM 0 => {-- draw front face poly3d _ SVPolygon3d.CreatePoly[meshRecord.len]; FOR i: NAT IN[1..meshRecord.len] DO poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[i][1]]; ENDLOOP; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, thisLinSurface.localWorld, thisLinSurface.localCamera, hiddenLine]; }; meshRecord.len + 1 => { -- draw back face poly3d _ SVPolygon3d.CreatePoly[meshRecord.len]; FOR i: NAT IN[1..meshRecord.len] DO poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[i][2]]; ENDLOOP; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, thisLinSurface.localWorld, thisLinSurface.localCamera, hiddenLine]; }; IN [1..meshRecord.len] => {-- draw side face poly3d _ SVPolygon3d.CreatePoly[4]; postPlusOne _ IF post = meshRecord.len THEN 1 ELSE post + 1; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[post][1]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[post][2]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[postPlusOne][2]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[postPlusOne][1]]; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, thisLinSurface.localWorld, thisLinSurface.localCamera, hiddenLine]; }; ENDCASE => ERROR; }; -- end of DrawPlanarSurfaceLinearSweep MaxDepth: PROC [poly: Poly3d] RETURNS [maxDepth: REAL] = { maxDepth _ poly[0][3]; FOR i: NAT IN[1..poly.len) DO IF poly[i][3] < maxDepth THEN maxDepth _ poly[i][3]; ENDLOOP; }; AverageDepthInCamera: PROC [poly: Poly3d, localCS, cameraCS: CoordSystem] RETURNS [avgDepth: REAL] = { sum: REAL _ 0; realLen: REAL _ poly.len; localPoint: Point3d; FOR i: NAT IN[0..poly.len) DO localPoint _ poly[i]; localPoint _ SVGraphics.LocalToCamera[localPoint, localCS, cameraCS]; sum _ sum + localPoint[3]; ENDLOOP; avgDepth _ sum/realLen; }; SortedRevoluteSurface: TYPE = REF SortedRevoluteSurfaceObj; SortedRevoluteSurfaceObj: TYPE = RECORD [lat, long: NAT, meshRecord: RevoluteMesh]; CountPlanarSurfacesRevoluteSweep: PUBLIC PROC [meshRecord: RevoluteMesh] RETURNS [len: NAT] = { len _ (meshRecord.linesOfLongitude)*(meshRecord.linesOfLatitude-1) + 2; }; CountVerticesRevoluteSweep: PUBLIC PROC [meshRecord: RevoluteMesh] RETURNS [len: NAT] = { len _ meshRecord.linesOfLongitude*meshRecord.linesOfLatitude; }; PlanarSurfacesRevoluteSweep: PUBLIC PROC [meshRecord: RevoluteMesh, assembly: Slice, cameraCS: CoordSystem] RETURNS [psl: PlanarSurfaceList] = { poly3d: Poly3d _ SVPolygon3d.CreatePoly[meshRecord.linesOfLongitude]; avgDepth: REAL; thisSortedSurface: PlanarSurface; shape: Shape _ NARROW[assembly.shape]; mo: MasterObject _ shape.mo; jPlusOne: NAT; localCS: CoordSystem _ shape.coordSys; psl _ NIL; <> SVPolygon3d.ClearPoly[poly3d]; FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[1][j]]; ENDLOOP; avgDepth _ AverageDepthInCamera[poly3d, localCS, cameraCS]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [ whichSurface: NEW[SortedRevoluteSurfaceObj _ [0,0,meshRecord]], assembly: assembly, normal: meshRecord.surfaces.top.normal, mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; <> SVPolygon3d.ClearPoly[poly3d]; FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[meshRecord.linesOfLatitude][j]]; ENDLOOP; avgDepth _ AverageDepthInCamera[poly3d, localCS, cameraCS]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [ whichSurface: NEW[SortedRevoluteSurfaceObj _ [meshRecord.linesOfLatitude,0,meshRecord]], assembly: assembly, normal: meshRecord.surfaces.bottom.normal, mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; <> FOR i: NAT IN[1..meshRecord.linesOfLatitude-1] DO FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO SVPolygon3d.ClearPoly[poly3d]; jPlusOne _ IF j = meshRecord.linesOfLongitude THEN 1 ELSE j + 1; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[i][j]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[i][jPlusOne]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[i+1][jPlusOne]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[i+1][j]]; avgDepth _ AverageDepthInCamera[poly3d, localCS, cameraCS]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [whichSurface: NEW[SortedRevoluteSurfaceObj _ [i,j,meshRecord]], assembly: assembly, normal: meshRecord.surfaces.sides[i][j].normal, mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; ENDLOOP; ENDLOOP; }; -- end of PlanarSurfacesRevoluteSweep DrawPlanarSurfaceRevoluteSweep: PUBLIC PROC [dc: Imager.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = { hiddenLine: BOOL = FALSE; -- should be an argument thisRevSurface: SortedRevoluteSurface; meshRecord: RevoluteMesh; lat, long, longPlusOne: NAT; poly3d: Poly3d; avgDepth: REAL; shape: Shape; localCS: CoordSystem; thisRevSurface _ NARROW[ps.whichSurface]; meshRecord _ thisRevSurface.meshRecord; shape _ NARROW[ps.assembly.shape]; localCS _ shape.coordSys; lat _ thisRevSurface.lat; long _ thisRevSurface.long; -- we have surface [lat][long] avgDepth _ ps.depth; IF long = 0 THEN { -- either top or bottom surface IF lat = 0 THEN { -- top surface <> poly3d _ SVPolygon3d.CreatePoly[meshRecord.linesOfLongitude]; FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[1][j]]; ENDLOOP; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, CoordSys.WRTWorld[localCS], CoordSys.WRTCamera[localCS, camera.coordSys], hiddenLine] } ELSE { <> poly3d _ SVPolygon3d.CreatePoly[meshRecord.linesOfLongitude]; FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[meshRecord.linesOfLatitude][j]]; ENDLOOP; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, CoordSys.WRTWorld[localCS], CoordSys.WRTCamera[localCS, camera.coordSys], hiddenLine]}; } ELSE { -- Draw the side face poly3d _ SVPolygon3d.CreatePoly[4]; longPlusOne _ IF long = meshRecord.linesOfLongitude THEN 1 ELSE long + 1; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[lat][long]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[lat][longPlusOne]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[lat+1][longPlusOne]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[lat+1][long]]; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, CoordSys.WRTWorld[localCS], CoordSys.WRTCamera[localCS, camera.coordSys], hiddenLine]; }; }; -- end of DrawPlanarSurfaceRevoluteSweep SortedToroidalSurface: TYPE = REF SortedToroidalSurfaceObj; SortedToroidalSurfaceObj: TYPE = RECORD [lat, long: NAT, meshRecord: ToroidalMesh]; CountPlanarSurfacesToroidalSweep: PUBLIC PROC [meshRecord: ToroidalMesh] RETURNS [len: NAT] = { len _ (meshRecord.linesOfLongitude)*(meshRecord.linesOfLatitude); }; CountVerticesToroidalSweep: PUBLIC PROC [meshRecord: ToroidalMesh] RETURNS [len: NAT] = { len _ meshRecord.linesOfLongitude*meshRecord.linesOfLatitude; }; PlanarSurfacesToroidalSweep: PUBLIC PROC [meshRecord: ToroidalMesh, assembly: Slice, cameraCS: CoordSystem] RETURNS [psl: PlanarSurfaceList] = { iPlusOne, jPlusOne: NAT; poly3d: Poly3d _ SVPolygon3d.CreatePoly[4]; avgDepth: REAL; shape: Shape _ NARROW[assembly.shape, Shape]; mo: MasterObject _ shape.mo; localCS: CoordSystem _ shape.coordSys; thisSortedSurface: PlanarSurface; <> FOR i: NAT IN[1..meshRecord.linesOfLatitude] DO iPlusOne _ IF i = meshRecord.linesOfLatitude THEN 1 ELSE i + 1; FOR j: NAT IN[1..meshRecord.linesOfLongitude] DO SVPolygon3d.ClearPoly[poly3d]; jPlusOne _ IF j = meshRecord.linesOfLongitude THEN 1 ELSE j + 1; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[i][j]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[i][jPlusOne]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[iPlusOne][jPlusOne]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[iPlusOne][j]]; avgDepth _ AverageDepthInCamera[poly3d, localCS, cameraCS]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [ whichSurface: NEW[SortedToroidalSurfaceObj _ [i,j,meshRecord]], assembly: assembly, normal: meshRecord.surfaces.sides[i][j].normal, mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; ENDLOOP; ENDLOOP; }; -- end of PlanarSurfacesToroidalSweep DrawPlanarSurfaceToroidalSweep: PUBLIC PROC [dc: Imager.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = { hiddenLine: BOOL = FALSE; -- should be an argument lat, long, longPlusOne, latPlusOne: NAT; poly3d: Poly3d _ SVPolygon3d.CreatePoly[4]; avgDepth: REAL; shape: Shape; localCS: CoordSystem; meshRecord: ToroidalMesh; thisTorSurface: SortedToroidalSurface; thisTorSurface _ NARROW[ps.whichSurface]; shape _ NARROW[ps.assembly.shape]; localCS _ shape.coordSys; meshRecord _ thisTorSurface.meshRecord; lat _ thisTorSurface.lat; long _ thisTorSurface.long; -- we have surface [lat][long] avgDepth _ ps.depth; <> latPlusOne _ IF lat = meshRecord.linesOfLatitude THEN 1 ELSE lat + 1; longPlusOne _ IF long = meshRecord.linesOfLongitude THEN 1 ELSE long + 1; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[lat][long]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[lat][longPlusOne]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[latPlusOne][longPlusOne]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, meshRecord.array[latPlusOne][long]]; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, CoordSys.WRTWorld[localCS], CoordSys.WRTCamera[localCS, camera.coordSys], hiddenLine]; }; -- end of DrawPlanarSurfaceToroidalSweep END.