-- File: SVTransformsImpl.mesa -- Last edited by Bier on December 18, 1982 1:34 am -- Author: Eric Bier before July 3, 1983 1:30 pm -- Contents: Procedures for Scaling, Translating, and Rotating assemblies with respect to an arbitrary coordinate system DIRECTORY CoordSys, CSGGraphics, DisplayList3d, MessageWindow, Matrix3d, SVTransforms, SVVector3d; SVTransformsImpl: PROGRAM IMPORTS CoordSys, DisplayList3d, Matrix3d, MessageWindow, SVVector3d EXPORTS SVTransforms = BEGIN Assembly: TYPE = DisplayList3d.Assembly; AssemblyList: TYPE = DisplayList3d.AssemblyList; Camera: TYPE = CSGGraphics.Camera; CoordSystem: TYPE = CoordSys.CoordSystem; MasterObject: TYPE = DisplayList3d.MasterObject; Matrix4by4: TYPE = Matrix3d.Matrix4by4; Scene: TYPE = DisplayList3d.Scene; Vector: TYPE = SVVector3d.Vector; TellAboutCameraAndWorld1: PUBLIC PROC [a: Assembly, camera: Camera, scene: Scene] = { -- tree walk through the tree to the leaves then concatenate all matrices (will later concatenate matrices as it goes). camera.coordSys.wrtWorld _ CoordSys.FindInTermsOfWorld[camera.coordSys]; FOR list: LIST OF Assembly _ DisplayList3d.ListOfPrimAssemblies[a, scene], list.rest UNTIL list = NIL DO list.first.coordSys.wrtCamera _ Matrix3d.LocalScale[CoordSys.FindInTermsOfCamera[list.first.coordSys, camera.coordSys], list.first.scalars[1], list.first.scalars[2], list.first.scalars[3]]; list.first.coordSys.wrtWorld _ Matrix3d.LocalScale[CoordSys.FindInTermsOfWorld[list.first.coordSys], list.first.scalars[1], list.first.scalars[2], list.first.scalars[3]]; list.first.coordSys.cameraWRTlocal _ Matrix3d.Inverse[list.first.coordSys.wrtCamera]; list.first.coordSys.worldWRTlocal _ Matrix3d.Inverse[list.first.coordSys.wrtWorld]; ENDLOOP; }; -- end of TellAboutCameraAndWorld TellAboutCameraAndWorld: PUBLIC PROC [a: Assembly, camera: Camera, scene: Scene] = { -- tree walk through the tree and concatenate all matrices (will later concatenate matrices as it goes). camera.coordSys.wrtWorld _ CoordSys.FindInTermsOfWorld[camera.coordSys]; WITH a.object SELECT FROM mo: MasterObject => { a.coordSys.wrtCamera _ Matrix3d.LocalScale[CoordSys.FindInTermsOfCamera[a.coordSys, camera.coordSys], a.scalars[1], a.scalars[2], a.scalars[3]]; a.coordSys.wrtWorld _ Matrix3d.LocalScale[CoordSys.FindInTermsOfWorld[a.coordSys], a.scalars[1], a.scalars[2], a.scalars[3]]; a.coordSys.cameraWRTlocal _ Matrix3d.Inverse[a.coordSys.wrtCamera]; a.coordSys.worldWRTlocal _ Matrix3d.Inverse[a.coordSys.wrtWorld]; }; alist: AssemblyList => { a.coordSys.wrtCamera _ CoordSys.FindInTermsOfCamera[a.coordSys, camera.coordSys]; a.coordSys.wrtWorld _ CoordSys.FindInTermsOfWorld[a.coordSys]; a.coordSys.cameraWRTlocal _ Matrix3d.Inverse[a.coordSys.wrtCamera]; a.coordSys.worldWRTlocal _ Matrix3d.Inverse[a.coordSys.wrtWorld]; TellAboutCameraAndWorldInList[alist, camera, scene]; }; ENDCASE => ERROR; }; -- end of TellAboutCameraAndWorld TellAboutCameraAndWorldInList: PRIVATE PROC [alist: AssemblyList, camera: Camera, scene: Scene] = { FOR list: LIST OF Assembly _ alist.list, list.rest UNTIL list = NIL DO TellAboutCameraAndWorld[list.first, camera, scene]; ENDLOOP; }; Translate: PUBLIC PROC [a: Assembly, cs: CoordSystem, tx, ty, tz: REAL] = { -- simple translate a's coordsys wrt cs by [tx, ty, tz]; CoordSys.TTranslateAwrtB[a.coordSys, cs, tx, ty, tz]; }; XRotate: PUBLIC PROC [a: Assembly, cs: CoordSystem, degrees: REAL] = { -- simple rotate a's coordsys wrt cs by degrees about the x axis CoordSys.TXRotateAwrtB[a.coordSys, cs, degrees]; }; YRotate: PUBLIC PROC [a: Assembly, cs: CoordSystem, degrees: REAL] = { -- simple rotate a's coordsys wrt cs by degrees about the y axis CoordSys.TYRotateAwrtB[a.coordSys, cs, degrees]; }; ZRotate: PUBLIC PROC [a: Assembly, cs: CoordSystem, degrees: REAL] = { -- simple rotate a's coordsys wrt cs by degrees about the z axis CoordSys.TZRotateAwrtB[a.coordSys, cs, degrees]; }; -- There are four ways to scale a cluster assembly -- 1) (ScalePrimitives) Scale each primitive in place, evenly or differentially. -- 2) (ScaleEven) If sx = sy = sz. Scale primitives in place and then translate all intermediate assemblies so the cluster assembly scales evenly as a unit -- 3) (ScaleAndShear) IF sx # sy or sy # sz then scale and shear the primitives and translate them differentially so the cluster assembly scales and shears as a unit. -- 4) (ScaleNoShear) IF sx # sy or sy # sz. Scale the primitives evenly so that their dimension in the direction of scaling increases or decreases to the same quantity it would have reached by method 3. This preserves shape of primitives. Global shape is not preserved (but almost). ScalePrimitive: PUBLIC PROC [a: Assembly, sx, sy, sz: REAL] = { IF NOT ISTYPE[a.object, MasterObject] THEN ERROR; a.scalars[1] _ a.scalars[1]*sx; a.scalars[2] _ a.scalars[2]*sy; a.scalars[3] _ a.scalars[3]*sz; }; ScalePrimitives: PUBLIC PROC [a: Assembly, sx, sy, sz: REAL] = { WITH a.object SELECT FROM mo: MasterObject => ScalePrimitive[a, sx, sy, sz]; alist: AssemblyList => { FOR list: LIST OF Assembly _ alist.list, list.rest UNTIL list = NIL DO ScalePrimitives[list.first, sx, sy, sz]; ENDLOOP; }; ENDCASE; -- IF a.object = NIL or something else, do nothing. }; ScaleEven: PUBLIC PROC [a: Assembly, cs: CoordSystem, scalar: REAL] = { displacements: Vector; WITH a.object SELECT FROM mo: MasterObject => { ScalePrimitive[a, scalar, scalar, scalar]; -- now translate a's coordSys so that its displacement from the origin of cs is scaled by scalar displacements _ CoordSys.FindTranslationOfAinTermsOfB[a.coordSys, cs]; displacements _ SVVector3d.Scale[displacements, scalar]; CoordSys.TPlaceTranslationAwrtB[a.coordSys, cs, displacements]; }; alist: AssemblyList => { FOR list: LIST OF Assembly _ alist.list, list.rest UNTIL list = NIL DO ScaleEven[list.first, a.coordSys, scalar]; -- recursively scale subassemblies with respect to their own coordinate systems ENDLOOP; -- now translate a's coordSys so that its displacement from the origin of cs is scaled by scalar displacements _ CoordSys.FindTranslationOfAinTermsOfB[a.coordSys, cs]; displacements _ SVVector3d.Scale[displacements, scalar]; CoordSys.TPlaceTranslationAwrtB[a.coordSys, cs, displacements]; }; ENDCASE; -- IF a.object = NIL or something else, do nothing. }; Scale: PUBLIC PROC [a: Assembly, cs: CoordSystem, sx, sy, sz: REAL] = { IF ISTYPE[a.object, MasterObject] AND cs = a.coordSys THEN ScalePrimitive[a, sx, sy, sz] ELSE ScaleEven[a, cs, sx]; }; Align: PUBLIC PROC [a: Assembly, cs: CoordSystem] = { -- aligning is a pure rotation so simply align a's coordsys wrt cs. CoordSys.TAlignAwrtB[a.coordSys, cs]; }; Abut: PUBLIC PROC [a: Assembly, cs: CoordSystem] = { -- abutting is a pure translation so simply abut a's coordsys wrt cs. CoordSys.TAbutAwrtB[a.coordSys, cs]; }; AbutX: PUBLIC PROC [a: Assembly, cs: CoordSystem] = { -- abutting is a pure translation so simply abut a's coordsys wrt cs. CoordSys.TAbutXAwrtB[a.coordSys, cs]; }; AbutY: PUBLIC PROC [a: Assembly, cs: CoordSystem] = { -- abutting is a pure translation so simply abut a's coordsys wrt cs. CoordSys.TAbutYAwrtB[a.coordSys, cs]; }; AbutZ: PUBLIC PROC [a: Assembly, cs: CoordSystem] = { -- abutting is a pure translation so simply abut a's coordsys wrt cs. CoordSys.TAbutZAwrtB[a.coordSys, cs]; }; Place: PUBLIC PROC [a: Assembly, cs: CoordSystem, mat: Matrix4by4] = { -- mat may have only translational and rotational components. Check to make sure this is so and then call the CoordSys PlaceAwrtB. IF MatrixHasScaling[mat] THEN {MessageWindow.Append["SVTransformImpl.Place got illegal matrix. Ignored."]; RETURN}; CoordSys.TPlaceAwrtB[a.coordSys, cs, mat]; }; MatrixHasScaling: PRIVATE PROC [mat: Matrix4by4] RETURNS [BOOL] = { sx, sy, sz: REAL; almostZero: REAL _ 1.0e-4; [sx, sy, sz] _ Matrix3d.ScaleFromMatrix[mat]; IF ABS[sx - 1.0] > almostZero OR ABS[sy-1.0] > almostZero OR ABS[sz - 1.0] > almostZero THEN RETURN[TRUE] ELSE RETURN [FALSE]; }; AlignIndirect: PUBLIC PROC [a: Assembly, tugBoat: CoordSystem, dock: CoordSystem] = { -- One way to proceed is this: -- 1) Find the a WRT tugBoat. -- 2) Align tugboat with dock. -- 3) Place a WRT tugBoat using (1) aWRTtugBoat: Matrix4by4 _ CoordSys.FindAinTermsOfB[a.coordSys, tugBoat]; CoordSys.TAlignAwrtB[tugBoat, dock]; Place[a, tugBoat, aWRTtugBoat]; }; AbutIndirect: PUBLIC PROC [a: Assembly, tugBoat: CoordSystem, dock: CoordSystem] = { aWRTtugBoat: Matrix4by4 _ CoordSys.FindAinTermsOfB[a.coordSys, tugBoat]; CoordSys.TAbutAwrtB[tugBoat, dock]; Place[a, tugBoat, aWRTtugBoat]; }; PlaceIndirect: PUBLIC PROC [a: Assembly, tugBoat: CoordSystem, dock: CoordSystem, mat: Matrix4by4] = { aWRTtugBoat: Matrix4by4; IF MatrixHasScaling[mat] THEN {MessageWindow.Append["SVTransformImpl.PlaceIndirect got illegal matrix. Ignored."]; RETURN}; aWRTtugBoat _ CoordSys.FindAinTermsOfB[a.coordSys, tugBoat]; CoordSys.TPlaceAwrtB[tugBoat, dock, mat]; Place[a, tugBoat, aWRTtugBoat]; }; END. ʘJšíÏcıœÏk œuœœ?œœ œ)œ'œ$œ'œ+œœ œÏnœœœ2xœIœœœDœœœ©œ"œŸœœœ2iœKœ œœÌœœ"œŸœœœ:œœœ"œœœ8œŸ œœœ,œ9œ=Ÿœœœ)œAœ8Ÿœœœ)œAœ8Ÿœœœ)œAœ8뜟œœœœœœœœœkŸœœœœœ œœQœœœ"œœœ/œœ4œŸ œœœ(œœ œœHaœçœœœ"œœœ/RœaœÌœ4œŸœœœ,œœœœœ œŸœœœ%Dœ-Ÿœœœ%Fœ,Ÿœœœ%Fœ-Ÿœœœ%Fœ-Ÿœœœ%Fœ-Ÿœœœ6„œœœVœ5Ÿœœœœœœœ;œœœœœœœœœœœœ Ÿ œœœ=œœœ$œ—Ÿ œœœÒŸ œœœhœœ]œ’œ˜ãG—…—#æ&ó