Esempio n. 1
0
        /// <summary>
        /// Computes the intersection, if any, between a ray and the objects in the character's bounding box.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="length">Length of the ray to use in units of the ray's length.</param>
        /// <param name="earliestHit">Earliest intersection location and information.</param>
        /// <returns>Whether or not the ray hit anything.</returns>
        public bool RayCast(Ray ray, float length, out RayHit earliestHit)
        {
            earliestHit = new RayHit();
            earliestHit.T = float.MaxValue;
            foreach (var collidable in characterBody.CollisionInformation.OverlappedCollidables)
            {
                //Check to see if the collidable is hit by the ray.
                float t;
                if (ray.Intersects(ref collidable.boundingBox, out t) && t < length)
                {
                    //Is it an earlier hit than the current earliest?
                    RayHit hit;
                    if (collidable.RayCast(ray, length, SupportRayFilter, out hit) && hit.T < earliestHit.T)
                    {
                        earliestHit = hit;
                    }
                }
            }
            if (earliestHit.T == float.MaxValue)
                return false;
            return true;

        }
Esempio n. 2
0
        /// <summary>
        /// Determines if a ray intersects any object in the character's bounding box.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="length">Length of the ray to use in units of the ray's length.</param>
        /// <returns>Whether or not the ray hit anything.</returns>
        public bool RayCastHitAnything(ref Ray ray, float length)
        {
            foreach (var collidable in characterBody.CollisionInformation.OverlappedCollidables)
            {
                //Check to see if the collidable is hit by the ray.
                float t;
                if (ray.Intersects(ref collidable.boundingBox, out t) && t < length)
                {
                    RayHit hit;
                    if (collidable.RayCast(ray, length, SupportRayFilter, out hit))
                    {
                        return true;
                    }
                }
            }
            return false;

        }
        public bool RayCast(Ray ray, float maximumLength, IList<BroadPhaseEntry> outputIntersections)
        {
            if (maximumLength == float.MaxValue) 
                throw new NotSupportedException("The Grid2DSortAndSweep broad phase cannot accelerate infinite ray casts.  Consider specifying a maximum length or using a broad phase which supports infinite ray casts.");
        
            //Use 2d line rasterization.
            //Compute the exit location in the cell.
            //Test against each bounding box up until the exit value is reached.
            float length = 0;
            Int2 cellIndex;
            Vector3 currentPosition = ray.Position;
            Grid2DSortAndSweep.ComputeCell(ref currentPosition, out cellIndex);
            while (true)
            {

                float cellWidth = 1 / Grid2DSortAndSweep.cellSizeInverse;
                float nextT; //Distance along ray to next boundary.
                float nextTy; //Distance along ray to next boundary along y axis.
                float nextTz; //Distance along ray to next boundary along z axis.
                //Find the next cell.
                if (ray.Direction.Y > 0)
                    nextTy = ((cellIndex.Y + 1) * cellWidth - currentPosition.Y) / ray.Direction.Y;
                else if (ray.Direction.Y < 0)
                    nextTy = ((cellIndex.Y) * cellWidth - currentPosition.Y) / ray.Direction.Y;
                else
                    nextTy = 10e10f;
                if (ray.Direction.Z > 0)
                    nextTz = ((cellIndex.Z + 1) * cellWidth - currentPosition.Z) / ray.Direction.Z;
                else if (ray.Direction.Z < 0)
                    nextTz = ((cellIndex.Z) * cellWidth - currentPosition.Z) / ray.Direction.Z;
                else
                    nextTz = 10e10f;

                bool yIsMinimum = nextTy < nextTz;
                nextT = yIsMinimum ? nextTy : nextTz;




                //Grab the cell that we are currently in.
                GridCell2D cell;
                if (owner.cellSet.TryGetCell(ref cellIndex, out cell))
                {
                    float endingX;
                    if(ray.Direction.X < 0)
                        endingX = currentPosition.X;
                    else
                        endingX = currentPosition.X + ray.Direction.X * nextT;

                    //To fully accelerate this, the entries list would need to contain both min and max interval markers.
                    //Since it only contains the sorted min intervals, we can't just start at a point in the middle of the list.
                    //Consider some giant bounding box that spans the entire list. 
                    for (int i = 0; i < cell.entries.Count 
                        && cell.entries.Elements[i].item.boundingBox.Min.X <= endingX; i++) //TODO: Try additional x axis pruning?
                    {
                        var item = cell.entries.Elements[i].item;
                        float t;
                        if (ray.Intersects(ref item.boundingBox, out t) && t < maximumLength && !outputIntersections.Contains(item))
                        {
                            outputIntersections.Add(item);
                        }
                    }
                }

                //Move the position forward.
                length += nextT;
                if (length > maximumLength) //Note that this catches the case in which the ray is pointing right down the middle of a row (resulting in a nextT of 10e10f).
                    break;
                Vector3 offset;
                Vector3.Multiply(ref ray.Direction, nextT, out offset);
                Vector3.Add(ref offset, ref currentPosition, out currentPosition);
                if (yIsMinimum)
                    if (ray.Direction.Y < 0)
                        cellIndex.Y -= 1;
                    else
                        cellIndex.Y += 1;
                else
                    if (ray.Direction.Z < 0)
                        cellIndex.Z -= 1;
                    else
                        cellIndex.Z += 1;
            }
            return outputIntersections.Count > 0;

        }
 //internal override void GetOverlaps(ref BoundingFrustum boundingFrustum, IList<int> outputOverlappedElements)
 //{
 //    bool intersects;
 //    boundingFrustum.Intersects(ref ChildA.BoundingBox, out intersects);
 //    if (intersects)
 //        ChildA.GetOverlaps(ref boundingFrustum, outputOverlappedElements);
 //    boundingFrustum.Intersects(ref ChildB.BoundingBox, out intersects);
 //    if (intersects)
 //        ChildB.GetOverlaps(ref boundingFrustum, outputOverlappedElements);
 //}
 internal override void GetOverlaps(ref Ray ray, float maximumLength, IList<int> outputOverlappedElements)
 {
     float? result;
     ray.Intersects(ref ChildA.BoundingBox, out result);
     if (result != null && result < maximumLength)
         ChildA.GetOverlaps(ref ray, maximumLength, outputOverlappedElements);
     ray.Intersects(ref ChildB.BoundingBox, out result);
     if (result != null && result < maximumLength)
         ChildB.GetOverlaps(ref ray, maximumLength, outputOverlappedElements);
 }
 /// <summary>
 /// Gets the triangles whose bounding boxes are overlapped by the query.
 /// </summary>
 /// <param name="ray">Shape to query against the tree.</param>
 /// <param name="maximumLength">Maximum length of the ray in units of the ray's length.</param>
 /// <param name="outputOverlappedElements">Indices of triangles in the index buffer with bounding boxes which are overlapped by the query.</param>
 /// <returns>Whether or not any elements were overlapped.</returns>
 public bool GetOverlaps(Ray ray, float maximumLength, IList<int> outputOverlappedElements)
 {
     if (root != null)
     {
         float? result;
         ray.Intersects(ref root.BoundingBox, out result);
         if (result != null)
             root.GetOverlaps(ref ray, maximumLength, outputOverlappedElements);
     }
     return outputOverlappedElements.Count > 0;
 }
 ///// <summary>
 ///// Gets the triangles whose bounding boxes are overlapped by the query.
 ///// </summary>
 ///// <param name="boundingFrustum">Shape to query against the tree.</param>
 ///// <param name="outputOverlappedElements">Indices of triangles in the index buffer with bounding boxes which are overlapped by the query.</param>
 ///// <returns>Whether or not any elements were overlapped.</returns>
 //public bool GetOverlaps(BoundingFrustum boundingFrustum, IList<int> outputOverlappedElements)
 //{
 //    if (root != null)
 //    {
 //        bool intersects;
 //        boundingFrustum.Intersects(ref root.BoundingBox, out intersects);
 //        if (intersects)
 //            root.GetOverlaps(ref boundingFrustum, outputOverlappedElements);
 //    }
 //    return outputOverlappedElements.Count > 0;
 //}
 /// <summary>
 /// Gets the triangles whose bounding boxes are overlapped by the query.
 /// </summary>
 /// <param name="ray">Shape to query against the tree.</param>
 /// <param name="outputOverlappedElements">Indices of triangles in the index buffer with bounding boxes which are overlapped by the query.</param>
 /// <returns>Whether or not any elements were overlapped.</returns>
 public bool GetOverlaps(Ray ray, IList<int> outputOverlappedElements)
 {
     if (root != null)
     {
         float result;
         if (ray.Intersects(ref root.BoundingBox, out result))
             root.GetOverlaps(ref ray, float.MaxValue, outputOverlappedElements);
     }
     return outputOverlappedElements.Count > 0;
 }