예제 #1
0
        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);
        }
예제 #2
0
        // 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));
            }
        }
예제 #3
0
            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;
            }
예제 #4
0
        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";
         }
     }
 }
예제 #6
0
        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);
        }
예제 #7
0
        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));
        }
예제 #8
0
 //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";
         }
     }
 }
예제 #9
0
        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);
        }
    }
예제 #12
0
        // 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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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;
        }
예제 #15
0
        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));
        }
예제 #16
0
        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");
            }
        }