<> <> <> <> <<>> DIRECTORY AtomButtonsTypes, CodeTimer, CoordSys, SVRay, DisplayListToTree, IO, Matrix3d, Preprocess3d, Real, SV2d, SV3d, SVAssembly, SVCastRays, SVGravity, SVInterfaceTypes, SVLines3d, SVModelTypes, SVRayTypes, SVScene, SVSceneTypes, SVState; SVGravityImpl: CEDAR PROGRAM IMPORTS CodeTimer, CoordSys, SVRay, DisplayListToTree, Matrix3d, Preprocess3d, SVAssembly, SVCastRays, SVLines3d, SVState EXPORTS SVGravity = BEGIN Slice: TYPE = SVSceneTypes.Slice; Camera: TYPE = SVSceneTypes.Camera; Classification: TYPE = SVRayTypes.Classification; CSGTree: TYPE = SVRayTypes.CSGTree; FeatureData: TYPE = SVInterfaceTypes.FeatureData; FeedbackData: TYPE = AtomButtonsTypes.FeedbackData; GravityType: TYPE = SVInterfaceTypes.GravityType; Line3d: TYPE = SV3d.Line3d; MasterObject: TYPE = SVSceneTypes.MasterObject; Matrix4by4: TYPE = SV3d.Matrix4by4; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; PointAndDone: TYPE = SVSceneTypes.PointAndDone; PointGenerator: TYPE = SVSceneTypes.PointGenerator; Primitive: TYPE = SVRayTypes.Primitive; Ray: TYPE = SVRayTypes.Ray; Scene: TYPE = SVSceneTypes.Scene; SearchDepth: TYPE = SVRayTypes.SearchDepth; Shape: TYPE = SVSceneTypes.Shape; SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor; TriggerBag: TYPE = SVInterfaceTypes.TriggerBag; Vector3d: TYPE = SV3d.Vector3d; SVData: TYPE = SVInterfaceTypes.SVData; RayMap: PUBLIC PROC [cameraPoint: Point2d, criticalR: REAL, alignBag: REF ANY, sceneBag: TriggerBag, svData: SVData] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, feature: FeatureData, hitData: REF ANY] = { gravityType: GravityType _ SVState.GetGravityType[svData]; searchDepth: SearchDepth _ SVState.GetSearchDepth[svData]; CodeTimer.StartInt[$RayMap, $Solidviews]; [surfacePtWORLD, normalWORLD, feature, hitData] _ PointsOrSurfaces[cameraPoint, criticalR, sceneBag, svData.camera, searchDepth, gravityType]; CodeTimer.StopInt[$RayMap, $Solidviews]; }; PointsPreferred: PUBLIC PROC [cameraPoint: Point2d, criticalR: REAL, alignBag: REF ANY, sceneBag: TriggerBag, svData: SVData, sceneOnly: BOOL] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, feature: FeatureData, hitData: REF ANY] = { RETURN RayMap[cameraPoint, criticalR, alignBag, sceneBag, svData]; }; StrictDistance: PUBLIC PROC [cameraPoint: Point2d, criticalR: REAL, alignBag: REF ANY, sceneBag: TriggerBag, svData: SVData, sceneOnly: BOOL] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, feature: FeatureData, hitData: REF ANY] = { RETURN RayMap[cameraPoint, criticalR, alignBag, sceneBag, svData]; }; PointsOrSurfaces: PUBLIC PROC [cameraPoint: Point2d, criticalR: REAL, sceneBag: TriggerBag, camera: Camera, searchDepth: SearchDepth, gravityType: GravityType] RETURNS [surfacePtWORLD: Point3d, normalWORLD: Vector3d, feature: FeatureData, hitData: REF ANY] = { pointsPtWORLD: Point3d; pointsNormalWORLD: Vector3d; pointsFeature: FeatureData; parallel: BOOL; pointsHitData: REF ANY; rayWORLD: Ray _ GetWorldRayFromCameraPoint[cameraPoint, camera]; -- from pool [surfacePtWORLD, normalWORLD, feature, hitData] _ RayAtSurfaces[rayWORLD, cameraPoint, criticalR, sceneBag, camera, searchDepth]; [pointsPtWORLD, pointsNormalWORLD, pointsFeature, pointsHitData] _ RayAtPoints[rayWORLD, cameraPoint, criticalR, sceneBag, camera, gravityType]; IF pointsFeature # NIL AND WithinTolerance[pointsPtWORLD, rayWORLD, criticalR] THEN { surfacePtWORLD _ pointsPtWORLD; IF pointsFeature # feature THEN { normalWORLD _ pointsNormalWORLD; feature _ pointsFeature; }; hitData _ pointsHitData; } ELSE IF feature # NIL THEN { } ELSE { [surfacePtWORLD, normalWORLD, parallel] _ RayMeetsCentralCameraPlane[cameraPoint, camera]; hitData _ NIL; }; SVRay.ReturnRayToPool[rayWORLD]; }; LineFromRay: PROC [ray: Ray] RETURNS [line: Line3d] = { basePt: Point3d; direction: Vector3d; [basePt, direction] _ SVRay.GetWorldRay[ray]; line _ SVLines3d.LineFromPointAndVector[basePt, direction]; }; WithinTolerance: PROC [point: Point3d, rayWORLD: Ray, criticalR: REAL] RETURNS [BOOL] = { line: Line3d; dist: REAL; line _ LineFromRay[rayWORLD]; dist _ SVLines3d.DistancePointToLine[point, line]; RETURN[dist <= criticalR]; }; GetWorldRayFromCameraPoint: PROC [cameraPoint: Point2d, camera: Camera] RETURNS [rayWORLD: Ray] = { rayCamera: Ray; cameraWORLD: Matrix4by4 _ CoordSys.WRTWorld[camera.coordSys]; rayCamera _ SVRay.GetRayFromPool[]; SVRay.StuffCameraRay[rayCamera, cameraPoint, camera]; rayWORLD _ SVRay.TransformRayToWorld[rayCamera, cameraWORLD]; -- allocates ray from pool SVRay.ReturnRayToPool[rayCamera]; }; RayAtSurfaces: PROC [rayWorld: Ray, cameraPoint: Point2d, criticalR: REAL, sceneBag: TriggerBag, camera: Camera, searchDepth: SearchDepth] RETURNS [surfacePtWorld: Point3d, normalWorld: Vector3d, feature: FeatureData, hitData: REF ANY] = { class: Classification; primitive: Primitive; assembly: Slice; class _ SingleRay[rayWorld, cameraPoint, sceneBag, camera, TRUE, NIL]; -- class from pool IF sceneBag.scene # NIL THEN [assembly, primitive] _ AssemblyAndPrimitiveAtSearchDepth[class, searchDepth, sceneBag.scene.assembly]; IF class.count > 0 THEN [surfacePtWorld, normalWorld] _ SurfacePointAndNormalAtSearchDepth[class, rayWorld, searchDepth, sceneBag.scene.assembly]; feature _ FindFeature[assembly, sceneBag]; hitData _ HitDataAtSearchDepth[class, searchDepth, sceneBag.scene.assembly]; SVCastRays.ReturnClassToPool[class]; }; FindFeature: PROC [assembly: Slice, sceneBag: TriggerBag] RETURNS [feature: FeatureData] = { sliceD: SliceDescriptor; IF assembly = NIL THEN RETURN[NIL]; FOR list: LIST OF FeatureData _ sceneBag.slices, list.rest UNTIL list = NIL DO sliceD _ NARROW[list.first.shape]; IF sliceD.slice = assembly THEN RETURN[list.first]; ENDLOOP; RETURN[NIL]; }; AssemblyAndPrimitiveAtSearchDepth: PROC [class: Classification, searchDepth: SearchDepth, root: Slice] RETURNS [assembly: Slice, primitive: Primitive] = { SELECT searchDepth FROM first => [assembly, primitive] _ SVCastRays.NthAssemblyAndPrimitive[class, 1]; lastOfFirst => [assembly, primitive] _ SVCastRays.NthAssemblyAndPrimitive[class, 1]; last => [assembly, primitive] _ SVCastRays.NthAssemblyAndPrimitive[class, class.count]; lastOfLevel1 => [assembly, primitive] _ SVCastRays.LastTopLevelAssemAndPrim[class, root]; ENDCASE => ERROR; }; SurfacePointAndNormalAtSearchDepth: PROC [class: Classification, rayWorld: Ray, searchDepth: SearchDepth, root: Slice] RETURNS [surfacePtWorld: Point3d, normalWorld: Vector3d] = { SELECT searchDepth FROM first => [surfacePtWorld, normalWorld] _ SVCastRays.NthSurfacePointAndNormal[class, rayWorld, 1]; lastOfFirst => [surfacePtWorld, normalWorld] _ SVCastRays.LastOfFirstPointAndNormal[class, rayWorld]; last => IF class.count = 0 THEN ERROR ELSE [surfacePtWorld, normalWorld] _ SVCastRays.NthSurfacePointAndNormal[class, rayWorld, class.count]; lastOfLevel1 => [surfacePtWorld, normalWorld] _ SVCastRays.LastTopLevelPointAndNormal[class, rayWorld, root]; ENDCASE => ERROR; }; HitDataAtSearchDepth: PROC [class: Classification, searchDepth: SearchDepth, root: Slice] RETURNS [hitData: REF ANY] = { SELECT searchDepth FROM first => hitData _ SVCastRays.NthHitData[class, 1]; lastOfFirst => hitData _ SVCastRays.LastOfFirstHitData[class]; last => IF class.count = 0 THEN ERROR ELSE hitData _ SVCastRays.NthHitData[class, class.count]; lastOfLevel1 => hitData _ SVCastRays.LastTopLevelHitData[class, root]; ENDCASE => ERROR; }; SingleRay: PUBLIC PROC [rayWorld: Ray, cameraPoint: Point2d, sceneBag: TriggerBag, camera: Camera, consolidate: BOOL _ TRUE, feedback: FeedbackData, makeStream: BOOL _ FALSE] RETURNS [class: Classification] = { tree: CSGTree _ sceneBag.tree; topNode: REF ANY; IF tree = NIL THEN { class _ SVCastRays.GetClassFromPool[]; SVCastRays.MakeClassAMiss[class]; RETURN; }; IF tree.outOfDate THEN { tree _ DisplayListToTree.AssemblyToTree[sceneBag.scene.assembly, sceneBag.scene, camera, tree]; [] _ Preprocess3d.PreprocessForInteraction[tree, camera]; tree.outOfDate _ FALSE; }; topNode _ tree.son; class _ SVCastRays.RayCast[cameraPoint, rayWorld, topNode, consolidate, feedback, makeStream, 0]; }; -- end of SingleRay RayAtPoints: PROC [ray: Ray, cameraPoint: Point2d, criticalR: REAL, sceneBag: TriggerBag, camera: Camera, gravityType: GravityType] RETURNS [bestPoint: Point3d, bestNormal: Vector3d, bestFeature: FeatureData, bestHitData: REF ANY] = { line3d: Line3d; bestDist, thisDist: REAL; pointWORLD: Point3d; feature: FeatureData; sliceD: SliceDescriptor; hitData: REF ANY; success: BOOL; scene: Scene _ sceneBag.scene; line3d _ LineFromRay[ray]; bestDist _ Real.LargestNumber; bestFeature _ NIL; IF gravityType = linesPreferred THEN { FOR list: LIST OF FeatureData _ sceneBag.slices, list.rest UNTIL list = NIL DO feature _ list.first; sliceD _ NARROW[feature.shape]; [thisDist, pointWORLD, hitData, success] _ SVAssembly.ClosestSegmentToLine[sliceD, cameraPoint, line3d, criticalR, camera]; IF success AND thisDist < bestDist THEN { bestDist _ thisDist; bestPoint _ pointWORLD; bestHitData _ hitData; bestFeature _ feature; }; ENDLOOP; }; FOR list: LIST OF FeatureData _ sceneBag.slices, list.rest UNTIL list = NIL DO feature _ list.first; sliceD _ NARROW[feature.shape]; [thisDist, pointWORLD, hitData, success] _ SVAssembly.ClosestPointToLine[sliceD, cameraPoint, line3d, criticalR, camera]; IF success AND thisDist < bestDist THEN { bestDist _ thisDist; bestPoint _ pointWORLD; bestHitData _ hitData; bestFeature _ feature; }; ENDLOOP; bestNormal _ Matrix3d.ZAxisOfMatrix[CoordSys.WRTWorld[camera.coordSys]]; }; RayMeetsCameraPlane: PROC [cameraPoint: Point2d, depth: REAL, camera: Camera] RETURNS [planePtCamera: Point3d, parallel: BOOL] = { rayWorld: Ray; worldCamera: Matrix4by4; planePtWorld: Point3d; rayWorld _ SVRay.GetRayFromPool[]; SVRay.StuffWorldRayFromCamera[rayWorld, cameraPoint, camera]; [planePtWorld, parallel] _ SVCastRays.RayMeetsPlaneOfCoordSystem[camera.coordSys, rayWorld, 3, depth]; worldCamera _ CoordSys.FindAInTermsOfB[CoordSys.Parent[camera.coordSys], camera.coordSys]; planePtCamera _ Matrix3d.Update[planePtWorld, worldCamera]; SVRay.ReturnRayToPool[rayWorld]; }; RayMeetsCentralCameraPlane: PROC [cameraPoint: Point2d, camera: Camera] RETURNS [pointWORLD: Point3d, normalWORLD: Vector3d, parallel: BOOL] = { worldCAMERA: Matrix4by4 _ CoordSys.FindWorldInTermsOf[camera.coordSys]; originCAMERA: Point3d _ Matrix3d.OriginOfMatrix[worldCAMERA]; depth: REAL _ originCAMERA[3]; rayWorld: Ray; rayWorld _ SVRay.GetRayFromPool[]; SVRay.StuffWorldRayFromCamera[rayWorld, cameraPoint, camera]; [pointWORLD, parallel] _ SVCastRays.RayMeetsPlaneOfCoordSystem[camera.coordSys, rayWorld, 3, depth]; normalWORLD _ Matrix3d.ZAxisOfMatrix[CoordSys.WRTWorld[camera.coordSys]]; SVRay.ReturnRayToPool[rayWorld]; }; InitStats: PROC = { interval: CodeTimer.Interval; interval _ CodeTimer.CreateInterval[$RayMap]; CodeTimer.AddInt[interval, $Solidviews]; }; InitStats[]; END.