Exemplo n.º 1
0
            public static DistanceSet GetDistanceToCamera(ushort lensIndex, Bounds targetBounds, FramingParameters framingParameters)
            {
                var   distanceSet = new DistanceSet();
                float frustumHeight;
                //find vertical field of view for given lens
                float vFov = ElPresidente.Instance.lensFovData[lensIndex]._unityVFOV * Mathf.Deg2Rad;

                frustumHeight   = getFrustumHeight(framingParameters.MinPercent, targetBounds);
                distanceSet.min = getDistanceForHeight(frustumHeight, vFov);

                frustumHeight   = getFrustumHeight(framingParameters.MaxPercent, targetBounds);
                distanceSet.max = getDistanceForHeight(frustumHeight, vFov);

                frustumHeight     = getFrustumHeight(framingParameters.TargetPercent, targetBounds);
                distanceSet.ideal = getDistanceForHeight(frustumHeight, vFov);

                return(distanceSet);
            }
Exemplo n.º 2
0
        private bool findCameraPositionByRadius(GameObject framingTarget, Bounds targetBounds, FramingParameters framingParameters,
                                                ushort lensIndex, float maxHorizontalSearchPercent, out CameraPositionAndLens result)
        {
            //if the badness is low, get on with life
            float BADNESS_THRESHOLD = 0.15f;

            result = new CameraPositionAndLens()
            {
                LensIndex = lensIndex,
                Badness   = float.MaxValue,
                Position  = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue)
            };

            bool subjectVisible = false;

            //find min,max,ideal camera distance for this lens
            var distanceToCamera = DistanceSet.GetDistanceToCamera(lensIndex, targetBounds, framingParameters);

            //search and track best match

            float  horizontalSearchSign         = 1;
            float  horizontalSearchStepSize     = 5f * Mathf.Deg2Rad;
            ushort horizontalSearchIterations   = 0;
            float  horizontalSearchAngleCurrent = 0;
            //bool verticalSearchSign = true; only searching up atm
            float  verticalSearchStepSize      = 1.5f * Mathf.Deg2Rad;
            ushort verticalSearchIterations    = 0;
            ushort verticalSearchIterationsMax = 10;
            float  verticalSearchAngleInitial  = (cameraAngle == null ? 0f : CameraActionFactory.angles[cameraAngle.AngleSetting]) * Mathf.Deg2Rad;

            RaycastHit hit;

            while (!subjectVisible)//search over the range about ideal position
            {
                horizontalSearchIterations++;

                //reset vertical angle to default/specified
                float verticalSearchAngleCurrent = verticalSearchAngleInitial;
                verticalSearchIterations = 0;
                while (!subjectVisible && verticalSearchIterations < verticalSearchIterationsMax)
                {
                    //find normalized direction vector given "direction" and angle measure
                    float   subjectToCameraHeading = getBaseCameraHeading(direction, framingTarget);
                    Vector3 subjectToCamera        = get3DDirection(framingTarget,
                                                                    new Vector3(verticalSearchAngleCurrent, horizontalSearchAngleCurrent),
                                                                    subjectToCameraHeading);

                    //raycast to check for LoS
                    Debug.DrawRay(targetLookAtPoint, subjectToCamera, Color.magenta, 10);
                    if (Physics.Raycast(targetLookAtPoint, subjectToCamera, out hit))
                    {
                        Opacity opacity = Opacity.High;
                        if (hit.collider.gameObject.name == "Terrain" && hit.point.y > 0.26f) //below a certain height, we expect ground.  this only works while we have flatness
                        {
                            opacity = getTreeOpacity(hit.point);
                        }

                        //if we get a hit, we will have to put the camera between the hit object and the
                        //subject.  again we are ignoring the range of valid sizes.  we should use
                        //min/max as stdev guidelines for "goodness" distribution

                        //find distance to hit point from subject
                        var distToHit = (targetLookAtPoint - hit.point).magnitude;

                        //if the object we hit is closer than our min camera distance for the framing,
                        //we need to check if it is least bad option so far
                        if (distToHit < distanceToCamera.ideal && opacity > Opacity.Medium)
                        {
                            float badness = Mathf.Abs(verticalSearchAngleCurrent - verticalSearchAngleInitial) +
                                            Mathf.Abs(horizontalSearchAngleCurrent) +
                                            Mathf.Abs((distanceToCamera.ideal - distToHit) / distanceToCamera.ideal);
                            if (badness < result.Badness) //update result with new position
                            {
                                result.Badness = badness;
                                //adjust position slightly off intercepted collider toward the subject
                                var cameraToSubjectOffset = (targetLookAtPoint - hit.point).normalized * 0.1f;
                                result.Position = hit.point + cameraToSubjectOffset;
                            }
                        }
                        else
                        {
                            float badness = Mathf.Abs(verticalSearchAngleCurrent - verticalSearchAngleInitial) + getOpacityBadness(opacity);
                            if (badness < result.Badness) //update result with new position
                            {
                                result.Badness  = badness;
                                result.Position = targetLookAtPoint + subjectToCamera * distanceToCamera.ideal;
                            }
                        }
                    }
                    else //if we get no hit, there is nothing that can occlude the camera position
                    {
                        //place camera at ideal distance along subjectToCamera vector
                        float badness = verticalSearchAngleCurrent + horizontalSearchAngleCurrent;
                        if (badness < result.Badness) //update result with new position
                        {
                            result.Badness  = badness;
                            result.Position = targetLookAtPoint + subjectToCamera * distanceToCamera.ideal;
                        }
                    }
                    if (result.Badness < BADNESS_THRESHOLD)
                    {
                        subjectVisible = true;
                        break;
                    }
                    //unless we find a very close match and break out of this loop, we will update the search angles
                    verticalSearchAngleCurrent += verticalSearchStepSize;
                    verticalSearchIterations++;
                }
                if (!subjectVisible)//search around the circle
                {
                    horizontalSearchSign         = -horizontalSearchSign;
                    horizontalSearchAngleCurrent = horizontalSearchSign * horizontalSearchIterations * horizontalSearchStepSize;

                    if (Mathf.Abs(horizontalSearchAngleCurrent) > 1.8 * maxHorizontalSearchPercent) //have we gone more than the allotted amount around the circle?
                    {
                        break;
                    }
                }
            }
            return(subjectVisible);
        }