public void EnterCamera() { usingCamera = true; InputHandlerStack.main.Push(this); Player main = Player.main; MainCameraControl.main.enabled = false; SNCameraRoot_Parent = SNCameraRoot.main.transform.parent; SNCameraRoot.main.transform.SetParent(control_instance.CannonCamPosition.transform, false); Player.main.SetHeadVisible(true); VRUtil.Recenter(); gameObject.SetActive(true); }
// called on per-frame Update() override public void PreRender() { gizmo.Show(); foreach (var v in Widgets) { float fScaling = VRUtil.GetVRRadiusForVisualAngle( v.Key.GetPosition(), parentScene.ActiveCamera.GetPosition(), SceneGraphConfig.DefaultPivotVisualDegrees); fScaling /= parentScene.GetSceneScale(); v.Key.SetLocalScale(new Vector3f(fScaling, fScaling, fScaling)); } }
public void UpdateSetWorldScale(Ray3f left, Ray3f right) { Vector3f hit1 = hitFrame.RayPlaneIntersection(left.Origin, left.Direction, 2); Vector3f hit2 = hitFrame.RayPlaneIntersection(right.Origin, right.Direction, 2); Vector3f avg = (hit1 + hit2) * 0.5f; float r0 = (hit1 - (Vector3f)go.transform.position).Length; float r1 = (hit2 - (Vector3f)go.transform.position).Length; float r = (r0 + r1) * 0.5f; float min_r = VRUtil.GetVRRadiusForVisualAngle(avg, camState.camPosition, 2.0f); r = (float)Math.Max(r, min_r); go.transform.localScale = r * Vector3f.One; go.GetComponent <Renderer>().material = (r > deadzone_r) ? mYes : mNo; }
public void UpdateMeasurePoint(Vector3d point, CoordSpace eSpace, int nPointNum, bool isFixedPoint = true) { if (eSpace == CoordSpace.ObjectCoords) { throw new NotSupportedException("TwoPointMeasureTool.UpdateMeasurePoint"); } Vector3d pointS = (eSpace == CoordSpace.SceneCoords) ? point : scene.ToSceneP(point); int i = MathUtil.Clamp(nPointNum, 0, 1); setPointsS[i] = pointS; snappedPointsS[i] = setPointsS[i]; point_initialized[i] = true; if (isFixedPoint) { return; } // snap List <SceneObject> targets = (SpecificTargets != null) ? SpecificTargets : new List <SceneObject>(scene.SceneObjects); float fAvgSnapDist = 0; int avgcount = 0; foreach (var so in targets) { fAvgSnapDist += VRUtil.GetVRRadiusForVisualAngle(so.GetLocalFrame(CoordSpace.WorldCoords).Origin, scene.ActiveCamera.GetPosition(), snapThresholdAngle); avgcount++; } if (avgcount == 0) { return; } fAvgSnapDist /= avgcount; SORayHit nearestW; Vector3d pointW = (eSpace == CoordSpace.WorldCoords) ? point : scene.ToWorldP(point); if (SceneUtil.FindNearestPoint(targets, pointW, fAvgSnapDist, out nearestW, CoordSpace.WorldCoords)) { snappedPointsS[i] = scene.ToSceneP(nearestW.hitPos); } }
public static void IGM_Awake_Postfix(IngameMenu __instance) { if (__instance != null && MainPatcher.recenterVRButton == null) { MainPatcher.recenterVRButton = UnityEngine.Object.Instantiate <Button>(__instance.quitToMainMenuButton.transform.parent.GetChild(0).gameObject.GetComponent <Button>(), __instance.quitToMainMenuButton.transform.parent); MainPatcher.recenterVRButton.transform.SetSiblingIndex(1); MainPatcher.recenterVRButton.name = "RecenterVR"; MainPatcher.recenterVRButton.onClick.RemoveAllListeners(); MainPatcher.recenterVRButton.onClick.AddListener(delegate() { VRUtil.Recenter(); }); foreach (Text text in MainPatcher.recenterVRButton.GetComponents <Text>().Concat(MainPatcher.recenterVRButton.GetComponentsInChildren <Text>())) { text.text = "Recenter VR"; } } }
public void PreRender(Vector3f cameraPosition) { // since we are supporting case where so is moving (ie bimanual grab), we need to // update position here. And SetGameObjectFrame() does not support SceneCoords. // So map scene to world Frame3f FrameW = SceneTransforms.TransformTo(FrameS, so, CoordSpace.SceneCoords, CoordSpace.WorldCoords); UnityUtil.SetGameObjectFrame(primGO, FrameW, CoordSpace.WorldCoords); float fScaling = VRUtil.GetVRRadiusForVisualAngle( primGO.transform.position, cameraPosition, SceneGraphConfig.DefaultPivotVisualDegrees * 0.98f); // [RMS] not sure this makes sense...eg what if we have multiple parents? they could // have different scalings, no? ParentScale seems to be inherited from scene scaling, // somehow, but it is unclear... float fParentScale = primGO.transform.parent.localScale[0]; float fSceneScale = so.GetScene().GetSceneScale(); fScaling = fScaling / fParentScale / fSceneScale; primGO.transform.localScale = new Vector3f(fScaling, fScaling, fScaling); }
public override Capture BeginCapture(InputState input, CaptureSide eSide) { HandInfo hi = new HandInfo(); hi.eMode = ActionMode.TransformCamera; Frame3f camFrame = cockpit.ActiveCamera.GetWorldFrame(); // if both rays hit scene and are within a few visual degrees, then we // we pull out a sphere and use it to re-scale the world. // Otherwise do normal hand-transform actions AnyRayHit hit1, hit2; bool bHit1 = cockpit.Scene.FindSceneRayIntersection(input.vLeftSpatialWorldRay, out hit1); bool bHit2 = cockpit.Scene.FindSceneRayIntersection(input.vRightSpatialWorldRay, out hit2); if (bHit1 && bHit2) { Vector3 avg = (hit1.hitPos + hit2.hitPos) * 0.5f; float d = VRUtil.GetVRRadiusForVisualAngle(avg, camFrame.Origin, 2.0f); if ((hit1.hitPos - hit2.hitPos).Length < d) { hi.eMode = ActionMode.SetWorldScale; Frame3f centerF = cockpit.Scene.SceneFrame; centerF.Origin = avg; Frame3f planeF = new Frame3f(centerF.Origin, camFrame.Z); hi.BeginSetWorldScale(centerF, planeF, 2 * d); hi.UpdateSetWorldScale(input.vLeftSpatialWorldRay, input.vRightSpatialWorldRay); } } hi.leftStartF = input.LeftHandFrame; hi.rightStartF = input.RightHandFrame; hi.camState = cockpit.ActiveCamera.Manipulator().GetCurrentState(cockpit.Scene); hi.camRight = camFrame.X; hi.camForward = camFrame.Z; cockpit.ActiveCamera.SetTargetVisible(true); return(Capture.Begin(this, CaptureSide.Both, hi)); }
//code copied from the quit to desktop mod and modified static void Postfix(IngameMenu __instance) { if (__instance != null && recenterVRButton == null) { //Clone the quitToMainMenuButton and update it Button menuButton = __instance.quitToMainMenuButton.transform.parent.GetChild(0).gameObject.GetComponent <Button>(); recenterVRButton = UnityEngine.Object.Instantiate <Button>(menuButton, __instance.quitToMainMenuButton.transform.parent); recenterVRButton.transform.SetSiblingIndex(1); //put the button in the second position in the menu recenterVRButton.name = "RecenterVR"; recenterVRButton.onClick.RemoveAllListeners(); //remove cloned listeners //add new listener recenterVRButton.onClick.AddListener(delegate() { VRUtil.Recenter(); }); //might be a better way to replace the text of the copied button IEnumerable <Text> enumerable = recenterVRButton.GetComponents <Text>().Concat(recenterVRButton.GetComponentsInChildren <Text>()); foreach (Text text in enumerable) { text.text = "Recenter VR"; } } }
override public bool UpdateCapture(InputEvent e) { if (in_drag) { float fRayT = 0.0f; if (RayIntersection.Sphere(e.ray.Origin, e.ray.Direction, hitFrame.Origin, IndicatorDistance, out fRayT) == false) { return(true); // should not happen, but I guess it could if user } // had arms out in some crazy position... Vector3f v = e.ray.Origin + fRayT * e.ray.Direction; Vector3f vToHit = (v - hitFrame.Origin).Normalized; Vector3f vToStart = (startHitPos - hitFrame.Origin).Normalized; float deltaUp = -VRUtil.PlaneAngleSigned(vToHit, vToStart, hitFrame.X); cockpit.TiltAngle = MathUtil.Clamp(start_tilt + deltaUp, -30.0f, 20.0f); float deltaLR = -VRUtil.PlaneAngleSigned(vToHit, vToStart, hitFrame.Y); cockpit.ShiftAngle = start_shift + deltaLR; //if ( tracker.IsLocked == false ) cockpit.ShiftAngle = MathUtil.Clamp(cockpit.ShiftAngle, -10.0f, 10.0f); } return(true); }
public static void Postfix(IngameMenu __instance) { if (__instance != null && recenterVRButton == null) { //I think this is copying an existing button Button menuButton = __instance.quitToMainMenuButton.transform.parent.GetChild(0).gameObject.GetComponent <Button>(); recenterVRButton = UnityEngine.Object.Instantiate <Button>(menuButton, __instance.quitToMainMenuButton.transform.parent); recenterVRButton.transform.SetSiblingIndex(1); //put the button in the second position in the menu recenterVRButton.name = "RecenterVR"; recenterVRButton.onClick.RemoveAllListeners(); //this seems to be removing listeners that would have been copied from the original button //add new listener recenterVRButton.onClick.AddListener(delegate() { VRUtil.Recenter(); }); //might be a better way to replace the text of the copied button var enumerable = recenterVRButton.GetComponents <TextMeshProUGUI>().Concat(recenterVRButton.GetComponentsInChildren <TextMeshProUGUI>()); foreach (var text in enumerable) { text.text = "Recenter VR"; } } }
// Use this for initialization public override void Awake() { // if we need to auto-configure Rift vs Vive vs (?) VR, we need // to do this before any other F3 setup, because MainCamera will change // and we are caching that in a lot of places... if (AutoConfigVR) { VRCameraRig = gs.VRPlatform.AutoConfigureVR(); } // restore any settings SceneGraphConfig.RestorePreferences(); // set up some defaults // this will move the ground plane down, but the bunnies will be floating... //SceneGraphConfig.InitialSceneTranslate = -4.0f * Vector3f.AxisY; SceneGraphConfig.DefaultSceneCurveVisualDegrees = 0.5f; SceneGraphConfig.DefaultPivotVisualDegrees = 1.5f; SceneGraphConfig.DefaultAxisGizmoVisualDegrees = 10.0f; SceneGraphConfig.InitialSceneTranslate = -4 * Vector3f.AxisY; SceneOptions options = new SceneOptions(); options.UseSystemMouseCursor = false; options.Use2DCockpit = false; options.EnableTransforms = true; options.EnableCockpit = true; options.CockpitInitializer = new PhotoToolCockpit(); options.MouseCameraControls = new MayaCameraHotkeys(); options.SpatialCameraRig = VRCameraRig; // very verbose options.LogLevel = 2; context = new FContext(); context.Start(options); // if you had other gizmos, you would register them here //context.TransformManager.RegisterGizmoType("snap_drag", new SnapDragGizmoBuilder()); //controller.TransformManager.SetActiveGizmoType("snap_drag"); // if you had other tools, you would register them here. context.ToolManager.RegisterToolType(DrawPrimitivesTool.Identifier, new DrawPrimitivesToolBuilder()); context.ToolManager.RegisterToolType(DrawSurfaceCurveTool.Identifier, new DrawSurfaceCurveToolBuilder() { AttachCurveToSurface = true, DefaultSamplingRateS = 0.0025f, DefaultSurfaceOffsetS = 0.0025f, CurveMaterialF = () => { var mat = context.Scene.DefaultCurveSOMaterial.Clone(); mat.RGBColor = Colorf.VideoRed; return(mat); } }); context.ToolManager.SetActiveToolType(DrawSurfaceCurveTool.Identifier, ToolSide.Right); // Set up standard scene lighting if requested if (options.EnableDefaultLighting) { GameObject lighting = GameObject.Find("SceneLighting"); if (lighting == null) { lighting = new GameObject("SceneLighting"); } SceneLightingSetup setup = lighting.AddComponent <SceneLightingSetup>(); setup.Context = context; setup.LightDistance = 30.0f; // related to total scene scale... } Context.Scene.DisableSelectionMaterial = true; /* * Import elements of Unity scene that already exist into the FScene */ // set up ground plane geometry (optional) GameObject groundPlane = GameObject.Find("GroundPlane"); if (groundPlane != null && groundPlane.IsVisible()) { context.Scene.AddWorldBoundsObject(groundPlane); } float fSquareSize = 1.0f; Vector3f eyePos = context.ActiveCamera.GetPosition(); System.Random rand = new System.Random(31337); // [RMS] this path only works in Editor, is relative to top-level project directory string sPhotoFolder = "Data\\PhotoSets\\kitchen"; string[] photos = Directory.GetFiles(sPhotoFolder); foreach (string filename in photos) { Texture2D tex = load_texture(filename); if (tex == null) { continue; } float fScale = fSquareSize / (float)tex.width; if (tex.height > tex.width) { fScale = fSquareSize / (float)tex.height; } float w = fScale * (float)tex.width; float h = fScale * (float)tex.height; TrivialRectGenerator rectgen = new TrivialRectGenerator() { Width = w, Height = h }; rectgen.Generate(); DMesh3 mesh = new DMesh3(MeshComponents.VertexUVs); rectgen.MakeMesh(mesh); SOMaterial material = new SOMaterial() { Name = "photomaterial", Type = SOMaterial.MaterialType.TextureMap, RGBColor = Colorf.White }; material.MainTexture = tex; DMeshSO so = new DMeshSO(); so.Create(mesh, material); context.Scene.AddSceneObject(so); float horz = rand.Next(-50, 50); float vert = rand.Next(-20, 25); int mult = 1000; float dist = (float)(rand.Next(2 * mult, 3 * mult)) / (float)mult; Ray3f r = VRUtil.MakeRayFromSphereCenter(horz, vert); r.Origin += eyePos; float fRayT = 0.0f; RayIntersection.Sphere(r.Origin, r.Direction, eyePos, dist, out fRayT); Vector3f v = r.Origin + fRayT * r.Direction; Frame3f f = new Frame3f(v, v.Normalized); Vector3f toEye = context.ActiveCamera.GetPosition() - f.Origin; toEye.Normalize(); f.AlignAxis(1, toEye); f.ConstrainedAlignAxis(2, Vector3f.AxisY, f.Y); so.SetLocalFrame(f, CoordSpace.WorldCoords); } }
// 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 Capture Update_TransformCamera(InputState input, CaptureData data) { // need both controllers to have valid positions if (input.bLeftControllerActive == false || input.bRightControllerActive == false) { return(Capture.Continue); } float fSceneScale = cockpit.Scene.GetSceneScale(); HandInfo hi = (HandInfo)data.custom_data; // deadzones and scaling factors const float fZoomDeadzoneInM = 0.1f; const float fZoomScale = 25.0f; const float fPanDeadzoneInM = 0.05f; const float fPanScale = 25.0f; const float fAzimuthDeadzoneInDeg = 10.0f; const float fAltitudeDeadzoneInDeg = 15.0f; const float fTrackAlpha = 0.1f; // larger == faster tracking // zoom is indicated by moving hands together/apart. But we want to get rid of // influence from other gestures (like rotate below) so we project to camera-right axis first. Frame3f camFrame = cockpit.ActiveCamera.GetWorldFrame(); Vector3 right = camFrame.X; float fOrig = Vector3.Dot((hi.rightStartF.Origin - hi.leftStartF.Origin), hi.camRight); float fCur = Vector3.Dot((input.RightHandFrame.Origin - input.LeftHandFrame.Origin), right); float deltaZAbs = fCur - fOrig; float deltaZ = (hi.bInZoomDeadzone) ? ApplyDeadzone(deltaZAbs, fZoomDeadzoneInM) : deltaZAbs - hi.fZoomShift; if (Math.Abs(deltaZ) > 0 && hi.bInZoomDeadzone) { hi.bInZoomDeadzone = false; hi.fZoomShift = deltaZAbs - deltaZ; } hi.runningZ = Mathf.Lerp(hi.runningZ, deltaZ, fTrackAlpha); float tz = hi.runningZ * fZoomScale; if (tz != 0.0f && hi.activeXForm == TransformType.NoTransform) { hi.activeXForm = TransformType.Zoom; } // translation is done by moving both hands in unison. We find the midpoint // of the start and current pairs, delta is translate Vector3f cOrig = 0.5f * (hi.leftStartF.Origin + hi.rightStartF.Origin); Vector3f cCur = 0.5f * (input.LeftHandFrame.Origin + input.RightHandFrame.Origin); Vector3f translateO = cCur - cOrig; Vector3f translate = (hi.bInPanDeadzone) ? ApplyDeadzone(translateO, fPanDeadzoneInM) : translateO - hi.vPanShift; if (translate.LengthSquared > 0 && hi.bInPanDeadzone) { hi.bInPanDeadzone = false; hi.vPanShift = translateO - translate; } hi.runningT = Vector3.Lerp(hi.runningT, translate, fTrackAlpha); Vector3f tx = hi.runningT * fPanScale * fSceneScale; if (tx.Length != 0.0f && hi.activeXForm == TransformType.NoTransform) { hi.activeXForm = TransformType.Pan; } // azimuth (left/right rotate) is specified by making a spin-the-wheel gesture, // where one hand slides forward and the other back. We guess a center-of-rotation // as the midpoint of the start and current frames, and then average the two rotation // angles in the XZ plane (by the vectors on the left and right sides). // *But* if there is also a translation, this goes wonky, so we have to subtract // of the translation first! // (above only applies if we permit simultaneous rotate & translate, which is currently disabled...) //Vector3 rotTranslate = translate; Vector3f rotTranslate = Vector3.zero; Vector3f origCenterXY = new Vector3(cOrig[0], 0, cOrig[2]); Vector3f shiftLeftO = input.LeftHandFrame.Origin - rotTranslate; Vector3f shiftRightO = input.RightHandFrame.Origin - rotTranslate; Vector3f shiftCenter = 0.5f * (shiftLeftO + shiftRightO); Vector3f curCenterXY = new Vector3(shiftCenter[0], 0, shiftCenter[2]); Vector3f sharedC = 0.5f * (origCenterXY + curCenterXY); float aLeft = VRUtil.PlaneAngleSigned(hi.leftStartF.Origin - sharedC, shiftLeftO - sharedC, 1); float aRight = VRUtil.PlaneAngleSigned(hi.rightStartF.Origin - sharedC, shiftRightO - sharedC, 1); float azO = -(aLeft + aRight) * 0.5f; float az = (hi.bInAzimuthDeadzone) ? ApplyDeadzone(azO, fAzimuthDeadzoneInDeg) : azO - hi.fAzimuthShift; if (Math.Abs(az) > 0 && hi.bInAzimuthDeadzone) { hi.bInAzimuthDeadzone = false; hi.fAzimuthShift = azO - az; } hi.runningAz = Mathf.Lerp(hi.runningAz, az, fTrackAlpha); float fAzimuth = hi.runningAz; if (fAzimuth != 0.0f && hi.activeXForm == TransformType.NoTransform) { hi.activeXForm = TransformType.Rotate; } // altitude (up/down rotate) is specified by tilting controllers up or down. // This is the trickiest one as hands tend to tilt up/down during the other actions. // We compute an average tilt up/down angle at the start, and then the per-hand delta // each frame, as well as the average delta, and use the smallest of these. // mean hand-tilt at start frame float o1 = VRUtil.PlaneAngleSigned(hi.leftStartF.Rotation * Vector3.forward, hi.camForward, hi.camRight); float o2 = VRUtil.PlaneAngleSigned(hi.rightStartF.Rotation * Vector3.forward, hi.camForward, hi.camRight); float oa = (o1 + o2) * 0.5f; // per-frame hand tilt Vector3 camfw = camFrame.Z, camright = camFrame.X; float c1 = VRUtil.PlaneAngleSigned(input.LeftHandFrame.Rotation * Vector3.forward, camfw, camright); float c2 = VRUtil.PlaneAngleSigned(input.RightHandFrame.Rotation * Vector3.forward, camfw, camright); // use the smallest per-hand tilt delta, to prevent one-hand tilting from having an effect float d1 = oa - c1, d2 = oa - c2; float altO = (Mathf.Abs(d1) < Mathf.Abs(d2)) ? d1 : d2; // also consider the average, to reduce crazy popping from each hand tilting in opposite direction float dm = 0.5f * (d1 + d2); altO = (Mathf.Abs(altO) < Mathf.Abs(dm)) ? altO : dm; // deadzone and smoothing float alt = (hi.bInAltitudeDeadzone) ? ApplyDeadzone(altO, fAltitudeDeadzoneInDeg) : altO - hi.fAltitudeShift; if (Math.Abs(alt) > 0 && hi.bInAltitudeDeadzone) { hi.bInAltitudeDeadzone = false; hi.fAltitudeShift = altO - alt; } hi.runningAlt = Mathf.Lerp(hi.runningAlt, alt, fTrackAlpha); float fAltitude = hi.runningAlt; if (fAltitude != 0.0f && hi.activeXForm == TransformType.NoTransform) { hi.activeXForm = TransformType.Rotate; } // reset view to state when we started, then apply the accumulated rotate/zoom/translate cockpit.ActiveCamera.Manipulator().SetCurrentSceneState(cockpit.Scene, hi.camState); if (hi.activeXForm == TransformType.Rotate) { cockpit.ActiveCamera.Manipulator().SceneOrbit(cockpit.Scene, cockpit.ActiveCamera, fAzimuth, fAltitude); } else if (hi.activeXForm == TransformType.Pan) { cockpit.ActiveCamera.Manipulator().SceneTranslate(cockpit.Scene, tx, false); } else if (hi.activeXForm == TransformType.Zoom) { cockpit.ActiveCamera.Manipulator().SceneZoom(cockpit.Scene, cockpit.ActiveCamera, tz); } return(Capture.Continue); }
public void UpdateTracking(Cockpit cockpit, fCamera camera) { fGameObject cockpitGO = cockpit.RootGameObject; if (!bInitialized) { currentFrame = cockpit.GetLevelViewFrame(CoordSpace.WorldCoords); currentFrame.ConstrainedAlignAxis(2, Vector3f.AxisZ, Vector3f.AxisY); bInitialized = true; } Vector3f vCamFW = camera.Forward(); vCamFW[1] = 0; vCamFW.Normalize(); // I don't think this is strictly necessary but // better to be safe for now... Vector3f vCamPos = camera.GetPosition(); //if (tracking_debug == null) // tracking_debug = UnityUtil.CreatePrimitiveGO("tracking_indicator", PrimitiveType.Sphere, MaterialUtil.CreateStandardMaterial(Color.green), false); //tracking_debug.transform.position = vCamPos + 15.0f * vCamFW; //if (tracking_avg == null) { // tracking_avg = UnityUtil.CreatePrimitiveGO("tracking_indicator", PrimitiveType.Sphere, MaterialUtil.CreateStandardMaterial(Color.blue), false); // tracking_avg.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); //} //tracking_avg.transform.position = vCamPos + 10.0f * vSlowViewDirTrack; //tracking_debug.SetVisible(false); //tracking_avg.SetVisible(false); if (vSlowViewDirTrack == Vector3f.Zero) { vSlowViewDirTrack = vCamFW; } float slowTrackSpeed = 0.05f; vSlowViewDirTrack = VRUtil.AngleLerp(vSlowViewDirTrack, vCamFW, slowTrackSpeed); // head position tracking if (IsLocked == false) { cockpitGO.SetPosition(vCamPos); } //Vector3 vDelta = (camera.transform.position - RootGameObject.transform.position); //if (vDelta.magnitude > 0.2f) // RootGameObject.transform.position = camera.transform.position; ////else if ( vDelta.magnitude > 0.05f) //else // RootGameObject.transform.position = // (1.0f - TrackingSpeed) * RootGameObject.transform.position + // (TrackingSpeed) * camera.transform.position; float RotationSpeed = 200.0f; float WarmupTrackingAngleThresh = 55.0f; float ImmediateTrackingAngleThresh = 65.0f; float StopTrackingAngleThresh = 5.0f; float TrackingWarmupDelay = 2.0f; float TrackingCooldownDelay = 0.75f; //Vector3 vCockpitFW = cockpitGO.transform.forward; Vector3f vCockpitFW = currentFrame.Z; float fSlowHDeviation = VRUtil.PlaneAngle(vCockpitFW, vSlowViewDirTrack); float fActualViewDeviation = VRUtil.PlaneAngle(vCockpitFW, vCamFW); bool bDoTrack = false; if (eState == TrackingState.NotTracking) { //tracking_debug.GetComponent<Renderer>().material = MaterialUtil.CreateStandardMaterial(Color.green); if (fSlowHDeviation > WarmupTrackingAngleThresh) { set_tracking_state(TrackingState.TrackingWarmup); stateChangeStartTime = FPlatform.RealTime(); } } else if (eState == TrackingState.TrackingWarmup) { //tracking_debug.GetComponent<Renderer>().material = MaterialUtil.CreateStandardMaterial(Color.yellow); if (fSlowHDeviation > ImmediateTrackingAngleThresh) { set_tracking_state(TrackingState.Tracking); } else if (fSlowHDeviation > WarmupTrackingAngleThresh) { if ((FPlatform.RealTime() - stateChangeStartTime) > TrackingWarmupDelay) { set_tracking_state(TrackingState.Tracking); } } else { set_tracking_state(TrackingState.NotTracking); } } else if (eState == TrackingState.Tracking) { bDoTrack = true; //tracking_debug.GetComponent<Renderer>().material = MaterialUtil.CreateStandardMaterial(Color.red); if (fActualViewDeviation < StopTrackingAngleThresh) { set_tracking_state(TrackingState.TrackingCooldown); stateChangeStartTime = FPlatform.RealTime(); } } else if (eState == TrackingState.TrackingCooldown) { bDoTrack = true; //tracking_debug.GetComponent<Renderer>().material = MaterialUtil.CreateStandardMaterial(Color.gray); if (fActualViewDeviation < StopTrackingAngleThresh) { if ((FPlatform.RealTime() - stateChangeStartTime) > TrackingCooldownDelay) { set_tracking_state(TrackingState.NotTracking); bDoTrack = false; } } else { set_tracking_state(TrackingState.Tracking); } } if (IsLocked) { bDoTrack = false; set_tracking_state(TrackingState.NotTracking); } if (bDoTrack) { float dt = (float)(FPlatform.RealTime() - animation_last_time); float fDelta = RotationSpeed * dt; Vector3f vCurrent = new Vector3f(vCockpitFW[0], 0, vCockpitFW[2]).Normalized; Vector3f vTarget = new Vector3f(vSlowViewDirTrack[0], 0, vSlowViewDirTrack[2]).Normalized; //Vector3 vTarget = new Vector3(vCamFW[0], 0, vCamFW[2]).normalized; Vector3f c = Vector3f.Cross(vCurrent, vTarget); float a = Vector3f.AngleD(vCurrent, vTarget); float fSign = (c[1] < 0) ? -1.0f : 1.0f; float fRotAngle = Math.Min(a, fDelta) * fSign; currentFrame.Rotate(Quaternionf.AxisAngleD(Vector3f.AxisY, fRotAngle)); } cockpitGO.SetRotation(currentFrame.Rotation); animation_last_time = FPlatform.RealTime(); if (indicator == null) { indicator = new CockpitTrackingWidget(); indicator.Create(this, cockpit); cockpit.AddUIElement(indicator, false); } indicator.EnableIndicator = show_indicator; }
public override Capture BeginCapture(InputState input, CaptureSide eSide) { if (input.LeftCaptureActive || input.RightCaptureActive || popup != null) { DebugUtil.Warning("SceneRightClickBehavior.BeginCapture - we should not be here..."); return(Capture.Ignore); } Ray3f useRay = new Ray3f(Vector3f.Zero, Vector3f.AxisY); if (input.IsForDevice(InputDevice.Mouse) || input.IsForDevice(InputDevice.Gamepad)) { useRay = (input.bRightMousePressed) ? input.vMouseWorldRay : input.vGamepadWorldRay; } else if (input.IsForDevice(InputDevice.AnySpatialDevice)) { useRay = (eSide == CaptureSide.Left) ? input.vLeftSpatialWorldRay : input.vRightSpatialWorldRay; } // raycast into scene to find hit object/position for menu. We try Pivots first, // because they are special and have priority (?? always ??). Then we cast into general scene. SORayHit pivotHit; bool bHitPivot = cockpit.Scene.FindSORayIntersection(useRay, out pivotHit, (x) => { return(x is PivotSO); }); AnyRayHit rayHit; if (bHitPivot) { rayHit = new AnyRayHit(pivotHit); } else { if (cockpit.Scene.FindSceneRayIntersection(useRay, out rayHit) == false) { return(Capture.Ignore); } } // find center of menu in space Vector3f vHUDCenter = cockpit.RootGameObject.GetPosition(); Vector3f menuLocation = rayHit.hitPos; if (Placement == PlacementMode.OnHUDSphere) { float fRayT; bool bHit = RayIntersection.Sphere(useRay.Origin, useRay.Direction, vHUDCenter, HUDRadius, out fRayT); Debug.Assert(bHit); menuLocation = useRay.Origin + fRayT * useRay.Direction; } // compute extents float fDiameter = VRUtil.GetVRRadiusForVisualAngle( menuLocation, cockpit.ActiveCamera.GetPosition(), VisualDiameter); if (rayHit.eType == HitType.SceneObjectHit && rayHit.hitSO is PivotSO) { popup = GeneratePivotRadialMenu(fDiameter, rayHit.hitSO as PivotSO); } else if (rayHit.eType == HitType.SceneObjectHit) { popup = GenerateSceneObjectRadialMenu(fDiameter, rayHit); } else { popup = GenerateDefaultRadialMenu(fDiameter, rayHit); } popup.Create(); popup.Name = "popup_menu"; if (Placement == PlacementMode.InScene) { HUDUtil.PlaceInScene(popup, vHUDCenter, menuLocation); } else { HUDUtil.PlaceInSphere(popup, HUDRadius, vHUDCenter, menuLocation); } // this is a bit of a hack...radial menu lives in-scene, if we attach it to // cockpit then it will move with cockpit, which is wrong. So we want to // stick it in the scene. But, at least for now, we still want it to be // drawn in the cockpit layer, so we add to cockpit first, them remove and // re-add to the scene cockpit.AddUIElement(popup, false); cockpit.RemoveUIElement(popup, false); cockpit.Scene.AddUIElement(popup, false); HUDUtil.AnimatedShow(popup, 0.2f); return(Capture.Begin(this, eSide)); }
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"); } }