File: SVRay.mesa
Author: Eric Bier in the summer of 1982
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by Bier on June 1, 1987 11:05:21 am PDT
Contents: The SVRay Solids Interface. Essentially maintains a database of csg trees each of which contains one or more combined primitives. Maintaining a tree involves creating primitives and adding them to trees with the SVRay operations, intersection, union, and difference.
DIRECTORY
Imager, Rope, SV2d, SV3d, SVBasicTypes, SVModelTypes, SVSceneTypes;
SVRay: CEDAR DEFINITIONS =
BEGIN
Artwork: TYPE = SVModelTypes.Artwork;
BoundBox: TYPE = SVBasicTypes.BoundBox;
BoundHedron: TYPE = SVBasicTypes.BoundHedron;
BoundSphere: TYPE = SVBasicTypes.BoundSphere;
Camera: TYPE = SVModelTypes.Camera;
Color: TYPE = Imager.Color;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
Matrix4by4: TYPE = SV3d.Matrix4by4;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
Surface: TYPE = SVSceneTypes.Surface;
Vector3d: TYPE = SV3d.Vector3d;
LightSourceList: TYPE = SVModelTypes.LightSourceList;
Ray: TYPE = SVSceneTypes.Ray;
PointSetOp: TYPE = SVSceneTypes.PointSetOp;
Classification: TYPE = SVSceneTypes.Classification;
Composite: TYPE = SVSceneTypes.Composite;
CSGTree: TYPE = SVSceneTypes.CSGTree;
In my current plan, all of the instances of each surface type will refer to the same underlying csg surface expressed in the instance (unit dimensions) coordinate system. Hence, I will build these primitve shapes into the code (this more or less must be done anyway because the formulas - x^2 + y^2 = R^2; z = constant, etc. - are hard to enter symbolically in Mesa).
However, for rapid rendering, I will have a line-drawing approximation to each world surface. These will involve a sweep-based representation with a finite mesh (translational sweep for blocks, rotational for cylinders and spheres). I will create one such representation for each of the primitive solid types in the same instance coordinate system in which the exact csg reps are defined. Rendering line-drawings with the sweep reps will then involve, using the same matrix transforms as are used to place the csg shapes, followed by a perspective transform and a call to 2d graphics routines.
StuffCameraRay: PROC [ray: Ray, screenPoint: Point2d, camera: Camera];
Creates a ray which passes through screenPoint. screenPoint should be in CAMERA coordinates. If camera.projection = orthogonal, the ray is perpendicular to the screen. If camera.projection = perspective, the ray has the same direction [eyepoint, screenPoint]. In any case, the ray originates from screenPoint (not, alas, eyepoint) and has "length" camera.focalLength.
StuffWorldRayFromCamera: PROC [ray: Ray, screenPoint: Point2d, camera: Camera];
The ray is in World coordinates but is the same ray as would be computed by StuffCameraRay.
StuffCameraRayLiterally: PROC [ray: Ray, base: Point3d, direction: Vector3d];
StuffWorldRay: PROC [ray: Ray, basePt: Point3d, direction: Vector3d, camera: Camera];
StuffWorldOnlyRay: PROC [ray: Ray, basePt: Point3d, direction: Vector3d];
StuffWorldRayFromPoints: PROC [ray: Ray, basePt: Point3d, directionPt: Point3d];
Useful for shadow rays which originate in the scene. Assumes basePt and direction are in WORLD coordinates.
StuffLocalRay: PROC [ray: Ray, basePt: Point3d, direction: Vector3d, camera: Camera, localCS: CoordSystem];
basePt and direction must be in the frame of localCS.
EvaluateCameraRay: PROC [ray: Ray, t: REAL] RETURNS [pt: Point3d];
EvaluateWorldRay: PROC [ray: Ray, t: REAL] RETURNS [pt: Point3d];
EvaluateLocalRay: PROC [ray: Ray, t: REAL] RETURNS [pt: Point3d];
EvaluateLocalRay2: PROC [ray: Ray, t: REAL] RETURNS [x, y, z: REAL];
GetCameraRay: PROC [ray: Ray] RETURNS [basePt: Point3d, direction: Vector3d];
GetWorldRay: PROC [ray: Ray] RETURNS [basePt: Point3d, direction: Vector3d];
GetLocalRay: PROC [ray: Ray] RETURNS [basePt: Point3d, direction: Vector3d];
CreateRay: PROC RETURNS [ray: Ray];
Pools of Large Records for Recycling.
GetRayFromPool: PROC RETURNS [ray: Ray];
ReturnRayToPool: PROC [ray: Ray];
TransformRay: PROC [ray: Ray, mat: Matrix4by4] RETURNS [newRay: Ray];
Say ray is in terms of Coordinate frame CAMERA. Then if mat is CAMERAWORLD, newRay will be in terms of WORLD. Remember to ReturnRayToPool when done.
TransformRayToWorld: PROC [ray: Ray, cameraWORLD: Matrix4by4] RETURNS [newRay: Ray];
Exactly like TransformRay except that the ray will remember its WORLD coordinate self even after it is transformed to somewhere else.
TransformNewRay: PROC [ray: Ray, mat: Matrix4by4] RETURNS [newRay: Ray];
Like TransformRay except that the ray is allocated with NEW so do NOT ReturnRayToPool.
AddRay: PROC [ray1, ray2: Ray];
Puts sum in ray2.
SubtractRays: PROC [ray1, ray2: Ray] RETURNS [ray1MinusRay2: Ray];
Puts difference in ray2.
CopyClass: PROC [class: Classification] RETURNS [copy: Classification];
Creates a NEW Classification from the Heap (not from the pool -- no need to return).
MakeCompositeCell: PROC [name: Rope.ROPE, operation: PointSetOp, LeftSolidPtr: REF ANY, RightSolidPtr: REF ANY] RETURNS [c: Composite];
MakeCSGTree: PROC [son: REF ANY, backgroundColor: Color, shadows: BOOL] RETURNS [tree: CSGTree];
CombineBoundBoxes: PROC [bb1, bb2: BoundBox, op: PointSetOp] RETURNS [newBB: BoundBox];
Dispatches to the appropriate SVBoundBox procedure depending on op.
CombineBoundSpheres: PROC [bs1, bs2: BoundSphere, op: PointSetOp] RETURNS [newBS: BoundSphere];
Dispatches to the appropriate SVBoundSphere procedure depending on op.
RayHitsBoundSphere: PROC [worldRay: Ray, boundSphere: BoundSphere] RETURNS [BOOL];
PointSetOpToRope: PROC [pointSetOp: PointSetOp] RETURNS [opRope: Rope.ROPE];
RopeToPointSetOp: PROC [opRope: Rope.ROPE] RETURNS [pointSetOp: PointSetOp];
Hit testing for bounding spheres.
END.