示例#1
0
    public BSPTreeNode GetLeafNode(Vector3i index)
    {
        BSPTreeNode n     = node;
        Vector3i    cells = GetCellCount();

        for (int i = 0; i < 3; i++)
        {
            int min = 0;
            int max = cells[i];
            while (max - 1 > min)
            {
                int    mid = (max + min) / 2;
                string s;
                if (index[i] > mid)
                {
                    n   = n.right;
                    min = mid;
                }
                else
                {
                    n   = n.left;
                    max = mid;
                }
            }
        }

        // Debug.Log("cells " + cells);
        return(n);
    }
示例#2
0
 public void Insert(Triangle3D t, T val)
 {
     if (node == null)
     {
         node = new BSPTreeNode(t, val);
     }
     else
     {
         node.Insert(t, val);
     }
 }
示例#3
0
 public void Insert(Plane3D p)
 {
     if (node == null)
     {
         node = new BSPTreeNode(p);
     }
     else
     {
         node.Insert(p);
     }
 }
示例#4
0
 public void DebugQuadPlanes(String s, BSPTreeNode n)
 {
     if (n == null || (n.triangles.Count > 0))
     {
         // Debug.Log("Tree "+s+" "+(n==null?-1:n.ToList().Count));
     }
     else
     {
         DebugQuadPlanes(s + n.plane.normal + n.plane.distance + "L", n.left);
         DebugQuadPlanes(s + n.plane.normal + n.plane.distance + "R", n.right);
     }
 }
示例#5
0
 // split both child spaces
 public void Insert(Plane3D p)
 {
     if (this.plane.normal == p.normal)
     {
         Vector3D point           = p.normal * -p.distance;
         double   distanceToPoint = this.plane.GetDistanceToPoint(point);
         if (distanceToPoint > 0)
         {
             if (left == null)
             {
                 left = new BSPTreeNode(p);
             }
             else
             {
                 left.Insert(p);
             }
         }
         else if (distanceToPoint < 0)
         {
             if (right == null)
             {
                 right = new BSPTreeNode(p);
             }
             else
             {
                 right.Insert(p);
             }
         }
         else
         {
             Debug.LogError("Splitting plane already defined");
         }
     }
     else
     {
         if (left == null)
         {
             left = new BSPTreeNode(p);
         }
         else
         {
             left.Insert(p);
         }
         if (right == null)
         {
             right = new BSPTreeNode(p);
         }
         else
         {
             right.Insert(p);
         }
     }
 }
示例#6
0
        public static object Serialize_BSPTreeNode(object _obj, System.Type type, OverloadLevelConvertSerializer serializer)
        {
            BSPTreeNode obj = (BSPTreeNode)_obj;

            if (serializer.IsWriting)
            {
                serializer.SerializeOut_vector4(obj.PlaneEq);
                serializer.SerializeOut_int32(obj.BackNodeIndex);
                serializer.SerializeOut_int32(obj.FrontNodeIndex);
            }
            else
            {
                obj.PlaneEq        = serializer.SerializeIn_vector4();
                obj.BackNodeIndex  = serializer.SerializeIn_int32();
                obj.FrontNodeIndex = serializer.SerializeIn_int32();
            }
            return(obj);
        }
示例#7
0
    void SplitNode(BSPTreeNode node, BSPSplitDirection splitDir, float splitRange, int recursionLevel, List <BSPTreeNode> leafNodes)
    {
        // Split a node so that we get a new range [min_x,min_y,max_x,max_y] so that a room can be created with these bounds
        // Note that these are bounds on the indices of the virtual map and that they are left-inclusive!
        //Debug.Log("LEVEL " + recursionLevel + " [" + node.areaBounds.min_x + "," + node.areaBounds.max_x + "] [" + node.areaBounds.min_y + "," + node.areaBounds.max_y + "]");
        if (recursionLevel == 0)
        {
            leafNodes.Add(node);
            return;
        }
        int splitPoint;

        // Pick a random coordinate on that direction
        splitPoint          = GetSplitPoint(node.areaBounds, splitDir, splitRange);
        node.splitDirection = splitDir;
        //Debug.Log("ON " + splitDir + " CHOSEN SPLIT: " + splitPoint);

        // Create child nodes from that split point
        switch (splitDir)
        {
        case BSPSplitDirection.VERTICAL:
            node.left  = new BSPTreeNode(node.areaBounds.min_x, node.areaBounds.min_y, splitPoint, node.areaBounds.max_y);
            node.right = new BSPTreeNode(splitPoint, node.areaBounds.min_y, node.areaBounds.max_x, node.areaBounds.max_y);
            break;

        case BSPSplitDirection.HORIZONTAL:
            node.left  = new BSPTreeNode(node.areaBounds.min_x, node.areaBounds.min_y, node.areaBounds.max_x, splitPoint);
            node.right = new BSPTreeNode(node.areaBounds.min_x, splitPoint, node.areaBounds.max_x, node.areaBounds.max_y);
            break;
        }

        // Next pass: go through child nodes
        recursionLevel--;
        splitDir = (BSPSplitDirection)Mathf.Repeat((int)(splitDir + 1), (int)BSPSplitDirection.MAX);
        SplitNode(node.left, splitDir, splitRange, recursionLevel, leafNodes);
        SplitNode(node.right, splitDir, splitRange, recursionLevel, leafNodes);
    }
示例#8
0
    void LinkCorridors(BSPTreeNode node, VirtualMap map, int recursionLevel, bool isLeft = false)
    {
        //Debug.Log("Linking at level " + recursionLevel);
        // We link corridors recursively
        if (node.left != null && node.right != null)
        {
            // First we recurse to the children
            LinkCorridors(node.left, map, recursionLevel + 1, isLeft: true);
            LinkCorridors(node.right, map, recursionLevel + 1, isLeft: false);

            // We get the left, we get the right, and we link them
            // We do this for non-leaf nodes
            if (node.left.roomBounds != null && node.right.roomBounds != null)
            {
                // DEBUG: Only connect at higher recursion level
                if (recursionLevel >= 0)
                {
                    if (node.splitDirection == BSPSplitDirection.HORIZONTAL)
                    {
                        CreateVerticalCorridor(map, node.left.roomBounds, node.right.roomBounds);
                    }
                    else
                    {
                        CreateHorizontalCorridor(map, node.left.roomBounds, node.right.roomBounds);
                    }
                }

                //if (isLeft)
                //return;
                //return;

                // Now that we linked the children, we update the bounds of this node, which had no roomBounds before
                BSPTreeNodeBounds lb = node.left.roomBounds;
                BSPTreeNodeBounds rb = node.right.roomBounds;

                // We always get the more central one, to make sure we can connect easily
                // Central one: has midpoint closest to the middle of the map
                int mid_x_map = map.ActualWidth / 2;
                int mid_y_map = map.ActualHeight / 2;
                int mid_x_lb  = (lb.min_x + lb.max_x) / 2;
                int mid_y_lb  = (lb.min_y + lb.max_y) / 2;
                int mid_x_rb  = (rb.min_x + rb.max_x) / 2;
                int mid_y_rb  = (rb.min_y + rb.max_y) / 2;

                //Debug.Log("MID_MAP " + mid_x_map);
                //Debug.Log("mid_x_lb " + mid_x_lb);
                //Debug.Log("mid_x_rb " + mid_x_rb);

                // Check the more central one
                int dist_lb = Mathf.Abs(mid_x_lb - mid_x_map) + Mathf.Abs(mid_y_lb - mid_y_map);
                int dist_rb = Mathf.Abs(mid_x_rb - mid_x_map) + Mathf.Abs(mid_y_rb - mid_y_map);

                //Debug.Log("RECURSION " + recursionLevel);
                //Debug.Log("THIS: " + node.areaBounds);// + "    CONNECTED INSIDE: " + node.roomBounds);
                //Debug.Log("Distance of L is " + dist_lb + " L: " + lb);
                //Debug.Log("Distance of R is " + dist_rb + " R: " + rb);
                //Debug.Log("CLOSEST L? " + (dist_lb <= dist_rb));
                if (dist_lb <= dist_rb)
                {
                    node.roomBounds = new BSPTreeNodeBounds(lb.min_x, lb.min_y, lb.max_x, lb.max_y);
                }
                else
                {
                    node.roomBounds = new BSPTreeNodeBounds(rb.min_x, rb.min_y, rb.max_x, rb.max_y);
                }

                // We use all the range (WRONG! may not connect!)

                /*
                 * node.roomBounds = new BSPTreeNodeBounds(Mathf.Min(lb.min_x, rb.min_x),
                 *                      Mathf.Min(lb.min_y, rb.min_y),
                 *                      Mathf.Max(lb.max_x, rb.max_x),
                 *                      Mathf.Max(lb.max_y, rb.max_y)
                 *                      );*/
                // We connect left or right, depending on where we are (WRONG)

                /*
                 * if (!isLeft)
                 * {
                 *  node.roomBounds =  new BSPTreeNodeBounds(lb.min_x, lb.min_y, lb.max_x, lb.max_y);
                 * }
                 * else
                 * {
                 *  node.roomBounds = new BSPTreeNodeBounds(rb.min_x, rb.min_y, rb.max_x, rb.max_y);
                 * }*/
                //node.roomBounds = new BSPTreeNodeBounds(lb.min_x, lb.min_y, lb.max_x, lb.max_y);
            }
        }
    }
示例#9
0
    VirtualRoom CreateRoom(VirtualMap map, RoomGenerator roomGenerator, BSPTreeNode node, CellLocation starting_location)
    {
        // Get the maximum bounds
        BSPTreeNodeBounds bounds = node.areaBounds;
        int range_x = bounds.max_x - bounds.min_x;
        int range_y = bounds.max_y - bounds.min_y;

        // Cannot create a room if the area is empty!
        if (range_x == 0 || range_y == 0)
        {
            Debug.LogWarning("Room size too small to be created! " + range_x + "," + range_y);
            return(null);
        }

        // Choose a random size for the room
        int min_size_x = Mathf.Max(1, Mathf.FloorToInt(range_x * roomSizeMinRange));
        int max_size_x = Mathf.Max(1, Mathf.CeilToInt(range_x * roomSizeMaxRange));
        int min_size_y = Mathf.Max(1, Mathf.FloorToInt(range_y * roomSizeMinRange));
        int max_size_y = Mathf.Max(1, Mathf.CeilToInt(range_y * roomSizeMaxRange));

        // Compute size
        int size_x = DungeonGenerator.Random.Instance.Next(min_size_x, max_size_x);
        int size_y = DungeonGenerator.Random.Instance.Next(min_size_y, max_size_y);

        // Compute start
        int start_x, start_y;

        start_x = bounds.min_x + DungeonGenerator.Random.Instance.Next(range_x - size_x);
        start_y = bounds.min_y + DungeonGenerator.Random.Instance.Next(range_y - size_y);

        // If the starting location is inside these bounds, we must force it to create the room on it
        if (starting_location.isValid() && bounds.Contain(starting_location))
        {
            //Debug.Log("YES IN");
            int x = starting_location.x / 2;
            int y = starting_location.y / 2;

            //Debug.Log("Start bounds: " + (new BSPTreeNodeBounds(start_x, start_y, start_x + size_x, start_y + size_y)).ToString());

            // Make sure the start includes this, or decrease it
            if (x < start_x)
            {
                start_x = x;
            }
            if (y < start_y)
            {
                start_y = y;
            }

            //Debug.Log(y);
            //Debug.Log(start_y + size_y);

            // Make sure the end includes thid, or increase it
            if (x + 1 >= start_x + size_x)
            {
                size_x = x + 1 - start_x;
            }
            if (y + 1 >= start_y + size_y)
            {
                size_y = y + 1 - start_y;
            }

            //Debug.Log("End bounds: " + (new BSPTreeNodeBounds(start_x, start_y, start_x + size_x, start_y + size_y)).ToString());
        }

        //Debug.Log("MIN " + min_size_x + " MAX " + max_size_x + " SIZE " + size_x);

        //Debug.Log("SPACE " + " [" + node.areaBounds.min_x + "," + node.areaBounds.max_x + "] [" + node.areaBounds.min_y + "," + node.areaBounds.max_y + "]");

        //Debug.Log("delta_low " + delta_low + " delta_high " + delta_high);

        //Debug.Log("CREATING ROOM: " + start_x + " + " + size_x + "   ||   " + start_y + " + " + size_y);

        node.roomBounds = new BSPTreeNodeBounds(start_x, start_y, start_x + size_x, start_y + size_y);

        // Start and end must be converted to whole-map sizes (not just floors)
        start_x = start_x * 2 + 1;
        start_y = start_y * 2 + 1;

        return(roomGenerator.CreateRoom(map, size_x, size_y, start_x, start_y));
    }
示例#10
0
        //-----------------------------------------------------------------------------

        static public World  FromWorldcraftMap(WorldcraftMap wm)
        {
            // create new world
            World world = new World();

            world.Textures = wm.Textures;
            world.SkyBox   = new SkyBox("redSky");
            world.FileName = Path.Combine(ExoEngine.sWorldPath, Path.ChangeExtension(Path.GetFileName(wm.FileName), ExoEngine.sWorldExtension));
            world.Dirty    = true;


            // find the starting location
            WorldcraftObject woStartPosition = wm.Objects.FindByClassName("StartPosition");

            if (woStartPosition == null)
            {
                return(null);
            }

            Vector3D ptStartPosition;

            FaceUtils.GetMidPoint(woStartPosition.Faces, out ptStartPosition);
            world.StartPosition    = ptStartPosition;
            world.StartOrientation = woStartPosition.GetPropertyInteger("orientation", 0);

            // find the main light
            WorldcraftObject woLight = wm.Objects.FindByClassName("Light");

            if (woLight == null)
            {
                return(null);
            }

            Vector3D ptLight;

            FaceUtils.GetMidPoint(woLight.Faces, out ptLight);
            world.Light = ptLight;

            // find "Default" group... it is the static world
            WorldcraftObject woDefault = wm.Objects.FindByClassName("Default");

            if (woDefault == null)
            {
                return(null);
            }

            // setup BSP tree
            Faces faces = new Faces();

            // handle the other objects
            foreach (WorldcraftObject wo in wm.Objects)
            {
                if (wo.ClassName == "Water")
                {
                    Vector3D ptMin, ptMax;
                    FaceUtils.GetExtents(wo.Faces, out ptMin, out ptMax);
                    Water water = new Water(ptMin, ptMax, wo.GetPropertyFloat("waveHeight", 100));
                    water.Color = wo.GetPropertyColor("color", Color.Azure);
                    world.Entities.Add(water);
                }
                else if (wo.ClassName == "Duck")
                {
                    Vector3D ptMin, ptMax;
                    FaceUtils.GetExtents(wo.Faces, out ptMin, out ptMax);
                    Duck duck = new Duck(ptMin, ptMax);
                    duck.LoadDataSet(Path.Combine(ExoEngine.sSpritePath, "duck.odf"), wo.GetPropertyColor("color", Color.Yellow));
                    world.Entities.Add(duck);

                    foreach (Face face in wo.Faces)
                    {
                        face.Visible = false;
                    }
                    faces.AddRange(wo.Faces);
                }
            }

            world.Entities.SortByPriority();

            faces.AddRange(woDefault.Faces);
            FaceUtils.OptimizeFaces(faces);
            world.BSPTreeRoot = BSPTreeNode.FromFaces(faces);

            return(world);
        }
示例#11
0
        public void Insert(Triangle3D newTriangle, T val)
        {
            var intersection = Intersect(newTriangle);

            if (intersection == IntersectionResult.InPlane)
            {
                triangles.Add(new BSPTriangle(newTriangle, val));
            }
            else if (intersection == IntersectionResult.Larger)
            {
                if (left == null)
                {
                    left = new BSPTreeNode(newTriangle, val);
                }
                else
                {
                    left.Insert(newTriangle, val);
                }
            }
            else if (intersection == IntersectionResult.Smaller)
            {
                if (right == null)
                {
                    right = new BSPTreeNode(newTriangle, val);
                }
                else
                {
                    right.Insert(newTriangle, val);
                }
            }
            else if (intersection == IntersectionResult.Intersection)
            {
                Triangle3D[] res;
                Split(newTriangle, out res);
                foreach (var l in res)
                {
                    double dist = plane.GetDistanceToPoint(l.ComputeCenter());
                    if (dist > 0)
                    {
                        if (left == null)
                        {
                            left = new BSPTreeNode(l, val);
                        }
                        else
                        {
                            left.Insert(l, val);
                        }
                    }
                    else
                    {
                        if (right == null)
                        {
                            right = new BSPTreeNode(l, val);
                        }
                        else
                        {
                            right.Insert(l, val);
                        }
                    }
                }
            }
        }