Example #1
0
        // same as LocalFrame, but LocalFrame may be tilted up/down, which we want to undo
        public virtual Frame3f GetLevelViewFrame(CoordSpace eSpace)
        {
            // otherwise we can't just set y to 0...
            Debug.Assert(eSpace == CoordSpace.WorldCoords);
            Frame3f viewF  = UnityUtil.GetGameObjectFrame(ActiveCamera.GameObject(), eSpace);
            float   fAngle = VRUtil.PlaneAngleSigned(Vector3f.AxisZ, viewF.Z, 1);

            return(new Frame3f(viewF.Origin, Quaternionf.AxisAngleD(Vector3f.AxisY, fAngle)));
        }
Example #2
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);
        }