<> <> <> DIRECTORY Atom, CedarProcess, ColorDisplay, Controls3d, FileNames, Imager, ImagerColor, ImagerColorMap, Matrix3d, Pixels, RealFns, Render3d, Rope, RuntimeError, Terminal, TextureMaps, ThreeDBasics, ThreeDMisc, ThreeDScenes, Vector3d, ViewerClasses, ViewerOps; Render3dImpl: CEDAR PROGRAM IMPORTS Atom, CedarProcess, ColorDisplay, Controls3d, FileNames, ImagerColorMap, RealFns, Rope, RuntimeError, Terminal, TextureMaps, ThreeDMisc, ThreeDScenes, Vector3d, ViewerOps EXPORTS Render3d ~ BEGIN OPEN Render3d; <> <> <> <> <> <<>> <> <> <> <> <<>> <> <> <> <> <> <> contexts3d: ARRAY [0..nGlobalContext3d) OF Context3d _ ALL[NIL]; processes: ARRAY [0..nGlobalContext3d) OF Process _ ALL[NIL]; <> CDNotifier: ColorDisplay.CDNotifyProc ~ { IF new.on AND (old.bpp # new.bpp OR old.gray # new.gray OR NOT Rope.Equal[old.monitorType, new.monitorType]) THEN FOR n: NAT IN [0..nGlobalContext3d) DO IF contexts3d[n] # NIL THEN { SetContext3dDisplay[contexts3d[n], new]; ThreeDMisc.MakeFrame[contexts3d[n]]; }; ENDLOOP; }; InitContext3d: PUBLIC PROC [background: Triple _ defaultBackground] RETURNS [Context3d] ~ { cdState: CDState _ GetColorDisplayStatus[]; context3d: Context3d _ ThreeDScenes.Create[]; backgroundRef: REF RGB _ NEW[RGB _ [background.x, background.y, background.z]]; IF NOT cdState.on THEN ColorDisplay.SetColorDisplayStatus[on: TRUE]; <> FOR n: NAT IN [0..nGlobalContext3d) DO IF contexts3d[n] = NIL THEN { contexts3d[n] _ context3d; EXIT; }; ENDLOOP; SetContext3dDisplay[context3d, cdState]; context3d.props _ Atom.PutPropOnList[ context3d.props, $WDir, FileNames.CurrentWorkingDirectory[]]; context3d.props _ Atom.PutPropOnList[context3d.props, $BackGround, backgroundRef]; [] _ ThreeDScenes.SetLight[context3d, "Light1", [-100.0, -200.0, 50.0]]; ThreeDScenes.SetView[context3d, [2.0, -10.0, 3.0], origin]; RETURN[context3d]; }; Context3dIndex: PROC [context3d: Context3d] RETURNS [INTEGER] ~ { FOR n: NAT IN [0..nGlobalContext3d) DO IF contexts3d[n] = context3d THEN RETURN[n]; ENDLOOP; RETURN[-1]; }; NullifyThreeDContext: PUBLIC PROC [context3d: Context3d] ~ { index: INTEGER _ Context3dIndex[context3d]; IF index # -1 THEN contexts3d[index] _ NIL; }; GetColorDisplayStatus: PROC RETURNS [CDState] ~ { on, onLeft, gray: BOOL; bpp, bppB: CARDINAL; monitorType: ROPE; [on, onLeft, gray, bpp, bppB, monitorType] _ ColorDisplay.GetColorDisplayStatus[]; RETURN[[on, onLeft, gray, bpp, bppB, monitorType]]; }; ChangeRenderMode: PROC [context3d: Context3d, mode: ATOM] ~ { SELECT mode FROM $Dithered => ImagerColorMap.SetStandardColorMap[Terminal.Current[]]; $PseudoColor => ThreeDMisc.LoadStd8BitClrMap[Terminal.Current[]]; $Grey => ThreeDMisc.LoadColorRamp[Terminal.Current[], [0.,0.,0.], [1.,1.,1.], [.43,.43,.43]]; ENDCASE; context3d.renderMode _ context3d.preferredRenderMode _ mode; context3d.display.props _ Atom.PutPropOnList[context3d.display.props, $RenderMode, mode]; }; SetContext3dDisplay: PROC [context3d: Context3d, cdState: CDState] ~ { CloseColorViewers[]; ThreeDScenes.DisplayFromTerminal[context3d, Terminal.Current[]]; IF cdState.gray AND context3d.renderMode = $PseudoColor THEN ChangeRenderMode[context3d, $Grey]; }; CloseColorViewers: PROC ~ { EnumProc: ViewerOps.EnumProc ~ { IF v.column = color THEN { ViewerOps.CloseViewer[v]; ViewerOps.ChangeColumn[v, left]; }; }; ViewerOps.EnumerateViewers[EnumProc]; }; <> AddFileShape: PUBLIC PROC [ context3d: Context3d, shapeName: ROPE, fileName: ROPE, position: Triple _ origin, color: RGB _ [0.7, 0.7, 0.7], renderStyle: RenderStyle _ none] ~ { ThreeDMisc.AddShapeAt[context3d, shapeName, fileName, position]; SELECT renderStyle FROM faceted => ThreeDMisc.SetFacetedColor[context3d, shapeName, color]; smooth =>ThreeDMisc.SetSmoothColor[context3d, shapeName, color]; ENDCASE; }; AddObject: PUBLIC PROC [ context3d: Context3d, polygons: REF NatTable, vertices: REF VertexSequence, shades: REF ShadingSequence, textures: TripleSequence _ NIL, position: Triple _ origin, name: ROPE _ NIL, renderStyle: RenderStyle _ faceted, insideVisible: BOOL _ FALSE, matrix: Matrix _ NIL] ~ { IF vertices # NIL AND vertices.length > 0 AND < 0 AND>> polygons # NIL AND polygons.length > 0 THEN { shape: REF ShapeInstance _ ThreeDScenes.NewShape[name]; surfaces: REF PtrPatchSequence _ NEW[PtrPatchSequence[polygons.length]]; shape.surface _ surfaces; shape.auxInfo _ textures; shape.type _ $ConvexPolygon; shape.insideVisible _ insideVisible; shape.vertex _ vertices; shape.shade _ shades; shape.numSurfaces _ polygons.length; FOR n: NAT IN [0..polygons.length) DO nVtces: INTEGER _ polygons[n].length; surfaces[n] _ NEW[PtrPatch _ [ vtxPtr: NEW[NatSequence[nVtces]], type: shape.type, oneSided: NOT insideVisible, nVtces: nVtces ]]; FOR i: NAT IN [0..nVtces) DO surfaces[n].vtxPtr[i] _ polygons[n][i]; ENDLOOP; ENDLOOP; context3d.shapes _ ThreeDScenes.DeleteShape[context3d.shapes, name ! ThreeDScenes.Error => CONTINUE]; context3d.shapes _ ThreeDScenes.AddShape[context3d.shapes, shape]; ThreeDScenes.PlaceShape[shape, position]; SetRenderStyle[context3d, name, renderStyle]; ThreeDMisc.SetFacetedColor[context3d, name, [0.7, 0.7, 0.7]]; ThreeDMisc.SetSmoothColor[context3d, name, [0.7, 0.7, 0.7]]; IF matrix # NIL THEN SetObjectMatrix[context3d, name, matrix]; }; }; SetBoundingSphere: PROC [shape: REF ShapeInstance] ~ { min, max: Triple _ [shape.vertex[0].x, shape.vertex[0].y, shape.vertex[0].z]; FOR n: NAT IN (1..shape.vertex.length) DO -- get min and max in x, y, and z vertex: REF Vertex _ shape.vertex[n]; IF vertex = NIL THEN LOOP; min.x _ MIN[min.x, vertex.x]; max.x _ MAX[max.x, vertex.x]; min.y _ MIN[min.y, vertex.y]; max.y _ MAX[max.y, vertex.y]; min.z _ MIN[min.z, vertex.z]; max.z _ MAX[max.z, vertex.z]; ENDLOOP; shape.centroid.x _ 0.5*(min.x+max.x); -- get middle point in each coordinate shape.centroid.y _ 0.5*(min.y+max.y); shape.centroid.z _ 0.5*(min.z+max.z); shape.boundingRadius _ 0.0; FOR n: NAT IN [0..shape.vertex.length) DO -- find radius dx: REAL _ shape.vertex[n].x-shape.centroid.x; dy: REAL _ shape.vertex[n].y-shape.centroid.y; dz: REAL _ shape.vertex[n].z-shape.centroid.z; radius: REAL _ dx*dx+dy*dy+dz*dz; IF radius > shape.boundingRadius THEN shape.boundingRadius _ radius; ENDLOOP; shape.boundingRadius _ 2.0*RealFns.SqRt[shape.boundingRadius]; }; <> SetRenderStyle: PUBLIC PROC [ context3d: Context3d, shapeName: ROPE, renderStyle: RenderStyle] ~ { shape: REF ShapeInstance _ ThreeDScenes.FindShape[context3d.shapes, shapeName]; shape.shadingProps _ Atom.RemPropFromList[shape.shadingProps, $Shininess]; SELECT renderStyle FROM shiny => { ThreeDMisc.SetSmoothColor[context3d, shapeName, [1.0, 1.0, 1.0]]; ThreeDMisc.SetShininess[context3d, shapeName, 50.0]; }; faceted => ThreeDMisc.SetFacetedColor[context3d, shapeName, [1.0, 1.0, 1.0]]; smooth => ThreeDMisc.SetSmoothColor[context3d, shapeName, [1.0, 1.0, 1.0]]; ENDCASE; }; SetInsideVisible: PUBLIC PROC [ context3d: Context3d, shapeName: ROPE, insideVisible: BOOL] ~ { shape: REF ShapeInstance _ ThreeDScenes.FindShape[context3d.shapes, shapeName]; IF shape # NIL THEN { surfaces: REF PtrPatchSequence _ NARROW[shape.surface]; shape.insideVisible _ insideVisible; FOR n: NAT IN [0..shape.numSurfaces) DO surfaces[n].oneSided _ NOT insideVisible; ENDLOOP; }; }; SetObjectMatrix: PUBLIC PROC [context3d: Context3d, shapeName: ROPE, matrix: Matrix] ~ { shape: REF ShapeInstance _ ThreeDScenes.FindShape[context3d.shapes, shapeName]; IF shape # NIL THEN { shape.position _ matrix; shape.positionInValid _ FALSE; }; }; SetTextureMap: PUBLIC PROC [ context3d: Context3d, shapeName, textureAIS: ROPE, textureType: TextureType _ intensity] ~ { <> <> atom: ATOM ~ SELECT textureType FROM bump => $Bump, color => $Color, ENDCASE => $Intensity; IF shapeName # NIL THEN { shape: REF ShapeInstance ~ ThreeDScenes.FindShape[context3d.shapes, shapeName]; textureMap: REF TextureMaps.TextureMap _ IF textureAIS # NIL THEN TextureMaps.TextureFromAIS[context3d, textureAIS, atom] ELSE NIL; TextureMaps.SetTexture[shape, textureMap]; TextureMaps.SumTexture[shape]; }; }; <> AddShape: PROC [ context3d: Context3d, shapeName: ROPE, points: TripleSequence, polygons: REF NatTable, normals: TripleSequence _ NIL, textures: TripleSequence _ NIL, position: Triple _ origin, renderStyle: RenderStyle _ smooth, insideVisible: BOOL _ FALSE] ~ { vertices: REF ThreeDBasics.VertexSequence ~ NEW[ThreeDBasics.VertexSequence[points.length]]; shades: REF ThreeDBasics.ShadingSequence ~ NEW[ThreeDBasics.ShadingSequence[points.length]]; FOR n: NAT IN [0..points.length) DO vertices[n] _ NEW[ThreeDBasics.Vertex]; shades[n] _ NEW[ThreeDBasics.ShadingValue]; [vertices[n].x, vertices[n].y, vertices[n].z] _ points[n]; IF normals # NIL AND n < normals.length THEN [shades[n].xn, shades[n].yn, shades[n].zn] _ normals[n]; ENDLOOP; AddObject[context3d, polygons, vertices, shades, textures, position, shapeName, renderStyle, insideVisible]; }; ScaleTexture: PROC [shape: REF ThreeDBasics.ShapeInstance, scale: Triple] ~ { IF shape.auxInfo # NIL THEN { textures: TripleSequence _ NARROW[shape.auxInfo]; FOR n: NAT IN [0..textures.length) DO textures[n] _ Vector3d.MulVectors[textures[n], scale]; ENDLOOP; }; }; <> ForkRender: CedarProcess.ForkableProc ~ { ThreeDMisc.MakeFrame[NARROW[data] ! ABORTED => CONTINUE]; }; Render: PUBLIC PROC [ context3d: Context3d, shapeName: ROPE, camera: Camera, fork: BOOL _ TRUE] ~ { index: INTEGER _ Context3dIndex[context3d]; Controls3d.SetContext3dView[context3d, camera]; SetBoundingSphere[ThreeDScenes.FindShape[context3d.shapes, shapeName]]; IF index # -1 THEN { IF processes[index] = NIL OR CedarProcess.GetStatus[processes[index]] # busy THEN processes[index] _ CedarProcess.Fork[ForkRender, context3d]; } < CONTINUE];>> ELSE ThreeDMisc.ShowShapes[context3d ! ABORTED => CONTINUE]; }; TurnOnAntiAliasing: PUBLIC PROC [context3d: Context3d] ~ { IF context3d # NIL AND context3d.alphaBuffer # TRUE THEN ThreeDScenes.AddAlphaBuffer[context3d]; }; TurnOffAntiAliasing: PUBLIC PROC [context3d: Context3d] ~ { save: ATOM ~ context3d.renderMode; IF context3d = NIL OR context3d.alphaBuffer = FALSE THEN RETURN; ThreeDScenes.DisplayFromTerminal[context3d, Terminal.Current[]]; IF save = $Grey AND context3d.renderMode = $PseudoColor THEN ChangeRenderMode[context3d, $Grey]; IF context3d.depthBuffer THEN ThreeDScenes.AddDepthBuffer[context3d]; context3d.alphaBuffer _ FALSE; }; <> PolygonsFromShape: PUBLIC PROC [shape: REF ShapeInstance] RETURNS [REF NatTable] ~ { surface: REF PtrPatchSequence _ NARROW[shape.surface]; polygons: REF NatTable _ NEW[NatTable[shape.numSurfaces]]; polygons.length _ shape.numSurfaces; FOR n: NAT IN [0..polygons.length) DO polygons[n] _ NEW[NatSequence[surface[n].nVtces]]; polygons[n].length _ surface[n].nVtces; FOR i: NAT IN [0..polygons[n].length) DO polygons[n][i] _ surface[n].vtxPtr[i]; ENDLOOP; ENDLOOP; RETURN[polygons]; }; <<>> PointsFromShape: PUBLIC PROC [ shape: REF ShapeInstance, triples: TripleSequence _ NIL] RETURNS [TripleSequence] ~ { Allocate: PROC RETURNS [TripleSequence] ~ { RETURN[NEW[TripleSequenceRep[shape.vertex.length]]]; }; ok: BOOL _ TRUE; IF triples = NIL OR triples.maxLength < shape.vertex.length THEN triples _ Allocate[! RuntimeError.BoundsFault => {ok _ FALSE; CONTINUE}]; IF NOT ok THEN RETURN[NIL]; triples.length _ shape.vertex.length; FOR n: NAT IN [0..triples.length) DO vertex: REF Vertex _ shape.vertex[n]; triples[n] _ [vertex.x, vertex.y, vertex.z]; ENDLOOP; RETURN[triples]; }; <> [] _ ColorDisplay.RegisterCDNotifyProc [CDNotifier, NIL]; END. .. SetRenderStyle: PUBLIC PROC [ context3d: Context3d, shapeName: ROPE, renderStyle: RenderStyle] ~ { IF renderStyle = shiny THEN ThreeDMisc.SetShininess[context3d, shapeName, 50.0] ELSE { shape: REF ShapeInstance _ ThreeDScenes.FindShape[context3d.shapes, shapeName]; IF shape # NIL THEN SELECT renderStyle FROM faceted => ThreeDScenes.PutShading[shape, $Type, $Faceted]; smooth => ThreeDScenes.PutShading[shape, $Type, $Smooth]; ENDCASE => NULL; }; }; <> <<>> <> <> <> <> <<>> <> <> <<>> <> <<>> <> <> <<>> <> <<>> <> <> <> <> <<[] _ ThreeDScenes.SetLight[context3d, "Light1", [-100.0, -200.0, 50.0]]; >> <> <> <<};>> <<>> <> <> <<>> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <> <<};>> <<>> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <<};>> <<>> <> <> <> <<>> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <<];>> <<};>> <<>> <> <> <> <> <> <<~ {>> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <<>> <> <> <> <<>> <> <> <> <> <<>> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <<]];>> <> <> <<>> <> < CONTINUE];>> <> <> <> <<};>> <<};>> <<>> <> <> <> <> <<};>> <<>> <> <> <> <> <> <<>> <> <> <<>> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> < 1.0 >> <> <> < window.h>> <> <> <<>> <> <> <> <> <> <> <<-context3d.hitherLimit/(1.0-context3d.hitherLimit/context3d.yonLimit);>> <<>> <> <> <> <> <> <> <> <<};>> <<};>> <<>> <<>>