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[];