コード例 #1
0
    // evaluates constraints in the given order in the list using lazy evaluation (so they should be ordered by
    // increasing evaluation cost)
    public override float EvaluateSatisfaction(CLCameraMan camera, float threshold)
    {
        if (!evaluated)
        {
            inScreenRatio = 1.0f;
            float currentSat    = 0.0f;
            float maxSat        = 1.0f;
            bool  lazyTriggered = false;
            int   weightIndex   = 0;

            foreach (CLVisualProperty f in this.properties)
            {
                currentSat   += f.EvaluateSatisfaction(camera) * weights[weightIndex];
                inScreenRatio = inScreenRatio * f.inScreenRatio;
                maxSat       -= weights [weightIndex++];
                if ((maxSat + currentSat) < threshold)
                {
                    lazyTriggered = true;
                    break;
                }
            }
            if (lazyTriggered)
            {
                currentSat = -1.0f;
            }

            evaluated    = true;
            satisfaction = currentSat;
        }

        return(satisfaction);
    }
コード例 #2
0
    /// <summary>
    /// Computes the screen size of the property target
    /// </summary>
    /// <returns>The value.</returns>
    /// <param name="camera">Camera.</param>
    public override float ComputeValue(CLCameraMan camera)
    {
        if (targets.Count == 1)           // one target, we report size with respect to the viewport
        {
            if (sizeType == SizeMode.AREA)
            {
                return(Mathf.Min(targets [0].screenArea, satFunction.domain.y));
            }

            if (sizeType == SizeMode.WIDTH)
            {
                return(Mathf.Min(targets [0].screenAABB.CalculateWidth(), satFunction.domain.y));
            }

            // else: height property
            return(Mathf.Min(targets [0].screenAABB.CalculateHeight(), satFunction.domain.y));
        }
        else             // there are two targets, we report size of first with respect to second
        {
            if (sizeType == SizeMode.AREA)
            {
                return(Mathf.Min(targets [0].screenArea / targets [1].screenArea, satFunction.domain.y));
            }

            if (sizeType == SizeMode.WIDTH)
            {
                return(Mathf.Min(targets [0].screenAABB.CalculateWidth() / targets [1].screenAABB.CalculateWidth(), satFunction.domain.y));
            }

            // else: height property
            return(Mathf.Min(targets [0].screenAABB.CalculateHeight() / targets [1].screenAABB.CalculateHeight(), satFunction.domain.y));
        }
    }
コード例 #3
0
    /// <summary>
    /// Computes the value of the property (depending on the actual mode)
    /// </summary>
    /// <returns>The value.</returns>
    /// <param name="camera">Camera.</param>
    public override float ComputeValue(CLCameraMan camera)
    {
        Vector3 viewTarget;
        // world target to camera
        Vector3 targetToCamera = (camera.unityCamera.transform.position - targets [0].boundingBox.center).normalized;
        // we must now convert it to

        float angle;

        if (orientation == OrientationMode.HORIZONTAL)
        {
            // retrieve local up vector for the target
            Vector3 up = targets [0].gameObject.transform.up.normalized;

            // up is the normal of the horizontal plane of the target
            // we project targetToCamera to the horizontal plane using
            // v1_projected = v1 - Dot(v1, n) * n;
            viewTarget = (targetToCamera - Vector3.Dot(targetToCamera, up) * up).normalized;

            angle = targets [0].ComputeAngleWith(viewTarget, TargetUtils.Axis.FORWARD);
        }
        else if (orientation == OrientationMode.VERTICAL)
        {
            viewTarget = targetToCamera;
            angle      = targets [0].ComputeAngleWith(viewTarget, TargetUtils.Axis.UP);
        }
        else              // orientation == OrientationMode.VERTICAL_WORLD)
        {
            viewTarget = targetToCamera;
            angle      = targets [0].ComputeAngleWith(viewTarget, TargetUtils.Axis.WORLD_UP);
        }

        return(Mathf.Min(angle, satFunction.domain.y));
    }
コード例 #4
0
    /// <summary>
    /// Evaluates the viewpoint using the provided camera man
    /// </summary>
    /// <returns>The viewpoint satisfaction in [0,1].</returns>
    /// <param name="camera">camera man object</param>
    public virtual float EvaluateViewpoint(CLCameraMan cameraman, bool setObjectiveFunction = false)
    {
        if (setObjectiveFunction)
        {
            cameraman.SetSpecification(properties);
            cameraman.UpdateTargets();
        }

        cameraman.unityCamera.transform.position = this.position;
        cameraman.unityCamera.transform.rotation = this.rotation;

        foreach (CLVisualProperty p in cameraman.properties)
        {
            p.evaluated = false;
        }
        foreach (CLTarget t in cameraman.targets)
        {
            t.rendered = false;
        }

        float result = properties[0].EvaluateSatisfaction(cameraman);

        satisfaction  = new List <float> ();
        inScreenRatio = new List <float> ();

        for (int i = 0; i < cameraman.properties.Count; i++)
        {
            satisfaction.Add(cameraman.properties [i].satisfaction);
            inScreenRatio.Add(cameraman.properties [i].inScreenRatio);
        }

        return(result);
    }
コード例 #5
0
    /// <summary>
    /// Computes how much screen representation is inside given rectangular frame
    /// </summary>
    /// <returns>The value.</returns>
    /// <param name="camera">Camera.</param>
    public override float ComputeValue(CLCameraMan camera)
    {
        // compute projection of target center
        Vector3 projectedCenter = camera.unityCamera.WorldToViewportPoint(targets[0].boundingBox.center);
        // compute distance from desidered point
        float distance = (position - new Vector2(projectedCenter[0], projectedCenter[1])).magnitude;

        return(Mathf.Min(distance, satFunction.domain.y));
    }
コード例 #6
0
    /// <summary>
    /// Generates a random viewpoint position that satisfies the property to some degree, with more probability where
    /// satisfaction is higher
    /// </summary>
    /// <returns>The random satisfying position.</returns>
    /// <param name="camera">Camera.</param>
    public override Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera)
    {
        Vector3 result = new Vector3();

        bool found = false;

        Vector2 minMaxDistance = new Vector2(0.1f, 1000f);           // just a placeholder; this method should not be used anymore

        int maxtries = 0;

        while (!found && maxtries < 30)
        {
            maxtries++;
            float x = satFunction.GenerateRandomXPoint();              // random angle
            //Debug.Log (x);
            //x = 0.0f;
            // generate random distance
            float distance = minMaxDistance.x + Random.value * (minMaxDistance.y - minMaxDistance.x);
            // generate random height
            float height = camera.ComputeRandomViewpoint(3)[1];
            if (orientation == OrientationMode.HORIZONTAL)
            {
                result.x = Mathf.Sin(Mathf.Deg2Rad * x) * distance;
                result.z = Mathf.Cos(Mathf.Deg2Rad * x) * distance;
                result   = targets [0].gameObject.transform.TransformPoint(result);
                result.y = height;
            }
            else                  // VERTICAL
                                  // generate a random theta in cilindrical coordinates
            {
                float theta = Random.value * 2 * Mathf.PI;
                float phi   = Mathf.Deg2Rad * x;

                // convert from spherical to cartesian
                result.x = Mathf.Sin(phi) * Mathf.Cos(theta) * distance;
                result.y = Mathf.Sin(phi) * Mathf.Sin(theta) * distance;
                result.z = Mathf.Cos(phi) * distance;

                result = targets [0].gameObject.transform.TransformPoint(result);
            }

            // if we are in problem bounds, ok - otherwise we throw away the point and generate a new one
            if (camera.InSearchSpace(new float[] { result.x, result.y, result.z }))
            {
                found = true;
            }
        }


        if (!found)
        {
            float[] randomCandidate = camera.ComputeRandomViewpoint(3);
            result = new Vector3(randomCandidate[0], randomCandidate[1], randomCandidate[2]);
        }

        return(result);
    }
コード例 #7
0
 public float EvaluateSatisfaction(CLCameraMan cameraMan, bool renderTargets, float threshold = -0.001f)
 {
     foreach (CLVisualProperty p in cameraMan.properties)
     {
         p.evaluated = false;
     }
     foreach (CLTarget t in targets)
     {
         t.rendered = false;
     }
     return(EvaluateSatisfaction(cameraMan, 0.001f));
 }
コード例 #8
0
    public override float EvaluateSatisfaction(CLCameraMan camera, float threshold)
    {
        if (!evaluated)
        {
            inScreenRatio = RenderTargets(camera);
            value         = this.ComputeValue(camera);
            satisfaction  = satFunction.ComputeSatisfaction(value) * inScreenRatio;
            evaluated     = true;
        }

        return(satisfaction);
    }
コード例 #9
0
    /// <summary>
    /// Computes how much the target is occluded by other objects by shooting rays and checking intersections with colliders
    /// </summary>
    public float ComputeOcclusion(CLCameraMan camera, bool frontBack = false, int _nRays = 0)
    {
        if (this.gameObject.layer == LayerMask.NameToLayer("Overlay"))
        {
            return(0.0f);
        }

        float          result = 0.0f;
        RaycastHit     hitFront;
        RaycastHit     hitBack;
        List <Vector3> points = new List <Vector3> ();
        int            n      = _nRays > 0? nRays: actualVisibilityPoints.Count;

        // now move all colliders to layer 2 (ignore ray cast)
        foreach (GameObject go in colliders)
        {
            go.layer = 2;
        }


        for (int i = 0; i < n; i++)
        {
            Vector3 p = actualVisibilityPoints[i];

            bool isOccludedFront = Physics.Linecast(camera.unityCamera.transform.position, p, out hitFront, layerMask);

            if (isOccludedFront)
            {
                result += 1.0f / n;
            }
            else if (frontBack)
            {
                bool isOccludedBack = Physics.Linecast(p, camera.unityCamera.transform.position, out hitBack, layerMask);
                if (isOccludedBack)
                {
                    result += 1.0f / n;
                }
            }
        }

        int j = 0;

        foreach (GameObject go in colliders)
        {
            go.layer = collidersLayers[j];
            j++;
        }

        return(Mathf.Min(result, 1.0f));
    }
コード例 #10
0
    // this is ok but it might not be necessary to render all targets once e.g. we know that one is off screen
    /// <summary>
    /// Renders the targets of the property
    /// </summary>
    /// <returns>The targets.</returns>
    /// <param name="camera">Camera from which to render</param>
    public float RenderTargets(CLCameraMan camera)
    {
        float inScreenRatio = 1.0f;

        foreach (CLTarget t in targets)
        {
            if (!t.rendered)
            {
                t.Render(camera);
                t.rendered = true;
            }
            inScreenRatio = t.screenRatio * inScreenRatio;
        }
        return(inScreenRatio);
    }
コード例 #11
0
    /// <summary>
    /// Computes the ratio between the area of the projected target inside frame, and the area inside viewport
    /// </summary>
    public float ComputeRatioInsideFrame(CLCameraMan camera, Rectangle frame)
    {
        if (this.screenArea < 0.00001)
        {
            // target is outside viewport or too small
            return(0.0f);
        }

        // clip screen representation by provided frame
        List <Vector2> partInFrame = new List <Vector2> (10);

        TargetUtils.Clip(frame, screenRepresentation, partInFrame);
        float framedArea = TargetUtils.ComputeScreenArea(partInFrame);

        return(framedArea / this.screenArea);
    }
コード例 #12
0
    /// <summary>
    /// Generates a random distance from the target with more probability where satisfaction is higher
    /// </summary>
    /// <returns>The random satisfying distance.</returns>
    /// <param name="camera">Camera.</param>
    public float GenerateRandomSatisfyingDistance(CLCameraMan camera)
    {
        float FOV, result;

        Vector2 yFOVrange = camera.cameraDomain.yFOVBounds;
        float   yFOV      = (yFOVrange [1] + yFOVrange [0]) / 2;   // required vertical FOV
        // AR is width/height
        float AR = camera.unityCamera.aspect;
        // we compute horizontal FOV
        float xFOV = AR * yFOV;

        if (sizeType == SizeMode.WIDTH)
        {
            FOV = xFOV;
        }
        else if (sizeType == SizeMode.HEIGHT)
        {
            FOV = yFOV;
        }
        else
        {
            // AREA property. We convert areas to radiuses, and use the min of the two FOVs
            FOV = Mathf.Min(xFOV, yFOV);
        }

        float bs_radius = targets [0].radius;
        float tmp       = 0.3f / Mathf.Tan(Mathf.Deg2Rad * FOV / 2);      // should be 0.5, but bs is bigger than AABB

        float randomSize = satFunction.GenerateRandomXPoint();

        // convert x, which is a size, to a distance from camera

        if (randomSize < 0.0001f)
        {
            randomSize = 0.0001f;             // to avoid computing an infinite distance.
        }
        if (sizeType == SizeMode.AREA)
        {
            // AREA property. We convert areas to radiuses, and use the average of the two FOVs
            randomSize = Mathf.Sqrt(randomSize / Mathf.PI);
        }

        result = (bs_radius / randomSize) * tmp;          // now x is a distance (instead of width, height or area)

        return(result);
    }
コード例 #13
0
    /// <summary>
    /// Generates a random viewpoint position that satisfies the property to some degree, with more probability where
    /// satisfaction is higher
    /// </summary>
    /// <returns>The random satisfying position.</returns>
    /// <param name="camera">Camera.</param>
    public override Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera)
    {
        Vector3 result = new Vector3();

        bool found = false;

        int maxtries = 0;

        while (!found && maxtries < 30)
        {
            maxtries++;
            float distance = GenerateRandomSatisfyingDistance(camera
                                                              );

            // check we are outside bs. we don't want to assign candidates inside bs.
            if (distance > targets [0].radius)
            {
                // generate random direction
                float inclination = (Mathf.PI) * Random.value;
                float azimuth     = Mathf.PI * 2 * Random.value;

                result.x = distance * Mathf.Sin(azimuth) * Mathf.Sin(inclination);
                result.y = distance * Mathf.Cos(inclination);
                result.z = distance * Mathf.Cos(azimuth) * Mathf.Sin(inclination);

                result = result + targets [0].boundingBox.center;

                if (camera.InSearchSpace(new float[] { result.x, result.y, result.z }))
                {
                    found = true;
                }
            }
        }

        if (!found)
        {
            float[] randomCandidate = camera.ComputeRandomViewpoint(3);
            result = new Vector3(randomCandidate[0], randomCandidate[1], randomCandidate[2]);
        }

        return(result);
    }
コード例 #14
0
    /// <summary>
    /// Computes the value of the property
    /// </summary>
    /// <returns>The value.</returns>
    /// <param name="camera">Camera.</param>
    public override float ComputeValue(CLCameraMan camera)
    {
        if (positionType == RelativePositionMode.LEFT)
        {
            return(targets [0].ComputeRatioInsideFrame(camera, new Rectangle(0.0f, targets [1].screenAABB.xMin, 0.0f, 1.0f)));
        }

        if (positionType == RelativePositionMode.BELOW)
        {
            return(targets [0].ComputeRatioInsideFrame(camera, new Rectangle(0.0f, 1.0f, 0.0f, targets [1].screenAABB.yMin)));
        }

        if (positionType == RelativePositionMode.RIGHT)
        {
            return(targets [0].ComputeRatioInsideFrame(camera, new Rectangle(targets [1].screenAABB.xMax, 1.0f, 0.0f, 1.0f)));
        }

        // else: ABOVE property
        return(targets [0].ComputeRatioInsideFrame(camera, new Rectangle(0.0f, 1.0f, targets [1].screenAABB.yMax, 1.0f)));
    }
コード例 #15
0
    //// <summary>
    /// Returns objective function value for the candidate, or -2 if candidate not in search space
    /// </summary>
    public float EvaluateSatisfaction(CLCameraMan evaluator, bool lazy)
    {
        // if we are not in search space there is no point evaluating the objective function
        if (!InSearchSpace(evaluator))
        {
            timesOutOfSearchSpace++;
            return(-2.0f);             // give penalty to out-of-bounds candidates
        }
        inSearchSpace = true;
        if (lazy)
        {
            evaluation = evaluator.EvaluateSatisfaction(position, bestEvaluation);
        }
        else
        {
            evaluation = evaluator.EvaluateSatisfaction(position, -0.001f);
        }

        return(evaluation);
    }
コード例 #16
0
    //// <summary>
    /// Returns the best found CLViewpoint given the allowed time in milliseconds,
    /// the required satisfaction threshold in [0,1], a CLCameraMan for evaluating a
    /// candidate satisfaction. If init is true, we start search from scratch, i.e. by
    /// first initializing candidates; otherwise, we use the current candidates
    /// </summary>
    public CLViewpoint SearchOptimal(float _timeLimit, float _satisfactionThreshold, CLCameraMan _evaluator, List <CLCandidate> initialCandidates, bool checkGeometry = false, bool init = true)
    {
        //if init, initialize n candidates ( with r_part candidates randomly initialized )
        beginTime   = Time.realtimeSinceStartup;
        elapsedTime = 0.0f;
        timeLimit   = _timeLimit / 1000.0f;

        if (init)
        {
            rnd                  = new System.Random();
            iterations           = 0;
            iterOfBest           = 0;
            this.evaluator       = _evaluator;
            this.maxSatisfaction = _satisfactionThreshold;
            globalBestViewpoints = new List <CLViewpoint> ();
            minSearchRange       = evaluator.GetMinCameraParameters(candidateDimension);
            maxSearchRange       = evaluator.GetMaxCameraParameters(candidateDimension);
            searchRanges         = evaluator.GetParametersRange(candidateDimension);
            averageRange         = 0.0f;
            for (int i = 0; i < candidateDimension; i++)
            {
                averageRange += searchRanges[i];
            }
            averageRange = averageRange / candidateDimension;
            InitializeCandidates(initialCandidates);
            InitSolverParameters(_timeLimit);
            elapsedTime = Time.realtimeSinceStartup - beginTime;
        }

        if (elapsedTime > timeLimit)
        {
            exitCondition = 0;
        }
        else
        {
            exitCondition = 2;
        }

        while (DoAnotherIteration())
        {
            iterations++;             // we start from 1

            //  execute loop body (dependent on method).
            exitCondition = ExecuteSearchIteration();
        }

        //elaborate results and return best solution (access to other solutions should be provided)

        // this is for handling the case where no optima have been found at all (e.g. not enough time)
        if (globalBestViewpoints.Count == 0)
        {
            CLViewpoint noSolution = new CLViewpoint();
            noSolution.satisfaction = new List <float>();
            noSolution.properties   = new List <CLVisualProperty> (evaluator.properties);
            foreach (CLVisualProperty p in noSolution.properties)
            {
                noSolution.satisfaction.Add(-1.0f);
            }
            noSolution.psoRepresentation = new float[] { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 60.0f };
            globalBestViewpoints.Add(noSolution);
        }

        // this returns only one solution !!!!
        return(globalBestViewpoints[globalBestViewpoints.Count - 1]);
    }
コード例 #17
0
 /// <summary>
 /// Computes the value of the property. In this case, a signed distance from the plane (positive if we are on the same side of the normal)
 /// </summary>
 /// <returns>The computed angle</returns>
 /// <param name="camera">Camera.</param>
 public override float ComputeValue(CLCameraMan camera)
 {
     return(referencePlane.GetDistanceToPoint(camera.unityCamera.transform.position));
 }
コード例 #18
0
    /// <summary>
    /// Given a desired on screen size (area, width, or height), computes camera distance, assuming the target is
    /// approximated by its bounding sphere, centered on the screen.
    /// </summary>
    /// <returns>the camera distance</returns>
    /// <param name="targetSize">Target size.</param>
    /// <param name="sizeMode">Size mode.</param>
    /// <param name="camera">Camera.</param>
    /// <param name="yFOV">yFOV, in degrees</param>
    public float ComputeDistanceFromSize(float targetSize, CLSizeProperty.SizeMode sizeMode, CLCameraMan camera, float yFOV)
    {
        // AR is width/height
        float AR = camera.unityCamera.aspect;
        // we compute horizontal FOV
        float yFOVRad = Mathf.Deg2Rad * yFOV;

        float projectedRadius = 1.0f;

        // now we need to compute distance from size
        if (sizeMode == CLSizeProperty.SizeMode.AREA)
        {
            // assuming viewport height is 1, area viewport is 1*AR. Our target area is therefore relative to targetSize*AR
            // projected radius should then be
            projectedRadius = Mathf.Sqrt(targetSize * AR / Mathf.PI);
        }
        else if (sizeMode == CLSizeProperty.SizeMode.HEIGHT)
        {
            // assuming viewport height is 1, our target height is correct (relative to 1). We need half height
            projectedRadius = 0.5f * targetSize;
        }
        else             // it is a width property

        // assuming viewport height is 1, our target width is relative to targetSize*AR
        {
            projectedRadius = 0.5f * targetSize * AR;
        }

        // this means, in world space, the distance from the center of the sphere to the top of the screen should be
        float halfscreen = radius * 0.5f / projectedRadius;

        // now solve with the usual trigonometry relation

        float distance = halfscreen / Mathf.Tan(yFOVRad / 2);

        return(distance);
    }
コード例 #19
0
 /// <summary>
 /// Check if candidate is in problem search space
 /// </summary>
 /// <returns><c>true</c>, if search space was ined, <c>false</c> otherwise.</returns>
 /// <param name="evaluator">CLCameraMan evaluator</param>
 /// <param name="checkGeometry">If set to <c>true</c> check geometry.</param>
 public bool InSearchSpace(CLCameraMan evaluator)
 {
     return(evaluator.InSearchSpace(position));
 }
コード例 #20
0
 /// <summary>
 /// Computes the property satisfaction.
 /// </summary>
 /// <returns>The satisfaction.</returns>
 /// <param name="cameraMan">Camera man.</param>
 /// <param name="threshold">Threshold for lazy evaluation. Defaults to non-lazy evaluation</param>
 public abstract float EvaluateSatisfaction(CLCameraMan cameraMan, float threshold = -0.001f);
コード例 #21
0
    // this method generates a random viewpoint with more probability where
    // target properties will be satisfied. It assumes we have at least a size
    // property for the target, plus optional angle and occlusion properties

    public Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera, bool considerVisibility = false)
    {
        Vector3 result = new Vector3();

        bool found = false;

        int ntries = 0;

        float yFOV = (camera.cameraDomain.yFOVBounds [0] + camera.cameraDomain.yFOVBounds [1]) / 2;

        // we allow for 30 tries before giving up
        while (ntries < 30 && !found)
        {
            float distance = 0.0f;
            float phi      = 0.0f;
            float theta    = 0.0f;

            foreach (CLGroundProperty p in groundProperties)
            {
                if (p is CLSizeProperty)
                {
                    CLSizeProperty sp = (CLSizeProperty)p;

                    // this returns a random area, or width, or height, depending on the type of size
                    // property, with more probability where the satisfaction is higher
                    float randomSize = p.satFunction.GenerateRandomXPoint();
                    if (randomSize < 0.0001f)
                    {
                        randomSize = 0.0001f;                         // to avoid computing an infinite distance.
                    }
                    // compute distance from target size
                    distance = ComputeDistanceFromSize(randomSize, sp.sizeType, camera, yFOV);
                }

                if (p is CLOrientationProperty)
                {
                    CLOrientationProperty op = (CLOrientationProperty)p;

                    if (op.orientation == CLOrientationProperty.OrientationMode.HORIZONTAL)
                    {
                        phi = Mathf.Deg2Rad * op.satFunction.GenerateRandomXPoint();                          // horizontal random angle
                    }
                    else
                    {
                        theta = Mathf.Deg2Rad * op.satFunction.GenerateRandomXPoint();                          // vertical random angle
                    }
                }
            }

            // if we are not inside bs sphere
            if (distance > radius)
            {
                result = ComputeWorldPosFromSphericalCoordinates(distance, phi, theta);


                if (camera.InSearchSpace(new float[] { result.x, result.y, result.z }))
                {
                    found = true;
                }
            }

            ntries++;
        }


        if (!found)
        {
            float[] randomCandidate = camera.cameraDomain.ComputeRandomViewpoint(3);
            result = new Vector3(randomCandidate [0], randomCandidate [1], randomCandidate [2]);
            //Debug.Log ("random candidate");
        }
        else
        {
            //Debug.Log ("smart candidate in " + ntries + " tries");
        }

        return(result);
    }
コード例 #22
0
    /// <summary>
    /// Computes and internally stores a screen representation of the target given the current camera. The screen
    /// representation is in turn used to reason about properties like size, framing, ...
    /// </summary>
    /// <param name="currentCamera">camera from which rendering is performed</param>
    /// <param name="performClipping">if true, we clip against the viewport. If not, screenArea can </param>
    public void Render(CLCameraMan camera, bool performClipping = true)
    {
        screenRepresentation.Clear();
        visibleBBVertices.Clear();

        /**
         *   ok, so ... using the world-space AABB of the game object is not ideal because it appears it is the world AABB
         *   of the world-transformed local AABB of the mesh, see http://answers.unity3d.com/questions/292874/renderer-bounds.html
         *   Also, using the AABB of the colliderMesh does not help (it appears to be identical to the renderer AABB)
         *
         *   Could transform the camera to local space and use the AABB of the mesh ...
         */

        // world position of the camera
        Vector3 eye = camera.unityCamera.transform.position;

        Bounds AABB = boundingBox;

        // World-space min-max corners of the target's AABB
        Vector3 minCorner = AABB.min;
        Vector3 maxCorner = AABB.max;

        /** Calculate bit-string position to perform lookup in the table, real
         * spatial relationship is not relevant, the relevant information is the
         * vertex ordering */
        int pos = ((eye.x < minCorner.x ? 1 : 0) << (int)TargetUtils.RelativePositioning.LEFT)
                  + ((eye.x > maxCorner.x ? 1 : 0) << (int)TargetUtils.RelativePositioning.RIGHT)
                  + ((eye.y < minCorner.y ? 1 : 0) << (int)TargetUtils.RelativePositioning.BOTTOM)
                  + ((eye.y > maxCorner.y ? 1 : 0) << (int)TargetUtils.RelativePositioning.TOP)
                  + ((eye.z < minCorner.z ? 1 : 0) << (int)TargetUtils.RelativePositioning.FRONT)
                  + ((eye.z > maxCorner.z ? 1 : 0) << (int)TargetUtils.RelativePositioning.BACK);

        // If camera inside bounding box return 0
        numVisibleBBVertices = TargetUtils.Number(pos);
        if (numVisibleBBVertices == 0)
        {
            this.screenArea = 0.0f;
            screenAABB      = new Rectangle(0.0f, 0.0f, 0.0f, 0.0f);
            screenRatio     = 0.0f;
            return;
        }

        // Otherwise project vertices on screen
        // Array for storing projected vertices
        List <Vector2> projectedBBVertices = new List <Vector2> (10);

        bool behindCamera = false;

        // project each visibile vertex
        for (int i = 0; i < numVisibleBBVertices; i++)
        {
            Vector3 visibleVertex   = TargetUtils.ReturnAABBVertex(TargetUtils.Vertex(i, pos), AABB);
            Vector3 projectedVertex = camera.unityCamera.WorldToViewportPoint(visibleVertex);
            if (projectedVertex.z >= 0)
            {
                projectedBBVertices.Add(projectedVertex);
                visibleBBVertices.Add(visibleVertex);
                //Debug.Log ( newPoint.ToString("F5"));
            }
            else
            {
                behindCamera = true;
            }
        }

        // clip them by viewport

        if (performClipping)
        {
            TargetUtils.Clip(camera.clipRectangle, projectedBBVertices, screenRepresentation);
        }

        // if there are less than three vertices on screen, area is zero
        if (screenRepresentation.Count < 3)
        {
            this.screenArea = 0;
            screenAABB      = new Rectangle(0.0f, 0.0f, 0.0f, 0.0f);
            screenRatio     = 0.0f;
        }
        else
        {
            // compute area
            this.screenArea = Mathf.Min(TargetUtils.ComputeScreenArea(screenRepresentation), 1.0f);

            // compute min and max vertices
            Vector2 minPoint = screenRepresentation [0];
            Vector2 maxPoint = screenRepresentation [1];


            for (int i = 0; i < screenRepresentation.Count; i++)
            {
                if (minPoint.x > screenRepresentation [i].x)
                {
                    minPoint.x = screenRepresentation [i].x;
                }
                if (minPoint.y > screenRepresentation [i].y)
                {
                    minPoint.y = screenRepresentation [i].y;
                }
                if (maxPoint.x < screenRepresentation [i].x)
                {
                    maxPoint.x = screenRepresentation [i].x;
                }
                if (maxPoint.y < screenRepresentation [i].y)
                {
                    maxPoint.y = screenRepresentation [i].y;
                }
            }

            screenAABB = new Rectangle(minPoint.x, maxPoint.x, minPoint.y, maxPoint.y);

            if (!behindCamera)
            {
                screenRatio = this.screenArea / TargetUtils.ComputeScreenArea(projectedBBVertices);
            }
            else
            {
                screenRatio = 0.5f;                  // this is just a hack since otherwise bb projected points behind camera
            }
            // are simply thrown away and the target, while partially on screen,
            // could be considered entirely on screen

            if (screenRatio > 1.0f && performClipping)
            {
                screenRatio = 0.0f;
            }
            else if (screenRatio > 1.0f)
            {
                // this means we have no clipping and the projected AABB is greater than the viewport
                screenRatio = 1.0f;
            }
        }
    }
コード例 #23
0
 /// <summary>
 /// Generates a random viewpoint position that satisfies the property to some degree, with more probability where satisfaction is higher
 /// </summary>
 /// <returns>The random satisfying position.</returns>
 /// <param name="camera">Camera.</param>
 public abstract Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera);
コード例 #24
0
 /// <summary>
 /// Computes how much screen representation is inside given rectangular frame
 /// </summary>
 /// <returns>The value.</returns>
 /// <param name="camera">Camera.</param>
 public override float ComputeValue(CLCameraMan camera)
 {
     return(Mathf.Min(targets [0].ComputeRatioInsideFrame(camera, frame), satFunction.domain.y));
 }
コード例 #25
0
 /// <summary>
 /// Generates a random viewpoint position that satisfies the property to some degree, with more probability where
 /// satisfaction is higher
 /// </summary>
 /// <returns>The random satisfying position.</returns>
 /// <param name="camera">Camera.</param>
 public override Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera)
 {
     return(new Vector3(0.0f, 0.0f, 0.0f));
 }
コード例 #26
0
 /// <summary>
 /// Computes the degree of occlusion
 /// </summary>
 /// <returns>The value.</returns>
 /// <param name="camera">Camera.</param>
 public override float ComputeValue(CLCameraMan camera)
 {
     return(Mathf.Min(targets [0].ComputeOcclusion(camera, frontBack), satFunction.domain.y));
 }
コード例 #27
0
 /// <summary>
 /// Computes the value of the property. In this case, the YFOV of the provided camera
 /// </summary>
 /// <returns>The computed angle</returns>
 /// <param name="camera">Camera.</param>
 public override float ComputeValue(CLCameraMan camera)
 {
     return(Mathf.Min(camera.unityCamera.fieldOfView, satFunction.domain.y));
 }
コード例 #28
0
    /// <summary>
    /// Computes the value of the property. In this case, the angle between the provided reference camera rotation, and the rotation of the camera
    /// </summary>
    /// <returns>The computed angle</returns>
    /// <param name="camera">Camera.</param>
    public override float ComputeValue(CLCameraMan camera)
    {
        bool result = Physics.Linecast(point, camera.unityCamera.transform.position, layerMask);

        return(result ? 0.0f : 1.0f);
    }
コード例 #29
0
 /// <summary>
 /// Computes the value of the property. In this case, the distance between the camera and the reference position
 /// </summary>
 /// <returns>The computed angle</returns>
 /// <param name="camera">Camera.</param>
 public override float ComputeValue(CLCameraMan camera)
 {
     return(Vector3.Distance(referencePosition, camera.unityCamera.transform.position));
 }
コード例 #30
0
 /// <summary>
 /// Computes the value of the property. In this case, the angle between the provided reference camera rotation, and the rotation of the camera
 /// </summary>
 /// <returns>The computed angle</returns>
 /// <param name="camera">Camera.</param>
 public override float ComputeValue(CLCameraMan camera)
 {
     return(Quaternion.Angle(referenceCameraOrientation, camera.unityCamera.transform.rotation));
 }