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] = { 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]; 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. xFile: ArnonSphereClassImpl.mesa Last edited by Bier on January 10, 1985 5:22:13 pm PST Author: Dennis Arnon and Eric Bier on January 10, 1985 10:08:46 pm PST RAY CASTING TYPES The ArnonSphere is: 2 2 2 F(x,y,z) = x + y + z - 1 = 0 arnonSphereData: ArnonSphereRec; arnonSphereData _ NARROW[arnonSphereRec]; The result of substituting 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 If the ray originates inside the sphere, treat as a single hit. Otherwise treat as a miss. Calculate the surface normals at the two hit points. To normalize, divide by norm. (I won't do this since the lighting model normalizes anyway) Use only the positive roots. Preserves the order of the roots, so they will still be in increasing order. Spheres can be built from scratch. ʘIhead1™J™6J™FJ˜šÏk ˜ J˜ Jšœ ˜ Jšœ˜Jšœ˜J˜J˜ J˜J˜J˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜J˜—šœ˜Jšœœ2˜RJšœ˜ —Jšœ˜J˜Iprocšœœ˜#Lšœ œ˜Lšœ œ˜L˜Lšœœ˜!Lšœœ˜L˜Lšœ™˜Lšœ œ˜'Lšœœ˜2Lšœ œ˜'Lšœœ˜/Lšœœ"˜9Lšœœ'Ïc˜^Lšœ œ˜'Lšœœ˜L˜Jšœ˜Jšœ$˜$J˜—J˜š Ïnœœœ5œœ˜jšœ˜#J˜JšÏf™Jšœ U™V—J™ Jšœœ˜Jšœ œ˜J˜ J˜ Lšœœœœ˜Lšœ œ˜šŸœœ œœ ˜:Jšœœ˜J˜J˜J˜Jšœ˜J˜—Lšœœ˜ Lšœœ˜ J˜J˜Jšœ$˜$Jšœœ™)Jšœ œž#˜GJšœ˜Jšœ˜Jšœ˜J˜˜J˜J™J™J™Jš 4™4J™J™ Jš ®™®—J˜˜J˜—šœ!˜!J˜J˜—šœ)˜)J˜J˜—Jšœ%˜%J˜J˜Lšœžœ˜4J™Lšœ ˜šœž˜Jšœ˜Jšœœ˜Jšœ˜—šœ˜L™[Lšœ ˜ šœ œž#˜5Lšœ˜Lšœ˜Lšœœ˜Lšœœ˜Lšœ˜Lšœ˜Lšœ%˜%Lšœ%˜%Lšœ%˜%Lšœ˜L˜—Lšœ ˜$Lšœ˜—šœžB˜HJšœ œ˜J˜Lšœ!ž,˜MLšœ,˜,Jšœœœ˜1Jšœœœœ˜QJšœ1˜1J™4JšœX˜XJšœ,˜,J™[JšœX˜XJšœ,˜,Jšœ˜—Jšœœ˜Jšœ˜J˜—šŸ œ œ œœ œœœœ˜uJ™jLšœœ˜ Lšœ=˜=Lšœœœ˜šœ˜šœœ˜šœœœ˜!Lšœ˜—Lšœ˜Lšœ˜L˜—Lšœ ˜—Lšœ˜Jšœ˜J˜—šŸœœ œœ˜GLšœ œœœ˜Lšœ œœœ˜Lšœ œœ ˜Lšœ œœœ˜Lšœj˜jLšœ˜L˜—š Ÿœœœœœ˜DLšœ"™"Lšœ œœ˜Lšœ˜Lšœ˜—šŸœœœœœ œœ˜]Lšœ&˜&Lšœ˜Lšœ˜L˜—šŸœœ˜Lšœ˜Jšœ-˜-šœ;˜;Lšœ˜LšŸœ˜LšŸœ˜Lšœ˜LšÏbœ˜Lšœ"˜"Lšœ)˜)Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ&˜&Lšœ$˜$Lšœ$˜$Lšœ˜Lšœ"˜"—L˜Lšœ.˜.Lšœ0˜0L˜L˜—Lšœ˜L˜Lšœ˜˜J˜J˜—J˜—…—H?