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
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 [surfacePt
WORLD: Point3d, normal
WORLD: 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[pointsPt
WORLD, ray
WORLD, 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, 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.FindInTermsOfWorld[camera.coordSys];
rayCamera ← CSG.GetRayFromPool[];
CSG.StuffCameraRay[rayCamera, cameraPoint, camera];
rayWORLD ← CSG.TransformRayToWorld[rayCamera, cameraWORLD]; -- allocates ray from pool
CSG.ReturnRayToPool[rayCamera];
};
RayAtSurfaces:
PROC [ray
World: Ray, cameraPoint: Point2d, camera: Camera, scene: Scene, tree: CSGTree, criticalR:
REAL, searchDepth: SearchDepth]
RETURNS [surfacePt
World: Point3d, normal
World: 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, ray
World: Ray, searchDepth: SearchDepth, root: Assembly]
RETURNS [surfacePt
World: Point3d, normal
World: 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 [ray
World: Ray, cameraPoint: Point2d, tree: CSGTree, consolidate:
BOOL ←
TRUE, feedback: FeedbackData, makeStream:
BOOL ←
FALSE]
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 [planePt
Camera: Point3d, parallel:
BOOL] = {
rayWorld: Ray;
worldCamera: Matrix4by4;
planePtWorld: Point3d;
rayWorld ← CSG.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 [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 ← CSG.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.