<> <> <> <> <> DIRECTORY SVUtility, Feedback, Rope, SV2d, SV3d, SVCastRays, SVMasterObject, SVMasterObjectTypes, SVModelTypes, SVObjectCast, SVRay, SVSceneTypes, SVVector3d; SVObjectCastImplA: CEDAR PROGRAM IMPORTS SVUtility, SVCastRays, SVRay, Feedback, SVVector3d EXPORTS SVObjectCast = BEGIN BlockHitData: TYPE = REF BlockHitDataObj; BlockHitDataObj: TYPE = SVMasterObject.BlockHitDataObj; Classification: TYPE = SVSceneTypes.Classification; Composite: TYPE = SVSceneTypes.Composite; CSGTree: TYPE = SVSceneTypes.CSGTree; LightSourceList: TYPE = SVModelTypes.LightSourceList; Matrix4by4: TYPE = SV3d.Matrix4by4; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; PointSetOp: TYPE = SVSceneTypes.PointSetOp; Primitive: TYPE = SVSceneTypes.Primitive; Ray: TYPE = SVSceneTypes.Ray; Surface: TYPE = REF ANY; Vector3d: TYPE = SV3d.Vector3d; RectSurface: TYPE = SVObjectCast.RectSurface; RectType: TYPE = SVObjectCast.RectType;-- {up, down, front, back, left, right}; TubeSurface: TYPE = SVObjectCast.TubeSurface; DiskSurface: TYPE = SVObjectCast.DiskSurface; DiskType: TYPE = SVObjectCast.DiskType;-- {top, bottom}; ShellSurface: TYPE = SVObjectCast.ShellSurface; HitRec: TYPE = REF HitRecObj; HitRecObj: TYPE = SVObjectCast.HitRecObj; HitArray: TYPE = REF HitArrayObj; HitArrayObj: TYPE = SVObjectCast.HitArrayObj; SurfaceArray: TYPE = SVSceneTypes.SurfaceArray; ParameterArray: TYPE = SVSceneTypes.ParameterArray; InOutArray: TYPE = SVSceneTypes.InOutArray; NormalArray: TYPE = SVSceneTypes.NormalArray; BlockData: TYPE = SVMasterObjectTypes.BlockData; globalHitArray: HitArray; globalHitArray2: HitArray; Between: PROC [test, bound1, bound2: REAL] RETURNS [BOOL] = { min, max: REAL; min _ MIN[bound1, bound2]; max _ MAX[bound1, bound2]; RETURN[min<= test AND test <= max]; }; BlockCast: PUBLIC PROC [localRay: Ray, prim: Primitive, blockRec: BlockData, surfs: SurfaceArray, positiveTOnly: BOOL _ TRUE] RETURNS [class: Classification] = { <> <> <> << loX d[2] < p[1]d[2] + hiY d[1] - p[2]d[1] < hiX d[2] x test for top face loZ d[2] < p[3]d[2] + hiY d[3] - p[2]d[3] < hiZ d[2] z test for top face loX d[2] < p[1]d[2] + loY d[1] - p[2]d[1] < hiX d[2] x test for bottom face loZ d[2] < p[3]d[2] + loY d[3] - p[2]d[3] < hiZ d[2] z test for bottom face>> << loY d[1] < p[2]d[1] + hiX d[2] - p[1]d[2] < hiY d[1] y test for right face loZ d[1] < p[3]d[1] + hiX d[3] - p[1]d[3] < hiZ d[1] z test for right face loY d[1] < p[2]d[1] + loX d[2] - p[1]d[2] < hiY d[1] y test for left face loZ d[1] < p[3]d[1] + loX d[3] - p[1]d[3] < hiZ d[1] z test for left face change the sign of the limit d[*] in d[*] < * < d[*] if d[*] is negative notice that with the six p(*)d(*) cross terms and the 18 [loX, hiX, loY, hiY, loZ, hiZ]d(*) cross terms, we can do all of these tests>> t: REAL; xd, yd, zd, D: REAL; hits: HitArray _ globalHitArray; loX, loY, loZ, hiX, hiY, hiZ: REAL; p1d2, p1d3, p2d1, p2d3, p3d1, p3d2: REAL; loZd1, hiZd1, loZd2, hiZd2, loZd3, hiZd3: REAL; loYd1, hiYd1, loYd2, hiYd2, loYd3, hiYd3: REAL; loXd1, hiXd1, loXd2, hiXd2, loXd3, hiXd3: REAL; p: Point3d; d: Vector3d; hitCount: NAT _ 0; doesHit: BOOL; upS, downS, frontS, backS, rightS, leftS: Surface; almostZero: REAL _ 1.0e-12; loX _ blockRec.box.loX; loY _ blockRec.box.loY; loZ _ blockRec.box.loZ; hiX _ blockRec.box.hiX; hiY _ blockRec.box.hiY; hiZ _ blockRec.box.hiZ; upS _ surfs[1]; downS _ surfs[2]; leftS _ surfs[3]; backS _ surfs[4]; rightS _ surfs[5]; frontS _ surfs[6]; class _ SVCastRays.GetClassFromPool[]; [p, d] _ SVRay.GetLocalRay[localRay]; p1d2 _ p[1]*d[2]; p1d3 _ p[1]*d[3]; p2d1 _ p[2]*d[1]; p2d3 _ p[2]*d[3]; p3d1 _ p[3]*d[1]; p3d2 _ p[3]*d[2]; loZd1 _ loZ*d[1]; hiZd1 _ hiZ*d[1]; loZd2 _ loZ*d[2]; hiZd2 _ hiZ*d[2]; loZd3 _ loZ*d[3]; hiZd3 _ hiZ*d[3]; loYd1 _ loY*d[1]; hiYd1 _ hiY*d[1]; loYd2 _ loY*d[2]; hiYd2 _ hiY*d[2]; loYd3 _ loY*d[3]; hiYd3 _ hiY*d[3]; loXd1 _ loX*d[1]; hiXd1 _ hiX*d[1]; loXd2 _ loX*d[2]; hiXd2 _ hiX*d[2]; loXd3 _ loX*d[3]; hiXd3 _ hiX*d[3]; <> D _ Abs[d[3]]; IF D > almostZero THEN { <> xd _ p1d3 + hiZd1 - p3d1; IF Between[xd, loXd3, hiXd3] THEN { yd _ p2d3 + hiZd2 - p3d2; IF Between[yd, loYd3, hiYd3] THEN doesHit _ TRUE ELSE doesHit _ FALSE} ELSE doesHit _ FALSE; IF doesHit THEN { t _ (hiZ - p[3])/d[3]; IF t>0 OR NOT positiveTOnly THEN { hitCount _ hitCount + 1; hits[hitCount]^ _ [t, frontS, [0,0,1]]; }; }; <> xd _ p1d3 + loZd1 - p3d1; IF Between[xd, loXd3, hiXd3] THEN { yd _ p2d3 + loZd2 - p3d2; IF Between[yd, loYd3, hiYd3] THEN doesHit _ TRUE ELSE doesHit _ FALSE} ELSE doesHit _ FALSE; IF doesHit THEN { t _ (loZ - p[3])/d[3]; IF t>0 OR NOT positiveTOnly THEN { hitCount _ hitCount + 1; hits[hitCount]^ _ [t, backS, [0,0,-1]]; }; }; }; <> D _ Abs[d[2]]; IF D > almostZero THEN { <> xd _ p1d2 + hiYd1 - p2d1; IF Between[xd, loXd2, hiXd2] THEN { zd _ p3d2 + hiYd3 - p2d3; IF Between[zd, loZd2, hiZd2] THEN doesHit _ TRUE ELSE doesHit _ FALSE} ELSE doesHit _ FALSE; IF doesHit THEN { t _ (hiY - p[2])/d[2]; IF t>0 OR NOT positiveTOnly THEN { hitCount _ hitCount + 1; hits[hitCount]^ _ [t, upS, [0,1,0]]; }; }; <> xd _ p1d2 + loYd1 - p2d1; IF Between[xd, loXd2, hiXd2] THEN { zd _ p3d2 + loYd3 - p2d3; IF Between[zd, loZd2, hiZd2] THEN doesHit _ TRUE ELSE doesHit _ FALSE} ELSE doesHit _ FALSE; IF doesHit THEN { t _ (loY - p[2])/d[2]; IF t>0 OR NOT positiveTOnly THEN { hitCount _ hitCount + 1; hits[hitCount]^ _ [t, downS, [0,-1,0]]; }; }; }; <> D _ Abs[d[1]]; IF D > almostZero THEN { <> yd _ p2d1 + hiXd2 - p1d2; IF Between[yd, loYd1, hiYd1] THEN { zd _ p3d1 + hiXd3 - p1d3; IF Between[zd, loZd1, hiZd1] THEN doesHit _ TRUE ELSE doesHit _ FALSE} ELSE doesHit _ FALSE; IF doesHit THEN { t _ (hiX - p[1])/d[1]; IF t>0 OR NOT positiveTOnly THEN { hitCount _ hitCount + 1; hits[hitCount]^ _ [t, rightS, [1,0,0]]; }; }; <> yd _ p2d1 + loXd2 - p1d2; IF Between[yd, loYd1, hiYd1] THEN { zd _ p3d1 + loXd3 - p1d3; IF Between[zd, loZd1, hiZd1] THEN doesHit _ TRUE ELSE doesHit _ FALSE} ELSE doesHit _ FALSE; IF doesHit THEN { t _ (loX - p[1])/d[1]; IF t>0 OR NOT positiveTOnly THEN { hitCount _ hitCount + 1; hits[hitCount]^ _ [t, leftS, [-1,0,0]]; }; }; }; SELECT hitCount FROM 0 => { -- ray misses block completely class.count _ 0; class.classifs[1] _ FALSE; }; 1 => { -- ray skims an edge and for some reason is noticed by only one surface or ray originates from inside the cube. If the later is true, class has one hit and classifs are TRUE, FALSE. IF loX < p[1] AND p[1] < hiX AND loY < p[2] AND p[2] < hiY AND loZ < p[3] AND p[3] < hiZ THEN { -- ray starts from inside the cube. class.count _ 1; class.params[1] _ hits[1].t; class.surfaces[1] _ hits[1].surf; class.stills[1] _ NARROW[hits[1].surf, BlockHitData].still; class.classifs[1] _ TRUE; class.classifs[2] _ FALSE; class.normals[1] _ hits[1].normal; class.primitives[1] _ prim; } ELSE { -- Count as a miss. SVCastRays.MakeClassAMiss[class]; }; }; 2 => { -- ray enters and exits block properly <> class.count _ 2; IF hits[1].t < hits[2].t THEN { class.params[1] _ hits[1].t; class.params[2] _ hits[2].t; class.surfaces[1] _ hits[1].surf; class.surfaces[2] _ hits[2].surf; class.stills[1] _ NARROW[hits[1].surf, BlockHitData].still; class.stills[2] _ NARROW[hits[2].surf, BlockHitData].still; class.normals[1] _ hits[1].normal; class.normals[2] _ hits[2].normal;} ELSE { class.params[2] _ hits[1].t; class.params[1] _ hits[2].t; class.surfaces[2] _ hits[1].surf; class.surfaces[1] _ hits[2].surf; class.stills[2] _ NARROW[hits[1].surf, BlockHitData].still; class.stills[1] _ NARROW[hits[2].surf, BlockHitData].still; class.normals[2] _ hits[1].normal; class.normals[1] _ hits[2].normal;}; class.classifs[1] _ FALSE; class.classifs[2] _ TRUE; class.classifs[3] _ FALSE; class.primitives[1] _ class.primitives[2] _ prim; }; 3 => { -- ray hits a vertex and is noticed by all 3 surfaces. Treat as two hits for now using the frontmost and rearmost values of class.params. perm: Permutation _ Rank[[hits[1].t, hits[2].t, hits[3].t]]; class.count _ 2; class.params[1] _ hits[perm[1]].t; class.params[2] _ hits[perm[3]].t; class.surfaces[1] _ hits[perm[1]].surf; class.surfaces[2] _ hits[perm[3]].surf; class.stills[1] _ NARROW[hits[1].surf, BlockHitData].still; class.stills[2] _ NARROW[hits[3].surf, BlockHitData].still; class.normals[1] _ hits[perm[1]].normal; class.normals[2] _ hits[perm[3]].normal; class.classifs[1] _ FALSE; class.classifs[2] _ TRUE; class.classifs[3] _ FALSE; class.primitives[1] _ class.primitives[2] _ prim; Feedback.AppendTypescriptRaw[$Solidviews, "Point of interest: Some block was hit 3 times", oneLiner]; }; ENDCASE => SIGNAL WierdHitCount; }; -- end of BlockCast <> <> <> <> <> << -d[2] < p[1]d[2] + d[1] - p[2]d[1] < d[2] x test for top face -d[2] < p[3]d[2] + d[3] - p[2]d[3] < d[2] z test for top face -d[2] < p[1]d[2] - d[1] - p[2]d[1] < d[2] x test for bottom face -d[2] < p[3]d[2] - d[3] - p[2]d[3] < d[2] z test for bottom face>> << -d[1] < p[2]d[1] + d[2] - p[1]d[2] < d[1] y test for right face -d[1] < p[3]d[1] + d[3] - p[1]d[3] < d[1] z test for right face -d[1] < p[2]d[1] - d[2] - p[1]d[2] < d[1] y test for right face -d[1] < p[3]d[1] - d[3] - p[1]d[3] < d[1] z test for right face change the sign of the limit d[*] in d[*] < * < d[*] if d[*] is negative notice that with the six p(*)d(*) cross terms, we can do all of these tests>> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <<[p, d] _ SVRay.GetLocalRay[localRay];>> <> <> <> <> <> <> <<>> <> <> < almostZero THEN {>> <> <> <> <> <> <> <> <> <> <0 THEN {>> <> <> <<};>> <<}; >> <> <> <> <> <> <> <> <> <> <0 THEN {>> <> <> <<};>> <<};>> <<};>> <<>> <> <> < almostZero THEN {>> <> <> <> <> <> <> <> <> <> <0 THEN {>> <> <> <<};>> <<}; >> <> <> <> <> <> <> <> <> <> <0 THEN {>> <> <> <<};>> <<};>> <<};>> <<>> <> <> < almostZero THEN {>> <> <> <> <> <> <> <> <> <> <0 THEN {>> <> <> <<};>> <<}; >> <> <> <> <> <> <> <> <> <> <0 THEN {>> <> <> <<};>> <<};>> <<};>> <<>> <