<> <> DIRECTORY ThreeDPackage USING [ConcatT, GetIDTransform, Normalize, Rotate3D, Transformation3D, Translate3D, Triple], PolygonPackage USING [BackFacing, ClipPoly, ClipState, ClrTriple, DoForPolygons, DoInSequence, GetColors, GetCoords, GetObject, GetPolyNormals, GetShades, GetSolidColor, GetTransforms, GetVtxNormals, LightList, LoadSortSequence, Object, ObjectPolygon, Polygon, PolygonTexture, PolygonTextureSequenceRep, PtrPoly, PtrPolySequenceRep, ShadingSequenceRep, ShadingValue, SortSequenceRep, VertexSequenceRep, XfmVtces], TilerPackage USING [FancyTiler, SetTexture, SumTexture, MipMapTexture, BlendPixels], Rope USING [ROPE, Equal], Real USING [RoundC, Fix, FixC, LargestNumber, Float], RealFns USING [Power, Sin, ArcTanDeg, SqRt], MessageWindow USING [Append], Imager USING [Context, Create, SetColor, Pair, SpecialOp, MaskRectangle, MaskVector, ShowCharacters, FONT, MakeFont, SetFont, SetXY], ImagerBasic USING [IntRectangle], ImagerDisplay USING [DisplayData], ImagerDisplayExtras USING [RGBSequence], ImagerPixelMaps USING [GetPixel], ImagerPixelMapsExtras USING [SetPixel, DrawLine, FillTrap], ConstantColors USING [NameToColor, RGBToColor], ImagerColorAIS USING [GetAISFile, PutAISFile]; ImagerObjectsMain: CEDAR PROGRAM IMPORTS ThreeDPackage, PolygonPackage, TilerPackage, Rope, Real, RealFns, Imager, ConstantColors, ImagerColorAIS, ImagerPixelMaps, ImagerPixelMapsExtras, MessageWindow ~ BEGIN ShadingUnspecified: PUBLIC SIGNAL = CODE; Triple: TYPE ~ ThreeDPackage.Triple; Pair: TYPE ~ RECORD [ x, y: REAL]; BooleanSequence: TYPE ~ RECORD [SEQUENCE length: NAT OF BOOLEAN]; ObjectList: TYPE ~ LIST OF REF PolygonPackage.Object; displayContext, currentContext: Imager.Context; sortSeq: REF PolygonPackage.SortSequenceRep; objectList: LIST OF REF PolygonPackage.Object; resFctrX, resFctrY: REAL; -- Scale factors for transform to image space eyeSpaceTransform: ThreeDPackage.Transformation3D; lights: PolygonPackage.LightList _ NIL; tempPoly, tempPoly2: REF PolygonPackage.Polygon _ NIL; Sqr: PROCEDURE [number: REAL] RETURNS [REAL] ~ INLINE { RETURN[number * number]; }; Sgn: PROCEDURE [number: REAL] RETURNS [REAL] ~ INLINE { IF number < 0. THEN RETURN[-1.] ELSE RETURN[1.]; }; Init: PROC[] ~ { displayContext _ Imager.Create[$Std8bpp, NIL]; currentContext _ displayContext; lights _ CONS[ [ThreeDPackage.Normalize[[-100., -200., 50.]], [1., 1., 1.], .2], lights]; }; ClearDisplay: PROC[] ~ { displayData: ImagerDisplay.DisplayData _ NARROW[currentContext.data, ImagerDisplay.DisplayData]; ImagerPixelMapsExtras.FillTrap[ displayData[0], displayData[0].sMin + displayData[0].sSize, -- top displayData[0].sMin, -- bottom displayData[0].fMin, displayData[0].fMin, -- left top and bottom displayData[0].fMin + displayData[0].fSize, displayData[0].fMin + displayData[0].fSize, 0 -- color ]; }; NameColor: PROC [color: Rope.ROPE] ~ { Imager.SetColor[displayContext, ConstantColors.NameToColor[color]]; }; RGBColor: PROC [r, g, b: REAL] ~ { Imager.SetColor[displayContext, ConstantColors.RGBToColor[r, g, b]]; }; LoadAndRotate8BitMap: PROC [duration: NAT] ~ { start: REF NAT _ NEW[NAT]; length: NAT _ 512; entries: REF ImagerDisplayExtras.RGBSequence _ NEW[ ImagerDisplayExtras.RGBSequence[length] ]; data: LIST OF REF ANY _ NIL; start^ _ 1; FOR i: NAT IN [0..40) DO -- greyscale entries[i + 216].r _ entries[i + 216].g _ entries[i + 216].b _ i*6; entries[i + 471].r _ entries[i + 471].g _ entries[i + 471].b _ 255 - i*6; ENDLOOP; FOR i: NAT IN [0..216) DO -- 6 x 6 x 6 color cube entries[i].r _ 36 * (i/36 + 1); entries[i + 255].r _ 255 - entries[i].r; entries[i].g _ 36 * ((i/6) MOD 6 + 1); entries[i + 255].g _ 255 - entries[i].g; entries[i].b _ 36 * (i MOD 6 + 1); entries[i + 255].b _ 255 - entries[i].b; ENDLOOP; data _ CONS[start, data]; data _ CONS[entries, data]; [] _ Imager.SpecialOp[displayContext, $LoadColorMap, data]; FOR i: NAT IN [0..duration*60) DO color: RECORD[ r, g, b: [0..256) ] _ [ entries[1].r, entries[1].g, entries[1].b ]; FOR j: NAT IN [2..length) DO entries[j-1] _ entries[j]; ENDLOOP; entries[length-1] _ [ color.r, color.g, color.b ]; [] _ Imager.SpecialOp[displayContext, $LoadColorMap, data]; ENDLOOP; }; LoadGrey8BitMap: PROC [] ~ { start: REF NAT _ NEW[NAT]; length: NAT _ 512; entries: REF ImagerDisplayExtras.RGBSequence _ NEW[ ImagerDisplayExtras.RGBSequence[length] ]; data: LIST OF REF ANY _ NIL; start^ _ 0; FOR i: NAT IN [0..256) DO -- greyscale j: NAT _ Real.FixC[RealFns.Power[i/256.0, .43] * 256.0]; entries[i].r _ j; entries[i + 255].r _ 255 - entries[i].r; entries[i].g _ j; entries[i + 255].g _ 255 - entries[i].g; entries[i].b _ j; entries[i + 255].b _ 255 - entries[i].b; ENDLOOP; data _ CONS[start, data]; data _ CONS[entries, data]; [] _ Imager.SpecialOp[displayContext, $LoadColorMap, data]; }; Load8BitRampMap: PROC [r1, g1, b1, r2, g2, b2: REAL] ~ { start: REF NAT _ NEW[NAT]; length: NAT _ 256; entries: REF ImagerDisplayExtras.RGBSequence _ NEW[ ImagerDisplayExtras.RGBSequence[length] ]; data: LIST OF REF ANY _ NIL; start^ _ 0; r1 _ MAX[0.0, MIN[1.0, r1]]; r2 _ MAX[0.0, MIN[1.0, r2]]; g1 _ MAX[0.0, MIN[1.0, g1]]; g2 _ MAX[0.0, MIN[1.0, g2]]; b1 _ MAX[0.0, MIN[1.0, b1]]; b2 _ MAX[0.0, MIN[1.0, b2]]; FOR i: NAT IN [0..256) DO -- linear ramp jr: NAT _ Real.FixC[RealFns.Power[r1 + i/255.0 * (r2 - r1), .43] * 255.0]; -- gamma correction jg: NAT _ Real.FixC[RealFns.Power[g1 + i/255.0 * (g2 - g1), .43] * 255.0]; jb: NAT _ Real.FixC[RealFns.Power[b1 + i/255.0 * (b2 - b1), .43] * 255.0]; entries[i].r _ jr; entries[i].g _ jg; entries[i].b _ jb; ENDLOOP; data _ CONS[start, data]; data _ CONS[entries, data]; [] _ Imager.SpecialOp[displayContext, $LoadColorMap, data]; }; FillRectangle: PROC [x, y, w, h: REAL] ~ { Imager.MaskRectangle[displayContext, x, y, w, h]; }; DrawLine: PROC [pt1, pt2: Imager.Pair, width: REAL] ~ { Imager.MaskVector[displayContext, pt1, pt2, width]; }; ShowRope: PROC[x, y: REAL, rope: Rope.ROPE, fontRope: Rope.ROPE _ NIL, size: REAL _ .008] ~ { font: Imager.FONT; IF fontRope = NIL THEN fontRope _ "Xerox/Pressfonts/TimesRoman/MRR"; font _ Imager.MakeFont[fontRope, size]; Imager.SetFont[displayContext, font]; Imager.SetXY[displayContext, [x, y]]; Imager.ShowCharacters[displayContext, rope, ]; }; GetAISFile: PUBLIC PROC[fileName: Rope.ROPE, xOffSet, yOffSet: INTEGER _ 0] ~ { ImagerColorAIS.GetAISFile[displayContext, fileName, xOffSet, yOffSet]; }; PutAISFile: PUBLIC PROC[fileName: Rope.ROPE] ~ { ImagerColorAIS.PutAISFile[displayContext, fileName]; }; <> TextureFromAIS: PROC[fileName: Rope.ROPE, x, y, w, h: NAT _ 0 ] ~ { textureContext: Imager.Context; refBox: REF ImagerBasic.IntRectangle _ NEW[ImagerBasic.IntRectangle]; refBox.x _ x; refBox.y _ y; refBox.w _ w; refBox.h _ h; textureContext _ Imager.Create[$Std8bpp, refBox]; ImagerColorAIS.GetAISFile[textureContext, fileName]; TilerPackage.SetTexture[textureContext]; }; MakeTxtrCoordsFromVtxNum: PROC[ objectName: Rope.ROPE, vtcesAround, vtcesOnProfile: NAT, botLeft, topLeft, topRight, botRight: Pair] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; -- get object ref polygon: REF PolygonPackage.PtrPolySequenceRep _ object.polygon; texture: REF PolygonPackage.PolygonTextureSequenceRep _ NEW[ PolygonPackage.PolygonTextureSequenceRep[polygon.length] ]; object.texture _ texture; -- set object texture ref IF polygon.length # vtcesAround * vtcesOnProfile THEN { MessageWindow.Append["Unexpected number of polygons", TRUE]; RETURN[]; }; FOR polyNumber: NAT IN [0..vtcesAround * vtcesOnProfile) DO minTxtrX, minTxtrY: REAL _ Real.LargestNumber; maxTxtrX: REAL _ 0.; texture[polyNumber] _ NEW[PolygonPackage.PolygonTexture[polygon[polyNumber].nVtces] ]; texture[polyNumber].nVtces _ polygon[polyNumber].nVtces; FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO OPEN texture[polyNumber].vtx[i]; vtx: NAT _ polygon[polyNumber].vtxPtr[i]; txtrX _ Real.Float[vtx MOD (vtcesAround+1)] / vtcesAround; txtrY _ Real.Float[vtx / (vtcesAround+1)] / vtcesOnProfile; IF txtrX < minTxtrX THEN minTxtrX _ txtrX; IF txtrX > maxTxtrX THEN maxTxtrX _ txtrX; ENDLOOP; IF maxTxtrX - minTxtrX > .5 -- wraparound seam THEN FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO OPEN texture[polyNumber].vtx[i]; IF maxTxtrX - txtrX > .5 THEN txtrX _ txtrX + 1.; ENDLOOP; minTxtrX _ minTxtrY _ Real.LargestNumber; FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO OPEN texture[polyNumber].vtx[i]; lPosX: REAL _ botLeft.x + txtrY * (topLeft.x - botLeft.x); lPosY: REAL _ botLeft.y + txtrY * (topLeft.y - botLeft.y); rPosX: REAL _ botRight.x + txtrY * (topRight.x - botRight.x); rPosY: REAL _ botRight.y + txtrY * (topRight.y - botRight.y); txtrX _ lPosX + txtrX * (rPosX - lPosX); txtrY _ lPosY + txtrX * (rPosY - lPosY); IF txtrX < minTxtrX THEN minTxtrX _ txtrX; IF txtrY < minTxtrY THEN minTxtrY _ txtrY; ENDLOOP; minTxtrX _ Real.Float[Real.Fix[minTxtrX]]; minTxtrY _ Real.Float[Real.Fix[minTxtrY]]; FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO OPEN texture[polyNumber].vtx[i]; txtrX _ txtrX - minTxtrX; txtrY _ txtrY - minTxtrY; ENDLOOP; ENDLOOP; }; MakeTxtrCoordsFromNormals: PROC[ objectName: Rope.ROPE, botLeft, topLeft, topRight, botRight: Pair] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; -- get object ref polygon: REF PolygonPackage.PtrPolySequenceRep _ object.polygon; texture: REF PolygonPackage.PolygonTextureSequenceRep _ NEW[ PolygonPackage.PolygonTextureSequenceRep[polygon.length] ]; polyTags: REF BooleanSequence _ NEW[BooleanSequence[8]]; object.texture _ texture; -- set object texture ref IF object.shade.length # object.vertex.length THEN { MessageWindow.Append["Texture only works with smooth shading", TRUE]; RETURN[]; }; FOR polyNumber: NAT IN [0..polygon.length) DO minTxtrX, minTxtrY: REAL _ Real.LargestNumber; maxTxtrX: REAL _ 0.; texture[polyNumber] _ NEW[PolygonPackage.PolygonTexture[polygon[polyNumber].nVtces] ]; texture[polyNumber].nVtces _ polygon[polyNumber].nVtces; FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO -- map from sphere to Cartesian OPEN texture[polyNumber].vtx[i]; -- map to 1st quadrant 0 - 1 range. shade: PolygonPackage.ShadingValue _ object.shade[polygon[polyNumber].vtxPtr[i]]; hypotenuse: REAL _ RealFns.SqRt[Sqr[shade.yn] + Sqr[shade.xn]]; txtrX _ RealFns.ArcTanDeg[shade.yn, shade.xn] / 360. + .5; txtrY _ RealFns.ArcTanDeg[shade.zn, hypotenuse] / 180. + .5; IF hypotenuse < .00001 THEN polyTags[i] _ TRUE ELSE { polyTags[i] _ FALSE; IF txtrX < minTxtrX THEN minTxtrX _ txtrX; IF txtrX > maxTxtrX THEN maxTxtrX _ txtrX; }; ENDLOOP; IF maxTxtrX - minTxtrX > .5 -- wrapping around seam, fix up coords THEN FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO OPEN texture[polyNumber].vtx[i]; IF maxTxtrX - txtrX > .5 THEN txtrX _ txtrX + 1.; ENDLOOP; minTxtrX _ Real.LargestNumber; maxTxtrX _ 0.; FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO -- get corrected max and min IF polyTags[i] = FALSE THEN { OPEN texture[polyNumber].vtx[i]; IF txtrX < minTxtrX THEN minTxtrX _ txtrX; IF txtrX > maxTxtrX THEN maxTxtrX _ txtrX; }; ENDLOOP; FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO -- fix up vertical normals OPEN texture[polyNumber].vtx[i]; IF polyTags[i] = TRUE THEN txtrX _ (maxTxtrX + minTxtrX) / 2.; ENDLOOP; minTxtrX _ minTxtrY _ Real.LargestNumber; FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO -- slew according to corner coords OPEN texture[polyNumber].vtx[i]; lPosX: REAL _ botLeft.x + txtrY * (topLeft.x - botLeft.x); lPosY: REAL _ botLeft.y + txtrY * (topLeft.y - botLeft.y); rPosX: REAL _ botRight.x + txtrY * (topRight.x - botRight.x); rPosY: REAL _ botRight.y + txtrY * (topRight.y - botRight.y); txtrX _ lPosX + txtrX * (rPosX - lPosX); txtrY _ lPosY + txtrX * (rPosY - lPosY); IF txtrX < minTxtrX THEN minTxtrX _ txtrX; IF txtrY < minTxtrY THEN minTxtrY _ txtrY; ENDLOOP; minTxtrX _ Real.Float[Real.Fix[minTxtrX]]; minTxtrY _ Real.Float[Real.Fix[minTxtrY]]; FOR i: NAT IN [0..polygon[polyNumber].nVtces) DO OPEN texture[polyNumber].vtx[i]; txtrX _ txtrX - minTxtrX; txtrY _ txtrY - minTxtrY; ENDLOOP; ENDLOOP; }; SumTexture: PROC[range, interp: REAL] ~ { TilerPackage.SumTexture[range, interp]; }; MipMapTexture: PROC[range: REAL,showMaps: BOOLEAN _ FALSE] ~ { TilerPackage.MipMapTexture[range, showMaps]; }; ClearTexture: PROC[] ~ { TilerPackage.SetTexture[ NIL ]; }; MakeStripes: PROC[numStripes: NAT, min, max, power: REAL] ~ { displayData: ImagerDisplay.DisplayData _ NARROW[currentContext.data, ImagerDisplay.DisplayData]; factor: REAL _ ( numStripes * 2. * 3.1416 ) / displayData[0].fSize; maxValue: REAL _ 256.0; FOR x: NAT IN [ displayData[0].fMin .. (displayData[0].fSize + displayData[0].fMin) ] DO pxlValue: CARDINAL; sineValue: REAL _ RealFns.Sin[ factor * (x - displayData[0].fMin) ]; sineValue _ RealFns.Power[ABS[sineValue], power] * Sgn[sineValue]; pxlValue _ Real.FixC[ maxValue * (((sineValue + 1.) / 2.0) * (max - min) + min) ]; ImagerPixelMapsExtras.SetPixel[displayData[0], displayData[0].sMin, x, pxlValue]; ENDLOOP; FOR y: NAT IN [ (displayData[0].sMin + 1) .. (displayData[0].sSize + displayData[0].sMin) ] DO FOR x: NAT IN [ displayData[0].fMin .. (displayData[0].fSize + displayData[0].fMin) ] DO ImagerPixelMapsExtras.SetPixel[displayData[0], y, x, ImagerPixelMaps.GetPixel[displayData[0], displayData[0].sMin, x]]; ENDLOOP; ENDLOOP; }; MakeSpots: PROC[spotsAcross: NAT, min, max, power: REAL] ~ { displayData: ImagerDisplay.DisplayData _ NARROW[currentContext.data, ImagerDisplay.DisplayData]; maxValue: REAL _ 256.0; factor: REAL _ (spotsAcross * 2 * 3.1416) / displayData[0].fSize; FOR y: NAT IN [ displayData[0].sMin .. (displayData[0].sSize + displayData[0].sMin) ) DO sineY: REAL _ RealFns.Sin[ factor * (y - displayData[0].sMin) ]; sineY _ RealFns.Power[ABS[sineY], power] * Sgn[sineY]; FOR x: NAT IN [ displayData[0].fMin .. (displayData[0].fSize + displayData[0].fMin) ) DO pxlValue: LONG CARDINAL; sineX: REAL _ RealFns.Sin[ factor * (x - displayData[0].fMin) ]; sineX _ RealFns.Power[ABS[sineX], power] * Sgn[sineX]; pxlValue _ Real.FixC[ maxValue * (((sineX * sineY + 1.) / 2.0) * (max - min) + min) ]; ImagerPixelMapsExtras.SetPixel[displayData[0], y, x, pxlValue]; ENDLOOP; ENDLOOP; }; MakePlane: PROC[objectName: Rope.ROPE, squaresPerSide: NAT] ~ { object: REF PolygonPackage.Object _ NEW[PolygonPackage.Object]; vtcesPerSide: NAT _ squaresPerSide + 1; object.name _ objectName; object.numPolys _ squaresPerSide * squaresPerSide; object.numVtces _ vtcesPerSide * vtcesPerSide; object.shadingInValid _ object.vtcesInValid _ TRUE; object.centroid _ [0., 0., 0.]; object.boundingRadius _ 1.414; object.shading _ none; object.color _ [1., 1., 1.]; object.shininess _ object.transmittance _ 0.; object.position _ ThreeDPackage.GetIDTransform[]; object.vertex _ NEW[PolygonPackage.VertexSequenceRep[object.numVtces]]; FOR i: INT IN [0..object.numVtces) DO divisor: REAL _ Real.Float[squaresPerSide] / 2.; object.vertex[i].x _ (i / vtcesPerSide) / divisor - 1.; -- x-coordinate object.vertex[i].y _ (i MOD vtcesPerSide) / divisor - 1.; -- y-coordinate object.vertex[i].z _ 0.; -- constant z-coordinate ENDLOOP; object.polygon _ NEW[PolygonPackage.PtrPolySequenceRep[object.numPolys]]; FOR i: INT IN [0..object.numPolys) DO vtxNumber: NAT _ i + (i / squaresPerSide); -- add one at end of each row object.polygon[i] _ NEW[PolygonPackage.PtrPoly[4]]; object.polygon[i].nVtces _ 4; object.polygon[i].vtxPtr[0] _ vtxNumber; object.polygon[i].vtxPtr[1] _ vtxNumber + 1; object.polygon[i].vtxPtr[2] _ vtxNumber + vtcesPerSide + 1; object.polygon[i].vtxPtr[3] _ vtxNumber + vtcesPerSide; ENDLOOP; objectList _ CONS[ object, objectList ]; }; AddObject: PROC[fileName: Rope.ROPE, position: Triple _ [0., 0., 0.] ] ~ { objectList _ CONS[ PolygonPackage.GetObject[fileName], objectList ]; PolygonPackage.GetPolyNormals[objectList.first]; -- for faceted shading MoveObject[fileName, position]; sortSeq _ NIL; }; DeleteObject: PROC[objectName: Rope.ROPE] ~ { objects: ObjectList _ NIL; WHILE objectList # NIL DO IF NOT Rope.Equal[objectList.first.name, objectName, FALSE] THEN objects _ CONS[objectList.first, objects]; objectList _ objectList.rest; ENDLOOP; objectList _ objects; sortSeq _ NIL; }; FindObject: PROC[objectName: Rope.ROPE, objectList: ObjectList] RETURNS[ REF PolygonPackage.Object ] ~ { WHILE objectList # NIL DO IF Rope.Equal[objectList.first.name, objectName, FALSE] THEN RETURN[objectList.first]; objectList _ objectList.rest; ENDLOOP; RETURN [ NIL ]; }; MoveObject: PROC[objectName: Rope.ROPE, delta: Triple] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; object.position _ ThreeDPackage.ConcatT[object.position, ThreeDPackage.Translate3D[delta] ]; object.shadingInValid _ TRUE; object.vtcesInValid _ TRUE; sortSeq _ NIL; }; ColorFacetedObject: PROC[objectName: Rope.ROPE, color: PolygonPackage.ClrTriple] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; PolygonPackage.GetSolidColor[color, object, object.numPolys]; PolygonPackage.GetPolyNormals[object]; object.shading _ faceted; object.shadingInValid _ TRUE; }; ColorSmoothObject: PROC[objectName: Rope.ROPE, color: PolygonPackage.ClrTriple] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; PolygonPackage.GetSolidColor[color, object, object.numVtces]; PolygonPackage.GetVtxNormals[object]; object.shading _ smooth; object.shadingInValid _ TRUE; }; ColorFancyObject: PROC[objectName: Rope.ROPE, color: PolygonPackage.ClrTriple] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; PolygonPackage.GetSolidColor[color, object, object.numVtces]; PolygonPackage.GetVtxNormals[object]; object.shading _ fancy; object.shadingInValid _ TRUE; }; RotateObject: PROC[objectName: Rope.ROPE, base, axis: Triple, theta: REAL] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; object.position _ ThreeDPackage.ConcatT[ ThreeDPackage.Rotate3D[base, axis, theta], object.position ]; object.shadingInValid _ TRUE; object.vtcesInValid _ TRUE; sortSeq _ NIL; }; SetLight: PROC[position: Triple, color: PolygonPackage.ClrTriple _ [1., 1., 1.], ambient: REAL _ .2] ~ { objects: ObjectList _ objectList; lights.first.pos _ ThreeDPackage.Normalize[position]; lights.first.clr _ color; lights.first.ambient _ ambient; WHILE objects # NIL DO objects.first.shadingInValid _ TRUE; objects _ objects.rest; ENDLOOP; }; SetView: PROC[eyePosition, ptOfInterest: Triple, x, y, w, h: NAT _ 0] ~ { objects: ObjectList _ objectList; contextData: ImagerDisplay.DisplayData _ NARROW[currentContext.data, ImagerDisplay.DisplayData];IF w > 0 AND h > 0 THEN { contextData[0].fMin _ x + contextData[0].fOrigin; contextData[0].sMin _ y + contextData[0].sOrigin; contextData[0].fSize _ w; contextData[0].sSize _ h; resFctrX _ (w - 1) / 2.; resFctrY _ (h - 1) / 2.; }; eyeSpaceTransform _ PolygonPackage.GetTransforms [ eyePosition, ptOfInterest, contextData[0].fSize, contextData[0].sSize ]; WHILE objects # NIL DO objects.first.vtcesInValid _ TRUE; objects _ objects.rest; ENDLOOP; sortSeq _ NIL; }; GetPolygonColors: PROC[objectName, colorFile: Rope.ROPE] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; PolygonPackage.GetColors[colorFile, object, object.numPolys]; PolygonPackage.GetPolyNormals[object]; object.shading _ faceted; object.shadingInValid _ TRUE; }; GetVertexColors: PROC[objectName, colorFile: Rope.ROPE] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; PolygonPackage.GetColors[colorFile, object, object.numVtces]; PolygonPackage.GetVtxNormals[object]; object.shading _ smooth; object.shadingInValid _ TRUE; }; <> GetTextureCoords: PROC[objectName, coordinateFile: Rope.ROPE] ~ { object: REF PolygonPackage.Object _ FindObject[objectName, objectList]; PolygonPackage.GetCoords[coordinateFile, object, object.numPolys]; }; ShowObjects: PROC[objects: LIST OF REF PolygonPackage.Object] ~ { objectList: LIST OF REF PolygonPackage.Object _ objects; WHILE objectList # NIL DO IF objectList.first.vtcesInValid THEN { compositeTransform: ThreeDPackage.Transformation3D _ ThreeDPackage.ConcatT[objectList.first.position, eyeSpaceTransform]; objectList.first.clipState _ PolygonPackage.XfmVtces[objectList.first, compositeTransform]; }; IF objectList.first.shadingInValid AND (objectList.first.clipState # out) THEN PolygonPackage.GetShades[objectList.first, lights, RGBtoPixel]; objectList _ objectList.rest; ENDLOOP; IF sortSeq = NIL THEN sortSeq _ PolygonPackage.LoadSortSequence[objects]; PolygonPackage.DoInSequence[sortSeq, OutputPoly]; }; ShowWireFrameObjects: PROC[objects: LIST OF REF PolygonPackage.Object] ~ { objectList: LIST OF REF PolygonPackage.Object _ objects; WHILE objectList # NIL DO IF objectList.first.vtcesInValid THEN { compositeTransform: ThreeDPackage.Transformation3D _ ThreeDPackage.ConcatT[objectList.first.position, eyeSpaceTransform]; objectList.first.clipState _ PolygonPackage.XfmVtces[objectList.first, compositeTransform]; }; IF objectList.first.shadingInValid AND (objectList.first.clipState # out) THEN PolygonPackage.GetShades[objectList.first, lights, RGBtoPixel]; objectList _ objectList.rest; ENDLOOP; PolygonPackage.DoForPolygons[objects, OutputLines]; }; RGBtoPixel: PROC [r, g, b: REAL] RETURNS [CARDINAL] = { RETURN [ Real.FixC[255. * (r + g + b) / 3.] ]; }; PixeltoRGB: PROC [pxlValue: CARDINAL] RETURNS [r, g, b: REAL] = TRUSTED { r _ g _ b _ Real.Float[pxlValue] / 255.; }; OutputLines: PROC[p: PolygonPackage.ObjectPolygon] ~ { displayData: ImagerDisplay.DisplayData _ NARROW[currentContext.data, ImagerDisplay.DisplayData]; poly: REF PolygonPackage.PtrPoly _ p.object.polygon[p.polygon]; vertex: REF PolygonPackage.VertexSequenceRep _ p.object.vertex; shadeValue: LONG CARDINAL; SELECT p.object.shading FROM faceted => shadeValue _ p.object.shade[p.polygon].value; smooth => shadeValue _ p.object.shade[poly.vtxPtr[0]].value; fancy => shadeValue _ p.object.shade[poly.vtxPtr[0]].value; ENDCASE => SIGNAL ShadingUnspecified[]; IF poly.clipState = in THEN { ax, ay, bx, by: INTEGER; FOR j: NAT IN [0..poly.nVtces] DO i: NAT _ IF j = poly.nVtces THEN 0 ELSE j; bx _ vertex[poly.vtxPtr[i]].ix; by _ vertex[poly.vtxPtr[i]].iy; bx _ bx + displayData[0].fMin; -- transform to display by _ displayData[0].sMin + displayData[0].sSize - (by + 1); IF j > 0 THEN ImagerPixelMapsExtras.DrawLine[displayData[0], [ax, ay], [bx, by], shadeValue]; ax _ bx; ay _ by; ENDLOOP; } ELSE IF poly.clipState = clipped THEN { IF (tempPoly = NIL) OR (tempPoly.length < 2 * poly.nVtces) THEN { tempPoly _ NEW[PolygonPackage.Polygon[2 * poly.nVtces] ]; tempPoly2 _ NEW[PolygonPackage.Polygon[2 * poly.nVtces] ]; }; tempPoly.nVtces _ poly.nVtces; FOR i: NAT IN [0..poly.nVtces) DO tempPoly.vtx[i].coord _ vertex[poly.vtxPtr[i]]; ENDLOOP; [tempPoly, tempPoly2] _ PolygonPackage.ClipPoly[tempPoly, tempPoly2, FALSE, FALSE]; IF tempPoly.nVtces > 2 THEN { ax, ay, bx, by: INTEGER; FOR j: NAT IN [0..tempPoly.nVtces] DO i: NAT _ IF j = tempPoly.nVtces THEN 0 ELSE j; { OPEN tempPoly.vtx[i].coord; bx _ Real.RoundC[ resFctrX * (ex / ez + 1.)]; by _ Real.RoundC[ resFctrY * (ey / ez + 1.)]; bx _ bx + displayData[0].fMin; -- transform to display by _ displayData[0].sMin + displayData[0].sSize - (by + 1); IF j > 0 THEN ImagerPixelMapsExtras.DrawLine[displayData[0], [ax, ay], [bx, by], shadeValue]; ax _ bx; ay _ by; }; ENDLOOP; }; }; }; SetPixelBlending: PROC[onNotOff: BOOLEAN _ TRUE] ~ { TilerPackage.BlendPixels[onNotOff]; }; DrawQuad: PROC[intensity: REAL, x1, y1, x2, y2, x3, y3, x4, y4: REAL] ~ { poly: REF PolygonPackage.Polygon _ NEW[ PolygonPackage.Polygon[4] ]; poly.nVtces _ 4; poly.vtx[0].coord.x _ x1; poly.vtx[0].coord.y _ y1; poly.vtx[0].shade.g _ intensity; poly.vtx[1].coord.x _ x2; poly.vtx[1].coord.y _ y2; poly.vtx[1].shade.g _ intensity; poly.vtx[2].coord.x _ x3; poly.vtx[2].coord.y _ y3; poly.vtx[2].shade.g _ intensity; poly.vtx[3].coord.x _ x4; poly.vtx[3].coord.y _ y4; poly.vtx[3].shade.g _ intensity; TilerPackage.FancyTiler[currentContext, poly]; }; OutputPoly: PROC[p: PolygonPackage.ObjectPolygon] ~ { SELECT p.object.shading FROM faceted => OutputFacetedPoly[p]; smooth => OutputSmoothPoly[p]; fancy => OutputFancyPoly[p]; ENDCASE => SIGNAL ShadingUnspecified[]; }; OutputFacetedPoly: PROC[ p: PolygonPackage.ObjectPolygon] ~ { <> <> <> <> <> <> <> <> <> <> <> << - (vertices[i].y + 1);>> <> <> <<}>> <> <> <> <> <<};>> <> <> <<[tempPoly, tempPoly2] _ PolygonPackage.ClipPoly[tempPoly, tempPoly2, FALSE, FALSE]; >> < 2 THEN {>> <> <> <> <> <> <> <> << - (vertices[i].y + 1);>> <> <> <<};>> <<};>> }; OutputSmoothPoly: PROC[p: PolygonPackage.ObjectPolygon] ~ { <> <> <> <<>> <> <> <> <> <> <> <> <> <> << - (vertices[i].y + 1);>> <> <> <<}>> <> <> <> <> <<};>> <> <> <> <> <> <<[tempPoly.vtx[i].shade.r, tempPoly.vtx[i].shade.g, tempPoly.vtx[i].shade.b] _>> << currentContext.deviceProcs.PixeltoRGB[shade[k].value];>> <> <<[tempPoly, tempPoly2] _ PolygonPackage.ClipPoly[tempPoly, tempPoly2, TRUE, FALSE];>> < 2 THEN {>> <> <> <> <> <> <> << TRUE];>> <> <> << - (vertices[i].y + 1);>> <> <> <<};>> <<};>> }; OutputFancyPoly: PROC[p: PolygonPackage.ObjectPolygon] ~ { poly: REF PolygonPackage.PtrPoly _ p.object.polygon[p.polygon]; vertex: REF PolygonPackage.VertexSequenceRep _ p.object.vertex; shade: REF PolygonPackage.ShadingSequenceRep _ p.object.shade; texture: REF PolygonPackage.PolygonTextureSequenceRep _ p.object.texture; tempPoly: REF PolygonPackage.Polygon; IF poly.clipState = out THEN RETURN[]; -- reject if outside frame tempPoly _ NEW[ PolygonPackage.Polygon[2 * poly.nVtces] ]; tempPoly.nVtces _ poly.nVtces; FOR i: NAT IN [0..poly.nVtces) DO k: NAT _ poly.vtxPtr[i]; tempPoly.vtx[i].coord _ vertex[k]; tempPoly.vtx[i].shade _ shade[k]; [tempPoly.vtx[i].shade.r, tempPoly.vtx[i].shade.g, tempPoly.vtx[i].shade.b] _ PixeltoRGB[shade[k].value]; IF texture # NIL THEN [tempPoly.vtx[i].shade.txtrX, tempPoly.vtx[i].shade.txtrY] _ texture[p.polygon].vtx[i]; ENDLOOP; IF PolygonPackage.BackFacing[tempPoly] THEN RETURN[]; -- reject if facing away from viewer IF poly.clipState = clipped THEN { tempPoly2 _ NEW[PolygonPackage.Polygon[2 * poly.nVtces] ]; [tempPoly, tempPoly2] _ PolygonPackage.ClipPoly[tempPoly, tempPoly2, TRUE, TRUE]; }; IF tempPoly.nVtces > 2 THEN { contextData: ImagerDisplay.DisplayData _ NARROW[currentContext.data, ImagerDisplay.DisplayData]; FOR i: NAT IN [0..tempPoly.nVtces) DO OPEN tempPoly.vtx[i]; coord.x _ resFctrX * (coord.ex / coord.ez + 1.); coord.y _ resFctrY * (coord.ey / coord.ez + 1.); coord.x _ coord.x + contextData[0].fMin; coord.y _ contextData[0].sMin + contextData[0].sSize - (coord.y + 1); ENDLOOP; TilerPackage.FancyTiler[currentContext, tempPoly]; }; }; <> Init[]; END.