public void BeginDraw_Ray(Ray3f ray, AnyRayHit rayHit, int nStep) { CreateNewPrimitive(); Vector3f hitPos = rayHit.hitPos; // try snap points SnapResult snap = Snaps.FindHitSnapPoint(ray); if (snap != null) { Frame3f snapF = scene.ToWorldFrame(snap.FrameS); hitPos = snapF.Origin; } Frame3f sceneW = scene.SceneFrame; if (rayHit.hitSO == null) { primStartW = sceneW; primStartW.Origin = hitPos; } else { if (scene.Context.TransformManager.ActiveFrameType == FrameType.WorldFrame) { primStartW = sceneW; primStartW.Origin = hitPos; } else if (rayHit.hitSO is PivotSO) { primStartW = (rayHit.hitSO as PivotSO).GetLocalFrame(CoordSpace.WorldCoords); primStartW.Origin = hitPos; } else if (rayHit.hitSO is PrimitiveSO) { // align with object frame as much as possible, given that we still want // to use hit normal... Frame3f objFrame = (rayHit.hitSO as PrimitiveSO).GetLocalFrame(CoordSpace.WorldCoords); int nBestAxis = MathUtil.MostParallelAxis(objFrame, rayHit.hitNormal); int nPerp = (nBestAxis + 1) % 3; primStartW = new Frame3f(hitPos, rayHit.hitNormal, 1); primStartW.ConstrainedAlignAxis(0, objFrame.GetAxis(nPerp), primStartW.Y); } else { primStartW = new Frame3f(hitPos, rayHit.hitNormal, 1); primStartW.ConstrainedAlignAxis(1, sceneW.Y, primStartW.Y); } } primitive.Frame = primStartW; primStartS = scene.ToSceneFrame(primStartW); }
// 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); }
public void UpdateDraw_Spatial(Ray3f ray, Frame3f handFrame, int nStep) { // scene xform may have changed during steps (eg view rotation), so we // need to reconstruct our local frame Frame3f primCurW = scene.ToWorldFrame(primStartS); // try snap points SnapResult snap = Snaps.FindHitSnapPoint(ray); bool bHaveSnap = (snap != null); Frame3f snapF = (bHaveSnap) ? scene.ToWorldFrame(snap.FrameS) : Frame3f.Identity; // step 1: find radius in plane if (nStep == 0) { if (bHaveSnap) { plane_hit_local = primCurW.ToFrameP( primCurW.ProjectToPlane(snapF.Origin, 1)); } else { Vector3f forwardDir = ray.Direction; Vector3f plane_hit = VRUtil.SafeRayPlaneIntersection(ray, forwardDir, primCurW.Origin, primCurW.Y); plane_hit_local = primCurW.ToFrameP(plane_hit); } } float fX = MathUtil.SignedClamp(plane_hit_local[0], MinDimension, MaxDimension); float fY = MinDimension; float fZ = MathUtil.SignedClamp(plane_hit_local[2], MinDimension, MaxDimension); float fR_plane = MathUtil.Clamp(plane_hit_local.Length, MinDimension / 2, MaxDimension / 2); // step 2: find height from plane if (nStep == 1) { Vector3f plane_hit = primCurW.FromFrameP(plane_hit_local); Line3d l = new Line3d(plane_hit, primCurW.Y); if (bHaveSnap) { fY = (float)l.Project(snapF.Origin); } else { Vector3f handTip = handFrame.Origin + SceneGraphConfig.HandTipOffset * handFrame.Z; float fHandDist = (float)l.DistanceSquared(handTip); if (fHandDist < fR_plane * 1.5f) { fY = (float)l.Project(handTip); } else { fY = (float)DistLine3Ray3.MinDistanceLineParam(ray, l); } } } // figure out possible dimensions, clamp to ranges fY = MathUtil.SignedClamp(fY, MinDimension, MaxDimension); // update frame primitive.Frame = primCurW; // update dimensions bool bIsCorner = (primitive.Center == CenterModes.Corner); float fScale = 1.0f; // object is not in scene coordinates! if (primitive.Type == MeshPrimitivePreview.PrimType.Cylinder) { primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale; primitive.Depth = primitive.Width; //primitive.Depth = Mathf.Sign(fZ) * primitive.Width; //primitive.Width = Mathf.Sign(fX) * primitive.Width; primitive.Height = fY * fScale; } else if (primitive.Type == MeshPrimitivePreview.PrimType.Box) { primitive.Width = (bIsCorner) ? fX : 2 * fX * fScale; primitive.Depth = (bIsCorner) ? fZ : 2 * fZ * fScale; primitive.Height = fY * fScale; } else if (primitive.Type == MeshPrimitivePreview.PrimType.Sphere) { primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale; primitive.Depth = primitive.Height = primitive.Width; //primitive.Depth = Mathf.Sign(fZ) * primitive.Width; //primitive.Width = Mathf.Sign(fX) * primitive.Width; //primitive.Height = Mathf.Sign(fY) * primitive.Width; } else { throw new NotImplementedException("SnapDrawPrimitivesTool.UpdateDraw_Ray - type not supported"); } }