<> <> <> DIRECTORY Algebra3d, CastRays, CSG, DisplayList3d, IO, Polynomial, Rope, SV2d, SV3d, SVModelTypes, SVRayTypes, SVSceneTypes, SVVector3d, TFI3d; ArnonSphereClassImpl: PROGRAM IMPORTS Algebra3d, CastRays, CSG, DisplayList3d, IO, Polynomial, SVVector3d, TFI3d EXPORTS = BEGIN Camera: TYPE = SVModelTypes.Camera; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Shape: TYPE = SVSceneTypes.Shape; Vector: TYPE = SV3d.Vector; <> Assembly: TYPE = SVSceneTypes.Assembly; Classification: TYPE = SVRayTypes.Classification; Composite: TYPE = SVRayTypes.Composite; MasterObject: TYPE = SVSceneTypes.MasterObject; MasterObjectClass: TYPE = SVSceneTypes.MasterObjectClass; MasterObjectClassList: TYPE = SVSceneTypes.MasterObjectClassList; -- LIST OF MasterObjectClass Primitive: TYPE = SVRayTypes.Primitive; Ray: TYPE = SVRayTypes.Ray; globalPoly: Polynomial.Ref; arnonSphereClass: MasterObjectClass; ArnonSphereCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = { <> << 2 2 2 F(x,y,z) = x + y + z - 1 = 0 >> <> x0, x1, y0, y1, z0, z1: REAL; a2, a1, a0: REAL; p: Point3d; d: Vector; tArray: ARRAY[1..2] OF REAL; rootCount: NAT; ArnonSphereGrad: PROC [x, y, z: REAL] RETURNS [Vector] ~ { gradx, grady, gradz: REAL; gradx _ 2. * x; grady _ 2. * y; gradz _ 2. * z; RETURN [[gradx, grady, gradz]]; }; pp: REAL; t1, t2: REAL; class _ CastRays.GetClassFromPool[]; <> [p, d] _ CSG.GetLocalRay[localRay]; -- p is base point, d is directiona x0 _ p[1]; x1 _ d[1]; y0 _ p[2]; y1 _ d[2]; z0 _ p[3]; z1 _ d[3]; <> <<>> <<>> << F, x: x1 * t + x0, y: y1 * t + y0, z: z1 * t + z0; >> <<>> << in Macsyma:>> << 2 2 2 2 2 2 2 2 (d4) t z1 + 2 t z0 z1 + z0 + t y1 + 2 t y0 y1 + y0 + t x1 + 2 t x0 x1 2 + x0 - 1 >> a2 _ z1 * z1 + y1 * y1 + x1 * x1; a1 _ 2.* ( z0 * z1 + y0 * y1 + x0 * x1 ); a0 _ z0 * z0 + y0 * y0 + x0 * x0 - 1; [tArray, rootCount, ----] _ PositiveRoots[a2,a1,a0]; <<>> SELECT rootCount FROM 0 => {-- complete miss. class.count _ 0; class.classifs[1] _ FALSE; }; 1 => { <> pp _ SVVector3d.DotProduct[p,p]; IF pp <1.0 THEN { -- ray originates inside the sphere class.count _ 1; t1 _ tArray[1]; class.classifs[1] _ TRUE; class.classifs[2] _ FALSE; class.params[1] _ t1; class.surfaces[1] _ NIL; class.normals[1][1] _ p[1] + d[1]*t1; class.normals[1][2] _ p[2] + d[2]*t1; class.normals[1][3] _ p[3] + d[3]*t1; class.primitives[1] _ prim; } ELSE CastRays.MakeClassAMiss[class]; }; 2 => {-- cuts one cross section of the ArnonSphere. Sort roots by size. x, y, z: REAL; class.count _ 2; t1 _ tArray[1]; t2 _ tArray[2]; -- since tArray[1] < tArray[2] is guaranteed class.params[1] _ t1; class.params[2] _ t2; class.surfaces[1] _ NIL; class.surfaces[2] _ NIL; class.classifs[1] _ FALSE; class.classifs[2] _ TRUE; class.classifs[3] _ FALSE; class.primitives[1] _ class.primitives[2] _ prim; <> x _ x0 + class.params[1]*x1; y _ y0 + class.params[1]*y1; z _ z0 + class.params[1]*z1; class.normals[1] _ ArnonSphereGrad[x, y, z]; <> x _ x0 + class.params[2]*x1; y _ y0 + class.params[2]*y1; z _ z0 + class.params[2]*z1; class.normals[2] _ ArnonSphereGrad[x, y, z]; }; ENDCASE => ERROR; }; PositiveRoots: PROCEDURE [a, b, c: REAL] RETURNS [rootArray: ARRAY[1..2] OF REAL, rootCount, totalRealRoots: NAT] = { <> i: NAT _ 1; [rootArray, rootCount] _ Algebra3d.QuadraticFormula[a, b, c]; IF rootCount = 0 THEN RETURN; WHILE i <= rootCount DO IF rootArray[i] <= 0 THEN { FOR j: NAT IN [i..rootCount-1] DO rootArray[j] _ rootArray[j+1]; ENDLOOP; rootCount _ rootCount - 1; } ELSE {i _ i + 1}; ENDLOOP; }; MakeMasterObject: PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = { mainBody: REF ANY _ NIL; lineBody: REF ANY _ NIL; shadeBody: REF ANY _ lineBody; rayCastBody: REF ANY _ NIL; mo _ DisplayList3d.CreateMasterObject[name, arnonSphereClass, mainBody, lineBody, shadeBody, rayCastBody]; }; ArnonSphereFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = { <> f.PutChar[IO.TAB]; f.PutF["data: procedural\n"]; }; ArnonSphereFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = { TFI3d.ReadRope[f, "data: procedural"]; TFI3d.ReadBlank[f]; mo _ MakeMasterObject[name]; }; Init: PROC = { arnonSphere: MasterObject; globalPoly _ Polynomial.Quartic[[0,0,0,0,0]]; arnonSphereClass _ DisplayList3d.RegisterMasterObjectClass[ "arnonSphere", ArnonSphereFilein, ArnonSphereFileout, DisplayList3d.NoOpFileoutPoly, ArnonSphereCast, DisplayList3d.NoOpRayCastNoBBoxes, DisplayList3d.NoOpRayCastBoundingSpheres, DisplayList3d.NoOpBoundHedron, DisplayList3d.NoOpPreprocess, DisplayList3d.NoOpLineDraw, DisplayList3d.NoOpNormalsDraw, DisplayList3d.NoOpCountPlanarSurfaces, DisplayList3d.NoOpGetPlanarSurfaces, DisplayList3d.NoOpDrawPlanarSurface, DisplayList3d.NoOpDrawSubBoxes, DisplayList3d.NoOpDrawSubSpheres]; arnonSphere _ MakeMasterObject["arnonSphere"]; DisplayList3d.RegisterMasterObject[arnonSphere]; }; Init[]; END.