File: SVHalfSpacesImpl.mesa
Author: Eric Bier on August 12, 1983 1:58 pm
Last edited by Bier: August 16, 1983 10:31 am
Contents: Implementation of the half-space object class
DIRECTORY
CastRays,
CoordSys,
CSG,
CSGGraphics,
DisplayList3d,
Draw3d,
Graphics,
IO,
Rope,
SV2d,
SV3d,
SVBoundBox,
SVHalfSpaces,
SVPolygon3d,
TFI3d;
SVHalfSpacesImpl: PROGRAM
IMPORTS CastRays, CSGGraphics, DisplayList3d, Draw3d, IO, SVPolygon3d, TFI3d
EXPORTS SVHalfSpaces =
BEGIN
BoundHedron: TYPE = SVBoundBox.BoundHedron;
CoordSystem: TYPE = REF CoordSysObj;
CoordSysObj: TYPE = CoordSys.CoordSysObj;
Classification: TYPE = REF ClassificationObj;
ClassificationObj: TYPE = CastRays.ClassificationObj;
LightSourceList: TYPE = DisplayList3d.LightSourceList;
Point2d: TYPE = SV2d.Point2d;
Ray: TYPE = REF RayObj;
RayObj: TYPE = CSG.RayObj;
PlanarSurface: TYPE = REF PlanarSurfaceObj;
PlanarSurfaceObj: TYPE = DisplayList3d.PlanarSurfaceObj;
PlanarSurfaceList: TYPE = DisplayList3d.PlanarSurfaceList;
Plane: TYPE = SVPolygon3d.Plane;
Point3d: TYPE = SV3d.Point3d;
Camera: TYPE = CSGGraphics.Camera;
MasterObjectClass: TYPE = REF MasterObjectClassObj;
MasterObjectClassObj: TYPE = DisplayList3d.MasterObjectClassObj;
MasterObject: TYPE = REF MasterObjectRec;
MasterObjectRec: TYPE = DisplayList3d.MasterObjectRec;
Primitive: TYPE = CSG.Primitive;
Surface: TYPE = REF ANY;
Assembly: TYPE = REF AssemblyObj;
AssemblyObj: TYPE = DisplayList3d.AssemblyObj;
BASIC SHAPES
HalfSpaceRec: TYPE = REF HalfSpaceRecObj;
HalfSpaceRecObj: TYPE = SVHalfSpaces.HalfSpaceRecObj;
PlaneSurface: TYPE = REF PlaneSurfaceObj;
PlaneSurfaceObj: TYPE = SVHalfSpaces.PlaneSurfaceObj;
halfSpaceClass: MasterObjectClass;
HalfSpaceBody: PRIVATE PROC RETURNS [halfSpaceRec: HalfSpaceRec] = {
halfSpaceRec ← NEW[HalfSpaceRecObj];
halfSpaceRec.gridSide ← 72.0;
};
HalfSpaceMakeMasterObject: PUBLIC PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = {
mainBody: HalfSpaceRec ← HalfSpaceBody[];
lineBody: REF ANY ← mainBody;
shadeBody: REF ANY ← mainBody;
rayCastBody: REF ANY ← HalfSpaceGetRayCastBody[];
mo ← DisplayList3d.CreateMasterObject[name, halfSpaceClass, mainBody, lineBody, shadeBody, rayCastBody];
};
HalfSpaceBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = {
hedron ← NIL;
};
HalfSpaceGetRayCastBody: PRIVATE PROC [] RETURNS [planeS: PlaneSurface] = {
planeS ← NEW[PlaneSurfaceObj];
};
HalfSpaceRayCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
mo: MasterObject ← NARROW[masterObject];
RETURN[HalfSpaceCastAux[localRay, NARROW[mo.rayCastBody], prim]];
};
HalfSpaceCastAux: PRIVATE PROC [localRay: Ray, plane: Surface, prim: Primitive] RETURNS [class: Classification] = {
Do one ray-plane intersection test.
The half space ends at the xz plane (i.e. the plane with equation y = 0.
Ray parameterization is R = p + t*d. For y, this is:
y[t] = p[2]+t*d[2].
If d has no y component, this has no solution. Otherwise, we find t = -p[2]/d[2]. Check to see which side of the plane the ray originates on. Check to see that t is positive.
almostZero: REAL ← 1.0e-12;
t: REAL;
rayStartsOut: BOOL;
class ← CastRays.GetClassFromPool[];
IF Abs[localRay.direction[2]] > almostZero THEN {
t ← -localRay.basePt[2]/localRay.direction[2];
rayStartsOut ← localRay.basePt[2] >0;
IF t > 0 THEN {
The ray hits the plane.
class.count ← 1;
class.params[1] ← t;
class.surfaces[1] ← plane;
class.normals[1] ← [0,1,0];
class.primitives[1] ← prim;
IF rayStartsOut THEN {
class.classifs[1] ← FALSE;
class.classifs[2] ← TRUE;
}
ELSE {
class.classifs[1] ← TRUE;
class.classifs[2] ← FALSE;
};
}
ELSE {
The plane is behind the ray.
class.count ← 0;
class.classifs[1] ← NOT rayStartsOut;
};
}
ELSE {
Ray is functionally parallel to the plane. Count a complete miss.
class.count ← 0;
class.classifs[1] ← FALSE;
};
}; -- end of HalfSpaceCastAux
Abs: PROC [r: REAL] RETURNS [REAL] = {
RETURN[IF r >= 0 THEN r ELSE -r];
};
HalfSpaceRayCastNoBBoxes: PUBLIC PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
mo: MasterObject ← NARROW[masterObject];
RETURN[HalfSpaceCastAux[localRay, NARROW[mo.rayCastBody], prim]];
};
HalfSpaceLineDraw: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
halfSpaceRec: HalfSpaceRec ← NARROW[data];
gridSide: REAL ← halfSpaceRec.gridSide;
plane: Plane ← SVPolygon3d.PlaneFromCoefficients[0,1,0,0];
CSGGraphics.DrawInfiniteLine[dc, [0,0,0], [1,0,0], camera, localCS];
CSGGraphics.DrawInfiniteLine[dc, [0,0,gridSide], [1,0,gridSide], camera, localCS];
CSGGraphics.DrawInfiniteLine[dc, [0,0,-gridSide], [1,0,-gridSide], camera, localCS];
CSGGraphics.DrawInfiniteLine[dc, [0,0,0], [0,0,1], camera, localCS];
CSGGraphics.DrawInfiniteLine[dc, [gridSide,0,0], [gridSide,0,1], camera, localCS];
CSGGraphics.DrawInfiniteLine[dc, [-gridSide,0,0], [-gridSide,0,1], camera, localCS];
CSGGraphics.DrawHorizonOfPlane[dc, plane, camera, localCS];
};
HalfSpaceDrawNormals: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
Draw3d.DrawLocalVector[dc, [0,1,0], [0,0,0], camera, localCS];
};
HalfSpaceCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
len ← 1;
};
HalfSpaceCountVert: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
len ← 0;
};
HalfSpaceGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = {
mo: MasterObject ← NARROW[assembly.object];
midPoint: Point3d ← CSGGraphics.LocalToCamera[[0,0,0], assembly.coordSys];
surface: PlanarSurface;
depth: REAL ← midPoint[3];
surface ← NEW[PlanarSurfaceObj ← [
NIL, assembly, mo, [0,1,0], depth]];
psl ← LIST[surface];
};
HalfSpaceDrawSurf: PUBLIC PROC [dc: Graphics.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = {
localCS: CoordSystem;
plane: Plane ← SVPolygon3d.PlaneFromCoefficients[0,1,0,0];
localCS ← ps.assembly.coordSys;
CSGGraphics.DrawInfinitePlaneShaded[dc, plane, ps.assembly.artwork, lightSources, camera, localCS];
};
HalfSpaceFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = {
HalfSpaces can be recovered from scratch.
f.PutChar[IO.TAB];
f.PutF["data: procedural\n"];
};
HalfSpaceFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = {
TFI3d.ReadRope[f, "data: procedural"];
TFI3d.ReadBlank[f];
mo ← HalfSpaceMakeMasterObject[name];
};
Init: PROC = {
halfSpace: MasterObject;
halfSpaceClass ← DisplayList3d.RegisterMasterObjectClass[
"halfSpace",
HalfSpaceFilein,
HalfSpaceFileout,
HalfSpaceRayCast,
HalfSpaceRayCastNoBBoxes,
HalfSpaceBoundHedron,
DisplayList3d.NoOpPreprocess,
HalfSpaceLineDraw,
HalfSpaceDrawNormals,
HalfSpaceCountSurf,
HalfSpaceGetSurf,
HalfSpaceDrawSurf,
DisplayList3d.NoOpDrawSubBoxes];
halfSpace ← HalfSpaceMakeMasterObject["halfSpace"];
DisplayList3d.RegisterMasterObject[halfSpace];
};
Init[];
END.