예제 #1
0
    private static int OccluderComparison(OccluderVector v1, OccluderVector v2)
    {
        if (v1.angle == v2.angle)
        {
            return(0);
        }

        if (v1.angle > v2.angle)
        {
            return(1);
        }

        return(-1);
    }
예제 #2
0
    private static int OccluderComparison(OccluderVector v1, OccluderVector v2)
    {
        if(v1.angle == v2.angle)
        {
            // If the angles are equivalent, sort on their distance from the camera
            if( v1.vec.sqrMagnitude > v2.vec.sqrMagnitude)
            {
                return 1;
            }
            else if( v2.vec.sqrMagnitude < v1.vec.sqrMagnitude)
            {
                return -1;
            }
            return 0;
        }

        if(v1.angle > v2.angle)
        {
            return 1;
        }

        return -1;
    }
예제 #3
0
    void OnEnable()
    {
        m_viewCollider = GetComponent <BoxCollider>();

        //validVerts.Capacity = m_maxOccluderVerts;
        extentsVals.Clear();

        // Bung four values into the extents to set the initial capacity
        extentsVals.Add(Vector3.zero);
        extentsVals.Add(Vector3.zero);
        extentsVals.Add(Vector3.zero);
        extentsVals.Add(Vector3.zero);


        for (int occluderID = 0; occluderID < m_maxOccluderVerts; occluderID++)
        {
            vertices[occluderID] = new Vector3();
            uvs[occluderID]      = new Vector2();
            normals[occluderID]  = new Vector3(0.0f, -1.0f, 0.0f);
            colors[occluderID]   = new Color(1.0f, 1.0f, 1.0f, 1.0f);

            m_occluders[occluderID] = new OccluderVector();
        }


        vertices[0] = new Vector3(0.0f, 0.0f, 0.0f);
        uvs[0]      = new Vector2(0.5f, 0.5f);

        m_occluders[m_maxOccluderVerts] = new OccluderVector();

        float extentsVal = Mathf.Abs(m_viewCollider.size.x * Mathf.Cos(Mathf.PI / 4));

        m_fixedExtents[0] = new Vector3(-extentsVal, 0.0f, extentsVal);
        m_fixedExtents[1] = new Vector3(-extentsVal, 0.0f, -extentsVal);
        m_fixedExtents[2] = new Vector3(extentsVal, 0.0f, extentsVal);
        m_fixedExtents[3] = new Vector3(extentsVal, 0.0f, -extentsVal);
    }
예제 #4
0
    /// <summary>
    /// Gets a list of all vertices that occlude the view area.
    /// The OccluderVector structure contains the hit-points of each collision, as well as the angle of the hit-point from the left extent.
    /// </summary>
    /// <returns>
    /// The occluder list, sorted around increasing angle from the left extent.
    /// </returns>
    private List<OccluderVector> GetOccluders()
    {
        Vector3 cameraDirection = m_camera.transform.rotation * Vector3.up;

        List<VectorOffsetPair> verts = new List<VectorOffsetPair>();

        // Loop through each collider and add its vertices to the list
        foreach(Collider viewCollider in m_collidersInView)
        {
            MeshFilter meshFilter = viewCollider.GetComponent<MeshFilter>();

            foreach(Vector3 vert in meshFilter.mesh.vertices)
            {
                Vector3 vertexWorldPos = viewCollider.transform.TransformPoint(vert); // This can be replaced with an addition of the transform position if everything is grid-aligned.
                Vector3 cameraToVertex = vertexWorldPos - transform.position;

                Debug.DrawRay (this.transform.position  + new Vector3(0.0f, 0.0f, -4.0f), cameraToVertex , Color.magenta);

                // This works out the magnitude of the vector if it were to reach the max range.
                // TODO: This could be removed if the camera area was a correct sweep rather than a triangle. The magnitude of the vector would just be
                //		 tested against the range. The difficulty is the lateral sweep becomes harder over a curve.
                float cameraDirVertexDot = Vector3.Dot(cameraDirection, Vector3.Normalize(cameraToVertex));
                float angle = Mathf.Acos(cameraDirVertexDot);
                float mag = (cameraToVertex).magnitude;

                float thing = mag * cameraDirVertexDot;

                if(thing < m_camera.range && angle <= Mathf.Deg2Rad * (m_camera.fov_degrees ) / 2.0f)
                {
                    VectorOffsetPair newPair = new VectorOffsetPair();
                    newPair.vec = 	vertexWorldPos;

                    Vector3 offsetDirection = newPair.vec - (meshFilter.mesh.bounds.center + meshFilter.gameObject.transform.position);
                    newPair.offsetVec = newPair.vec + (offsetDirection * m_nudgeMagnitude);
                    newPair.offsetVec.z = newPair.vec.z;

                    verts.Add(newPair);
                }
            }
        }

        List<Vector3> validVerts = new List<Vector3>();
        validVerts.Clear();

        RaycastHit hitInfo;

        // Manually cast the edges
        Vector3 right = Quaternion.Euler(0.0f, 0.0f, -((m_camera.fov_degrees / 2.0f))) * cameraDirection;
        Vector3 left = Quaternion.Euler(0.0f, 0.0f, ((m_camera.fov_degrees / 2.0f))) * cameraDirection;

        Vector3 leftDirection = left;

        float edgeCosTheta = Vector3.Dot(cameraDirection, Vector3.Normalize(right));
        float edgeMaxMagnitude = m_camera.range / edgeCosTheta;

        right = Vector3.Normalize(right) * edgeMaxMagnitude;
        left = Vector3.Normalize(left) * edgeMaxMagnitude;

        List<OccluderVector> occluders = new List<OccluderVector>();

        if(!Physics.Raycast(this.transform.position, right, out hitInfo, edgeMaxMagnitude, collisionLayer))
        {
            validVerts.Add(transform.position + right);
        }
        else
        {
            validVerts.Add(hitInfo.point);
        }

        if(!Physics.Raycast(this.transform.position, left, out hitInfo, edgeMaxMagnitude, collisionLayer))
        {
            validVerts.Add(transform.position + left);
        }
        else
        {
            validVerts.Add(hitInfo.point);
        }

        right += transform.position;
        left += transform.position;

        // Iterate through the initial verts and add both valid verts and projected offset vert intersections
        foreach(VectorOffsetPair vert in verts)
        {
            Vector3 directionToVert = vert.vec - this.transform.position;

            directionToVert = vert.offsetVec - this.transform.position;
            float magnitude = directionToVert.magnitude * 0.98f;

            // Check to see if the original vertex is occluded
            if (!Physics.Raycast (this.transform.position, directionToVert, out hitInfo, magnitude, collisionLayer))
            {
                // Not occluded. The vert itself is fine. Next we check the projected ray...
                validVerts.Add(vert.vec);

                float cosTheta = Vector3.Dot(cameraDirection, Vector3.Normalize(directionToVert));
                float maxMagnitude = m_camera.range / cosTheta;

                Vector3 maxPosition = transform.position + (Vector3.Normalize(directionToVert) * maxMagnitude);
                Vector3 newDirection = Vector3.Normalize(directionToVert) * maxMagnitude ;

                if(!Physics.Raycast(this.transform.position, newDirection, out hitInfo, newDirection.magnitude, collisionLayer))
                {
                    validVerts.Add(maxPosition);
                }
                else
                {
                    validVerts.Add (hitInfo.point);
                }
            }
        }

        // Ray-cast along the extent of the wedge
        RaycastHit[] hits;
        RaycastHit[] hitsReverse;
        Vector3 direction = right - left;

        hits 		= Physics.RaycastAll(left, direction, direction.magnitude, collisionLayer);
        hitsReverse = Physics.RaycastAll(right, -direction, direction.magnitude, collisionLayer);

        RaycastHit[] allHits = new RaycastHit[hits.Length + hitsReverse.Length];
        hits.CopyTo(allHits, 0);
        hitsReverse.CopyTo(allHits, hits.Length);

        foreach(RaycastHit hit in allHits)
        {
            Vector3 directionToVert = hit.point - this.transform.position;
            if (!Physics.Raycast (this.transform.position, directionToVert, out hitInfo, directionToVert.magnitude * 0.99f, collisionLayer))
            {
                validVerts.Add(hit.point);
            }
        }

        // Output all results
        foreach(Vector3 vert in validVerts)
        {
            Vector3 directionToVert = vert - this.transform.position;

            OccluderVector newOccluder = new OccluderVector();
            newOccluder.vec = vert;
            Vector3 normalDirection = Vector3.Normalize(directionToVert);

            float angle = Mathf.Acos(Vector3.Dot(Vector3.Normalize(leftDirection), normalDirection));

            if(Vector3.Normalize(leftDirection) == normalDirection)
            {
                angle = 0.0f;
            }

            newOccluder.angle = angle;
            occluders.Add(newOccluder);
        }

        occluders.Sort(OccluderComparison);

        foreach(OccluderVector vert in occluders)
        {
            Debug.DrawRay (this.transform.position  + new Vector3(0.0f, 0.0f, -5.0f), vert.vec - this.transform.position , Color.green);
        }

        return occluders;
    }