public override void Start()
        {
            //Set up our obstacle course
            ActorFactory.Instance.LoadLevel("maze");

            //Create the bounding box that will limit the pathfinding search area
            BoundingBox2D bounds = new BoundingBox2D(new Vector2(-20, -20), new Vector2(20, 20));

            //Create our pathfinding graph. In our 2D worlds, this is a relatively fast
            // operation -- you shouldn't be doing it every frame, but recalculating every
            // so often if your world has changed is not inappropriate.
            SpatialGraphManager.Instance.CreateGraph(
                0.75f, //The size of the entity you want to pathfind (so the generator
                       //  can know how small a space can be and still have it fit.)
                ref bounds //The search area
            );

            //Create a MazeFinder (class definition below), and put him in the bottom
            //  left corner of the maze
            _mf = new MazeFinder();
            _mf.Position = new Vector2(-11.5f, -8.0f);
            World.Instance.Add(_mf, 2);

            //Send him to the upper right, watch him scurry
            _mf.GoTo(Vector2.Zero);

            // Register this object as the mouse listener
            InputManager.Instance.RegisterMouseListener(this);

            //Demo housekeeping below this point.
            #region Demo housekeeping
            String description = "This little dude is pathfinding through the area.";
            description += "\n\nClick the mouse to give him a new target.";
            description += "\n\nPress [B] to see the pathfinding graph.";
            TextActor t = new TextActor("Console", description);
            t.TextAlignment = TextActor.Alignment.Center;
            t.Position = new Vector2(0.0f, -5.0f);
            World.Instance.Add(t, 2);
            TextActor fileLoc = new TextActor("ConsoleSmall", "DemoScreenPathfinding.cs");
            fileLoc.Position = World.Instance.Camera.ScreenToWorld(5, 755);
            fileLoc.Color = new Color(.3f, .3f, .3f);
            World.Instance.Add(fileLoc, 2);
            _objects.Add(fileLoc);
            _objects.Add(t);
            _objects.Add(_mf);

            Actor[] walls = TagCollection.Instance.GetObjectsTagged("maze_wall");
            foreach(Actor a in walls)
                _objects.Add(a);
            #endregion
        }
        public static BoundingBox2D CreateFromPoints(ref Vector2[] points)
        {
            if( points.Length < 1 )
                return new BoundingBox2D(Vector2.Zero, Vector2.Zero);

            BoundingBox2D retVal = new BoundingBox2D( new Vector2(float.MaxValue, float.MaxValue),
                new Vector2(float.MinValue, float.MinValue));
            for( int i = 0 ; i < points.Length; ++i )
            {
                retVal.Min = Vector2.Min(retVal.Min, points[i]);
                retVal.Max = Vector2.Max(retVal.Max, points[i]);
            }
            return retVal;
        }
 public ContainmentType Contains(ref BoundingBox2D box)
 {
     if ((Max.X < box.Min.X) || (Min.X > box.Max.X))
     {
         return ContainmentType.Disjoint;
     }
     if ((Max.Y < box.Min.Y) || (Min.Y > box.Max.Y))
     {
         return ContainmentType.Disjoint;
     }
     if ((((Min.X <= box.Min.X) && (box.Max.X <= Max.X)) && ((Min.Y <= box.Min.Y) && (box.Max.Y <= Max.Y))))
     {
         return ContainmentType.Within;
     }
     return ContainmentType.Intersects;
 }
Example #4
0
        public static void SplitBoundingBox(ref BoundingBox2D source, AABBSplittingAxis axis, out BoundingBox2D LHS, out BoundingBox2D RHS)
        {
            LHS = source;
            RHS = source;

            switch (axis)
            {
                case AABBSplittingAxis.X:
                    LHS.Max.X = MathHelper.Lerp(LHS.Min.X, LHS.Max.X, 0.5f);
                    RHS.Min.X = LHS.Max.X;
                    break;
                case AABBSplittingAxis.Y:
                    LHS.Max.Y = MathHelper.Lerp(LHS.Min.Y, LHS.Max.Y, 0.5f);
                    RHS.Min.Y = LHS.Max.Y;
                    break;
            }
        }
        public SpatialGraph(float entityWidth, ref BoundingBox2D startBox)
        {
            _entityWidth = entityWidth;
            float maxDimension = MathHelper.Max(startBox.Max.Y - startBox.Min.Y, startBox.Max.X - startBox.Min.X);
            int depth = 0;
            while (maxDimension > _entityWidth)
            {
                maxDimension /= 2.0f;
                depth += 2;
            }
            _depth = depth > 1 ? depth : 1;
            if (_depth > 24)
                _depth = 24;

            uint depthMask = ~(0xFFFFFFFF << _depth);

            _dirMasks[0] = 0x1;
            _dirMasks[1] = 0x2;
            _dirMasks[2] = 0xaaaaaaaa & depthMask;
            _dirMasks[3] = _dirMasks[2] >> 1;

            _root = CreateTree(_depth + 1, ref startBox, null, 0);

            //Get smallest dimension
            _smallestDimensions = startBox.Max - startBox.Min;
            for (int i = 0; i < _depth; i++)
            {
                if (i % 2 != 0)
                    _smallestDimensions.Y *= 0.5f;
                else
                    _smallestDimensions.X *= 0.5f;
            }

            ComputeNeighbors(_root);
            ValidateNeighbors(_root);
        }
 public void CreateGraph(float entityWidth, ref BoundingBox2D bounds)
 {
     _spatialGraph = new SpatialGraph(entityWidth, ref bounds);
 }
        public void GetGridPoints(out List<Vector2> points, out int xPoints, out int yPoints)
        {
            xPoints = 0;
            yPoints = 0;

            Vector2 vSmallestDimensions = Tree.SmallestDimensions;
            Vector2 vMyBoxDimensions = BBox.Max - BBox.Min;

            /*
            if( vSmallestDimensions == vMyBoxDimensions )
            {
                xPoints = 1;
                yPoints = 1;
                points.push_back( BBox.Centroid() );
                return;
            }
            */

            xPoints = (int)(vMyBoxDimensions.X / vSmallestDimensions.X);
            yPoints = (int)(vMyBoxDimensions.Y / vSmallestDimensions.Y);
            points = new List<Vector2>(xPoints*yPoints);

            Vector2 vBottomLeftStartBox = new Vector2( BBox.Min.X, BBox.Max.Y - vSmallestDimensions.Y );
            BoundingBox2D startBox = new BoundingBox2D( vBottomLeftStartBox, vBottomLeftStartBox + vSmallestDimensions);
            BoundingBox2D checkBox = startBox;

            for( int yDim = 0; yDim < yPoints; ++yDim )
            {
                for( int xDim = 0; xDim < xPoints; ++xDim )
                {
                    points.Add( checkBox.Centroid() );

                    checkBox.Min.X += vSmallestDimensions.X;
                    checkBox.Max.X += vSmallestDimensions.X;
                }

                checkBox.Min.X = startBox.Min.X;
                checkBox.Max.X = startBox.Max.X;

                checkBox.Min.Y -= vSmallestDimensions.Y;
                checkBox.Max.Y -= vSmallestDimensions.Y;
            }
        }
 public SpatialGraphKDNode(BoundingBox2D bb, SpatialGraphKDNode parent)
 {
     BBox = bb;
     Parent = parent;
 }
        private SpatialGraphKDNode CreateTree(int depth, ref BoundingBox2D bbox, SpatialGraphKDNode parent, int index)
        {
            SpatialGraphKDNode node = new SpatialGraphKDNode(bbox, parent);
            node.Tree = this;
            node.Blocked = false;

            //query physics to see if we're blocked
            node.Blocked = IsBlocked( ref bbox );

            //Calculate my index
            if( parent != null )
                node.Index = index;
            else
                node.Index = 0;

            //Bail out if we reach max depth
            depth--;
            node.Depth = _depth - depth;
            if (depth > 0 && node.Blocked )
            {
                BoundingBox2D LHSbbox, RHSbbox;
                MathUtil.SplitBoundingBox(ref bbox, depth % 2 == 0 ? MathUtil.AABBSplittingAxis.Y : MathUtil.AABBSplittingAxis.X, out LHSbbox, out RHSbbox);
                node.LHC = CreateTree(depth, ref LHSbbox, node, node.Index << 1);
                node.RHC = CreateTree(depth, ref RHSbbox, node, (node.Index << 1) + 1);

                uint iMask = ~(0xFFFFFFFF << depth );
                //If I have children, pad my index
                node.Index = (int)((((uint)node.Index) << depth) | iMask);

                //If all my children are blocked, then destroy my children
                if( IsFullyBlocked(node) )
                {
                    node.LHC = null;
                    node.RHC = null;
                }
            }

            return node;
        }
 private SpatialGraphKDNode CreateTree(int depth, ref BoundingBox2D bbox)
 {
     return CreateTree(depth, ref bbox, null, 0);
 }
        private static void NudgePointOnPlane( ref BoundingBox2D BBox, ref Vector2 vPointOnPlane )
        {
            //Get off the x planes
            if( vPointOnPlane.X == BBox.Min.X )
            {
                vPointOnPlane.X += MathUtil.Epsilon;
            }
            else if( vPointOnPlane.X == BBox.Max.X )
            {
                vPointOnPlane.X -= MathUtil.Epsilon;
            }

            //Get off the Y planes
            if( vPointOnPlane.Y == BBox.Min.Y )
            {
                vPointOnPlane.Y += MathUtil.Epsilon;
            }
            else if( vPointOnPlane.Y == BBox.Max.Y )
            {
                vPointOnPlane.Y -= MathUtil.Epsilon;
            }
        }
        private static bool IsBlocked(ref BoundingBox2D bbox)
        {
            const int maxShapeCount = 1024;
            AABB physBounds;
            physBounds.LowerBound = new Vector2( bbox.Min.X, bbox.Min.Y );
            physBounds.UpperBound = new Vector2( bbox.Max.X, bbox.Max.Y );

            Shape[] tempShapes = new Shape[maxShapeCount];
            int numBroadphase = Angel.World.Instance.PhysicsWorld.Query( physBounds, tempShapes, maxShapeCount );

            //No bodies here
            if( numBroadphase == 0 )
                return false;

            PolygonDef shapeBoundsDef = new PolygonDef();
            shapeBoundsDef.VertexCount = 4;
            shapeBoundsDef.Vertices[0] = new Vector2( physBounds.LowerBound.X, physBounds.LowerBound.Y );
            shapeBoundsDef.Vertices[1] = new Vector2( physBounds.UpperBound.X, physBounds.LowerBound.Y );
            shapeBoundsDef.Vertices[2] = new Vector2( physBounds.UpperBound.X, physBounds.UpperBound.Y );
            shapeBoundsDef.Vertices[3] = new Vector2( physBounds.LowerBound.X, physBounds.UpperBound.Y );

            BodyDef fakeBodyDef = new BodyDef();
            //b2Vec2 center = physBounds.lowerBound + (0.5f * shapeBoundsDef.extents);
            fakeBodyDef.Position = Vector2.Zero;
            Body fakeBody = new Body( fakeBodyDef, Angel.World.Instance.PhysicsWorld );
            PolygonShape shapeBounds = new PolygonShape( shapeBoundsDef );

            for( int i = 0; i < numBroadphase; i++ )
            {
                Shape Sh = tempShapes[i];
                if( Sh.Type == ShapeType.PolygonShape  )
                {
                    PolygonShape PolyShape = (PolygonShape)Sh;

                    Manifold m0 = new Manifold();
                    XForm xf1 = fakeBody.XForm;
                    XForm xf2 = PolyShape.Body.XForm;
                    Collision.CollidePolygons(ref m0, shapeBounds, ref xf1, PolyShape, ref xf2);

                    if( m0.PointCount > 0 )
                        return true;

                }
                else if( Sh.Type == ShapeType.CircleShape )
                {
                    CircleShape CircleShape = (CircleShape)Sh;
                    Manifold m0 = new Manifold();
                    Collision.CollidePolygonAndCircle( ref m0, shapeBounds, fakeBody.XForm, CircleShape, CircleShape.Body.XForm );
                    if( m0.PointCount > 0 )
                        return true;
                }
            }

            return false;
        }
 public SpatialGraphKDNode FindNode(ref BoundingBox2D bbox)
 {
     return FindNode(_root, ref bbox);
 }
        public SpatialGraphKDNode FindNode(SpatialGraphKDNode node, ref BoundingBox2D bbox)
        {
            if (node == null)
                return null;
            //check if this bbox fits entirely within our node
            if (node.BBox.Contains(ref bbox) == BoundingBox2D.ContainmentType.Within)
            {
                //Check our children
                SpatialGraphKDNode retVal = FindNode(node.LHC, ref bbox);
                if (retVal != null)
                    return retVal;
                retVal = FindNode(node.RHC, ref bbox);
                if (retVal != null)
                    return retVal;

                //otherwise, return ourselves
                return node;
            }

            return null;
        }
 public static BoundingBox2D CreateMerged(ref BoundingBox2D original, ref BoundingBox2D additional)
 {
     return new BoundingBox2D(Vector2.Min(original.Min, additional.Min), Vector2.Max(original.Max, additional.Max));
 }