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
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 [surfacePt
WORLD: Point3d, normal
WORLD: 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 [surfacePt
WORLD: Point3d, normal
WORLD: 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 [surfacePt
WORLD: Point3d, normal
WORLD: 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 [surfacePt
WORLD: Point3d, normal
WORLD: 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[pointsPt
WORLD, ray
WORLD, 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, ray
WORLD: 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 [ray
WORLD: Ray] = {
rayCamera: Ray;
cameraWORLD: Matrix4by4 ← CoordSys.WRTWorld[camera.coordSys];
rayCamera ← SVRay.GetRayFromPool[];
SVRay.StuffCameraRay[rayCamera, cameraPoint, camera];
rayWORLD ← SVRay.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, ray
World: Ray, searchDepth: SearchDepth, root: Slice]
RETURNS [surfacePt
World: Point3d, normal
World: 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:
BOOL ←
TRUE, feedback: FeedbackData, makeStream:
BOOL ←
FALSE]
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 [planePt
Camera: Point3d, parallel:
BOOL] = {
rayWorld: Ray;
worldCamera: Matrix4by4;
planePtWorld: Point3d;
rayWorld ← SVRay.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 [point
WORLD: Point3d, normal
WORLD: Vector3d, parallel:
BOOL] = {
worldCAMERA: Matrix4by4 ← CoordSys.FindWorldInTermsOf[camera.coordSys];
originCAMERA: Point3d ← Matrix3d.OriginOfMatrix[worldCAMERA];
depth: REAL ← originCAMERA[3];
rayWorld: Ray;
rayWorld ← SVRay.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.