コード例 #1
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);
    }
コード例 #2
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;
            }
        }
    }