Пример #1
0
        InteractNode GetInteractNode(Microsoft.Xna.Framework.Ray lookRay)
        {
            float collisionDist;
            CollisionSkin skin = null;
            Vector3 pos, normal;
            Segment seg = new Segment(lookRay.Position, lookRay.Direction * MAX_INTERACT_DIST);
            scene.GetPhysicsEngine().CollisionSystem.SegmentIntersect(out collisionDist, out skin, out pos, out normal, seg, pred);

            float bestDist = (skin != null) ? collisionDist : float.PositiveInfinity;
            InteractNode bestNode = null;
            for (int i = 0; i < interactables.Count; i++)
            {
                InteractObject interactObj = interactables[i].GetInteractObject();

                BoundingBox bounds =  interactObj.Transformation.TransformBounds(interactObj.GetMesh().GetBounds());
                float? intersection = lookRay.Intersects(bounds);
                if (intersection.HasValue)
                {
                    float dist = intersection.Value;
                    if (dist < bestDist && dist <= MAX_INTERACT_DIST)
                    {
                        InteractNode node = interactObj.GetInteractNode();
                        if (node.IsEnabled())
                        {
                            bestDist = dist;
                            bestNode = interactObj.GetInteractNode();
                        }
                    }
                }
            }
            return bestNode;
        }
Пример #2
0
        Vector3 GetTerrainVector(Microsoft.Xna.Framework.Ray mRay)
        {
            Vector3 pos = new Vector3(0, 0, 0);
            Nullable<float> curDist = 10000f;

            for (int i = 0; i < terrainEngine.vertices.Length - 3; i += 3)
            {
                Nullable<float> rayDist;
                Vector3 firstPos;

                firstPos = terrainEngine.vertices[i].Position;

                BoundingSphere sphere = new BoundingSphere(firstPos, 2);
                rayDist = mRay.Intersects(sphere);
                if (rayDist != null)
                {
                    if (rayDist < curDist)
                    {
                        curDist = rayDist;
                        pos = sphere.Center;
                        posList.Add(pos);
                    }

                }
            }

            return pos;
        }
Пример #3
0
 public override HitType GetHit(Microsoft.Xna.Framework.Ray ray, float maxDistance, out float hitDistance)
 {
     BoundingBox hitBounds = model.GetHitBounds();
     float? dist;
     ray.Intersects(ref hitBounds, out dist);
     if (dist.HasValue && dist.Value <= maxDistance)
     {
         float bestDist = float.PositiveInfinity;
         HitType bestHit = HitType.None;
         SortedList<HitType, BoundingBox> hitBoxes = model.GetHitBoxes();
         for (int i = 0; i < hitBoxes.Count; i++)
         {
             HitType currHitType = hitBoxes.Keys[i];
             float? hitDist;
             BoundingBox bounds = hitBoxes[currHitType];
             ray.Intersects(ref bounds, out hitDist);
             if (hitDist.HasValue && hitDist.Value <= maxDistance && hitDist.Value < bestDist)
             {
                 bestDist = hitDist.Value;
                 bestHit = currHitType;
             }
         }
         hitDistance = bestDist;
         return bestHit;
     }
     hitDistance = 0;
     return HitType.None;
 }
Пример #4
0
        public void GetData(Microsoft.Xna.Framework.Rectangle playerBounds, Color[] result, Color[] buffer, int startIndex, int count)
        {
            Point currentPoint = new Point(0, 0);
            MapSegment segment1 = null;
            MapSegment segment2 = null;
            Rectangle segment1Rect = Rectangle.Empty;
            Rectangle segment2Rect = Rectangle.Empty;

            foreach (MapSegment seg in this.segments)
            {
                Rectangle textureRect = new Rectangle(currentPoint.X, currentPoint.Y, seg.MapTexture.Width, seg.MapTexture.Height);
                if (playerBounds.Intersects(textureRect))
                {
                    if (segment1 == null)
                    {
                        segment1 = seg;
                        segment1Rect = textureRect;
                    }
                    else if (segment2 == null)
                    {
                        segment2 = seg;
                        segment2Rect = textureRect;
                    }
                    else
                    {
                        throw new ArgumentException("Goose object intersects more than two level segments. Please increase the size of the segments to avoid this.");
                    }
                }

                currentPoint.X += seg.DisplayTexture.Width;
            }

            for (int i = 0; i < result.Length; i++)
            {
                result[i] = ColorConsts.SolidWallColor;
            }

            if (segment1 != null)
            {
                Texture2D texture = segment1.MapTexture;
                Rectangle bounds = Intersect(playerBounds, segment1Rect);

                bounds.Offset(-segment1Rect.X, -segment1Rect.Y);
                lock (syncObj)
                {
                    if (segment2 == null)
                    {
                        texture.GetData<Color>(0, bounds, result, 0, bounds.Width * bounds.Height);
                        return;
                    }
                    else
                    {
                        texture.GetData<Color>(0, bounds, buffer, 0, bounds.Width * bounds.Height);
                    }
                }
                bounds.Offset(segment1Rect.Location);
                MapData(playerBounds, bounds, result, buffer);
            }
            if (segment2 != null)
            {
                Texture2D texture = segment2.MapTexture;
                Rectangle bounds = Intersect(playerBounds, segment2Rect);

                bounds.Offset(-segment2Rect.X, -segment2Rect.Y);
                lock (syncObj)
                {
                    texture.GetData<Color>(0, bounds, buffer, 0, bounds.Width * bounds.Height);
                }
                bounds.Offset(segment2Rect.Location);
                MapData(playerBounds, bounds, result, buffer);
            }
        }
        public bool RayCast(Microsoft.Xna.Framework.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?
                    {
                        float? intersects;
                        var item = cell.entries.Elements[i].item;
                        ray.Intersects(ref item.boundingBox, out intersects);
                        if (intersects != null && intersects < 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;

        }
        public void GetEntries(Microsoft.Xna.Framework.BoundingSphere boundingShape, IList<BroadPhaseEntry> overlaps)
        {
            //Create a bounding box based on the bounding sphere.
            //Compute the min and max of the bounding box.
            //Loop through the cells and select bounding boxes which overlap the x axis.
#if !WINDOWS
            Vector3 offset = new Vector3();
#else
            Vector3 offset;
#endif
            offset.X = boundingShape.Radius;
            offset.Y = offset.X;
            offset.Z = offset.Y;
            BoundingBox box;
            Vector3.Add(ref boundingShape.Center, ref offset, out box.Max);
            Vector3.Subtract(ref boundingShape.Center, ref offset, out box.Min);

            Int2 min, max;
            Grid2DSortAndSweep.ComputeCell(ref box.Min, out min);
            Grid2DSortAndSweep.ComputeCell(ref box.Max, out max);
            for (int i = min.Y; i <= max.Y; i++)
            {
                for (int j = min.Z; j <= max.Z; j++)
                {
                    //Grab the cell that we are currently in.
                    Int2 cellIndex;
                    cellIndex.Y = i;
                    cellIndex.Z = j;
                    GridCell2D cell;
                    if (owner.cellSet.TryGetCell(ref cellIndex, out cell))
                    {

                        //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 k = 0; k < cell.entries.count
                            && cell.entries.Elements[k].item.boundingBox.Min.X <= box.Max.X; k++) //TODO: Try additional x axis pruning? A bit of optimization potential due to overlap with AABB test.
                        {
                            bool intersects;
                            var item = cell.entries.Elements[k].item;
                            boundingShape.Intersects(ref item.boundingBox, out intersects);
                            if (intersects && !overlaps.Contains(item))
                            {
                                overlaps.Add(item);
                            }
                        }
                    }
                }
            }
        }