// 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); }
public override bool UpdateCapture(ITransformable target, Ray3f worldRay) { // find hit SnapResult snap = Targets.FindHitSnapPoint(worldRay); snapState.UpdateState(snap); if (snapState.IsSnapped) { SnapResult useSnap = snapState.ActiveSnapTarget; Frame3f hitFrameS = Frame3f.Identity; if (useSnap != null) { hitFrameS = new Frame3f(useSnap.FrameS); } Frame3f targetF = originalTargetS; // target.GetLocalFrame(CoordSpace.WorldCoords); Frame3f pivotF = hitFrameS; targetF.Origin = pivotF.Origin; if (parent.CurrentFrameMode == FrameType.WorldFrame) { targetF.Rotation = Quaternion.identity; } else { targetF.Rotation = pivotF.Rotation; } Vector3f deltaInT = targetF.FromFrameV(SourceFrameL.Origin); targetF.Origin -= deltaInT; // why is this minus? target.SetLocalFrame(targetF, CoordSpace.SceneCoords); } else { Func <SceneObject, bool> filter = null; if (TargetObjects != null && TargetObjects.Count > 0) { filter = (x) => { return(TargetObjects.Contains(x) == false); } } ; AnyRayHit hit; if (scene.FindSceneRayIntersection(worldRay, out hit, true, filter)) { Vector3f hitPosS = scene.ToSceneP(hit.hitPos); Vector3f hitNormS = scene.ToSceneN(hit.hitNormal); Frame3f targetF = originalTargetS; targetF.Origin = hitPosS; targetF.AlignAxis(1, hitNormS); if (parent.CurrentFrameMode == FrameType.WorldFrame) { targetF.Rotation = Quaternion.identity; } Vector3f deltaInT = targetF.FromFrameV(SourceFrameL.Origin); targetF.Origin -= deltaInT; // why is this minus? target.SetLocalFrame(targetF, CoordSpace.SceneCoords); } else { target.SetLocalFrame(originalTargetS, CoordSpace.SceneCoords); } } return(true); }