SVCaretImpl.mesa
Copyright © 1987 by Xerox Corporation. All rights reserved.
Last edited by Bier on May 22, 1987 3:58:24 pm PDT
Contents: Routines for placing the skitter in a Gargoyle3D scene.
DIRECTORY
SVCoordSys, SVMatrix3d, SV2d, SV3d, SVAssembly, SVCaret, SVInterfaceTypes, SVModelTypes, SVSceneTypes, SVVector3d;
SVCaretImpl: CEDAR PROGRAM
IMPORTS SVCoordSys, SVMatrix3d, SVAssembly, SVVector3d
EXPORTS SVCaret =
BEGIN
AlignmentObject: TYPE = SVSceneTypes.AlignmentObject;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
Matrix4by4: TYPE = SV3d.Matrix4by4;
Primitive: TYPE = SVSceneTypes.Primitive;
Skitter: TYPE = REF SkitterObj;
SkitterObj: TYPE = SVSceneTypes.SkitterObj;
Slice: TYPE = SVSceneTypes.Slice;
SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor;
Vector3d: TYPE = SV3d.Vector3d;
Create: PUBLIC PROC RETURNS [skitter: Skitter] = {
skitter ← NEW[SkitterObj];
};
Copy: PUBLIC PROC [from: Skitter, to: Skitter] = {
to^ ← from^;
};
Kill: PUBLIC PROC [skitter: Skitter] = {
skitter.alive ← FALSE;
skitter.attractor ← NIL;
};
Exists: PUBLIC PROC [skitter: Skitter] RETURNS [BOOL] = {
RETURN[skitter.alive];
};
GetPosition: PUBLIC PROC [skitter: Skitter] RETURNS [skitterWorld: Matrix4by4] = {
skitterWorld ← skitter.skitterWorld;
};
GetPoint: PUBLIC PROC [skitter: Skitter] RETURNS [origin: Point3d] = {
origin ← SVMatrix3d.OriginOfMatrix[skitter.skitterWorld];
};
SetAssemblyAndPrimitive: PUBLIC PROC [skitter: Skitter, assembly: Slice, primitive: Primitive] = {
skitter.attractor ← SVAssembly.NewParts[assembly, NIL, [0,0,0], slice];
skitter.primitive ← primitive;
};
SetAttractor: PUBLIC PROC [skitter: Skitter, cameraPt: Point2d, surfacePtWorld: Point3d, normalWorld: Vector3d, attractor: AlignmentObject] = {
skitterWorld: Matrix4by4;
IF attractor # NIL AND ISTYPE[attractor, SliceDescriptor] THEN {
sliceD: SliceDescriptor ← NARROW[attractor];
skitterWorld ← MakeAlignedMat[normalWorld, surfacePtWorld, sliceD.slice.coordSys];
skitter.attractor ← attractor;
skitter.primitive ← NIL;
}
ELSE {
skitterWorld ← SVMatrix3d.MakeHorizontalMatFromZAxis[normalWorld, surfacePtWorld];
skitter.attractor ← attractor;
skitter.primitive ← NIL;
};
PositionFromMatrix[skitter, cameraPt, skitterWorld];
};
NoAttractor: PUBLIC PROC [skitter: Skitter] = {
skitter.attractor ← NIL;
};
GetAttractor: PUBLIC PROC [skitter: Skitter] RETURNS [attractor: AlignmentObject] = {
attractor ← skitter.attractor;
};
PositionFromMatrix: PUBLIC PROC [skitter: Skitter, cameraPt: Point2d, skitterWorld: Matrix4by4] = {
skitter.alive ← TRUE;
skitter.cameraPt ← cameraPt;
skitter.skitterWorld ← skitterWorld;
};
MakeAlignedMat: PROC [worldNormal: Vector3d, surfacePtInWorld: Point3d, cs: CoordSystem] RETURNS [mat: Matrix4by4] = {
Create a Matrix4by4 with origin at surfacePtInWorld whose z axis is parallel to worldNormal and whose x zxis is orthogonal to both worldNormal and the y axis of cs in WORLD coordinates. Assume that cs.wrtWorld is accurate
yAxisOfCS: Vector3d ← SVMatrix3d.YAxisOfMatrix[SVCoordSys.WRTWorld[cs]];
xAxis: Vector3d;
IF SVVector3d.Parallel[yAxisOfCS, worldNormal] THEN {
xAxis ← SVMatrix3d.XAxisOfMatrix[SVCoordSys.WRTWorld[cs]];
IF AntiParallel[yAxisOfCS, worldNormal] THEN xAxis ← SVVector3d.Negate[xAxis];
Allows positioning code to distinguish between top surfaces and bottom surfaces.
}
ELSE xAxis ← SVVector3d.CrossProduct[yAxisOfCS, worldNormal];
mat ← SVMatrix3d.MakeMatFromZandXAxis[worldNormal, xAxis, surfacePtInWorld];
};
AntiParallel: PROC [v1, v2: Vector3d] RETURNS [BOOL] = {
RETURN[Sign[v1[1]] = -Sign[v2[1]] OR
Sign[v1[2]] = -Sign[v2[2]] OR
Sign[v1[3]] = -Sign[v2[3]] ];
};
Sign: PROC [r: REAL] RETURNS [INT] = {
IF r = 0.0 THEN RETURN[2];
IF r < 0.0 THEN RETURN[-1]
ELSE RETURN[1];
};
END.