// returns snapped world-frame, or input frame if no snap public Frame3f UpdateSnapW(Frame3f fSourceFrameW, SnapSet Snaps) { FScene scene = targetSO.GetScene(); float fSnapRadiusW = VRUtil.GetVRRadiusForVisualAngle(fSourceFrameW.Origin, scene.ActiveCamera.GetPosition(), SnapThreshVisualAngleDeg); float fSnapRadiusS = fSnapRadiusW / scene.GetSceneScale(); // fSourceFrameW in Scene coordinates Frame3f fSourceS = scene.ToSceneFrame(fSourceFrameW); SnapResult best_snap = null; float fNearest = float.MaxValue; Frame3f fBestSourceL = Frame3f.Identity; // snapframes are stored in local coords relative to object foreach (Frame3f fPointFrameL in snapFramesL) { // convert local-coord snap frame into scene coords Frame3f fPointFrameS = fSourceS.FromFrame(fPointFrameL); SnapResult snap = Snaps.FindNearestSnapPointS(fPointFrameS, fSnapRadiusS); if (snap != null) { float d = ((Vector3f)snap.FrameS.Origin - fPointFrameS.Origin).Length; if (d < fNearest) { fNearest = d; fBestSourceL = fPointFrameL; best_snap = snap; } } } snapState.UpdateState(best_snap, fBestSourceL); if (snapState.IsSnapped) { SnapResult useSnap = snapState.ActiveSnapTarget; Frame3f useSourceL = (Frame3f)snapState.ActiveSnapData; if (SnapOrientation) { // compute min-rotation frame, then align origins Frame3f fAlignedSourceS = Frame3f.SolveMinRotation(fSourceS, useSnap.FrameS); Frame3f fPointFrameS = fAlignedSourceS.FromFrame(useSourceL); Vector3f deltaS = (Vector3f)useSnap.FrameS.Origin - fPointFrameS.Origin; snapFrameS = fAlignedSourceS.Translated(deltaS); //// this is tricky...we have an object-space frame useSourceL, which //// we want to snap to a scene-space frame usePoint.FrameS. So we need //// to shift origin of that frame by -useSourceL_in_FrameS! //snapFrameS = usePoint.FrameS.Translated( // -usePoint.FrameS.FromFrameV(useSourceL.Origin)); } else { // translation-only snap - find shift in scene space, apply to input source frame Frame3f fPointFrameS = fSourceS.FromFrame(useSourceL); Vector3f deltaS = (Vector3f)useSnap.FrameS.Origin - fPointFrameS.Origin; snapFrameS = fSourceS.Translated(deltaS); } // now convert to world frame for return return(scene.ToWorldFrame(snapFrameS)); } return(fSourceFrameW); }