Exemple #1
0
 public UniversalTarget()
 {
     displayName      = "Universal";
     m_SubTargets     = TargetUtils.GetSubTargets(this);
     m_SubTargetNames = m_SubTargets.Select(x => x.displayName).ToList();
     TargetUtils.ProcessSubTargetList(ref m_ActiveSubTarget, ref m_SubTargets);
 }
Exemple #2
0
 public BuiltInTarget()
 {
     displayName      = "Built-In";
     m_SubTargets     = TargetUtils.GetSubTargets(this);
     m_SubTargetNames = m_SubTargets.Select(x => x.displayName).ToList();
     TargetUtils.ProcessSubTargetList(ref m_ActiveSubTarget, ref m_SubTargets);
 }
    public override float GenerateRandomXPoint()
    {
        float Y_point = UnityEngine.Random.Range(0.0f, cumulativeSatYPoints [cumulativeSatYPoints.Count - 1]);

        // computes the value x such that cumulative_sat(x) = Y_point.
        return(TargetUtils.LinearSpline(Y_point, cumulativeSatYPoints, cumulativeSatXPoints));
    }
    /// <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);
    }
Exemple #5
0
 public UniversalTarget()
 {
     displayName  = "Universal";
     m_SubTargets = TargetUtils.GetSubTargetsOfType <UniversalTarget>();
 }
 /// <summary>
 /// Computes the satisfaction in [0,1], given a value
 /// </summary>
 /// <returns>The satisfaction.</returns>
 /// <param name="value">Value.</param>
 public override float ComputeSatisfaction(float value)
 {
     return(TargetUtils.LinearSpline(value, satXPoints, satYPoints));
 }
    /// <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;
            }
        }
    }
    /// <summary>
    /// Precomputes a number of visibility points inside the target BB, to be used later for visibility checking.
    /// Visibility points are generated according to the chosen method (value of visibilityPointGeneration member)
    /// We generate 50 visibility points (this could be a parameter ...)
    /// </summary>
    /// <param name="standingOnGround">If set to <c>true</c> standing on ground.</param>
    private void PreComputeVisibilityPoints(bool standingOnGround, int numberofPoints = 50)
    {
        visibilityPoints = new List <Vector3> (numberofPoints);


        switch (visibilityPointGeneration)
        {
        case VisibilityPointGenerationMethod.ON_MESH:
        {
            // remove everything in scene except target (it should be enough to simply move the target to a special layer)

            foreach (GameObject go in colliders)
            {
                go.layer = LayerMask.NameToLayer("CameraControl");
            }

            // find target center, and proper distance such that target is entirely on screen from every angle
            float d = radius / Mathf.Tan(50.0f);                      // supposing a h-fow of 100

            // compute n points on unit sphere
            List <Vector3> samples = TargetUtils.ComputePointsOnSphere(numberofPoints, boundingBox.center, radius);

            // for visibility: cast 1 ray from each point to center, save point of intersection
            foreach (Vector3 point in samples)
            {
                RaycastHit hitPoint;
                bool       hit = Physics.Linecast(point, boundingBox.center, out hitPoint, 1 << LayerMask.NameToLayer("CameraControl"));

                if (hit)
                {
                    visibilityPoints.Add(hitPoint.point);
                }
            }



            break;
        }

        case VisibilityPointGenerationMethod.UNIFORM_IN_BB:
        {
            // We take the AABB, and choose a number of points inside it . For simplicity, we allow only an odd number of rays.
            // For more than 9 points, we move to random generation

            visibilityPoints.Add(boundingBox.center);

            if (numberofPoints > 1 && numberofPoints < 10)                        // add two points along the longest dimension of the AABB

            {
                float[] extents = new float[] { boundingBox.extents.x, boundingBox.extents.y, boundingBox.extents.z };
                int[]   indices = new int[] { 0, 1, 2 };
                Array.Sort(extents, indices);
                int longest       = indices [2];
                int secondLongest = indices [1];
                int shortest      = indices [0];

                Vector3 p1 = boundingBox.center;
                p1 [longest] = 0.25f * boundingBox.min [longest] + 0.75f * boundingBox.max [longest];

                Vector3 p2 = boundingBox.center;
                p2 [longest] = 0.75f * boundingBox.min [longest] + 0.25f * boundingBox.max [longest];

                if (numberofPoints > 3)
                {
                    Vector3 p3 = boundingBox.center;
                    p3 [secondLongest] = 0.75f * boundingBox.min [secondLongest] + 0.25f * boundingBox.max [secondLongest];

                    Vector3 p4 = boundingBox.center;
                    p4 [secondLongest] = 0.25f * boundingBox.min [secondLongest] + 0.75f * boundingBox.max [secondLongest];

                    if (numberofPoints > 5)
                    {
                        p1 [secondLongest] = 0.25f * boundingBox.min [secondLongest] + 0.75f * boundingBox.max [secondLongest];
                        p1 [shortest]      = 0.25f * boundingBox.min [shortest] + 0.75f * boundingBox.max [shortest];

                        p2 [secondLongest] = 0.25f * boundingBox.min [secondLongest] + 0.75f * boundingBox.max [secondLongest];
                        p2 [shortest]      = 0.25f * boundingBox.min [shortest] + 0.75f * boundingBox.max [shortest];

                        p3 [shortest] = 0.25f * boundingBox.min [shortest] + 0.75f * boundingBox.max [shortest];

                        p4 [shortest] = 0.75f * boundingBox.min [shortest] + 0.25f * boundingBox.max [shortest];

                        Vector3 p5 = boundingBox.center;
                        p5 [longest]       = 0.25f * boundingBox.min [longest] + 0.75f * boundingBox.max [longest];
                        p5 [secondLongest] = 0.75f * boundingBox.min [secondLongest] + 0.25f * boundingBox.max [secondLongest];
                        p5 [shortest]      = 0.75f * boundingBox.min [shortest] + 0.25f * boundingBox.max [shortest];

                        Vector3 p6 = boundingBox.center;
                        p6 [longest]       = 0.75f * boundingBox.min [longest] + 0.25f * boundingBox.max [longest];
                        p6 [secondLongest] = 0.75f * boundingBox.min [secondLongest] + 0.25f * boundingBox.max [secondLongest];
                        p6 [shortest]      = 0.75f * boundingBox.min [shortest] + 0.25f * boundingBox.max [shortest];

                        if (numberofPoints == 9)
                        {
                            p3 [longest] = 0.75f * boundingBox.min [longest] + 0.25f * boundingBox.max [longest];

                            p4 [longest] = 0.25f * boundingBox.min [longest] + 0.75f * boundingBox.max [longest];

                            Vector3 p7 = boundingBox.center;
                            p7 [longest]       = 0.25f * boundingBox.min [longest] + 0.75f * boundingBox.max [longest];
                            p7 [secondLongest] = 0.75f * boundingBox.min [secondLongest] + 0.25f * boundingBox.max [secondLongest];
                            p7 [shortest]      = 0.25f * boundingBox.min [shortest] + 0.75f * boundingBox.max [shortest];

                            Vector3 p8 = boundingBox.center;
                            p8 [longest]       = 0.75f * boundingBox.min [longest] + 0.25f * boundingBox.max [longest];
                            p8 [secondLongest] = 0.25f * boundingBox.min [secondLongest] + 0.75f * boundingBox.max [secondLongest];
                            p8 [shortest]      = 0.75f * boundingBox.min [shortest] + 0.25f * boundingBox.max [shortest];

                            visibilityPoints.Add(p7);
                            visibilityPoints.Add(p8);
                        }

                        visibilityPoints.Add(p5);
                        visibilityPoints.Add(p6);
                    }

                    visibilityPoints.Add(p3);
                    visibilityPoints.Add(p4);
                }


                visibilityPoints.Add(p1);
                visibilityPoints.Add(p2);
            }
            else
            {
                visibilityPointGeneration = VisibilityPointGenerationMethod.RANDOM;
            }

            break;
        }

        case (VisibilityPointGenerationMethod.RANDOM):
        {                  // random generation, corresponds to VisibilityPointGenerationMethod.RANDOM
            if (numberofPoints >= colliders.Count)
            {
                // assign 1 random point per collider, until they are over
                int colliderIndex = 0;
                while (numberofPoints > 0)
                {
                    Vector3 newPoint = TargetUtils.RandomPointInsideBounds(colliders [colliderIndex].GetComponent <Collider> ().bounds);
                    visibilityPoints.Add(newPoint);
                    colliderIndex = (colliderIndex + 1) % colliders.Count;
                    numberofPoints--;
                }
            }
            else                          // if we have more colliders than points, then let's consider the AABB of the target assign points inside it. Not ideal, but...

            {
                while (numberofPoints > 0)
                {
                    Vector3 newPoint = TargetUtils.RandomPointInsideBounds(boundingBox);
                    visibilityPoints.Add(newPoint);
                    numberofPoints--;
                }
            }

            break;
        }


        default:
        {
            Debug.Log("Warning: NO visibility points computed for target " + name);
            break;
        }
        }
    }