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, CodeTimer, CoordSys, SVRay, DisplayListToTree, IO, Matrix3d, Preprocess3d, Real, SV2d, SV3d, SVAssembly, SVCastRays, SVGravity, SVInterfaceTypes, SVLines3d, SVModelTypes, SVRayTypes, SVScene, SVSceneTypes, SVState;
SVGravityImpl: CEDAR PROGRAM
IMPORTS CodeTimer, CoordSys, SVRay, DisplayListToTree, Matrix3d, Preprocess3d, SVAssembly, SVCastRays, SVLines3d, SVState
EXPORTS SVGravity =
BEGIN
Slice: TYPE = SVSceneTypes.Slice;
Camera: TYPE = SVSceneTypes.Camera;
Classification: TYPE = SVRayTypes.Classification;
CSGTree: TYPE = SVRayTypes.CSGTree;
FeatureData: TYPE = SVInterfaceTypes.FeatureData;
FeedbackData: TYPE = AtomButtonsTypes.FeedbackData;
GravityType: TYPE = SVInterfaceTypes.GravityType;
Line3d: TYPE = SV3d.Line3d;
MasterObject: TYPE = SVSceneTypes.MasterObject;
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;
SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor;
TriggerBag: TYPE = SVInterfaceTypes.TriggerBag;
Vector3d: TYPE = SV3d.Vector3d;
SVData: TYPE = SVInterfaceTypes.SVData;
RayMap: PUBLIC PROC [cameraPoint: Point2d, criticalR: REAL, alignBag: REF ANY, sceneBag: TriggerBag, svData: SVData] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, feature: FeatureData, hitData: REF ANY] = {
gravityType: GravityType ← SVState.GetGravityType[svData];
searchDepth: SearchDepth ← SVState.GetSearchDepth[svData];
CodeTimer.StartInt[$RayMap, $Solidviews];
[surfacePtWORLD, normalWORLD, feature, hitData] ← PointsOrSurfaces[cameraPoint, criticalR, sceneBag, svData.camera, searchDepth, gravityType];
CodeTimer.StopInt[$RayMap, $Solidviews];
};
PointsPreferred: PUBLIC PROC [cameraPoint: Point2d, criticalR: REAL, alignBag: REF ANY, sceneBag: TriggerBag, svData: SVData, sceneOnly: BOOL] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, feature: FeatureData, hitData: REF ANY] = {
RETURN RayMap[cameraPoint, criticalR, alignBag, sceneBag, svData];
};
StrictDistance: PUBLIC PROC [cameraPoint: Point2d, criticalR: REAL, alignBag: REF ANY, sceneBag: TriggerBag, svData: SVData, sceneOnly: BOOL] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, feature: FeatureData, hitData: REF ANY] = {
RETURN RayMap[cameraPoint, criticalR, alignBag, sceneBag, svData];
};
PointsOrSurfaces: PUBLIC PROC [cameraPoint: Point2d, criticalR: REAL, sceneBag: TriggerBag, camera: Camera, searchDepth: SearchDepth, gravityType: GravityType] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, feature: FeatureData, hitData: REF ANY] = {
pointsPtWORLD: Point3d;
pointsNormalWORLD: Vector3d;
pointsFeature: FeatureData;
parallel: BOOL;
pointsHitData: REF ANY;
rayWORLD: Ray ← GetWorldRayFromCameraPoint[cameraPoint, camera]; -- from pool
[surfacePtWORLD, normalWORLD, feature, hitData] ← RayAtSurfaces[rayWORLD, cameraPoint, criticalR, sceneBag, camera, searchDepth];
[pointsPtWORLD, pointsNormalWORLD, pointsFeature, pointsHitData] ← RayAtPoints[rayWORLD, cameraPoint, criticalR, sceneBag, camera, gravityType];
IF pointsFeature # NIL AND WithinTolerance[pointsPtWORLD, rayWORLD, criticalR] THEN {
surfacePtWORLD ← pointsPtWORLD;
IF pointsFeature # feature THEN {
normalWORLD ← pointsNormalWORLD;
feature ← pointsFeature;
};
hitData ← pointsHitData;
}
ELSE IF feature # NIL THEN {
}
ELSE {
[surfacePtWORLD, normalWORLD, parallel] ← RayMeetsCentralCameraPlane[cameraPoint, camera];
hitData ← NIL;
};
SVRay.ReturnRayToPool[rayWORLD];
};
LineFromRay: PROC [ray: Ray] RETURNS [line: Line3d] = {
basePt: Point3d;
direction: Vector3d;
[basePt, direction] ← SVRay.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.WRTWorld[camera.coordSys];
rayCameraSVRay.GetRayFromPool[];
SVRay.StuffCameraRay[rayCamera, cameraPoint, camera];
rayWORLDSVRay.TransformRayToWorld[rayCamera, cameraWORLD]; -- allocates ray from pool
SVRay.ReturnRayToPool[rayCamera];
};
RayAtSurfaces: PROC [rayWorld: Ray, cameraPoint: Point2d, criticalR: REAL, sceneBag: TriggerBag, camera: Camera, searchDepth: SearchDepth] RETURNS [surfacePtWorld: Point3d, normalWorld: Vector3d, feature: FeatureData, hitData: REF ANY] = {
class: Classification;
primitive: Primitive;
assembly: Slice;
class ← SingleRay[rayWorld, cameraPoint, sceneBag, camera, TRUE, NIL]; -- class from pool
IF sceneBag.scene # NIL THEN
[assembly, primitive] ← AssemblyAndPrimitiveAtSearchDepth[class, searchDepth, sceneBag.scene.assembly];
IF class.count > 0 THEN
[surfacePtWorld, normalWorld] ← SurfacePointAndNormalAtSearchDepth[class, rayWorld, searchDepth, sceneBag.scene.assembly];
feature ← FindFeature[assembly, sceneBag];
hitData ← HitDataAtSearchDepth[class, searchDepth, sceneBag.scene.assembly];
SVCastRays.ReturnClassToPool[class];
};
FindFeature: PROC [assembly: Slice, sceneBag: TriggerBag] RETURNS [feature: FeatureData] = {
sliceD: SliceDescriptor;
IF assembly = NIL THEN RETURN[NIL];
FOR list: LIST OF FeatureData ← sceneBag.slices, list.rest UNTIL list = NIL DO
sliceD ← NARROW[list.first.shape];
IF sliceD.slice = assembly THEN RETURN[list.first];
ENDLOOP;
RETURN[NIL];
};
AssemblyAndPrimitiveAtSearchDepth: PROC [class: Classification, searchDepth: SearchDepth, root: Slice] RETURNS [assembly: Slice, primitive: Primitive] = {
SELECT searchDepth FROM
first => [assembly, primitive] ← SVCastRays.NthAssemblyAndPrimitive[class, 1];
lastOfFirst => [assembly, primitive] ← SVCastRays.NthAssemblyAndPrimitive[class, 1];
last => [assembly, primitive] ← SVCastRays.NthAssemblyAndPrimitive[class, class.count];
lastOfLevel1 => [assembly, primitive] ← SVCastRays.LastTopLevelAssemAndPrim[class, root];
ENDCASE => ERROR;
};
SurfacePointAndNormalAtSearchDepth: PROC [class: Classification, rayWorld: Ray, searchDepth: SearchDepth, root: Slice] RETURNS [surfacePtWorld: Point3d, normalWorld: Vector3d] = {
SELECT searchDepth FROM
first =>
[surfacePtWorld, normalWorld] ← SVCastRays.NthSurfacePointAndNormal[class, rayWorld, 1];
lastOfFirst =>
[surfacePtWorld, normalWorld] ← SVCastRays.LastOfFirstPointAndNormal[class, rayWorld];
last =>
IF class.count = 0 THEN ERROR
ELSE [surfacePtWorld, normalWorld] ← SVCastRays.NthSurfacePointAndNormal[class, rayWorld, class.count];
lastOfLevel1 =>
[surfacePtWorld, normalWorld] ← SVCastRays.LastTopLevelPointAndNormal[class, rayWorld, root];
ENDCASE => ERROR;
};
HitDataAtSearchDepth: PROC [class: Classification, searchDepth: SearchDepth, root: Slice] RETURNS [hitData: REF ANY] = {
SELECT searchDepth FROM
first =>
hitData ← SVCastRays.NthHitData[class, 1];
lastOfFirst =>
hitData ← SVCastRays.LastOfFirstHitData[class];
last =>
IF class.count = 0 THEN ERROR
ELSE hitData ← SVCastRays.NthHitData[class, class.count];
lastOfLevel1 =>
hitData ← SVCastRays.LastTopLevelHitData[class, root];
ENDCASE => ERROR;
};
SingleRay: PUBLIC PROC [rayWorld: Ray, cameraPoint: Point2d, sceneBag: TriggerBag, camera: Camera, consolidate: BOOLTRUE, feedback: FeedbackData, makeStream: BOOLFALSE] RETURNS [class: Classification] = {
tree: CSGTree ← sceneBag.tree;
topNode: REF ANY;
IF tree = NIL THEN {
class ← SVCastRays.GetClassFromPool[];
SVCastRays.MakeClassAMiss[class];
RETURN;
};
IF tree.outOfDate THEN {
tree ← DisplayListToTree.AssemblyToTree[sceneBag.scene.assembly, sceneBag.scene, camera, tree];
[] ← Preprocess3d.PreprocessForInteraction[tree, camera];
tree.outOfDate ← FALSE;
};
topNode ← tree.son;
class ← SVCastRays.RayCast[cameraPoint, rayWorld, topNode, consolidate, feedback, makeStream, 0];
}; -- end of SingleRay
RayAtPoints: PROC [ray: Ray, cameraPoint: Point2d, criticalR: REAL, sceneBag: TriggerBag, camera: Camera, gravityType: GravityType] RETURNS [bestPoint: Point3d, bestNormal: Vector3d, bestFeature: FeatureData, bestHitData: REF ANY] = {
line3d: Line3d;
bestDist, thisDist: REAL;
pointWORLD: Point3d;
feature: FeatureData;
sliceD: SliceDescriptor;
hitData: REF ANY;
success: BOOL;
scene: Scene ← sceneBag.scene;
line3d ← LineFromRay[ray];
bestDist ← Real.LargestNumber;
bestFeature ← NIL;
IF gravityType = linesPreferred THEN {
FOR list: LIST OF FeatureData ← sceneBag.slices, list.rest UNTIL list = NIL DO
feature ← list.first;
sliceD ← NARROW[feature.shape];
[thisDist, pointWORLD, hitData, success] ← SVAssembly.ClosestSegmentToLine[sliceD, cameraPoint, line3d, criticalR, camera];
IF success AND thisDist < bestDist THEN {
bestDist ← thisDist;
bestPoint ← pointWORLD;
bestHitData ← hitData;
bestFeature ← feature;
};
ENDLOOP;
};
FOR list: LIST OF FeatureData ← sceneBag.slices, list.rest UNTIL list = NIL DO
feature ← list.first;
sliceD ← NARROW[feature.shape];
[thisDist, pointWORLD, hitData, success] ← SVAssembly.ClosestPointToLine[sliceD, cameraPoint, line3d, criticalR, camera];
IF success AND thisDist < bestDist THEN {
bestDist ← thisDist;
bestPoint ← pointWORLD;
bestHitData ← hitData;
bestFeature ← feature;
};
ENDLOOP;
bestNormal ← Matrix3d.ZAxisOfMatrix[CoordSys.WRTWorld[camera.coordSys]];
};
RayMeetsCameraPlane: PROC [cameraPoint: Point2d, depth: REAL, camera: Camera] RETURNS [planePtCamera: Point3d, parallel: BOOL] = {
rayWorld: Ray;
worldCamera: Matrix4by4;
planePtWorld: Point3d;
rayWorldSVRay.GetRayFromPool[];
SVRay.StuffWorldRayFromCamera[rayWorld, cameraPoint, camera];
[planePtWorld, parallel] ← SVCastRays.RayMeetsPlaneOfCoordSystem[camera.coordSys, rayWorld, 3, depth];
worldCamera ← CoordSys.FindAInTermsOfB[CoordSys.Parent[camera.coordSys], camera.coordSys];
planePtCamera ← Matrix3d.Update[planePtWorld, worldCamera];
SVRay.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;
rayWorldSVRay.GetRayFromPool[];
SVRay.StuffWorldRayFromCamera[rayWorld, cameraPoint, camera];
[pointWORLD, parallel] ← SVCastRays.RayMeetsPlaneOfCoordSystem[camera.coordSys, rayWorld, 3, depth];
normalWORLD ← Matrix3d.ZAxisOfMatrix[CoordSys.WRTWorld[camera.coordSys]];
SVRay.ReturnRayToPool[rayWorld];
};
InitStats: PROC = {
interval: CodeTimer.Interval;
interval ← CodeTimer.CreateInterval[$RayMap];
CodeTimer.AddInt[interval, $Solidviews];
};
InitStats[];
END.