DIRECTORY CoordSys, Matrix3d, Rope, SV3d, SVError, SVModelTypes, SVSceneTypes, SVTransforms, SVVector3d; SVTransformsImpl: PROGRAM IMPORTS CoordSys, Matrix3d, Rope, SVError, SVVector3d EXPORTS SVTransforms = BEGIN Assembly: TYPE = SVSceneTypes.Assembly; AssemblyList: TYPE = SVSceneTypes.AssemblyList; Camera: TYPE = SVModelTypes.Camera; CoordSystem: TYPE = SVModelTypes.CoordSystem; CoordSysList: TYPE = SVModelTypes.CoordSysList; Matrix4by4: TYPE = SV3d.Matrix4by4; Point3d: TYPE = SV3d.Point3d; Scene: TYPE = SVSceneTypes.Scene; Shape: TYPE = SVSceneTypes.Shape; Vector: TYPE = SV3d.Vector; IncTransf: PUBLIC PROC [C: CoordSystem, D: CoordSystem, M: Matrix4by4, DFixed: BOOL _ FALSE] = { P: CoordSystem; IF C.parent = NIL THEN ERROR; -- cannot translate WORLD for now IF D = NIL THEN ERROR; P _ C.parent; IF MatrixHasScaling[M] THEN { SVError.Append["SVTransform.IncTransf got illegal matrix. Ignored."]; SVError.Blink[]; RETURN}; SELECT TRUE FROM D.parent = NIL => { -- D = WORLD CWORLD, WORLDP, PWORLD: Matrix4by4; CWORLD _ CoordSys.FindInTermsOfWorld[C]; PWORLD _ CoordSys.FindInTermsOfWorld[P]; WORLDP _ Matrix3d.Inverse[PWORLD]; C.mat _ Matrix3d.MatMult[Matrix3d.MatMult[WORLDP, M], CWORLD]; }; C = D => { -- local tranformation C.mat _ Matrix3d.MatMult[C.mat, M]; }; D = P => { -- transformation relative to parent C.mat _ Matrix3d.MatMult[M, C.mat]; }; ENDCASE => { -- general transformation CWORLD, DWORLD, CD, WORLDP, PWORLD: Matrix4by4; CWORLD _ CoordSys.FindInTermsOfWorld[C]; DWORLD _ CoordSys.FindInTermsOfWorld[D]; -- we will preserve this relationship if DFixed PWORLD _ CoordSys.FindInTermsOfWorld[P]; WORLDP _ Matrix3d.Inverse[PWORLD]; CD _ CoordSys.FindAInTermsOfB[C, D]; C.mat _ Matrix3d.MatMult[Matrix3d.MatMult[Matrix3d.MatMult[WORLDP, DWORLD], M], CD]; IF DFixed THEN { DPWORLD, DDP: Matrix4by4; DPWORLD _ CoordSys.FindInTermsOfWorld[D.parent]; DDP _ Matrix3d.WorldToLocal[DPWORLD, DWORLD]; D.mat _ DDP; }; }; }; IncTransfMatrix: PUBLIC PROC [C: CoordSystem, DWORLD: Matrix4by4, M: Matrix4by4] = { P: CoordSystem; CWORLD, CD, WORLDP, PWORLD: Matrix4by4; IF C.parent = NIL THEN ERROR; -- cannot translate WORLD for now P _ C.parent; IF MatrixHasScaling[M] THEN { SVError.Append["SVTransform.IncTransfMatrix got illegal matrix. Ignored."]; SVError.Blink[]; RETURN}; CWORLD _ CoordSys.FindInTermsOfWorld[C]; PWORLD _ CoordSys.FindInTermsOfWorld[P]; WORLDP _ Matrix3d.Inverse[PWORLD]; CD _ Matrix3d.WorldToLocal[DWORLD, CWORLD]; C.mat _ Matrix3d.MatMult[Matrix3d.MatMult[Matrix3d.MatMult[WORLDP, DWORLD], M], CD]; }; PlaneOriginRotate: PUBLIC PROC [C: CoordSystem, D: CoordSystem, degrees: REAL, plane: NAT] = { M, PivotWORLD, CWORLD, DWORLD: Matrix4by4; origin: Point3d; xAxis, yAxis, zAxis: Vector; CWORLD _ CoordSys.FindInTermsOfWorld[C]; DWORLD _ CoordSys.FindInTermsOfWorld[D]; origin _ Matrix3d.OriginOfMatrix[CWORLD]; xAxis _ Matrix3d.XAxisOfMatrix[DWORLD]; yAxis _ Matrix3d.YAxisOfMatrix[DWORLD]; zAxis _ Matrix3d.ZAxisOfMatrix[DWORLD]; PivotWORLD _ Matrix3d.MakeMatFromAxes[xAxis, yAxis, zAxis, origin]; SELECT plane FROM 1 => M _ Matrix3d.MakeRotateXMat[degrees]; 2 => M _ Matrix3d.MakeRotateYMat[degrees]; 3 => M _ Matrix3d.MakeRotateZMat[degrees]; ENDCASE => ERROR; IncTransfMatrix[C, PivotWORLD, M]; }; AbsTransf: PUBLIC PROC [C: CoordSystem, D: CoordSystem, N: Matrix4by4, DFixed: BOOL _ FALSE] = { P: CoordSystem; IF Rope.Equal[C.name, "SCREEN", TRUE] THEN {C.mat _ N; RETURN}; IF C.parent = NIL THEN ERROR; -- cannot transform WORLD. IF D = NIL THEN ERROR; P _ C.parent; IF MatrixHasScaling[N] THEN { SVError.Append["SVTransform.AbsTransf got illegal matrix. Ignored."]; SVError.Blink[]; RETURN}; SELECT TRUE FROM D.parent = NIL => { -- D = WORLD WORLDP, PWORLD: Matrix4by4; PWORLD _ CoordSys.FindInTermsOfWorld[P]; WORLDP _ Matrix3d.Inverse[PWORLD]; C.mat _ Matrix3d.MatMult[WORLDP, N]; }; C = D => { -- local tranformation C.mat _ Matrix3d.MatMult[C.mat, N]; }; D = P => { -- transformation relative to parent C.mat _ N; }; ENDCASE => { -- general transformation DWORLD, WORLDP, PWORLD: Matrix4by4; DWORLD _ CoordSys.FindInTermsOfWorld[D]; PWORLD _ CoordSys.FindInTermsOfWorld[P]; WORLDP _ Matrix3d.Inverse[PWORLD]; C.mat _ Matrix3d.MatMult[Matrix3d.MatMult[WORLDP, DWORLD], N]; IF DFixed THEN { DPWORLD, DDP: Matrix4by4; DPWORLD _ CoordSys.FindInTermsOfWorld[D.parent]; DDP _ Matrix3d.WorldToLocal[DPWORLD, DWORLD]; D.mat _ DDP; }; }; }; TugTransf: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem, N: Matrix4by4] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; AbsTransf[tugBoat, D, N]; AbsTransf[C, tugBoat, F]; }; TugTransfLeaveTug: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem, N: Matrix4by4] = { F: Matrix4by4; saveTugMat: Matrix4by4 _ tugBoat.mat; F _ CoordSys.FindAInTermsOfB[C, tugBoat]; AbsTransf[tugBoat, D, N]; AbsTransf[C, tugBoat, F]; tugBoat.mat _ saveTugMat; }; Translate: PUBLIC PROC [C: CoordSystem, D: CoordSystem, tx, ty, tz: REAL, DFixed: BOOL _ FALSE] = { M: Matrix4by4; M _ Matrix3d.MakeTranslateMat[tx, ty, tz]; IncTransf[C, D, M, DFixed]; }; XRotate: PUBLIC PROC [C: CoordSystem, D: CoordSystem, degrees: REAL, DFixed: BOOL _ FALSE] = { M: Matrix4by4; M _ Matrix3d.MakeRotateXMat[degrees]; IncTransf[C, D, M, DFixed]; }; YRotate: PUBLIC PROC [C: CoordSystem, D: CoordSystem, degrees: REAL, DFixed: BOOL _ FALSE] = { M: Matrix4by4; M _ Matrix3d.MakeRotateYMat[degrees]; IncTransf[C, D, M, DFixed]; }; ZRotate: PUBLIC PROC [C: CoordSystem, D: CoordSystem, degrees: REAL, DFixed: BOOL _ FALSE] = { M: Matrix4by4; M _ Matrix3d.MakeRotateZMat[degrees]; IncTransf[C, D, M, DFixed]; }; AbsTranslateOnly: PUBLIC PROC [C: CoordSystem, D: CoordSystem, vD: Point3d] = { P: CoordSystem; -- parent of C vP: Vector; IF Rope.Equal[C.name, "SCREEN", TRUE] THEN { C.mat[1][4] _ vD[1]; C.mat[2][4] _ vD[2]; C.mat[3][4] _ vD[3]; RETURN}; IF C.parent = NIL THEN ERROR; -- cannot transform WORLD. IF D = NIL THEN ERROR; P _ C.parent; SELECT TRUE FROM D.parent = NIL => { -- D = WORLD WORLDP, PWORLD: Matrix4by4; PWORLD _ CoordSys.FindInTermsOfWorld[P]; WORLDP _ Matrix3d.Inverse[PWORLD]; vP _ Matrix3d.Update[WORLDP, vD]; C.mat[1][4] _ vP[1]; C.mat[2][4] _ vP[2]; C.mat[3][4] _ vP[3]; }; C = D => { -- local tranformation C.mat _ Matrix3d.LocalTranslate[C.mat, vD[1], vD[2], vD[3]]; }; D = P => { -- transformation relative to parent C.mat[1][4] _ vD[1]; C.mat[2][4] _ vD[2]; C.mat[3][4] _ vD[3]; }; ENDCASE => { -- general transformation DWORLD, WORLDP, PWORLD: Matrix4by4; DWORLD _ CoordSys.FindInTermsOfWorld[D]; PWORLD _ CoordSys.FindInTermsOfWorld[P]; WORLDP _ Matrix3d.Inverse[PWORLD]; vP _ Matrix3d.Update[WORLDP, Matrix3d.Update[DWORLD, vD]]; C.mat[1][4] _ vP[1]; C.mat[2][4] _ vP[2]; C.mat[3][4] _ vP[3]; }; }; Align: PUBLIC PROC [C: CoordSystem, D: CoordSystem] = { CD: Matrix4by4; xAxisChoices, zAxisChoices: ARRAY[1..3] OF NAT; xAxis, zAxis, newXAxis, newYAxis, newZAxis: Vector; xNegArray, zNegArray: ARRAY[1..3] OF BOOL; origin: Point3d; CD _ CoordSys.FindAInTermsOfB[C, D]; xAxis _ Matrix3d.XAxisOfMatrix[CD]; zAxis _ Matrix3d.ZAxisOfMatrix[CD]; origin _ Matrix3d.OriginOfMatrix[CD]; [xAxisChoices, xNegArray] _ IndicesOfMax[xAxis]; -- Find largest component [zAxisChoices, zNegArray] _ IndicesOfMax[zAxis]; IF zAxisChoices[1] = xAxisChoices[1] THEN zAxisChoices[1] _ zAxisChoices[2]; newXAxis _ [0,0,0]; newXAxis[xAxisChoices[1]] _ SVVector3d.Magnitude[xAxis]; IF xNegArray[xAxisChoices[1]] THEN newXAxis[xAxisChoices[1]] _ -newXAxis[xAxisChoices[1]]; newZAxis _ [0,0,0]; newZAxis[zAxisChoices[1]] _ SVVector3d.Magnitude[zAxis]; IF zNegArray[zAxisChoices[1]] THEN newZAxis[zAxisChoices[1]] _ -newZAxis[zAxisChoices[1]]; newYAxis _ SVVector3d.CrossProduct[newZAxis, newXAxis]; CD _ Matrix3d.MakeMatFromAxes[newXAxis, newYAxis, newZAxis, origin]; AbsTransf[C, D, CD]; }; -- end of Align IndicesOfMax: PRIVATE PROC [v: Vector] RETURNS [indices: ARRAY[1..3] OF NAT, negArray: ARRAY[1..3] OF BOOL] = { temp: REAL; tempIndex: NAT; IF v[1] < 0 THEN {negArray[1] _ TRUE; v[1] _ -v[1]} ELSE negArray[1] _ FALSE; IF v[2] < 0 THEN {negArray[2] _ TRUE; v[2] _ -v[2]} ELSE negArray[2] _ FALSE; IF v[3] < 0 THEN {negArray[3] _ TRUE; v[3] _ -v[3]} ELSE negArray[3] _ FALSE; indices _ [1,2,3]; IF v[1] < v[2] THEN { temp _ v[1]; v[1] _ v[2]; v[2] _ temp; tempIndex _ indices[1]; indices[1] _ indices[2]; indices[2] _ tempIndex}; IF v[2] < v[3] THEN { temp _ v[2]; v[2] _ v[3]; v[3] _ temp; tempIndex _ indices[2]; indices[2] _ indices[3]; indices[3] _ tempIndex}; IF v[1] < v[2] THEN { temp _ v[1]; v[1] _ v[2]; v[2] _ temp; tempIndex _ indices[1]; indices[1] _ indices[2]; indices[2] _ tempIndex}; }; Abut: PUBLIC PROC [C: CoordSystem, D: CoordSystem] = { AbsTranslateOnly[C, D, [0,0,0]]; }; AbutX: PUBLIC PROC [C: CoordSystem, D: CoordSystem] = { vD: Vector; vD _ CoordSys.FindTranslationOfAinTermsOfB[C, D]; AbsTranslateOnly[C, D, [0, vD[2], vD[3]]]; }; AbutY: PUBLIC PROC [C: CoordSystem, D: CoordSystem] = { vD: Vector; vD _ CoordSys.FindTranslationOfAinTermsOfB[C, D]; AbsTranslateOnly[C, D, [vD[1], 0, vD[3]]]; }; AbutZ: PUBLIC PROC [C: CoordSystem, D: CoordSystem] = { vD: Vector; vD _ CoordSys.FindTranslationOfAinTermsOfB[C, D]; AbsTranslateOnly[C, D, [vD[1], vD[2], 0]]; }; NormalizeRot: PUBLIC PROC [C: CoordSystem, D: CoordSystem] = { oldMat, newMat: Matrix4by4; oldMat _ CoordSys.FindAInTermsOfB[a: C, b: D]; newMat _ Matrix3d.NormalizeNoRotation[oldMat]; AbsTransf[C, D, newMat]; }; Normalize: PUBLIC PROC [C: CoordSystem, D: CoordSystem] = { AbsTransf[C, D, Matrix3d.Identity[]]; }; NormalizeRotTug: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; NormalizeRot[tugBoat, D]; AbsTransf[C, tugBoat, F, TRUE]; }; NormalizeTug: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; Normalize[tugBoat, D]; AbsTransf[C, tugBoat, F, TRUE]; }; AlignTug: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; Align[tugBoat, D]; AbsTransf[C, tugBoat, F, TRUE]; }; AbutTug: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; Abut[tugBoat, D]; AbsTransf[C, tugBoat, F, TRUE]; }; AbutXTug: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; AbutX[tugBoat, D]; AbsTransf[C, tugBoat, F, TRUE]; }; AbutYTug: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; AbutY[tugBoat, D]; AbsTransf[C, tugBoat, F, TRUE]; }; AbutZTug: PUBLIC PROC [C: CoordSystem, tugBoat: CoordSystem, D: CoordSystem] = { F: Matrix4by4 _ CoordSys.FindAInTermsOfB[C, tugBoat]; AbutZ[tugBoat, D]; AbsTransf[C, tugBoat, F, TRUE]; }; DirtyAssembly: PUBLIC PROC [a: Assembly] = { WITH a.shape SELECT FROM shape: Shape => { a.coordSys.dirty _ TRUE; }; alist: AssemblyList => { a.coordSys.dirty _ TRUE; DirtyAssemblyList[alist]; }; ENDCASE => ERROR; }; -- end of DirtyAssembly DirtyAssemblyList: PRIVATE PROC [alist: AssemblyList] = { FOR list: LIST OF Assembly _ alist.list, list.rest UNTIL list = NIL DO DirtyAssembly[list.first]; ENDLOOP; }; TidyUpCoordSysTree: PUBLIC PROC [root: CoordSystem] = { parent: CoordSystem _ root.parent; IF root.scalarsOnly THEN { IF root.children # NIL THEN ERROR; -- scalars-only coordinate systems must be leaves. root.scalars _ Matrix3d.TidyUpVector[root.scalars]; } ELSE { root.mat _ Matrix3d.TidyUpMatrix[root.mat]; IF root.children # NIL THEN { -- Process the children as well FOR list: CoordSysList _ root.children, list.rest UNTIL list = NIL DO TidyUpCoordSysTree[list.first]; ENDLOOP; }; }; }; -- end of TidyUpCoordSysTree TellAboutCameraAndWorld: PUBLIC PROC [root: CoordSystem, camera: Camera, scene: Scene] = { camera.coordSys.wrtWorld _ CoordSys.FindInTermsOfWorld[camera.coordSys]; TellAboutCameraAndWorldAux[root, camera, scene]; }; TellAboutCameraAndWorldAux: PRIVATE PROC [root: CoordSystem, camera: Camera, scene: Scene] = { parent: CoordSystem _ root.parent; IF root.scalarsOnly THEN { IF root.children # NIL THEN ERROR; -- scalars only coordinate systems must be leaves. root.wrtCamera _ Matrix3d.LocalScale[CoordSys.FindInTermsOfCamera[parent, camera.coordSys], root.scalars[1], root.scalars[2], root.scalars[3]]; root.wrtWorld _ Matrix3d.LocalScale[CoordSys.FindInTermsOfWorld[parent], root.scalars[1], root.scalars[2], root.scalars[3]]; root.cameraWRTlocal _ Matrix3d.Inverse[root.wrtCamera]; root.worldWRTlocal _ Matrix3d.Inverse[root.wrtWorld]; } ELSE { root.wrtCamera _ CoordSys.FindInTermsOfCamera[root, camera.coordSys]; root.wrtWorld _ CoordSys.FindInTermsOfWorld[root]; root.cameraWRTlocal _ Matrix3d.Inverse[root.wrtCamera]; root.worldWRTlocal _ Matrix3d.Inverse[root.wrtWorld]; IF root.children # NIL THEN { -- Process the children as well FOR list: CoordSysList _ root.children, list.rest UNTIL list = NIL DO TellAboutCameraAndWorldAux[list.first, camera, scene]; ENDLOOP; }; }; }; -- end of TellAboutCameraAndWorldAux TellAboutCameraAndWorldInList: PRIVATE PROC [clist: CoordSysList, camera: Camera, scene: Scene] = { FOR list: CoordSysList _ clist, list.rest UNTIL list = NIL DO TellAboutCameraAndWorld[list.first, camera, scene]; ENDLOOP; }; TellAboutParent: PUBLIC PROC [cs: CoordSystem] = { cs.wrtWorld _ Matrix3d.MatMult[cs.parent.wrtWorld, cs.mat]; cs.wrtCamera _ Matrix3d.MatMult[cs.parent.wrtCamera, cs.mat]; cs.worldWRTlocal _ Matrix3d.Inverse[cs.wrtWorld]; cs.cameraWRTlocal _ Matrix3d.Inverse[cs.wrtCamera]; }; ScalePrimitive: PUBLIC PROC [a: Assembly, sx, sy, sz: REAL] = { shape: Shape; scalarCS: CoordSystem; IF NOT ISTYPE[a.shape, Shape] THEN ERROR; shape _ NARROW[a.shape]; scalarCS _ shape.coordSys; scalarCS.scalars[1] _ scalarCS.scalars[1]*sx; scalarCS.scalars[2] _ scalarCS.scalars[2]*sy; scalarCS.scalars[3] _ scalarCS.scalars[3]*sz; }; ScalePrimitives: PUBLIC PROC [a: Assembly, sx, sy, sz: REAL] = { WITH a.shape SELECT FROM shape: Shape => 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.shape = NIL or something else, do nothing. }; ScaleEven: PUBLIC PROC [a: Assembly, cs: CoordSystem, scalar: REAL] = { displacements: Vector; WITH a.shape SELECT FROM shape: Shape => { ScalePrimitive[a, scalar, scalar, scalar]; displacements _ CoordSys.FindTranslationOfAinTermsOfB[a.coordSys, cs]; displacements _ SVVector3d.Scale[displacements, scalar]; AbsTranslateOnly[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]; ENDLOOP; displacements _ CoordSys.FindTranslationOfAinTermsOfB[a.coordSys, cs]; displacements _ SVVector3d.Scale[displacements, scalar]; AbsTranslateOnly[a.coordSys, cs, displacements]; }; ENDCASE; -- IF a.shape = NIL or something else, do nothing. }; AssemblyHasNoChildren: PUBLIC ERROR = CODE; ScaleEvenChildren: PUBLIC PROC [a: Assembly, cs: CoordSystem, scalar: REAL] ~ { WITH a.shape SELECT FROM shape: Shape => ERROR AssemblyHasNoChildren; alist: AssemblyList => { FOR list: LIST OF Assembly _ alist.list, list.rest UNTIL list = NIL DO ScaleEven[list.first, list.first.coordSys, scalar]; ENDLOOP; }; ENDCASE => ERROR AssemblyHasNoChildren; -- IF a.shape = NIL or something else, report a problem. }; ScaleDistancesChildren: PUBLIC PROC [a: Assembly, cs: CoordSystem, sx, sy, sz: REAL] = { displacements: Vector; WITH a.shape SELECT FROM shape: Shape => ERROR AssemblyHasNoChildren; alist: AssemblyList => { FOR list: LIST OF Assembly _ alist.list, list.rest UNTIL list = NIL DO displacements _ CoordSys.FindTranslationOfAinTermsOfB[list.first.coordSys, cs]; displacements[1] _ displacements[1]*sx; displacements[2] _ displacements[2]*sy; displacements[3] _ displacements[3]*sz; AbsTranslateOnly[list.first.coordSys, cs, displacements]; ENDLOOP; }; ENDCASE => ERROR AssemblyHasNoChildren; -- IF a.shape = NIL or something else, report a problem. }; ScaleAndShear: PUBLIC PROC [a: Assembly, cs: CoordSystem, sx, sy, sz: REAL] = { }; ScaleNoShear: PUBLIC PROC [a: Assembly, cs: CoordSystem, sx, sy, sz: REAL] = { }; Scale: PUBLIC PROC [a: Assembly, cs: CoordSystem, sx, sy, sz: REAL] = { IF ISTYPE[a.shape, Shape] AND cs = a.coordSys THEN ScalePrimitive[a, sx, sy, sz] ELSE ScaleEven[a, cs, sx]; }; 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]; }; END. ŽFile: SVTransformsImpl.mesa Last edited by Bier on January 4, 1985 6:07:07 pm PST Copyright c 1984 by Xerox Corporation. All rights reserved. Contents: Procedures for Scaling, Translating, and Rotating assemblies with respect to an arbitrary coordinate system Incrementally transform C with respect to D by M. If D is a descendent of C, this could result in D moving as well. If this is not desired, set DFixed to TRUE and IncTransf makes sure that D doesn't move. Make sure that D hasn't moved. Rotates C about an axis parallel to the plane axis of D, passing thru the origin of C. Absolutely transform C with respect to D by M. If D is a descendent of C, this could result in D moving as well. If this is not desired, set DFixed to TRUE and AbsTransf makes sure that D doesn't move. Now make sure that D hasn't moved. Like TugTransf, but returns the Tugboat to its original position. A set of routines which call IncTransf Simple rotate C's coordsys wrt D by degrees about the x axis Simple rotate C's coordsys wrt D by degrees about the y axis Simple rotate C's coordsys wrt D by degrees about the z axis Here is an example of the way these operations used to be performed. This is fairly fast because it uses Matrix3d.RotateAboutXAxis instead of Matrix3d.MatMult, but the IncTransf, AbsTransf, TugTransf pathway is much cleaner. XRotateAwrtB: PUBLIC PROC [a: CoordSystem, b: CoordSystem, degrees: REAL] = { aWorld, bWorld, aInTermsOfb, newAWorld, withRespectToWorld, aInTermsOfWRT: Matrix4by4; parent: CoordSystem; IF b = NIL THEN ERROR ELSE bWorld _ CoordSys.FindInTermsOfWorld[b]; aWorld _ CoordSys.FindInTermsOfWorld[a]; aInTermsOfb _ IF a = b THEN Matrix3d.Identity[] ELSE Matrix3d.WorldToLocal[bWorld,aWorld]; aInTermsOfb _ Matrix3d.RotateAboutXAxis[aInTermsOfb, degrees]; -- must be a global translate. newAWorld _ Matrix3d.MatMult[bWorld, aInTermsOfb]; IF a.parent = NIL THEN ERROR; -- cannot translate WORLD for now parent _ a.parent; withRespectToWorld _ CoordSys.FindInTermsOfWorld[parent]; aInTermsOfWRT _ Matrix3d.WorldToLocal[withRespectToWorld, newAWorld]; a.mat _ aInTermsOfWRT; }; ScaleAwrtB: PRIVATE PROC [a: CoordSystem, b: CoordSystem, sx, sy, sz: REAL] = { Because scaling is only allowed at primitive assemblies, we define the arbitrary scaling of an assembly with respect to a coordinate system as follows: If the assembly is a primitive, change its scalar vector aWorld, bWorld, aInTermsOfb, newAWorld, withRespectToWorld, aInTermsOfWRT: Matrix4by4; parent: CoordSystem; IF b = NIL THEN ERROR ELSE bWorld _ CoordSys.FindInTermsOfWorld[b]; aWorld _ CoordSys.FindInTermsOfWorld[a]; aInTermsOfb _ IF a = b THEN Matrix3d.Identity[] ELSE Matrix3d.WorldToLocal[bWorld,aWorld]; aInTermsOfb _ Matrix3d.Scale[aInTermsOfb, sx, sy, sz]; -- must be a global translate. newAWorld _ Matrix3d.MatMult[bWorld, aInTermsOfb]; IF a.parent = NIL THEN ERROR; -- cannot translate WORLD for now parent _ a.parent; withRespectToWorld _ CoordSys.FindInTermsOfWorld[parent]; aInTermsOfWRT _ Matrix3d.WorldToLocal[withRespectToWorld, newAWorld]; a.mat _ aInTermsOfWRT; }; A set of routines which call AbsTransf Places C so that the rotation from C to D remains as it is, but the translation becomes vD. Find CD. Compute the magnitude of its axes. Make CD have axes of the same magnitude, aligned with respect to the nearest axes of D. This direction is now taken. z axis must find another. zAxis gets second choice if xAxis has its first choice Bubble sort Leaving the rotation of C as it is, put C's origin coincident with the origin of D. Leave the rotation of C as it is. Put C's origin in the x = 0 plane of D. Leave the rotation of C as it is. Put C's origin in the y = 0 plane of D. Leave the rotation of C as it is. Put C's origin in the z = 0 plane of D. Leave translation between C and D as is. The axes of C become parallel to the axes of D. C becomes identical to D. A set of routines which specialize TugTransf Routines for updating cached matrices: TellAboutCameraAndWorld1: PUBLIC PROC [a: Assembly, camera: Camera, scene: Scene] = { Flatten the tree to get the leaf assemblies then update their cached values. 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 TellAboutCameraAndWorld1 This assembly has moved. Mark its coordinate system and those of its children as dirty. If a component is almost a multiple of .5, make it exactly so. Tree walk through the tree and concatenate all matrices (will later concatenate matrices as it goes). This computes values for intermediate matrices as well as primitive matrices. Can be started using any assembly as root. Our matrices result from scaling our parent's matrices. Updates the wrtWorld, and wrtCamera fields of cs by premultiplying cs.mat by cs.parent.wrtWorld and cs.parent.wrtCamera respectively Scaling operations (IncTransf derivatives but more complicated). There are five 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) (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). 4) (ScaleEvenChildren) Perform a ScaleEven on each of the children of the cluster assembly but leave their relative translations fixed. This is equivalent to performing a ScaleEven (child, child's cs, scalar) on each child individually. 5) (ScaleDistancesChildren) Doesn't change the size or shape of any of the children of assembly. Simply translates all of the children as they would be translated by a Scale even of assembly. Just a bit tricky. If a is a Primitive and cs is any coordinate frame, just scale and translate it from the center of cs by scalar times its current translation. If a is a cluster, and cs is any coordinate frame, evenly scale each component of a about a's center, then translate a as a unit, the appropriate distance from the center of cs. now translate a's coordSys so that its displacement from the origin of cs is scaled by scalar Recursively scale subassemblies with respect to their own coordinate systems Now translate a's coordSys so that its displacement from the origin of cs is scaled by scalar For each child of a, find its current displacement from the center of cs. Scale this displacement by [sx, sy, sz]. not yet implemented. not yet implemented. สื˜Iheadšœ™Jšœ5™5Jšœ ฯmœ1™L˜—šžœžœ ˜!Lšžœžœžœ˜#L˜—šžœžœ $˜/Lšžœžœžœ˜#L˜—šžœ ˜&Lšžขœžขœžกขžกขžขœ ˜/Lšžขœžœ˜(Lšžกœžœ %œ  ˜XLšžขœžœ˜(Lšฃกœžขœ˜"Lšžขœ"˜$Lš žœ:ฃกœžขœžœžกœ˜Tšžœžœ˜L™Lšžกœžกœ ˜Lšžกœžœ ˜0Lš žกœžกœžกœ˜-Lšžœžกœ˜ L˜—L˜—Lšœ˜L˜—š Ÿœžœžœžœžกœžœ˜TLšžœ˜Lšžขœžกœขžกœขžขœ ˜'L˜Lš žœžœ žœžœžœ !˜?Lšžœžœ˜ šžœžœžœ˜JšœL˜LJšœ˜Jšžœ˜—L˜Lšžขœžœ˜(Lšžขœžœ˜(Lšฃกœžขœ˜"Lš žขœžขœžขœ˜+Lš žœ:ฃกœžขœžœžกœ˜TLšœ˜L˜J˜—šŸœžœžœžœžœžœ žœ˜^J™VJš žœขžกขžกœ ˜*Jšœ˜Jšœ˜J˜Jšžกœžœ˜(Jšžกœžœ˜(Jšœ!žกœ˜)Jšœžกœ˜'Jšœžกœ˜'Jšœžกœ˜'Jšœขœ9˜CJ˜Jšžœž˜Jšœžœ$˜*Jšœžœ$˜*Jšœžœ$˜*Jšžœžœ˜Lšœžœขœžœ˜"Jšœ˜J˜—šŸ œžœžœžœžœžœžœžœ˜`Jšœžœžœžœžœžœžœ8žœžœ™หLšžœ˜L˜Lšžœ žœžœžœžœžœžœ˜?Lš žœžœ žœžœžœ ˜8Lš žœžœžœžœžœ˜Lšžœžœ˜ šžœžœžœ˜JšœF˜FJšœ˜Jšžœ˜—L˜Lšžœžœž˜šžœ žœ  ˜ Lšžกขžกœ ˜Lšžกœžœ˜(Lšฃกœžกœ˜"Lšžœžกœžœ˜$L˜—šžœžœ ˜!Lšžœžœžœ˜#L˜—šžœžœ $˜/Lšžœžœ˜ L˜—šžœ ˜&Lš žกขžกขžกœ ˜#Lšžกœžœ˜(Lšžกœžœ˜(Lšฃกœžกœ˜"Lš žœ)ฃกœžกœžœ˜>šžœžœ˜L™"Lšžกœžกœ ˜Lšžกœžœ ˜0Lš žกœžกœžกœ˜-Lšžœžกœ˜ L˜—L˜—Lšœ˜L˜—š Ÿ œžœžœžœ%žœžœ˜`Jšžœ(žœ ˜5Jšœžœžœ˜Jšœ žœ žœ˜J˜J˜—š ะbnœž œžœ%žœžœ˜hJ™AJšžœ ˜Jšœ%˜%J˜Jšžœžœ ˜)Jšœžœžœ˜Jšœ žœ žœ˜Jšœ˜J˜J˜J˜—JšœŸ ™&J™šŸ œžœžœžœžœžœ žœžœ˜cLšžœ ˜Lšžœ)˜*Lšœ žœžœžœ˜Lšœ˜L˜—šŸœžœžœžœžœžœ žœžœ˜^Jšœ<™L™YJšœ˜Jšœ.˜.Jšœ.˜.Jšœ˜J˜L˜—šŸ œž œžœžœ˜;L™Lšœ%˜%L˜—J™Jšœ#Ÿ ™,J™š Ÿœžœžœžœ%žœ˜WJšžœ(žœ ˜5Jšฯb œ žœ˜Jšœ žœ žœ˜Jšœ˜—š Ÿ œžœžœžœ%žœ˜TJšžœ(žœ ˜5Jšฅ œ žœ˜Jšœ žœ žœ˜Jšœ˜—šŸœžœžœ;˜PJšœ5˜5Jšฅœ ˜Jšœžœ˜Jšœ˜—šŸœžœžœ;˜OJšœ5˜5Jšฅœ ˜Jšœžœ˜Jšœ˜—š Ÿœžœžœžœ%žœ˜PJšžœ(žœ ˜5Jšฅœ žœ˜Jšœ žœ žœ˜Jšœ˜—š Ÿœžœžœžœ%žœ˜PJšžœ(žœ ˜5Jšฅœ žœ˜Jšœ žœ žœ˜Jšœ˜—š Ÿœžœžœžœ%žœ˜PJšžœ(žœ ˜5Jšฅœ žœ˜Jšœ žœ žœ˜Jšœ˜J˜—Jšœฅœ™&J™šŸœžœžœ0™UJ™MJšœH™HJšžœžœžœC™Tšžœžœž™Jšœฟ™ฟJšœซ™ซJšœU™UJšœS™S—Jšžœ™Jšœ "™%J™—šŸ œžœžœ˜,J™Xšžœ žœž˜šœ˜Jšœžœ˜Jšœ˜—šœ˜Jšœžœ˜Jšœ˜Jšœ˜—Jšžœžœ˜—Jšœ ˜J˜—šœŸœžœžœ˜:š žœžœžœ"žœžœž˜FJšœ˜—Jšžœ˜Jšœ˜—J˜šŸœžœžœ˜7J™>Jšœ"˜"šžœžœ˜Jš žœžœžœžœ 2˜UJšœ3˜3J˜—šžœ˜Jšœ+˜+šžœžœžœ ˜=šžœ/žœžœž˜EJšฅœ ˜—Jšžœ˜Jšœ˜—Jšœ˜—Jšœ ˜J˜—šŸœžœžœ6˜ZJšœเ™เJšœH˜HJšœ0˜0J˜J˜—šŸœžœžœ6˜^Jšœ"˜"šžœžœ˜š žœžœžœžœ 2˜UJ™7—Jšœ˜Jšœ|˜|Jšœ7˜7Jšœ5˜5J˜—šžœ˜JšœE˜EJšœ2˜2Jšœ7˜7Jšœ5˜5šžœžœžœ ˜=šžœ/žœžœž˜EJšฅœ˜6—Jšžœ˜Jšœ˜—Jšœ˜—Jšœ $˜'J˜—šœŸœžœžœ8˜dšžœ'žœžœž˜=Jšœ3˜3—Jšžœ˜Jšœ˜J˜—šŸœžœžœ˜2Lšœ„™„Lšœ;˜;Lšœ=˜=Lšœ1˜1Lšœ3˜3Lšœ˜—J˜Jšฅœ9™@˜Jšœ/™/JšœN™NJšœš™šJšœœ™œJšœํ™ํJ™ภ—J˜šŸœžœžœžœ˜?Jšœ ˜ J˜Jš žœžœžœžœžœ˜)Jšœ˜Jšœ˜Jšœ-˜-Jšœ-˜-Jšœ-˜-Jšœ˜J˜—šŸœžœžœžœ˜@šžœ žœž˜Jšœ.˜.šœ˜š žœžœžœ"žœžœž˜FJšœ(˜(—Jšžœ˜Jšœ˜—Jšžœ 3˜;—Jšœ˜J˜—šŸ œžœžœ(žœ˜GJ™J™ŽJ™ฑJšœ˜šžœ žœž˜šœ˜Jšœ*˜*Jšœ]™]JšœF˜FJšœ8˜8Jšœ0˜0Jšœ˜—šœ˜š žœžœžœ"žœžœž˜Fšœ*˜*JšœL™L——Jšžœ˜Jšœ]™]JšœF˜FJšœ8˜8Jšœ0˜0Jšœ˜—Jšžœ 2˜;—Jšœ˜J˜—Jšœžœžœžœ˜+šŸœž œ(žœ˜Ošžœ žœž˜Jšœ,˜,šœ˜š žœžœžœ"žœžœž˜FJšœ3˜3—Jšžœ˜Jšœ˜—Jšž œ 9˜`—Jšœ˜—šŸœž œ,žœ˜XJšœs™sJšœ˜šžœ žœž˜Jšœžœ˜,šœ˜š žœžœžœ"žœžœž˜FJšœO˜OJšœ'˜'Jšœ'˜'Jšœ'˜'Jšœ9˜9—Jšžœ˜Jšœ˜—Jšžœžœ 9˜`—Jšœ˜—šŸ œž œ,žœ˜OJšœ˜Jšœ™—šŸ œž œ,žœ˜NJšœ˜Jšœ™—šŸœžœžœ,žœ˜GJšžœžœžœžœ˜PJšžœ˜Jšœ˜—J˜š Ÿœžœžœžœžœ˜CJšœ žœ˜Jšœ žœ ˜Jšœ-˜-Jš žœžœžœžœžœžœ˜WJšžœžœžœ˜Jšžœžœžœ˜Jšœ˜—J˜Jšžœ˜—…—Aยz'