SVGravityImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last edited by Bier on February 17, 1987 11:19:15 pm PST
Contents: Routines to snap the skitter to faces, segments, and points in the scene.
DIRECTORY
AtomButtonsTypes, CastRays, CoordSys, CSG, DisplayListToTree, IO, Matrix3d, Preprocess3d, Real, SV2d, SV3d, SVGravity, SVLines3d, SVModelTypes, SVRayTypes, SVScene, SVSceneTypes;
SVGravityImpl: CEDAR PROGRAM
IMPORTS CastRays, CoordSys, CSG, DisplayListToTree, Matrix3d, Preprocess3d, SVLines3d, SVScene
EXPORTS SVGravity =
BEGIN
Assembly: TYPE = SVSceneTypes.Assembly;
Camera: TYPE = SVSceneTypes.Camera;
Classification: TYPE = SVRayTypes.Classification;
CSGTree: TYPE = SVRayTypes.CSGTree;
FeedbackData: TYPE = AtomButtonsTypes.FeedbackData;
Matrix4by4: TYPE = SV3d.Matrix4by4;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
PointAndDone: TYPE = SVSceneTypes.PointAndDone;
PointGenerator: TYPE = SVSceneTypes.PointGenerator;
Primitive: TYPE = SVRayTypes.Primitive;
Ray: TYPE = SVRayTypes.Ray;
Scene: TYPE = SVSceneTypes.Scene;
SearchDepth: TYPE = SVRayTypes.SearchDepth;
Shape: TYPE = SVSceneTypes.Shape;
Vector3d: TYPE = SV3d.Vector3d;
Line3d: TYPE = SV3d.Line3d;
MasterObject: TYPE = SVSceneTypes.MasterObject;
MasterObjectDescriptor: TYPE = SVSceneTypes.MasterObjectDescriptor;
MasterObjectDescriptorObj: TYPE = SVSceneTypes.MasterObjectDescriptorObj;
PointsOrSurfaces: PUBLIC PROC [cameraPoint: Point2d, camera: Camera, scene: Scene, tree: CSGTree, criticalR: REAL, searchDepth: SearchDepth] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, assembly: Assembly] = {
pointsPtWORLD: Point3d;
pointsNormalWORLD: Vector3d;
pointsAssembly: Assembly;
parallel: BOOL;
rayWORLD: Ray ← GetWorldRayFromCameraPoint[cameraPoint, camera]; -- from pool
[surfacePtWORLD, normalWORLD, assembly] ← RayAtSurfaces[rayWORLD, cameraPoint, camera, scene, tree, criticalR, searchDepth];
[pointsPtWORLD, pointsNormalWORLD, pointsAssembly] ← RayAtPoints[rayWORLD, scene, camera, criticalR];
IF WithinTolerance[pointsPtWORLD, rayWORLD, criticalR] THEN {
surfacePtWORLD ← pointsPtWORLD;
IF pointsAssembly # assembly THEN {
normalWORLD ← pointsNormalWORLD;
assembly ← pointsAssembly;
};
};
IF assembly = NIL THEN {
[surfacePtWORLD, normalWORLD, parallel] ← RayMeetsCentralCameraPlane[cameraPoint, camera];
};
CSG.ReturnRayToPool[rayWORLD];
};
LineFromRay: PROC [ray: Ray] RETURNS [line: Line3d] = {
basePt: Point3d;
direction: Vector3d;
[basePt, direction] ← CSG.GetWorldRay[ray];
line ← SVLines3d.LineFromPointAndVector[basePt, direction];
};
WithinTolerance: PROC [point: Point3d, rayWORLD: Ray, criticalR: REAL] RETURNS [BOOL] = {
line: Line3d;
dist: REAL;
line ← LineFromRay[rayWORLD];
dist ← SVLines3d.DistancePointToLine[point, line];
RETURN[dist <= criticalR];
};
GetWorldRayFromCameraPoint: PROC [cameraPoint: Point2d, camera: Camera] RETURNS [rayWORLD: Ray] = {
rayCamera: Ray;
cameraWORLD: Matrix4by4 ← CoordSys.FindInTermsOfWorld[camera.coordSys];
rayCameraCSG.GetRayFromPool[];
CSG.StuffCameraRay[rayCamera, cameraPoint, camera];
rayWORLDCSG.TransformRayToWorld[rayCamera, cameraWORLD]; -- allocates ray from pool
CSG.ReturnRayToPool[rayCamera];
};
RayAtSurfaces: PROC [rayWorld: Ray, cameraPoint: Point2d, camera: Camera, scene: Scene, tree: CSGTree, criticalR: REAL, searchDepth: SearchDepth] RETURNS [surfacePtWorld: Point3d, normalWorld: Vector3d, assembly: Assembly] = {
class: Classification;
primitive: Primitive;
IF tree.outOfDate THEN {
tree ← DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera, tree];
[] ← Preprocess3d.PreprocessForInteraction[tree, camera];
tree.outOfDate ← FALSE;
};
class ← SingleRay[rayWorld, cameraPoint, tree, TRUE, NIL]; -- from pool
[assembly, primitive] ← AssemblyAndPrimitiveAtSearchDepth[class, searchDepth, scene.assembly];
IF class.count > 0 THEN
[surfacePtWorld, normalWorld] ← SurfacePointAndNormalAtSearchDepth[class, rayWorld, searchDepth, scene.assembly];
CastRays.ReturnClassToPool[class];
};
AssemblyAndPrimitiveAtSearchDepth: PROC [class: Classification, searchDepth: SearchDepth, root: Assembly] RETURNS [assembly: Assembly, primitive: Primitive] = {
SELECT searchDepth FROM
first => [assembly, primitive] ← CastRays.NthAssemblyAndPrimitive[class, 1];
lastOfFirst => [assembly, primitive] ← CastRays.NthAssemblyAndPrimitive[class, 1];
last => [assembly, primitive] ← CastRays.NthAssemblyAndPrimitive[class, class.count];
lastOfLevel1 => [assembly, primitive] ← CastRays.LastTopLevelAssemAndPrim[class, root];
ENDCASE => ERROR;
};
SurfacePointAndNormalAtSearchDepth: PROC [class: Classification, rayWorld: Ray, searchDepth: SearchDepth, root: Assembly] RETURNS [surfacePtWorld: Point3d, normalWorld: Vector3d] = {
SELECT searchDepth FROM
first =>
[surfacePtWorld, normalWorld] ← CastRays.NthSurfacePointAndNormal[class, rayWorld, 1];
lastOfFirst =>
[surfacePtWorld, normalWorld] ← CastRays.LastOfFirstPointAndNormal[class, rayWorld];
last =>
IF class.count = 0 THEN ERROR
ELSE [surfacePtWorld, normalWorld] ← CastRays.NthSurfacePointAndNormal[class, rayWorld, class.count];
lastOfLevel1 =>
[surfacePtWorld, normalWorld] ← CastRays.LastTopLevelPointAndNormal[class, rayWorld, root];
ENDCASE => ERROR;
};
SingleRay: PUBLIC PROC [rayWorld: Ray, cameraPoint: Point2d, tree: CSGTree, consolidate: BOOLTRUE, feedback: FeedbackData, makeStream: BOOLFALSE] RETURNS [class: Classification] = {
topNode: REF ANY ← tree.son;
class ← CastRays.RayCast[cameraPoint, rayWorld, topNode, consolidate, feedback, makeStream, 0];
}; -- end of SingleRay
RayAtPoints: PROC [ray: Ray, scene: Scene, camera: Camera, criticalR: REAL] RETURNS [bestPoint: Point3d, bestNormal: Vector3d, bestAssembly: Assembly] = {
primList: LIST OF Assembly ← SVScene.ListOfPrimAssemblies[scene.assembly, scene];
line3d: Line3d;
bestDist, thisDist: REAL;
pointWORLD: Point3d;
pointGen: PointGenerator;
shape: Shape;
assembly: Assembly;
mo: MasterObject;
moWORLD: Matrix4by4;
moD: MasterObjectDescriptor;
line3d ← LineFromRay[ray];
bestDist ← Real.LargestNumber;
bestAssembly ← NIL;
FOR list: LIST OF Assembly ← primList, list.rest UNTIL list = NIL DO
assembly ← list.first;
shape ← NARROW[assembly.shape];
mo ← shape.mo;
moWORLD ← CoordSys.FindInTermsOfWorld[shape.coordSys];
moD ← NEW[MasterObjectDescriptorObj ← [mo, NIL]];
pointGen ← mo.class.pointsInDescriptor[moD];
FOR pointAndDone: PointAndDone ← mo.class.nextPoint[pointGen], mo.class.nextPoint[pointGen] UNTIL pointAndDone.done = TRUE DO
pointWORLD ← Matrix3d.Update[pointAndDone.point, moWORLD];
thisDist ← SVLines3d.DistancePointToLine[pointWORLD, line3d];
IF thisDist < bestDist THEN {
bestDist ← thisDist;
bestPoint ← pointWORLD;
bestAssembly ← assembly;
};
ENDLOOP;
ENDLOOP;
bestNormal ← Matrix3d.ZAxisOfMatrix[CoordSys.FindInTermsOfWorld[camera.coordSys]];
};
RayMeetsCameraPlane: PROC [cameraPoint: Point2d, depth: REAL, camera: Camera] RETURNS [planePtCamera: Point3d, parallel: BOOL] = {
rayWorld: Ray;
worldCamera: Matrix4by4;
planePtWorld: Point3d;
rayWorldCSG.GetRayFromPool[];
CSG.StuffWorldRayFromCamera[rayWorld, cameraPoint, camera];
[planePtWorld, parallel] ← CastRays.RayMeetsPlaneOfCoordSystem[camera.coordSys, rayWorld, 3, depth];
worldCamera ← CoordSys.FindAInTermsOfB[camera.coordSys.parent, camera.coordSys];
planePtCamera ← Matrix3d.Update[planePtWorld, worldCamera];
CSG.ReturnRayToPool[rayWorld];
};
RayMeetsCentralCameraPlane: PROC [cameraPoint: Point2d, camera: Camera] RETURNS [pointWORLD: Point3d, normalWORLD: Vector3d, parallel: BOOL] = {
worldCAMERA: Matrix4by4 ← CoordSys.FindWorldInTermsOf[camera.coordSys];
originCAMERA: Point3d ← Matrix3d.OriginOfMatrix[worldCAMERA];
depth: REAL ← originCAMERA[3];
rayWorld: Ray;
rayWorldCSG.GetRayFromPool[];
CSG.StuffWorldRayFromCamera[rayWorld, cameraPoint, camera];
[pointWORLD, parallel] ← CastRays.RayMeetsPlaneOfCoordSystem[camera.coordSys, rayWorld, 3, depth];
normalWORLD ← Matrix3d.ZAxisOfMatrix[CoordSys.FindInTermsOfWorld[camera.coordSys]];
CSG.ReturnRayToPool[rayWorld];
};
END.