<> <> <> <> DIRECTORY SVCoordSys, Feedback, SVMatrix3d, Rope, SV3d, SVAssembly, SVCoordSysType, SVMatrixOps, SVModelTypes, SVSceneTypes, SVTransforms, SVVector3d; SVTransformsImpl: CEDAR PROGRAM IMPORTS SVCoordSys, Feedback, SVMatrix3d, Rope, SVAssembly, SVMatrixOps, SVVector3d EXPORTS SVTransforms, SVModelTypes = BEGIN Slice: TYPE = SVSceneTypes.Slice; SliceList: TYPE = SVSceneTypes.SliceList; Camera: TYPE = SVModelTypes.Camera; CoordSystem: TYPE = REF CoordSysObj; CoordSysObj: PUBLIC TYPE = SVCoordSysType.CoordSysObj; CoordSysList: TYPE = SVModelTypes.CoordSysList; Matrix4by4: TYPE = SV3d.Matrix4by4; Point3d: TYPE = SV3d.Point3d; Scene: TYPE = SVSceneTypes.Scene; Shape: TYPE = SVSceneTypes.Shape; Vector3d: TYPE = SV3d.Vector3d; IncTransfMatrix: PUBLIC PROC [c: CoordSystem, dWorld: Matrix4by4, m: Matrix4by4] = { p: CoordSystem; cWorld, pWorld: Matrix4by4; IF MatrixHasScaling[m] THEN { SIGNAL Feedback.Problem[msg: "SVTransform.IncTransfMatrix got illegal matrix. Ignored."]; RETURN}; p _ SVCoordSys.Parent[c]; IF p = NIL THEN ERROR; -- cannot translate WORLD for now cWorld _ SVCoordSys.WRTWorld[c]; pWorld _ SVCoordSys.WRTWorld[p]; SVCoordSys.SetMat[c, SVMatrixOps.IncTransf[cWorld, pWorld, dWorld, m]]; }; PlaneOriginRotate: PUBLIC PROC [c: CoordSystem, d: CoordSystem, degrees: REAL, plane: NAT] = { <> m, PivotWORLD, CWORLD, DWORLD: Matrix4by4; origin: Point3d; xAxis, yAxis, zAxis: Vector3d; CWORLD _ SVCoordSys.WRTWorld[c]; DWORLD _ SVCoordSys.WRTWorld[d]; origin _ SVMatrix3d.OriginOfMatrix[CWORLD]; xAxis _ SVMatrix3d.XAxisOfMatrix[DWORLD]; yAxis _ SVMatrix3d.YAxisOfMatrix[DWORLD]; zAxis _ SVMatrix3d.ZAxisOfMatrix[DWORLD]; PivotWORLD _ SVMatrix3d.MakeMatFromAxes[xAxis, yAxis, zAxis, origin]; SELECT plane FROM 1 => m _ SVMatrix3d.MakeRotateXMat[degrees]; 2 => m _ SVMatrix3d.MakeRotateYMat[degrees]; 3 => m _ SVMatrix3d.MakeRotateZMat[degrees]; ENDCASE => ERROR; IncTransfMatrix[c, PivotWORLD, m]; }; AbsTransfScreen: PUBLIC PROC [c: CoordSystem, n: Matrix4by4] = { SVCoordSys.SetMat[c, n]; }; AbsTransfMatrix: PUBLIC PROC [c: CoordSystem, dWorld: Matrix4by4, n: Matrix4by4] = { p: CoordSystem; pWORLD: Matrix4by4; IF Rope.Equal[c.name, "SCREEN", TRUE] THEN {SVCoordSys.SetMat[c, n]; RETURN}; p _ SVCoordSys.Parent[c]; IF p = NIL THEN ERROR; -- cannot translate WORLD for now IF MatrixHasScaling[n] THEN { SIGNAL Feedback.Problem[msg: "SVTransform.AbsTransf got illegal matrix. Ignored."]; RETURN}; pWORLD _ SVCoordSys.WRTWorld[p]; SVCoordSys.SetMat[c, SVMatrixOps.AbsTransf[pWORLD, dWorld, n]]; }; <> <<>> Translate: PUBLIC PROC [c: Slice, scene: Scene, vec: Point3d, d: CoordSystem _ NIL, dFixed: BOOL _ FALSE] = { m: Matrix4by4; m _ SVMatrix3d.MakeTranslateMat[vec[1], vec[2], vec[3]]; SVAssembly.IncTransf[c, scene, m, d, dFixed]; DirtyAssembly[c]; }; Rotate: PUBLIC PROC [c: Slice, scene: Scene, axis: [1..3], degrees: REAL, d: CoordSystem _ NIL, dFixed: BOOL _ FALSE] = { <> m: Matrix4by4; SELECT axis FROM 1 => m _ SVMatrix3d.MakeRotateXMat[degrees]; 2 => m _ SVMatrix3d.MakeRotateYMat[degrees]; 3 => m _ SVMatrix3d.MakeRotateZMat[degrees]; ENDCASE => ERROR; SVAssembly.IncTransf[c, scene, m, d, dFixed]; DirtyAssembly[c]; }; <> <<>> AbsTranslateOnly: PUBLIC PROC [c: Slice, scene: Scene, d: CoordSystem, vD: Point3d] = { <> CD: Matrix4by4; CD _ SVCoordSys.FindAInTermsOfB[c.coordSys, d]; CD[1][4] _ vD[1]; CD[2][4] _ vD[2]; CD[3][4] _ vD[3]; SVAssembly.AbsTransf[c, scene, CD, d]; DirtyAssembly[c]; }; Align: PUBLIC PROC [c: Slice, scene: Scene, d: CoordSystem] = { <> CD: Matrix4by4; xAxisChoices, zAxisChoices: ARRAY[1..3] OF NAT; xAxis, zAxis, newXAxis, newYAxis, newZAxis: Vector3d; xNegArray, zNegArray: ARRAY[1..3] OF BOOL; origin: Point3d; CD _ SVCoordSys.FindAInTermsOfB[c.coordSys, d]; xAxis _ SVMatrix3d.XAxisOfMatrix[CD]; zAxis _ SVMatrix3d.ZAxisOfMatrix[CD]; origin _ SVMatrix3d.OriginOfMatrix[CD]; [xAxisChoices, xNegArray] _ IndicesOfMax[xAxis]; -- Find largest component << This direction is now taken. z axis must find another.>> [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 _ SVMatrix3d.MakeMatFromAxes[newXAxis, newYAxis, newZAxis, origin]; SVAssembly.AbsTransf[c, scene, CD, d]; DirtyAssembly[c]; }; -- end of Align IndicesOfMax: PRIVATE PROC [v: Vector3d] 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: Slice, scene: Scene, d: CoordSystem] = { <> AbsTranslateOnly[c, scene, d, [0,0,0]]; }; AbutAxis: PUBLIC PROC [c: Slice, scene: Scene, axis: [1..3], d: CoordSystem] = { <> vD: Vector3d; vD _ SVCoordSys.FindTranslationOfAinTermsOfB[c.coordSys, d]; SELECT axis FROM 1 => AbsTranslateOnly[c, scene, d, [0, vD[2], vD[3]]]; 2 => AbsTranslateOnly[c, scene, d, [vD[1], 0, vD[3]]]; 3 => AbsTranslateOnly[c, scene, d, [vD[1], vD[2], 0]]; ENDCASE; }; NormalizeRot: PUBLIC PROC [c: Slice, scene: Scene, d: CoordSystem] = { <> oldMat, newMat: Matrix4by4; oldMat _ SVCoordSys.FindAInTermsOfB[a: c.coordSys, b: d]; newMat _ SVMatrix3d.NormalizeNoRotation[oldMat]; SVAssembly.AbsTransf[c, scene, newMat, d]; DirtyAssembly[c]; }; Normalize: PUBLIC PROC [c: Slice, scene: Scene, d: CoordSystem] = { <> SVAssembly.AbsTransf[c, scene, SVMatrix3d.Identity[], d]; DirtyAssembly[c]; }; <<>> <> <<>> NormalizeRotTug: PUBLIC PROC [c: Slice, scene: Scene, tugBoat: Slice, d: CoordSystem] = { f: Matrix4by4 _ SVCoordSys.FindAInTermsOfB[c.coordSys, tugBoat.coordSys]; NormalizeRot[tugBoat, scene, d]; SVAssembly.AbsTransf[c, scene, f, tugBoat.coordSys, TRUE]; DirtyAssembly[c]; }; NormalizeTug: PUBLIC PROC [c: Slice, scene: Scene, tugBoat: Slice, d: CoordSystem] = { f: Matrix4by4 _ SVCoordSys.FindAInTermsOfB[c.coordSys, tugBoat.coordSys]; Normalize[tugBoat, scene, d]; SVAssembly.AbsTransf[c, scene, f, tugBoat.coordSys, TRUE]; DirtyAssembly[c]; }; AlignTug: PUBLIC PROC [c: Slice, scene: Scene, tugBoat: Slice, d: CoordSystem] = { f: Matrix4by4 _ SVCoordSys.FindAInTermsOfB[c.coordSys, tugBoat.coordSys]; Align[tugBoat, scene, d]; SVAssembly.AbsTransf[c, scene, f, tugBoat.coordSys, TRUE]; DirtyAssembly[c]; }; AbutTug: PUBLIC PROC [c: Slice, scene: Scene, tugBoat: Slice, d: CoordSystem] = { f: Matrix4by4 _ SVCoordSys.FindAInTermsOfB[c.coordSys, tugBoat.coordSys]; Abut[tugBoat, scene, d]; SVAssembly.AbsTransf[c, scene, f, tugBoat.coordSys, TRUE]; DirtyAssembly[c]; }; AbutTugAxis: PUBLIC PROC [c: Slice, scene: Scene, axis: [1..3], tugBoat: Slice, d: CoordSystem] = { f: Matrix4by4 _ SVCoordSys.FindAInTermsOfB[c.coordSys, tugBoat.coordSys]; AbutAxis[tugBoat, scene, axis, d]; SVAssembly.AbsTransf[c, scene, f, tugBoat.coordSys, TRUE]; DirtyAssembly[c]; }; <<>> <> <<>> DirtyAssembly: PUBLIC PROC [a: Slice] = { <> <> < {>> <> <> <<};>> < {>> <> <> <> <<};>> < ERROR;>> }; -- end of DirtyAssembly <> <> <> <> <<};>> 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 _ SVMatrix3d.TidyUpVector[root.scalars]; } ELSE { root.mat _ SVMatrix3d.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 <> <> <> <> <<};>> <<>> <> <> <> <> <> <> <> <> <> <<}>> <> <> <> <> <> <> <> <> <> <<};>> <<};>> <<}; -- end of TellAboutCameraAndWorldAux>> <<>> <> <> <> <> <> <> <<};>> <> <> <<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.>> ScalePrimitives: PUBLIC PROC [a: Slice, sx, sy, sz: REAL] = { WITH a.shape SELECT FROM shape: Shape => SVAssembly.ScalePrimitive[a, sx, sy, sz]; alist: SliceList => { FOR list: LIST OF Slice _ 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: Slice, scene: Scene, scalar: REAL, d: CoordSystem _ NIL] = { <> <> <> displacements: Vector3d; WITH a.shape SELECT FROM shape: Shape => { SVAssembly.ScalePrimitive[a, scalar, scalar, scalar]; <> displacements _ SVCoordSys.FindTranslationOfAinTermsOfB[a.coordSys, d]; displacements _ SVVector3d.Scale[displacements, scalar]; AbsTranslateOnly[a, scene, d, displacements]; }; alist: SliceList => { FOR list: LIST OF Slice _ alist.list, list.rest UNTIL list = NIL DO ScaleEven[list.first, scene, scalar, a.coordSys]; <> ENDLOOP; <> displacements _ SVCoordSys.FindTranslationOfAinTermsOfB[a.coordSys, d]; displacements _ SVVector3d.Scale[displacements, scalar]; AbsTranslateOnly[a, scene, d, displacements]; }; ENDCASE; -- IF a.shape = NIL or something else, do nothing. }; AssemblyHasNoChildren: PUBLIC ERROR = CODE; ScaleEvenChildren: PUBLIC PROC [a: Slice, scene: Scene, scalar: REAL, d: CoordSystem _ NIL] ~ { WITH a.shape SELECT FROM shape: Shape => ERROR AssemblyHasNoChildren; alist: SliceList => { FOR list: LIST OF Slice _ alist.list, list.rest UNTIL list = NIL DO ScaleEven[list.first, scene, scalar, list.first.coordSys]; ENDLOOP; }; ENDCASE => ERROR AssemblyHasNoChildren; -- IF a.shape = NIL or something else, report a problem. }; ScaleDistancesChildren: PUBLIC PROC [c: Slice, scene: Scene, sx, sy, sz: REAL, d: CoordSystem _ NIL] = { <> displacements: Vector3d; WITH c.shape SELECT FROM shape: Shape => ERROR AssemblyHasNoChildren; alist: SliceList => { FOR list: LIST OF Slice _ alist.list, list.rest UNTIL list = NIL DO displacements _ SVCoordSys.FindTranslationOfAinTermsOfB[list.first.coordSys, d]; displacements[1] _ displacements[1]*sx; displacements[2] _ displacements[2]*sy; displacements[3] _ displacements[3]*sz; AbsTranslateOnly[list.first, scene, d, displacements]; ENDLOOP; }; ENDCASE => ERROR AssemblyHasNoChildren; -- Problem IF a.shape = NIL or something else. }; Scale: PUBLIC PROC [c: Slice, scene: Scene, sx, sy, sz: REAL, d: CoordSystem _ NIL] = { IF ISTYPE[c.shape, Shape] AND d = c.coordSys THEN SVAssembly.ScalePrimitive[c, sx, sy, sz] ELSE ScaleEven[c, scene, sx, d]; }; MatrixHasScaling: PRIVATE PROC [mat: Matrix4by4] RETURNS [BOOL] = { sx, sy, sz: REAL; almostZero: REAL _ 1.0e-4; [sx, sy, sz] _ SVMatrix3d.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.