DIRECTORY Atom USING [ GetPropFromList, PutPropOnList, PropList, RemPropFromList ], Commander USING [ PrependWorkingDir ], G3dVector USING [ Length, Sub ], G3dMatrix USING [ Identity, MakeRotate, Mul ], ImagerColorMap USING [ SetStandardColorMap ], Rope USING [ Length, ROPE, Substr ], Real USING [ Fix, Float ], RealFns USING [ SqRt ], RuntimeError USING [ BoundsFault ], ThreeDBasics USING [ Box, Context, ContextClass, ErrorDesc, Patch, Rectangle, RGB, ShadingClass, ShapeClass, ShapeInstance, Triple, Xfm3DRep ]; ThreeDBasicsImpl: CEDAR PROGRAM IMPORTS Atom, Commander, G3dMatrix, G3dVector, ImagerColorMap, Real, RealFns, Rope, RuntimeError EXPORTS ThreeDBasics ~ BEGIN Error: PUBLIC SIGNAL [reason: ThreeDBasics.ErrorDesc] = CODE; Context: TYPE ~ ThreeDBasics.Context; RGB: TYPE ~ ThreeDBasics.RGB; Triple: TYPE ~ ThreeDBasics.Triple; Xfm3DRep: TYPE ~ ThreeDBasics.Xfm3DRep; Rectangle: TYPE ~ ThreeDBasics.Rectangle; Box: TYPE ~ ThreeDBasics.Box; Patch: TYPE ~ ThreeDBasics.Patch; ShapeInstance: TYPE ~ ThreeDBasics.ShapeInstance; ContextClass: TYPE ~ ThreeDBasics.ContextClass; ShadingClass: TYPE ~ ThreeDBasics.ShadingClass; ShapeClass: TYPE ~ ThreeDBasics.ShapeClass; registeredDisplayTypes: Atom.PropList _ NIL; -- keeps active display types registeredSurfaceTypes: Atom.PropList _ NIL; -- keeps active surface types registeredShadingClasses: Atom.PropList _ NIL; -- keeps active shading classes Sqr: PROCEDURE [number: REAL] RETURNS [REAL] ~ INLINE { RETURN[number * number]; }; RectangleFromBox: PUBLIC PROC[box: Box] RETURNS[ Rectangle] ~ { RETURN [[ x: Real.Float[box.min.f], y: Real.Float[box.min.s], w: Real.Float[box.max.f - box.min.f], h: Real.Float[box.max.s - box.min.s] ]]; }; BoxFromRectangle: PUBLIC PROC[ rect: Rectangle ] RETURNS[ Box ] ~ { RETURN [[ min: [ f: Real.Fix[rect.x], s: Real.Fix[rect.y] ], max: [ f: Real.Fix[rect.x + rect.w], s: Real.Fix[rect.y + rect.h] ] ]]; }; IntersectRectangles: PUBLIC PROC[ rect1, rect2: Rectangle ] RETURNS[ Rectangle ] ~ { intersection: Rectangle; intersection.x _ MAX[rect1.x, rect2.x]; intersection.y _ MAX[rect1.y, rect2.y]; intersection.w _ MIN[rect1.w - (intersection.x - rect1.x), rect2.w - (intersection.x - rect2.x)]; intersection.h _ MIN[rect1.h - (intersection.y - rect1.y), rect2.h - (intersection.y - rect2.y)]; RETURN [intersection]; }; RegisterDisplayType: PUBLIC PROC[ class: ContextClass, type: ATOM ] ~ { registeredDisplayTypes _ Atom.PutPropOnList[registeredDisplayTypes, type, NEW[ContextClass _ class] ]; }; GetDisplayType: PUBLIC PROC[ type: ATOM ] RETURNS[ class: ContextClass ] ~ { refClass: REF ContextClass _ NARROW[Atom.GetPropFromList[registeredDisplayTypes, type]]; IF refClass # NIL THEN class _ refClass^ ELSE SIGNAL Error[[$Unimplemented, "Unregistered display type"]] }; LoadDisplayType: PUBLIC PROC[ context: REF Context, type: ATOM ] ~ { class: REF ContextClass _ NARROW[Atom.GetPropFromList[registeredDisplayTypes, type]]; IF class = NIL THEN Error[[$Unimplemented, "Unregistered display type"]]; context.class _ NEW[ ContextClass _ class^ ]; context.pixels _ NIL; --this and next line for saving VM context.displayProps _ Atom.RemPropFromList[context.displayProps, $FullDisplayMemory]; context.class.setUpDisplayType[context]; -- maps in pixels, sets up color map IF Atom.GetPropFromList[context.props, $BufferContext] # NIL THEN { SIGNAL Error[[$Warning, "Dropping Buffer context"]]; -- insufficient info to update context.props _ Atom.RemPropFromList[context.props, $BufferContext]; }; WITH Atom.GetPropFromList[context.props, $BackGround] SELECT FROM backGrdCtx: REF Context => { SIGNAL Error[[$Warning, "Dropping BackGround context"]]; -- no info for update context.props _ Atom.RemPropFromList[context.props, $BackGround]; }; ENDCASE; }; RegisterSurfaceType: PUBLIC PROC[ class: ShapeClass, type: ATOM ] ~ { registeredSurfaceTypes _ Atom.PutPropOnList[registeredSurfaceTypes, type, NEW[ShapeClass _ class] ]; }; GetSurfaceType: PUBLIC PROC[ type: ATOM ] RETURNS[ class: ShapeClass ] ~ { refClass: REF ShapeClass _ NARROW[Atom.GetPropFromList[registeredSurfaceTypes, type]]; IF refClass # NIL THEN class _ refClass^ ELSE SIGNAL Error[[$Unimplemented, "Unregistered surface type"]]; }; LoadSurfaceType: PUBLIC PROC[shape: REF ShapeInstance, type: ATOM _ $ConvexPolygon] ~{ class: REF ShapeClass _ NARROW[Atom.GetPropFromList[registeredSurfaceTypes, type]]; IF class = NIL THEN SIGNAL Error[[$Unimplemented, "Unregistered surface type"]]; IF shape.class = NIL THEN shape.class _ NEW[ ShapeClass _ class^ ] ELSE { new: REF ShapeClass _ NEW[ ShapeClass _ class^ ]; IF new.validate = NIL THEN new.validate _ shape.class.validate; IF new.display = NIL THEN new.display _ shape.class.display; IF new.displayPatch = NIL THEN new.displayPatch _ shape.class.displayPatch; IF new.doBeforeFrame = NIL THEN new.doBeforeFrame _ shape.class.doBeforeFrame; shape.class _ new; }; IF shape.shadingClass = NIL THEN LoadShadingClass[shape]; -- load default class shape.shadingInValid _ TRUE; -- in case we're changing the type on an existing shape shape.vtcesInValid _ TRUE; shape.props _ Atom.RemPropFromList[ shape.props, $LinesList ]; -- list may not be valid }; RegisterShadingClass: PUBLIC PROC[ class: ShadingClass, type: ATOM ] ~ { registeredShadingClasses _ Atom.PutPropOnList[registeredShadingClasses, type, NEW[ShadingClass _ class] ]; }; GetShadingClass: PUBLIC PROC[ type: ATOM ] RETURNS[ class: ShadingClass ] ~ { ref: REF ShadingClass _ NARROW[Atom.GetPropFromList[registeredShadingClasses, type]]; IF ref # NIL THEN class _ ref^ ELSE SIGNAL Error[[$Unimplemented, "Unregistered shading class"]]; }; LoadShadingClass: PUBLIC PROC[ shape: REF ShapeInstance, type: ATOM _ $Default ] ~ { class: REF ShadingClass _ NARROW[Atom.GetPropFromList[registeredShadingClasses, type]]; IF class = NIL THEN SIGNAL Error[[$Unimplemented, "Unregistered shading class"]]; IF shape.shadingClass = NIL THEN shape.shadingClass _ NEW[ ShadingClass _ class^ ] ELSE { new: REF ShadingClass _ NEW[ ShadingClass _ class^ ]; IF new.shadingType = NIL THEN new.shadingType _ shape.shadingClass.shadingType; new.color _ shape.shadingClass.color; new.shininess _ shape.shadingClass.shininess; new.transmittance _ shape.shadingClass.transmittance; IF new.patchShade = NIL THEN new.patchShade _ shape.shadingClass.patchShade; IF new.texture = NIL THEN new.texture _ shape.shadingClass.texture; IF new.cnvrtVtx = NIL THEN new.cnvrtVtx _ shape.shadingClass.cnvrtVtx; IF new.getColor = NIL THEN new.getColor _ shape.shadingClass.getColor; IF new.loadShapeAux = NIL THEN new.loadShapeAux _ shape.shadingClass.loadShapeAux; IF new.loadVtxAux = NIL THEN new.loadVtxAux _ shape.shadingClass.loadVtxAux; IF new.shadeVtx = NIL THEN new.shadeVtx _ shape.shadingClass.shadeVtx; shape.shadingClass _ new; }; shape.shadingProps _ NIL; -- WHY??? }; Create: PUBLIC PROC[] RETURNS [REF Context] ~ { context: REF Context _ NEW[Context]; wDir: Rope.ROPE _ Commander.PrependWorkingDir[" "]; -- add needed space (wierdness) wDir _ Rope.Substr[ base: wDir, len: Rope.Length[wDir] - 1 ]; -- drop space context.props _ Atom.PutPropOnList[context.props, $WDir, wDir]; -- keep directory context.eyeSpaceXfm _ G3dMatrix.Identity[]; -- can't do this in initialization, so do it here context.stopMe _ NEW[ BOOLEAN _ FALSE ]; RETURN[context]; }; SetView: PUBLIC PROC[context: REF Context, eyePoint, ptOfInterest: Triple, fieldOfView: REAL _ 40.0, rollAngle: REAL _ 0.0, upDirection: Triple _ [ 0., 0., 1.], hitherLimit: REAL _ .01, yonLimit: REAL _ 1000.0] ~ { context.eyePoint _ eyePoint; context.ptOfInterest _ ptOfInterest; context.fieldOfView _ fieldOfView; context.rollAngle _ rollAngle; context.upDirection _ upDirection; context.hitherLimit _ hitherLimit; context.yonLimit _ yonLimit; context.viewInValid _ TRUE; }; SetPosition: PUBLIC PROC[shape: REF ShapeInstance, concat: BOOLEAN _ FALSE] ~ { hypotenuse: REAL _ RealFns.SqRt[ Sqr[shape.orientation.x] + Sqr[shape.orientation.y] ]; IF NOT concat THEN shape.position _ G3dMatrix.Identity[]; -- clear to identity transform shape.position _ G3dMatrix.Mul[ shape.position, -- rotation about arbitrary axis G3dMatrix.MakeRotate[ axis: G3dVector.Sub[shape.axisEnd, shape.axisBase], theta: shape.rotation, base: shape.axisBase ] ]; IF hypotenuse > 0.0 -- orientation THEN { length: REAL _ G3dVector.Length[shape.orientation]; cosA, sinA, cosB, sinB: REAL; cosA _ shape.orientation.x / hypotenuse; sinA _ shape.orientation.y / hypotenuse; shape.position _ G3dMatrix.Mul[ shape.position, -- longitudinal rotation into x-z plane, left handed about z-up NEW[ Xfm3DRep _ [ [cosA,-sinA,0.,0.], [sinA,cosA,0.,0.], [0.,0.,1.,0.], [0.,0.,0.,1.] ] ] ]; cosB _ shape.orientation.z / length; sinB _ hypotenuse / length; shape.position _ G3dMatrix.Mul[ shape.position, -- latitudinal rotation, right-handed about y-north NEW[ Xfm3DRep _ [ [cosB,0.,-sinB,0.], [0.,1.,0.,0.], [sinB,0.,cosB,0.], [0.,0.,0.,1.] ] ] ]; shape.position _ G3dMatrix.Mul[ shape.position, -- longitudinal rotation from x-z plane, right handed about z-up NEW[ Xfm3DRep _ [ [cosA,sinA,0.,0.], [-sinA,cosA,0.,0.], [0.,0.,1.,0.], [0.,0.,0.,1.] ] ] ]; } ELSE IF shape.orientation.z < 0.0 THEN shape.position _ G3dMatrix.Mul[ shape.position, -- turn upside down NEW[ Xfm3DRep _ [ [-1.,0.,0.,0.], [0.,1.,0.,0.], [0.,0.,-1.,0.], [0.,0.,0.,1.] ] ] ]; shape.position _ G3dMatrix.Mul[ shape.position, -- translation NEW[ Xfm3DRep _ [[1.,0.,0.,0.], [0.,1.,0.,0.], [0.,0.,1.,0.], [shape.location.x, shape.location.y, shape.location.z, 1.]] ] ]; shape.positionInValid _ FALSE; }; CloseDisplay: PUBLIC PROC[context: REF Context] ~ { context.pixels _ NIL; -- throw away buffer bits context.displayProps _ Atom.RemPropFromList[context.displayProps, $FullDisplayMemory]; ImagerColorMap.SetStandardColorMap[ context.terminal -- restore standard color map ! RuntimeError.BoundsFault => CONTINUE]; }; END. ThreeDBasicsImpl.mesa Copyright c 1984, 1986 by Xerox Corporation. All rights reserved. Last Edited by: Crow, February 9, 1988 5:32:02 pm PST Bloomenthal, August 14, 1988 5:26:51 pm PDT Basic Types Global Variables Utility Procedures Procedures for Registering Classes Adds class to list of registered ShadingClasses, for fancy texturing procs, etc. Retrieves registered class for use or modification Puts ShadingClass in shape record Procedures for Standard Operations Get Working directory Makes matrix from position parameters and either replaces or concatenates to the existing matrix Shuts down display gracefully, restores standard color map Κ n˜IheadšΟb™šœ Οmœ7™BJ™5Icode™+J˜šΟk ˜ Jšœ Ÿœ?˜MIdefaultšœ Ÿœ˜(Mšœ ŸœŸ˜#Mšœ Ÿœ˜1MšœŸœ˜.Jšœ Ÿœ Ÿœ ˜(Jšœ Ÿœ˜Jšœ Ÿœ ˜JšœŸœ˜$MšœŸœ<ŸœI˜›——head2šœŸœŸ˜IašŸœX˜`OšŸœ˜J˜JšœŸ˜—head3š ™ OšΟnœŸœŸœ$Ÿœ˜>Jšœ Ÿœ˜%JšŸœŸœŸœ˜JšœŸœ˜#Jšœ Ÿœ˜'Jšœ Ÿœ˜)JšΟtœŸœ‘œ˜JšœŸœ˜!JšœŸœ˜1JšœŸœ˜/JšœŸœ˜/Jšœ Ÿœ˜+J˜—š™Mšœ(ŸœΟc˜LMšœ(Ÿœ’˜LMšœ*Ÿœ’˜P—š™Mš œŸ œ ŸœŸœŸœŸœŸœ˜Tš  œŸœŸœ‘œŸœ˜?šŸœ˜ Mšœ‘œ ˜Mšœ‘œ˜Mšœ‘œ ‘œ ˜&Mšœ‘œ ‘œ˜$M˜—M˜—š  œŸœŸœŸœ‘œ˜CšŸœ˜ Mšœ ‘ œ ‘ œ‘œ˜3Mšœ‘œ‘ œ˜CM˜—M˜—š œŸœŸœŸœ˜TM˜MšœŸœ˜(MšœŸœ˜(MšœŸœM˜aMšœŸœM˜aMšŸœ˜M˜—M˜—š"™"š œŸ œŸœ˜GJšœYŸœ˜vM˜—š  œŸœŸœŸœŸœ˜LMšœ ŸœŸœ5˜XšŸœ Ÿœ˜MšŸœ˜MšŸœŸœ5˜@—M˜—š œŸ œ ŸœŸœ˜DMšœŸœŸœ5˜UMšŸœ ŸœŸœ6˜IJšœŸœ˜-JšœŸœ ’"˜AJ˜WJšœ+’$˜OšŸœ7ŸœŸœ˜CMšŸœ0’˜TM˜DM˜—šŸœ2ŸœŸ˜Ašœ Ÿœ ˜MšŸœ2’˜NM˜AM˜—MšŸœ˜—M˜—š œŸ œŸœ˜EJšœYŸœ˜tM˜—š  œŸœŸœŸœŸœ˜JMšœ ŸœŸœ5˜VšŸœ Ÿœ˜MšŸœ˜MšŸœŸœ6˜A—M˜—š œŸ œŸœŸœ˜VMšœŸœŸœ5˜SMšŸœ ŸœŸœŸœ6˜PšŸœŸœ˜JšŸœŸœ˜-šŸœ˜JšœŸœŸœ˜1JšŸœŸœŸœ%˜?JšŸœŸœŸœ#˜