示例#1
0
        // try to compute a stable ray/plane intersection. when origin is at < +/- an altitude threshold,
        // use ray/line distance with view-perp line, instead of actual intersection
        public static Vector3f SafeRayPlaneIntersection(Ray3f ray, Vector3f forwardDir,
                                                        Vector3f planeOrigin, Vector3f planeNormal, float fAngleThresh = 10.0f)
        {
            // determine if we are in unstable condition
            float fOriginAngleDeg = (float)Math.Abs(
                planeNormal.AngleD((planeOrigin - ray.Origin).Normalized));
            bool bOriginUnstable = Math.Abs(fOriginAngleDeg - 90.0f) < fAngleThresh;

            // we use ray/plane intersect if stable
            Frame3f  planeF   = new Frame3f(planeOrigin, planeNormal);
            Vector3f planeHit = planeF.RayPlaneIntersection(ray.Origin, ray.Direction, 2);

            if (bOriginUnstable == false)
            {
                return(planeHit);
            }

            // if unstable, find "right" direction in plane (ie perp to forward dir, which
            //  may just be ray dir), then intersection is ray/axis closest point
            Vector3f fwDirInPlane   = (forwardDir - planeNormal.Dot(forwardDir)).Normalized;
            Vector3f perpDirInPlane = Quaternionf.AxisAngleD(planeNormal, 90.0f) * fwDirInPlane;
            float    fAxisDist      = (float)DistLine3Ray3.MinDistanceLineParam(ray, new Line3d(planeOrigin, perpDirInPlane));

            return(planeOrigin + fAxisDist * perpDirInPlane);
        }
示例#2
0
 public static float PlaneAngle(Vector3f a, Vector3f b, int nPlaneNormalIdx = 1)
 {
     a[nPlaneNormalIdx] = b[nPlaneNormalIdx] = 0.0f;
     a.Normalize();
     b.Normalize();
     return(Vector3f.AngleD(a, b));
 }
示例#3
0
        public static float PlaneAngleSigned(Vector3f vFrom, Vector3f vTo, int nPlaneNormalIdx = 1)
        {
            vFrom[nPlaneNormalIdx] = vTo[nPlaneNormalIdx] = 0.0f;
            vFrom.Normalize();
            vTo.Normalize();
            float fSign  = Math.Sign(Vector3f.Cross(vFrom, vTo)[nPlaneNormalIdx]);
            float fAngle = fSign * Vector3f.AngleD(vFrom, vTo);

            return(fAngle);
        }
示例#4
0
        public static float PlaneAngleSigned(Vector3f vFrom, Vector3f vTo, Vector3f planeN)
        {
            vFrom = vFrom - Vector3f.Dot(vFrom, planeN) * planeN;
            vTo   = vTo - Vector3f.Dot(vTo, planeN) * planeN;
            vFrom.Normalize();
            vTo.Normalize();
            Vector3f c      = Vector3f.Cross(vFrom, vTo);
            float    fSign  = Math.Sign(Vector3f.Dot(c, planeN));
            float    fAngle = fSign * Vector3f.AngleD(vFrom, vTo);

            return(fAngle);
        }
示例#5
0
        //   we orbit view to be level, then again so that the normal of the hit point points towards
        //   the camera. Then we pull back along that direction. Unless we want to face away,
        //   then we rotate an extra 180 degrees, and set the target out by the pullback distance
        static public void Teleport_LevelNormalOffset(fCamera camera, FScene scene,
                                                      Vector3f targetPoint, Vector3f targetNormal, float fPullback, bool bFaceAwayFromSurface = false)
        {
            fPullback *= scene.GetSceneScale();

            Vector3f vCurCamFW    = camera.GetWorldFrame().Z;
            Vector3f vCurCamFWXZ  = new Vector3f(vCurCamFW[0], 0.0f, vCurCamFW[2]).Normalized;
            Vector3f vHitNormalXZ = new Vector3f(targetNormal[0], 0.0f, targetNormal[2]).Normalized;

            float fFace   = bFaceAwayFromSurface ? -1.0f : 1.0f;
            float fRotate = Vector3f.AngleD(-vCurCamFWXZ, fFace * vHitNormalXZ);
            float fSign   = Vector3f.Cross(vCurCamFWXZ, fFace * vHitNormalXZ)[1] > 0 ? -1 : 1;

            fRotate *= fSign;
            // now we use cam instead of normal here because we rotated normal to face cam!
            Vector3f vNewCamPos    = targetPoint - fFace * fPullback * vCurCamFWXZ;
            Vector3f vNewTargetPos = (bFaceAwayFromSurface) ? vNewCamPos + fPullback * vCurCamFWXZ : targetPoint;

            camera.Animator().Teleport_Level(vNewCamPos, vNewTargetPos, targetPoint, fRotate);
        }
示例#6
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;
        }