Exemplo n.º 1
0
        internal static void Search(GridGraph graph, GridSearch search, int x, int y, float[,] weights, IComparer <GridEdge> comparer)
        {
            search.Clear();
            int width  = graph.Width;
            int height = graph.Height;

            search.IsVisited[x, y] = true;
            search.Order.Add(new Vector2i(x, y));
            search.Parent[x, y] = new Vector2i(x, y);

            PriorityQueue <GridEdge> queue = new PriorityQueue <GridEdge>(comparer);

            List <GridEdge> edges = new List <GridEdge>(8);

            graph.GetEdges(x, y, edges, weights);

            if (edges.Count != 0)
            {
                foreach (GridEdge edge in edges)
                {
                    queue.Push(edge);
                }

                edges.Clear();
            }

            while (queue.Count != 0)
            {
                GridEdge edge = queue.Pop();

                Vector2i v = edge.To;
                if (search.IsVisited[v.x, v.y])
                {
                    continue;
                }

                search.Order.Add(v);
                search.IsVisited[v.x, v.y] = true;
                search.Parent[v.x, v.y]    = edge.From;

                if (graph.Edges[v.x, v.y] == 0)
                {
                    continue;
                }

                graph.GetEdges(v.x, v.y, edges, weights);

                foreach (GridEdge e in edges)
                {
                    if (search.IsVisited[e.To.x, e.To.y])
                    {
                        continue;
                    }
                    queue.Push(e);
                }

                edges.Clear();
            }
        }
Exemplo n.º 2
0
    public GridEdge <T, U> AddEdge(GridNode <T, U> from, GridNode <T, U> to, U data)
    {
        GridEdge <T, U> newEdge = new GridEdge <T, U>(from, to, data);

        from.Edges[newEdge.Direction] = newEdge;
        _edgeCount++;

        return(newEdge);
    }
Exemplo n.º 3
0
        //간선을 추가한다.
        public void AddEdge(GridEdge newEdge)
        {
            //목적지가 같은 Edge를 허용하지 않음.
            foreach (GridEdge gridEdge in edges)
            {
                if (gridEdge.EndVertexGrid == newEdge.EndVertexGrid)
                {
                    throw new System.NotSupportedException();
                }
            }

            edges.Add(newEdge);
        }
Exemplo n.º 4
0
    /// <summary>
    /// Adds the edge data to the cell at startXYZ + cornerOffsetXYZ if it exists (not out of range)
    /// return the cell so we can preprocess for meshing?
    /// </summary>
    public GridCell AddToCellQEF(GridEdge e, int sx, int sy, int sz, int cox, int coy, int coz)
    {
        int x = sx + cox;
        int y = sy + coy;
        int z = sz + coz;

        if (x >= 0 && x < subdivisions &&
            y >= 0 && y < subdivisions &&
            z >= 0 && z < subdivisions)
        {
            //it exists
            GridCell cell = cells[x, y, z];
            cell.AddQEF(e.intersection, e.normal);
            return(cell);
        }
        else
        {
            //NOPE! Chuck Testa
            return(null);
        }
    }
Exemplo n.º 5
0
        public void JoiningEdge_NeighborNodes_Edge()
        {
            Vec2     position = new Vec2(3, 3);
            GridNode node     = _grid[position];

            IPathfindingEdge joiningEdge = node.JoiningEdge(_grid[position + Direction.N]);
            IPathfindingEdge edge        = new GridEdge(position, Direction.N);

            Assert.AreEqual(edge, joiningEdge);

            joiningEdge = node.JoiningEdge(_grid[position + Direction.W]);
            edge        = new GridEdge(position, Direction.W);
            Assert.AreEqual(edge, joiningEdge);

            joiningEdge = node.JoiningEdge(_grid[position + Direction.E]);
            edge        = new GridEdge(new Vec2(position.x + 1, position.y), Direction.W);
            Assert.AreEqual(edge, joiningEdge);

            joiningEdge = node.JoiningEdge(_grid[position + Direction.S]);
            edge        = new GridEdge(new Vec2(position.x, position.y + 1), Direction.N);
            Assert.AreEqual(edge, joiningEdge);

            joiningEdge = node.JoiningEdge(_grid[position + Direction.NW]);
            edge        = new GridVertex(position);
            Assert.AreEqual(edge, joiningEdge);

            joiningEdge = node.JoiningEdge(_grid[position + Direction.NE]);
            edge        = new GridVertex(new Vec2(position.x + 1, position.y));
            Assert.AreEqual(edge, joiningEdge);

            joiningEdge = node.JoiningEdge(_grid[position + Direction.SW]);
            edge        = new GridVertex(new Vec2(position.x, position.y + 1));
            Assert.AreEqual(edge, joiningEdge);

            joiningEdge = node.JoiningEdge(_grid[position + Direction.SE]);
            edge        = new GridVertex(new Vec2(position.x + 1, position.y + 1));
            Assert.AreEqual(edge, joiningEdge);
        }
Exemplo n.º 6
0
 public virtual void Insert(Control item, Control existui, GridEdge at, int xspan, int yspan, int hexpand, HorizontalAlignment halign, int vexpand, VerticalAlignment valign)
 {
     NativeMethods.GridInsertAt(Owner.handle, item.handle, existui.handle, at, xspan, yspan, hexpand, halign, vexpand, valign);
     base.Insert(existui.Index, item);
 }
Exemplo n.º 7
0
 public static extern void GridInsertAt(IntPtr grid, IntPtr child, IntPtr existing, GridEdge at, int xspan, int yspan, int hexpand, HorizontalAlignment halign, int vexpand, VerticalAlignment valign);
Exemplo n.º 8
0
        public void IsTraversable_DoesNotContainMotility_False()
        {
            GridEdge edge = new GridEdge(1f, Motility.Land, Vec2.One, Direction.N);

            Assert.IsFalse(edge.IsTraversable(Motility.Burrow));
        }
Exemplo n.º 9
0
        public void IsTraversable_ContainsMotility_True()
        {
            GridEdge edge = new GridEdge(1f, Motility.Land, Vec2.One, Direction.N);

            Assert.IsTrue(edge.IsTraversable(Motility.Land));
        }
Exemplo n.º 10
0
        public void IsTraversable_UnconstrainedEdge_True()
        {
            GridEdge edge = new GridEdge(1f, Motility.Unconstrained, Vec2.One, Direction.N);

            Assert.IsTrue(edge.IsTraversable(Motility.Land));
        }
Exemplo n.º 11
0
        public void Fill_SetEdge_Equals()
        {
            Vec2            vec2 = new Vec2(2, 2);
            PathfindingGrid grid = new PathfindingGrid(vec2);

            Assert.IsNull(grid[0, 0, Direction.N]);
            Assert.IsNull(grid[0, 0, Direction.W]);
            Assert.IsNull(grid[0, 0, Direction.E]);
            Assert.IsNull(grid[0, 0, Direction.S]);

            Assert.IsNull(grid[0, 1, Direction.N]);
            Assert.IsNull(grid[0, 1, Direction.W]);
            Assert.IsNull(grid[0, 1, Direction.E]);
            Assert.IsNull(grid[0, 1, Direction.S]);

            Assert.IsNull(grid[1, 0, Direction.N]);
            Assert.IsNull(grid[1, 0, Direction.W]);
            Assert.IsNull(grid[1, 0, Direction.E]);
            Assert.IsNull(grid[1, 0, Direction.S]);

            Assert.IsNull(grid[1, 1, Direction.N]);
            Assert.IsNull(grid[1, 1, Direction.W]);
            Assert.IsNull(grid[1, 1, Direction.E]);
            Assert.IsNull(grid[1, 1, Direction.S]);

            grid.Fill(position => new GridNode(Tiles.Stone, position, grid));
            grid.FillEdges((position, annotation) => new GridEdge(position, annotation));
            //grid.FillVertices((position) => new GridVertex(position));

            Assert.IsNotNull(grid[0, 0, Direction.N]);
            Assert.IsNotNull(grid[0, 0, Direction.W]);
            Assert.IsNotNull(grid[0, 0, Direction.E]);
            Assert.IsNotNull(grid[0, 0, Direction.S]);

            Assert.IsNotNull(grid[0, 1, Direction.N]);
            Assert.IsNotNull(grid[0, 1, Direction.W]);
            Assert.IsNotNull(grid[0, 1, Direction.E]);
            Assert.IsNotNull(grid[0, 1, Direction.S]);

            Assert.IsNotNull(grid[1, 0, Direction.N]);
            Assert.IsNotNull(grid[1, 0, Direction.W]);
            Assert.IsNotNull(grid[1, 0, Direction.E]);
            Assert.IsNotNull(grid[1, 0, Direction.S]);

            Assert.IsNotNull(grid[1, 1, Direction.N]);
            Assert.IsNotNull(grid[1, 1, Direction.W]);
            Assert.IsNotNull(grid[1, 1, Direction.E]);
            Assert.IsNotNull(grid[1, 1, Direction.S]);

            Assert.AreEqual(new GridEdge(Vec2.Zero, Direction.N), grid[0, 0, Direction.N]);
            Assert.AreEqual(new GridEdge(Vec2.Zero, Direction.W), grid[0, 0, Direction.W]);
            Assert.AreEqual(new GridEdge(new Vec2(1, 0), Direction.W), grid[0, 0, Direction.E]);
            Assert.AreEqual(new GridEdge(new Vec2(0, 1), Direction.N), grid[0, 0, Direction.S]);

            Assert.AreEqual(new GridEdge(new Vec2(0, 1), Direction.N), grid[0, 1, Direction.N]);
            Assert.AreEqual(new GridEdge(new Vec2(0, 1), Direction.W), grid[0, 1, Direction.W]);
            Assert.AreEqual(new GridEdge(new Vec2(1, 1), Direction.W), grid[0, 1, Direction.E]);

            var expected = new GridEdge(new Vec2(0, 2), Direction.N);
            var actual   = grid[0, 1, Direction.S];

            Assert.AreEqual(new GridEdge(new Vec2(0, 2), Direction.N), grid[0, 1, Direction.S]);

            Assert.AreEqual(new GridEdge(new Vec2(1, 0), Direction.N), grid[1, 0, Direction.N]);
            Assert.AreEqual(new GridEdge(new Vec2(1, 0), Direction.W), grid[1, 0, Direction.W]);
            Assert.AreEqual(new GridEdge(new Vec2(2, 0), Direction.W), grid[1, 0, Direction.E]);
            Assert.AreEqual(new GridEdge(new Vec2(1, 1), Direction.N), grid[1, 0, Direction.S]);

            Assert.AreEqual(new GridEdge(new Vec2(1, 1), Direction.N), grid[1, 1, Direction.N]);
            Assert.AreEqual(new GridEdge(new Vec2(1, 1), Direction.W), grid[1, 1, Direction.W]);
            Assert.AreEqual(new GridEdge(new Vec2(2, 1), Direction.W), grid[1, 1, Direction.E]);
            Assert.AreEqual(new GridEdge(new Vec2(1, 2), Direction.N), grid[1, 1, Direction.S]);
        }
Exemplo n.º 12
0
 protected PathEdge MakePathEdge(GridEdge edge)
 {
     return(new PathEdge(edge.StartLoc, edge.EndLoc));
 }
Exemplo n.º 13
0
    //caxo - corner A x offset
    //cbyo - corner B y offset, etc
    //should be faster to just use ints instead of passing in vec3's, might be negligicable, but isn't too much more compliated
    /// <summary>
    /// Checks the edge created beteween the two points xyz+ cornerAXYZoffset and xyz + cornerBXYZoffset for a sign change between the densities of the corners
    /// if there is a sign change the edge is added to a list and the neighbouring cells that share this edge have the edge added to their QEF solver
    /// </summary>
    public void CheckEdge(int x, int y, int z, int caxo, int cayo, int cazo, int cbxo, int cbyo, int cbzo)
    {
        GridCorner cA = corners[x + caxo, y + cayo, z + cazo];
        GridCorner cB = corners[x + cbxo, y + cbyo, z + cbzo];



        List <GridCell> facesTemp = new List <GridCell>();

        if (cA.density * cB.density <= 0f)  //different sign
        {
            GridEdge e = new GridEdge(cA.position, cB.position);

            int intersectionSteps = 8;
            if (subdivisionLevel == 1)
            {
                intersectionSteps = 16;
            }

            e.intersection = ApproximateEdgeIntersection(cA.position, cB.position, Density, intersectionSteps);
            e.normal       = CalculateSurfaceNormal(e.intersection, Density);
            //e.intersection = e.normal = Vector3.zero;

            edges.Add(e);
            #region swapping and comments
            //need to find every cell that shares this edge so we can do QEF solve stuff per cell
            //get start corner indicies, sorted by smallest corner first
            //then find the direction we're going on (offset from start to end)
            //then just manually find neighbours

            #region swapping logic
            //swap so they're ordred properly
            //could do this in the density block only when we need to
            bool swap = false;
            if (x + caxo < x + cbxo)
            {
                //good
            }
            else if (x + caxo == x + cbxo)    //same check next
            {
                if (y + cayo < y + cbyo)
                {
                    //good
                }
                else if (y + cayo == y + cbyo)    //same, check next
                {
                    if (z + cazo < z + cbzo)
                    {
                        //good
                    }
                    else if (z + cazo == z + cbzo)
                    {
                        //same...all components were the same..  This should never happen
                    }
                    else
                    {
                        swap = true;
                    }
                }
                else
                {
                    swap = true;
                }
            }
            else
            {
                swap = true;
            }
            #endregion

            int sx;
            int sy;
            int sz;
            int dx;
            int dy;
            int dz;

            if (swap)
            {
                sx = x + cbxo;
                sy = y + cbyo;
                sz = z + cbzo;

                dx = (caxo - cbxo);
                dy = (cayo - cbyo);
                dz = (cazo - cbzo);
            }
            else
            {
                sx = x + caxo;
                sy = y + cayo;
                sz = z + cazo;

                dx = (cbxo - caxo);
                dy = (cbyo - cayo);
                dz = (cbzo - cazo);
            }
            #endregion

            //we should have six directions
            if (dx == 1 && dy == 0 && dz == 0)
            {
                //cells offsets [0,0,0] [0,0,-1] [0,-1,-1] [0,-1,0]
                //check each offset to see if it exists (and doesn't cause an out of range error)
                //if it exists add to the QEF and solve and stuff
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, 0, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, 0, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, -1, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, -1, 0));
            }
            else if (dx == -1 && dy == 0 && dz == 0)
            {
                //this case will never happen, because we sort on x first so that the direction is always+.
                //If x *was* to be -, we would have swapped corners
                //but lets just fill it in anyways
                //cells offsets [-1,0,0] [-1,0,-1] [-1,-1,-1] [-1,-1,0]
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, 0, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, 0, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, -1, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, -1, 0));
            }
            else if (dx == 0 && dy == 1 && dz == 0)
            {
                //cell offsets [0,0,-1] [0,0,0] [-1,0,0] [-1,0,-1]
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, 0, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, 0, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, 0, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, 0, -1));
            }
            else if (dx == 0 && dy == -1 && dz == 0)
            {
                //cell offsets [0,-1,0] [0,-1,-1] [-1,-1,-1] [-1,-1,0]
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, -1, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, -1, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, -1, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, -1, -1));
            }
            else if (dx == 0 && dy == 0 && dz == 1)
            {
                //cell offsets [0,0,0] [0,-1,0] [-1,-1,0] [-1,0,0]
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, 0, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, -1, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, -1, 0));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, 0, 0));
            }
            else if (dx == 0 && dy == 0 && dz == -1)
            {
                //cell offsets [0,0,-1] [0,-1,-1] [-1,-1,-1] [-1,0,-1]
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, 0, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, 0, -1, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, -1, -1));
                facesTemp.Add(AddToCellQEF(e, sx, sy, sz, -1, 0, -1));
            }

            if (facesTemp.Count == 4)
            {
                facesTemp.Sort();
                //need to sort the faces so we don't get any duplicates
                //and then we need to check to make sure the faces list doesn't contain this face
                GridCell ft0 = facesTemp[0];
                //Debug.Log(ft0 == null);
                //Debug.Log(ft0.cellIndex == null);
                Vector3 index = new Vector3(ft0.cellIndex.x, ft0.cellIndex.y, ft0.cellIndex.z);

                List <GridFace> fl = null;
                if (faces.ContainsKey(index))
                {
                    fl = faces[index];
                }

                //we need to check every element in FL to make sure we don't already have this face

                if (fl == null)
                {
                    //cant check because this face doesn't have a spot in the list yet
                    //so we can just add it because it doesn't exist, so this will be the first one
                    fl = new List <GridFace>();
                    GridFace f = new GridFace();
                    f.faces.Add(facesTemp[0]);
                    f.faces.Add(facesTemp[1]);
                    f.faces.Add(facesTemp[2]);
                    f.faces.Add(facesTemp[3]);
                    fl.Add(f);
                    faces[index] = fl;
                }
                else
                {
                    if (fl.Count == 0)
                    {
                        //cant check.  For some reason the list was created, but never added to
                        //add because it doesn't exist yet
                        GridFace f = new GridFace();
                        f.faces.Add(facesTemp[0]);
                        f.faces.Add(facesTemp[1]);
                        f.faces.Add(facesTemp[2]);
                        f.faces.Add(facesTemp[3]);
                        fl.Add(f);
                    }
                    else
                    {
                        for (int i = 0; i < fl.Count; i++)
                        {
                            //we can skip checking facesTemp[0].cellIndex against fl[0][0] because we know they're the same
                            //because that's how we sort the main list anyways
                            if (fl[i].faces[1] == facesTemp[1])
                            {
                                //second cell is the same
                                if (fl[i].faces[2] == facesTemp[2])
                                {
                                    //third cell is the same
                                    if (fl[i].faces[3] == facesTemp[3])
                                    {
                                        //last cell is the same... all match, so we don't want to add this faceTemp to the real list
                                        //because it will be a duplicate
                                    }
                                    else
                                    {
                                        //diff
                                        GridFace f = new GridFace();
                                        f.faces.Add(facesTemp[0]);
                                        f.faces.Add(facesTemp[1]);
                                        f.faces.Add(facesTemp[2]);
                                        f.faces.Add(facesTemp[3]);
                                        fl.Add(f);
                                        break;
                                    }
                                }
                                else
                                {
                                    //diff
                                    GridFace f = new GridFace();
                                    f.faces.Add(facesTemp[0]);
                                    f.faces.Add(facesTemp[1]);
                                    f.faces.Add(facesTemp[2]);
                                    f.faces.Add(facesTemp[3]);
                                    fl.Add(f);
                                    break;
                                }
                            }
                            else
                            {
                                //diff
                                GridFace f = new GridFace();
                                f.faces.Add(facesTemp[0]);
                                f.faces.Add(facesTemp[1]);
                                f.faces.Add(facesTemp[2]);
                                f.faces.Add(facesTemp[3]);
                                fl.Add(f);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
        public GridCell(Vector3 center, float gridScale = 1f)
        {
            QefSolver qef = new QefSolver();

            //check each corner against the density function
            //and generate SOMETHING at that position to see if our density function is right
            //we can cache the results from each corner, as we need to check every one anyways
            //is there a smarter way
            //we can have up to 4 sign changes per cell..
            // 0 ---- 1
            // |      |
            // 1------0  <---- opposite for the top face = 4 total


            //get corner positions
            //take the center (int coords), convert them to world positions, then +/- on every axis
            this.gridScale = gridScale;
            worldPos       = center * gridScale;

            //need to do corners in the same order every time
            //assign the corners to their density value at that corner position
            for (int i = 0; i < 8; i++)
            {
                float v = DualContouring1.density(worldPos + DualContouring1.cornerOffsets[i] * 0.5f * gridScale);
                //thresholding here to turn the density into an ID
                corners[i] = v >= 0 ? 1 : 0;
            }

            //check if any edges have sign changes
            //I guess only store the edges that are important, like the ones that have a sign change.
            //we need to check every corner against it's neighbour cells, so we need to know which ones are it's neighbours.
            //Each corner has three neighbours,
            for (int i = 0; i < 4; i++)  //but we only want to check half of them, otherwise we have doubles?
            {
                for (int j = 0; j < 3; j++)
                {
                    int neighbour = cornerNeighbours[i, j];
                    if (corners[i] != corners[neighbour])  //if this corner has a different density value than any of it's neighbours
                    //we need to be able to find neighbours based on edges...
                    //not sure how
                    //make a naive implimentation first
                    {
                        GridEdge e = new GridEdge(i, neighbour, center);

                        edges.Add(e);
                        DualContouring1.edges.Add(e);

                        Vector3 edgeCornerA = worldPos + DualContouring1.cornerOffsets[e.corners[0]] * 0.5f * gridScale;
                        Vector3 edgeCornerB = worldPos + DualContouring1.cornerOffsets[e.corners[1]] * 0.5f * gridScale;
                        //need these for meshing to find shared edges I guess
                        e.cornersOffset[0] = DualContouring1.cornerOffsets[e.corners[0]];
                        e.cornersOffset[1] = DualContouring1.cornerOffsets[e.corners[1]];
                        //computing the intersection position and normal of this edge against the density function
                        e.position = DualContouring1.ApproximateEdgeIntersection(edgeCornerA, edgeCornerB, DualContouring1.density);
                        e.normal   = DualContouring1.CalculateSurfaceNormal(e.position, DualContouring1.density);

                        //from here we have to get the actual position of the vertex for this cell
                        //we do this using the QefSolver.  For every edge intersection add the position and normal
                        qef.add(e.position, e.normal);
                        //add the normal so we can grab it later (summed, so we have to grab normal/edges.Count
                        normal += e.normal;
                        Debug.Log("1");
                    }
                }
            }

            if (edges.Count != 0)
            {
                vertex = Vector3.zero;
                qef.solve(vertex, QEF_ERROR, QEF_SWEEPS, QEF_ERROR);
                Vector3 min = center + DualContouring1.cornerOffsets[0] * 0.5f * gridScale;
                Vector3 max = center + DualContouring1.cornerOffsets[6] * 0.5f * gridScale;

                if (vertex.x < min.x || vertex.x > max.x ||
                    vertex.y < min.y || vertex.y > max.y ||
                    vertex.z < min.z || vertex.z > max.z)
                {
                    vertex = qef.getMassPoint();
                }
                DualContouring1.verticies.Add(new MeshVertex(vertex, (normal / edges.Count).normalized));
                vertexIndex = DualContouring1.verticies.Count - 1;
                if (vertex == Vector3.zero)
                {
                    Debug.Log("Zero");
                }
                Debug.Log("2");
                hasVertex = true;
            }
        }