Exemple #1
0
        public static void ClusterEdge(OctreeNode[] nodes, int direction, ref int surface_index, List<Vertex> collected_vertices)
        {
            if ((nodes[0] == null || nodes[0].type != NodeType.Internal) && (nodes[1] == null || nodes[1].type != NodeType.Internal) && (nodes[2] == null || nodes[2].type != NodeType.Internal) && (nodes[3] == null || nodes[3].type != NodeType.Internal))
            {
                ClusterIndexes(nodes, direction, ref surface_index, collected_vertices);
            }
            else
            {
                for (int i = 0; i < 2; i++)
                {
                    OctreeNode[] edge_nodes = new OctreeNode[4];

                    for (int j = 0; j < 4; j++)
                    {
                        if (nodes[j] == null)
                            continue;
                        if (nodes[j].type == NodeType.Leaf)
                            edge_nodes[j] = nodes[j];
                        else
                            edge_nodes[j] = nodes[j].children[Utilities.TEdgeProcEdgeMask[direction, i, j]];
                    }

                    ClusterEdge(edge_nodes, Utilities.TEdgeProcEdgeMask[direction, i, 4], ref surface_index, collected_vertices);
                }
            }
        }
Exemple #2
0
        public override long Contour(float threshold)
        {
            Stopwatch watch = new Stopwatch();

            watch.Start();
            if (tree == null)
            {
                VerticesDN.Clear();
                tree = new OctreeNode();
                List<VertexPositionColorNormalNormal> vs = new List<VertexPositionColorNormalNormal>();

                tree.ConstructBase(Resolution, 0, ref vs);
                tree.ClusterCellBase(0);
                //VerticesDN = vs.ToList();

                tree.GenerateVertexBuffer(VerticesDN);

                if (VerticesDN.Count > 0)
                    VertexBuffer.SetData<VertexPositionColorNormalNormal>(VerticesDN.ToArray());
                VertexCount = VerticesDN.Count;
            }

            OutlineLocation = 0;
            //ConstructTreeGrid(tree);
            CalculateIndexes(threshold);
            watch.Stop();

            return watch.ElapsedMilliseconds;
        }
Exemple #3
0
        public void ConstructTreeGrid(OctreeNode node)
        {
            if (node == null)
                return;
            VertexPositionColor[] vs = new VertexPositionColor[24];
            int x = (int)node.position.X;
            int y = (int)node.position.Y;
            int z = (int)node.position.Z;
            Color c = Color.LightSteelBlue;
            Color v = Color.Red;

            float size = node.size;

            vs[0] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 0 * size), c);
            vs[1] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 0 * size), c);
            vs[2] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 0 * size), c);
            vs[3] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 0 * size), c);
            vs[4] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 0 * size), c);
            vs[5] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 0 * size), c);
            vs[6] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 0 * size), c);
            vs[7] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 0 * size), c);

            vs[8] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 1 * size), c);
            vs[9] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 1 * size), c);
            vs[10] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 1 * size), c);
            vs[11] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 1 * size), c);
            vs[12] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 1 * size), c);
            vs[13] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 1 * size), c);
            vs[14] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 1 * size), c);
            vs[15] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 1 * size), c);

            vs[16] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 0 * size), c);
            vs[17] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 1 * size), c);
            vs[18] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 0 * size), c);
            vs[19] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 1 * size), c);

            vs[20] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 0 * size), c);
            vs[21] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 1 * size), c);
            vs[22] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 0 * size), c);
            vs[23] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 1 * size), c);

            OutlineBuffer.SetData<VertexPositionColor>(OutlineLocation * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 24, VertexPositionColor.VertexDeclaration.VertexStride);
            OutlineLocation += 24;

            /*if (node.type != OctreeNodeType.Leaf || node.draw_info.index == -1 || true)
            {
                OutlineBuffer.SetData<VertexPositionColor>(outline_location * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 8, VertexPositionColor.VertexDeclaration.VertexStride);
                outline_location += 8;
            }
            else
            {
                x += (int)(node.draw_info.position.X * (float)this.size);
                y += (int)(node.draw_info.position.Y * (float)this.size);
                float r = 2;
                vs[8] = new VertexPositionColor(new Vector3(x - r, y - r, 0), v);
                vs[9] = new VertexPositionColor(new Vector3(x + r, y - r, 0), v);
                vs[10] = new VertexPositionColor(new Vector3(x + r, y - r, 0), v);
                vs[11] = new VertexPositionColor(new Vector3(x + r, y + r, 0), v);
                vs[12] = new VertexPositionColor(new Vector3(x + r, y + r, 0), v);
                vs[13] = new VertexPositionColor(new Vector3(x - r, y + r, 0), v);
                vs[14] = new VertexPositionColor(new Vector3(x - r, y + r, 0), v);
                vs[15] = new VertexPositionColor(new Vector3(x - r, y - r, 0), v);
                OutlineBuffer.SetData<VertexPositionColor>(outline_location * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 16, VertexPositionColor.VertexDeclaration.VertexStride);
                outline_location += 16;
            }*/

            if (node.type == NodeType.Internal && node.vertices.Length == 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    ConstructTreeGrid(node.children[i]);
                }
            }
        }
Exemple #4
0
        public void ConstructTreeGrid(OctreeNode node)
        {
            if (node == null)
            {
                return;
            }
            VertexPositionColor[] vs = new VertexPositionColor[24];
            int   x = (int)node.position.X;
            int   y = (int)node.position.Y;
            int   z = (int)node.position.Z;
            Color c = Color.LightSteelBlue;
            Color v = Color.Red;

            float size = node.size;

            /*vs[0] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 0 * size), c);
             * vs[1] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 0 * size), c);
             * vs[2] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 0 * size), c);
             * vs[3] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 0 * size), c);
             * vs[4] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 0 * size), c);
             * vs[5] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 0 * size), c);
             * vs[6] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 0 * size), c);
             * vs[7] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 0 * size), c);
             *
             * vs[8] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 1 * size), c);
             * vs[9] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 1 * size), c);
             * vs[10] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 1 * size), c);
             * vs[11] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 1 * size), c);
             * vs[12] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 1 * size), c);
             * vs[13] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 1 * size), c);
             * vs[14] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 1 * size), c);
             * vs[15] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 1 * size), c);
             *
             * vs[16] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 0 * size), c);
             * vs[17] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, z + 1 * size), c);
             * vs[18] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 0 * size), c);
             * vs[19] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, z + 1 * size), c);
             *
             * vs[20] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 0 * size), c);
             * vs[21] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, z + 1 * size), c);
             * vs[22] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 0 * size), c);
             * vs[23] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, z + 1 * size), c);
             *
             * OutlineBuffer.SetData<VertexPositionColor>(OutlineLocation * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 24, VertexPositionColor.VertexDeclaration.VertexStride);
             * OutlineLocation += 24;*/

            /*if (node.type != OctreeNodeType.Leaf || node.draw_info.index == -1 || true)
             * {
             *      OutlineBuffer.SetData<VertexPositionColor>(outline_location * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 8, VertexPositionColor.VertexDeclaration.VertexStride);
             *      outline_location += 8;
             * }
             * else
             * {
             *      x += (int)(node.draw_info.position.X * (float)this.size);
             *      y += (int)(node.draw_info.position.Y * (float)this.size);
             *      float r = 2;
             *      vs[8] = new VertexPositionColor(new Vector3(x - r, y - r, 0), v);
             *      vs[9] = new VertexPositionColor(new Vector3(x + r, y - r, 0), v);
             *      vs[10] = new VertexPositionColor(new Vector3(x + r, y - r, 0), v);
             *      vs[11] = new VertexPositionColor(new Vector3(x + r, y + r, 0), v);
             *      vs[12] = new VertexPositionColor(new Vector3(x + r, y + r, 0), v);
             *      vs[13] = new VertexPositionColor(new Vector3(x - r, y + r, 0), v);
             *      vs[14] = new VertexPositionColor(new Vector3(x - r, y + r, 0), v);
             *      vs[15] = new VertexPositionColor(new Vector3(x - r, y - r, 0), v);
             *      OutlineBuffer.SetData<VertexPositionColor>(outline_location * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 16, VertexPositionColor.VertexDeclaration.VertexStride);
             *      outline_location += 16;
             * }*/

            if (node.type == NodeType.Internal && node.vertices.Length == 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    ConstructTreeGrid(node.children[i]);
                }
            }
        }
Exemple #5
0
        public static void ClusterFace(OctreeNode[] nodes, int direction, ref int surface_index, List <Vertex> collected_vertices)
        {
            if (nodes[0] == null || nodes[1] == null)
            {
                return;
            }

            if (nodes[0].type != NodeType.Leaf || nodes[1].type != NodeType.Leaf)
            {
                for (int i = 0; i < 4; i++)
                {
                    OctreeNode[] face_nodes = new OctreeNode[2];

                    for (int j = 0; j < 2; j++)
                    {
                        if (nodes[j] == null)
                        {
                            continue;
                        }
                        if (nodes[j].type != NodeType.Internal)
                        {
                            face_nodes[j] = nodes[j];
                        }
                        else
                        {
                            face_nodes[j] = nodes[j].children[Utilities.TFaceProcFaceMask[direction, i, j]];
                        }
                    }

                    ClusterFace(face_nodes, Utilities.TFaceProcFaceMask[direction, i, 2], ref surface_index, collected_vertices);
                }
            }

            int[,] orders =
            {
                { 0, 0, 1, 1 },
                { 0, 1, 0, 1 },
            };

            for (int i = 0; i < 4; i++)
            {
                OctreeNode[] edge_nodes = new OctreeNode[4];

                for (int j = 0; j < 4; j++)
                {
                    if (nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]] == null)
                    {
                        continue;
                    }
                    if (nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]].type != NodeType.Internal)
                    {
                        edge_nodes[j] = nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]];
                    }
                    else
                    {
                        edge_nodes[j] = nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]].children[Utilities.TFaceProcEdgeMask[direction, i, 1 + j]];
                    }
                }

                ClusterEdge(edge_nodes, Utilities.TFaceProcEdgeMask[direction, i, 5], ref surface_index, collected_vertices);
            }
        }
Exemple #6
0
        /*
         * Cell stage
         */
        public void ClusterCell(float error)
        {
            if (type != NodeType.Internal)
            {
                return;
            }

            /*
             * First cluster all the children nodes
             */

            int[] signs    = { -1, -1, -1, -1, -1, -1, -1, -1 };
            int   mid_sign = -1;

            bool is_collapsible = true;

            for (int i = 0; i < 8; i++)
            {
                if (children[i] == null)
                {
                    continue;
                }

                children[i].ClusterCell(error);
                if (children[i].type == NodeType.Internal)                 //Can't cluster if the child has children
                {
                    is_collapsible = false;
                }
                else
                {
                    mid_sign = (children[i].corners >> (7 - i)) & 1;
                    signs[i] = (children[i].corners >> i) & 1;
                }
            }

            corners = 0;
            for (int i = 0; i < 8; i++)
            {
                if (signs[i] == -1)
                {
                    corners |= (byte)(mid_sign << i);
                }
                else
                {
                    corners |= (byte)(signs[i] << i);
                }
            }

            //if (!is_collapsible)
            //	return;

            int           surface_index      = 0;
            List <Vertex> collected_vertices = new List <Vertex>();
            List <Vertex> new_vertices       = new List <Vertex>();



            if (index == 31681)
            {
            }
            if (index == 61440)
            {
            }
            if (index == 7715)
            {
            }

            if ((int)position.X == 12 && (int)position.Y == 18 && (int)position.Z == 26)
            {
            }

            /*
             * Find all the surfaces inside the children that cross the 6 Euclidean edges and the vertices that connect to them
             */
            for (int i = 0; i < 12; i++)
            {
                OctreeNode[] face_nodes = new OctreeNode[2];

                int c1 = Utilities.TEdgePairs[i, 0];
                int c2 = Utilities.TEdgePairs[i, 1];

                face_nodes[0] = children[c1];
                face_nodes[1] = children[c2];

                ClusterFace(face_nodes, Utilities.TEdgePairs[i, 2], ref surface_index, collected_vertices);
            }


            for (int i = 0; i < 6; i++)
            {
                OctreeNode[] edge_nodes =
                {
                    children[Utilities.TCellProcEdgeMask[i, 0]],
                    children[Utilities.TCellProcEdgeMask[i, 1]],
                    children[Utilities.TCellProcEdgeMask[i, 2]],
                    children[Utilities.TCellProcEdgeMask[i, 3]]
                };
                if (size == 4 && i == 1)
                {
                }
                ClusterEdge(edge_nodes, Utilities.TCellProcEdgeMask[i, 4], ref surface_index, collected_vertices);
            }

            if (size == 16 && position.X == 0 && position.Y == 16 && position.Z == 16)
            {
            }
            if (index == 61440)
            {
            }

            int highest_index = surface_index;

            if (highest_index == -1)
            {
                highest_index = 0;
            }

            /*
             * Gather the stray vertices
             */
            foreach (OctreeNode n in children)
            {
                if (n == null)
                {
                    continue;
                }
                foreach (Vertex v in n.vertices)
                {
                    if (v == null)
                    {
                        continue;
                    }
                    if (v.surface_index == -1)
                    {
                        v.surface_index = highest_index++;
                        collected_vertices.Add(v);
                    }
                }
            }
            //GatherVertices(this, collected_vertices, ref highest_index);

            //if (surface_index == 0 && highest_index > 1)
            //	return;

            if (highest_index == 7)
            {
            }

            int clustered_count = 0;

            if (collected_vertices.Count > 0)
            {
                for (int i = 0; i <= highest_index; i++)
                {
                    QEFProper.QEFSolver qef    = new QEFProper.QEFSolver();
                    Vector3             normal = Vector3.Zero;
                    int   count = 0;
                    int[] edges = new int[12];
                    int   euler = 0;
                    int   e     = 0;
                    foreach (Vertex v in collected_vertices)
                    {
                        if (v.surface_index == i)
                        {
                            /*if (!v.qef.hasSolution)
                             *      v.qef.Solve(1e-6f, 4, 1e-6f);
                             * if (v.qef.GetError() > error)
                             * {
                             *      count = 0;
                             *      break;
                             * }*/

                            /* Calculate ei(Sv) */
                            for (int k = 0; k < 3; k++)
                            {
                                int edge = Utilities.TExternalEdges[v.in_cell, k];
                                edges[edge] += v.eis[edge];
                            }
                            /* Calculate e(Svk) */
                            for (int k = 0; k < 9; k++)
                            {
                                int edge = Utilities.TInternalEdges[v.in_cell, k];
                                e += v.eis[edge];
                            }

                            euler += v.euler;
                            qef.Add(ref v.qef.data);
                            normal += v.normal;
                            count++;
                        }
                    }

                    /*
                     * One vertex might have an error greater than the threshold, preventing simplification.
                     * When it's just one, we can ignore the error and proceed.
                     */
                    if (count == 0)
                    {
                        continue;
                    }

                    bool face_prop2 = true;
                    for (int f = 0; f < 6 && face_prop2; f++)
                    {
                        int intersections = 0;
                        for (int ei = 0; ei < 4; ei++)
                        {
                            intersections += edges[Utilities.TFaces[f, ei]];
                        }
                        if (!(intersections == 0 || intersections == 2))
                        {
                            face_prop2 = false;
                        }
                    }

                    Vertex new_vertex = new Vertex();
                    normal /= (float)count;
                    normal.Normalize();
                    new_vertex.normal = normal;
                    new_vertex.qef    = qef;
                    new_vertex.eis    = edges;
                    new_vertex.euler  = euler - e / 4;
                    if (new_vertex.euler != 1)
                    {
                    }
                    new_vertex.in_cell    = this.child_index;
                    new_vertex.face_prop2 = face_prop2;
                    if (face_prop2)
                    {
                    }
                    if (new_vertex.euler != 1)
                    {
                    }
                    new_vertices.Add(new_vertex);
                    //new_vertex.index = rnd.Next();

                    qef.Solve(1e-6f, 4, 1e-6f);
                    float err = qef.GetError();
                    new_vertex.collapsible = err <= error /* && new_vertex.euler == 1 && face_prop2*/;
                    new_vertex.error       = err;
                    clustered_count++;

                    if (count > 4)
                    {
                    }

                    foreach (Vertex v in collected_vertices)
                    {
                        if (v.surface_index == i)
                        {
                            Vertex p = v;
                            //p.surface_index = -1;

                            /*while (p.parent != null)
                             * {
                             *      p = p.parent;
                             *      //p.surface_index = -1;
                             *      if (p == p.parent)
                             *      {
                             *              p.parent = null;
                             *              break;
                             *      }
                             * }*/
                            if (p != new_vertex)
                            {
                                p.parent = new_vertex;
                            }
                            else
                            {
                                p.parent = null;
                            }
                        }
                    }
                }
            }
            else
            {
                return;
            }

            if (new_vertices.Count >= collected_vertices.Count)
            {
            }

            //if (clustered_count <= 0)
            {
                foreach (Vertex v2 in collected_vertices)
                {
                    v2.surface_index = -1;
                }
            }

            //this.type = NodeType.Collapsed;
            //for (int i = 0; i < 8; i++)
            //	children[i] = null;
            this.vertices = new_vertices.ToArray();
            if (this.vertices.Length > 4)
            {
            }
        }
Exemple #7
0
        public bool ConstructNodes(List <VertexPositionColorNormalNormal> vertices, ref int n_index, int threaded = 0)
        {
            if (size == 1)
            {
                return(ConstructLeaf(ref vertices, ref n_index));
            }

            type = NodeType.Internal;
            int  child_size   = size / 2;
            bool has_children = false;

            //Task[] threads = new Task[8];
            bool[] return_values = new bool[8];

            for (int i = 0; i < 8; i++)
            {
                this.index = n_index++;
                Vector3 child_pos = Utilities.TCornerDeltas[i];
                children[i]             = new OctreeNode(position + child_pos * (float)child_size, child_size, NodeType.Internal);
                children[i].child_index = i;

                int index = i;

                /*if (threaded > 0 && size > 2)
                 * {
                 *      threads[index] = Task.Factory.StartNew(
                 *              () =>
                 *              {
                 *                      int temp = 0;
                 *                      return_values[index] = children[index].ConstructNodes(vertices, ref temp, threaded - 1);
                 *                      if (!return_values[index])
                 *                              children[index] = null;
                 *              }, TaskCreationOptions.AttachedToParent);
                 *      //threads[index].Start();
                 * }*/
                if (size > 2)
                {
                    int temp = 0;
                    return_values[index] = children[index].ConstructNodes(vertices, ref temp, threaded - 1);
                    if (!return_values[index])
                    {
                        children[index] = null;
                    }
                    //threads[index].Start();
                }
                else
                {
                    if (children[i].ConstructNodes(vertices, ref n_index, 0))
                    {
                        has_children = true;
                    }
                    else
                    {
                        children[i] = null;
                    }
                }
            }

            if (size > 2)
            {
                for (int i = 0; i < 8; i++)
                {
                    //threads[i].Wait();
                    if (return_values[i])
                    {
                        has_children = true;
                    }
                }
            }

            /*if (threaded > 0 && size > 2)
             * {
             *      for (int i = 0; i < 8; i++)
             *      {
             *              threads[i].Wait();
             *              if (return_values[i])
             *                      has_children = true;
             *      }
             * }*/

            return(has_children);
        }
Exemple #8
0
        public bool ConstructNodes(List<VertexPositionColorNormalNormal> vertices, ref int n_index, int threaded = 0)
        {
            if (size == 1)
                return ConstructLeaf(ref vertices, ref n_index);

            type = NodeType.Internal;
            int child_size = size / 2;
            bool has_children = false;

            Task[] threads = new Task[8];
            bool[] return_values = new bool[8];

            for (int i = 0; i < 8; i++)
            {
                this.index = n_index++;
                Vector3 child_pos = Utilities.TCornerDeltas[i];
                children[i] = new OctreeNode(position + child_pos * (float)child_size, child_size, NodeType.Internal);
                children[i].child_index = i;

                int index = i;
                if (threaded > 0 && size > 2)
                {
                    threads[index] = Task.Factory.StartNew(
                        () =>
                        {
                            int temp = 0;
                            return_values[index] = children[index].ConstructNodes(vertices, ref temp, threaded - 1);
                            if (!return_values[index])
                                children[index] = null;
                        }, TaskCreationOptions.AttachedToParent);
                    //threads[index].Start();
                }
                else
                {
                    if (children[i].ConstructNodes(vertices, ref n_index, 0))
                        has_children = true;
                    else
                        children[i] = null;
                }
            }

            if (threaded > 0 && size > 2)
            {
                for (int i = 0; i < 8; i++)
                {
                    threads[i].Wait();
                    if (return_values[i])
                        has_children = true;
                }
            }

            return has_children;
        }
Exemple #9
0
        /*
         * Cell stage
         */
        public void ClusterCell(float error)
        {
            if (type != NodeType.Internal)
                return;

            /*
             * First cluster all the children nodes
             */

            int[] signs = { -1, -1, -1, -1, -1, -1, -1, -1 };
            int mid_sign = -1;

            bool is_collapsible = true;
            for (int i = 0; i < 8; i++)
            {
                if (children[i] == null)
                    continue;

                children[i].ClusterCell(error);
                if (children[i].type == NodeType.Internal) //Can't cluster if the child has children
                    is_collapsible = false;
                else
                {
                    mid_sign = (children[i].corners >> (7 - i)) & 1;
                    signs[i] = (children[i].corners >> i) & 1;
                }
            }

            corners = 0;
            for (int i = 0; i < 8; i++)
            {
                if (signs[i] == -1)
                    corners |= (byte)(mid_sign << i);
                else
                    corners |= (byte)(signs[i] << i);
            }

            //if (!is_collapsible)
            //	return;

            int surface_index = 0;
            List<Vertex> collected_vertices = new List<Vertex>();
            List<Vertex> new_vertices = new List<Vertex>();

            if (index == 31681)
            {
            }
            if (index == 61440)
            {
            }
            if (index == 7715)
            {
            }

            if ((int)position.X == 12 && (int)position.Y == 18 && (int)position.Z == 26)
            {
            }

            /*
             * Find all the surfaces inside the children that cross the 6 Euclidean edges and the vertices that connect to them
             */
            for (int i = 0; i < 12; i++)
            {
                OctreeNode[] face_nodes = new OctreeNode[2];

                int c1 = Utilities.TEdgePairs[i, 0];
                int c2 = Utilities.TEdgePairs[i, 1];

                face_nodes[0] = children[c1];
                face_nodes[1] = children[c2];

                ClusterFace(face_nodes, Utilities.TEdgePairs[i, 2], ref surface_index, collected_vertices);
            }

            for (int i = 0; i < 6; i++)
            {
                OctreeNode[] edge_nodes =
                    {
                        children[Utilities.TCellProcEdgeMask[i, 0]],
                        children[Utilities.TCellProcEdgeMask[i, 1]],
                        children[Utilities.TCellProcEdgeMask[i, 2]],
                        children[Utilities.TCellProcEdgeMask[i, 3]]
                    };
                if (size == 4 && i == 1)
                {
                }
                ClusterEdge(edge_nodes, Utilities.TCellProcEdgeMask[i, 4], ref surface_index, collected_vertices);
            }

            if (size == 16 && position.X == 0 && position.Y == 16 && position.Z == 16)
            {
            }
            if (index == 61440)
            {
            }

            int highest_index = surface_index;

            if (highest_index == -1)
                highest_index = 0;
            /*
             * Gather the stray vertices
             */
            foreach (OctreeNode n in children)
            {
                if (n == null)
                    continue;
                foreach (Vertex v in n.vertices)
                {
                    if (v == null)
                        continue;
                    if (v.surface_index == -1)
                    {
                        v.surface_index = highest_index++;
                        collected_vertices.Add(v);
                    }
                }
            }
            //GatherVertices(this, collected_vertices, ref highest_index);

            //if (surface_index == 0 && highest_index > 1)
            //	return;

            if (highest_index == 7)
            {
            }

            int clustered_count = 0;
            if (collected_vertices.Count > 0)
            {

                for (int i = 0; i <= highest_index; i++)
                {
                    QEFProper.QEFSolver qef = new QEFProper.QEFSolver();
                    Vector3 normal = Vector3.Zero;
                    int count = 0;
                    int[] edges = new int[12];
                    int euler = 0;
                    int e = 0;
                    foreach (Vertex v in collected_vertices)
                    {
                        if (v.surface_index == i)
                        {
                            /*if (!v.qef.hasSolution)
                                v.qef.Solve(1e-6f, 4, 1e-6f);
                            if (v.qef.GetError() > error)
                            {
                                count = 0;
                                break;
                            }*/

                            /* Calculate ei(Sv) */
                            for (int k = 0; k < 3; k++)
                            {
                                int edge = Utilities.TExternalEdges[v.in_cell, k];
                                edges[edge] += v.eis[edge];
                            }
                            /* Calculate e(Svk) */
                            for (int k = 0; k < 9; k++)
                            {
                                int edge = Utilities.TInternalEdges[v.in_cell, k];
                                e += v.eis[edge];
                            }

                            euler += v.euler;
                            qef.Add(ref v.qef.data);
                            normal += v.normal;
                            count++;
                        }
                    }

                    /*
                     * One vertex might have an error greater than the threshold, preventing simplification.
                     * When it's just one, we can ignore the error and proceed.
                     */
                    if (count == 0)
                    {
                        continue;
                    }

                    bool face_prop2 = true;
                    for (int f = 0; f < 6 && face_prop2; f++)
                    {
                        int intersections = 0;
                        for (int ei = 0; ei < 4; ei++)
                        {
                            intersections += edges[Utilities.TFaces[f, ei]];
                        }
                        if (!(intersections == 0 || intersections == 2))
                            face_prop2 = false;
                    }

                    Vertex new_vertex = new Vertex();
                    normal /= (float)count;
                    normal.Normalize();
                    new_vertex.normal = normal;
                    new_vertex.qef = qef;
                    new_vertex.eis = edges;
                    new_vertex.euler = euler - e / 4;
                    if (new_vertex.euler != 1)
                    {
                    }
                    new_vertex.in_cell = this.child_index;
                    new_vertex.face_prop2 = face_prop2;
                    if (face_prop2)
                    {
                    }
                    if (new_vertex.euler != 1)
                    {
                    }
                    new_vertices.Add(new_vertex);
                    //new_vertex.index = rnd.Next();

                    qef.Solve(1e-6f, 4, 1e-6f);
                    float err = qef.GetError();
                    new_vertex.collapsible = err <= error/* && new_vertex.euler == 1 && face_prop2*/;
                    new_vertex.error = err;
                    clustered_count++;

                    if (count > 4)
                    {
                    }

                    foreach (Vertex v in collected_vertices)
                    {
                        if (v.surface_index == i)
                        {
                            Vertex p = v;
                            //p.surface_index = -1;
                            /*while (p.parent != null)
                            {
                                p = p.parent;
                                //p.surface_index = -1;
                                if (p == p.parent)
                                {
                                    p.parent = null;
                                    break;
                                }
                            }*/
                            if (p != new_vertex)
                                p.parent = new_vertex;
                            else
                                p.parent = null;
                        }
                    }
                }
            }
            else
            {
                return;
            }

            if (new_vertices.Count >= collected_vertices.Count)
            {
            }

            //if (clustered_count <= 0)
            {
                foreach (Vertex v2 in collected_vertices)
                {
                    v2.surface_index = -1;
                }
            }

            //this.type = NodeType.Collapsed;
            //for (int i = 0; i < 8; i++)
            //	children[i] = null;
            this.vertices = new_vertices.ToArray();
            if (this.vertices.Length > 4)
            {
            }
        }
Exemple #10
0
        public static void ProcessFace(OctreeNode[] nodes, int direction, List<int> indexes, List<int> tri_count, float threshold)
        {
            if (nodes[0] == null || nodes[1] == null)
                return;

            if (nodes[0].type != NodeType.Leaf || nodes[1].type != NodeType.Leaf)
            {
                for (int i = 0; i < 4; i++)
                {
                    OctreeNode[] face_nodes = new OctreeNode[2];

                    for (int j = 0; j < 2; j++)
                    {
                        if (nodes[j].type == NodeType.Leaf)
                            face_nodes[j] = nodes[j];
                        else
                            face_nodes[j] = nodes[j].children[Utilities.TFaceProcFaceMask[direction, i, j]];
                    }

                    ProcessFace(face_nodes, Utilities.TFaceProcFaceMask[direction, i, 2], indexes, tri_count, threshold);
                }

                int[,] orders =
                {
                    { 0, 0, 1, 1 },
                    { 0, 1, 0, 1 },
                };

                for (int i = 0; i < 4; i++)
                {
                    OctreeNode[] edge_nodes = new OctreeNode[4];

                    for (int j = 0; j < 4; j++)
                    {
                        if (nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]].type == NodeType.Leaf)
                            edge_nodes[j] = nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]];
                        else
                            edge_nodes[j] = nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]].children[Utilities.TFaceProcEdgeMask[direction, i, 1 + j]];
                    }

                    ProcessEdge(edge_nodes, Utilities.TFaceProcEdgeMask[direction, i, 5], indexes, tri_count, threshold);
                }
            }
        }
Exemple #11
0
        public static void ProcessIndexes(OctreeNode[] nodes, int direction, List<int> indexes, List<int> tri_count, float threshold)
        {
            int min_size = 10000000;
            int min_index = 0;
            int[] indices = { -1, -1, -1, -1 };
            bool flip = false;
            bool sign_changed = false;
            int v_count = 0;
            //return;

            for (int i = 0; i < 4; i++)
            {
                int edge = Utilities.TProcessEdgeMask[direction, i];
                int c1 = Utilities.TEdgePairs[edge, 0];
                int c2 = Utilities.TEdgePairs[edge, 1];

                int m1 = (nodes[i].corners >> c1) & 1;
                int m2 = (nodes[i].corners >> c2) & 1;

                if (nodes[i].size < min_size)
                {
                    min_size = nodes[i].size;
                    min_index = i;
                    flip = m1 == 1;
                    sign_changed = ((m1 == 0 && m2 != 0) || (m1 != 0 && m2 == 0));
                }

                //if (!((m1 == 0 && m2 != 0) || (m1 != 0 && m2 == 0)))
                //	continue;

                //find the vertex index
                int index = 0;
                bool skip = false;
                if (nodes[i].corners == 179)
                {
                }
                for (int k = 0; k < 16; k++)
                {
                    int e = Utilities.TransformedEdgesTable[nodes[i].corners, k];
                    if (e == -1)
                    {
                        index++;
                        continue;
                    }
                    if (e == -2)
                    {
                        skip = true;
                        break;
                    }
                    if (e == edge)
                        break;
                }

                if (skip)
                    continue;
                if (nodes[i].index == 30733)
                {
                }

                v_count++;
                if (index >= nodes[i].vertices.Length)
                    return;
                Vertex v = nodes[i].vertices[index];
                Vertex highest = v;
                while (highest.parent != null)
                {
                    if ((highest.parent.error <= threshold && (!EnforceManifold || (highest.parent.euler == 1 && highest.parent.face_prop2))))
                        highest = v = highest.parent;
                    else
                        highest = highest.parent;
                }

                //Vector3 p = v.qef.Solve(1e-6f, 4, 1e-6f);
                indices[i] = v.index;
                if (v.index == -1)
                {
                }

                //sign_changed = true;
            }

            if (v_count > 0 && v_count < 4)
            {
            }

            /*
             * Next generate the triangles.
             * Because we're generating from the finest levels that were collapsed, many triangles will collapse to edges or vertices.
             * That's why we check if the indices are different and discard the triangle, as mentioned in the paper.
             */
            if (sign_changed)
            {
                int count = 0;
                if (!flip)
                {
                    if (indices[0] != -1 && indices[1] != -1 && indices[2] != -1 && indices[0] != indices[1] && indices[1] != indices[3])
                    {
                        indexes.Add(indices[0]);
                        indexes.Add(indices[1]);
                        indexes.Add(indices[3]);
                        count++;
                    }

                    if (indices[0] != -1 && indices[2] != -1 && indices[3] != -1 && indices[0] != indices[2] && indices[2] != indices[3])
                    {
                        indexes.Add(indices[0]);
                        indexes.Add(indices[3]);
                        indexes.Add(indices[2]);
                        count++;
                    }
                }
                else
                {
                    if (indices[0] != -1 && indices[3] != -1 && indices[1] != -1 && indices[0] != indices[1] && indices[1] != indices[3])
                    {
                        indexes.Add(0x10000000 | indices[0]);
                        indexes.Add(0x10000000 | indices[3]);
                        indexes.Add(0x10000000 | indices[1]);
                        count++;
                    }

                    if (indices[0] != -1 && indices[2] != -1 && indices[3] != -1 && indices[0] != indices[2] && indices[2] != indices[3])
                    {
                        indexes.Add(0x10000000 | indices[0]);
                        indexes.Add(0x10000000 | indices[2]);
                        indexes.Add(0x10000000 | indices[3]);
                        count++;
                    }
                }

                if (count > 0)
                    tri_count.Add(count);
            }
        }
Exemple #12
0
        public static void ProcessEdge(OctreeNode[] nodes, int direction, List<int> indexes, List<int> tri_count, float threshold)
        {
            if (nodes[0] == null || nodes[1] == null || nodes[2] == null || nodes[3] == null)
                return;

            if (nodes[0].type == NodeType.Leaf && nodes[1].type == NodeType.Leaf && nodes[2].type == NodeType.Leaf && nodes[3].type == NodeType.Leaf)
            {
                ProcessIndexes(nodes, direction, indexes, tri_count, threshold);
            }
            else
            {
                for (int i = 0; i < 2; i++)
                {
                    OctreeNode[] edge_nodes = new OctreeNode[4];

                    for (int j = 0; j < 4; j++)
                    {
                        if (nodes[j].type == NodeType.Leaf)
                            edge_nodes[j] = nodes[j];
                        else
                            edge_nodes[j] = nodes[j].children[Utilities.TEdgeProcEdgeMask[direction, i, j]];
                    }

                    ProcessEdge(edge_nodes, Utilities.TEdgeProcEdgeMask[direction, i, 4], indexes, tri_count, threshold);
                }
            }
        }
Exemple #13
0
 public static void GatherVertices(OctreeNode n, List<Vertex> dest, ref int surface_index)
 {
     if (n == null)
         return;
     if (n.size > 1)
     {
         for (int i = 0; i < 8; i++)
             GatherVertices(n.children[i], dest, ref surface_index);
     }
     else
     {
         foreach (Vertex v in n.vertices)
         {
             if (v.surface_index == -1)
             {
                 v.surface_index = surface_index++;
                 dest.Add(v);
             }
         }
     }
 }
Exemple #14
0
        public static void ClusterIndexes(OctreeNode[] nodes, int direction, ref int max_surface_index, List<Vertex> collected_vertices)
        {
            if (nodes[0] == null && nodes[1] == null && nodes[2] == null && nodes[3] == null)
                return;

            Vertex[] vertices = new Vertex[4];
            int v_count = 0;
            int node_count = 0;

            for (int i = 0; i < 4; i++)
            {
                if (nodes[i] == null)
                    continue;
                if (nodes[i].size > 1)
                {
                }
                node_count++;
                if (nodes[i].vertices.Length > 1)
                {
                }

                int edge = Utilities.TProcessEdgeMask[direction, i];
                int c1 = Utilities.TEdgePairs[edge, 0];
                int c2 = Utilities.TEdgePairs[edge, 1];

                int m1 = (nodes[i].corners >> c1) & 1;
                int m2 = (nodes[i].corners >> c2) & 1;

                //if (!((m1 == 0 && m2 != 0) || (m1 != 0 && m2 == 0)))
                //	continue;

                //find the vertex index
                int index = 0;
                bool skip = false;
                for (int k = 0; k < 16; k++)
                {
                    int e = Utilities.TransformedEdgesTable[nodes[i].corners, k];
                    if (e == -1)
                    {
                        index++;
                        continue;
                    }
                    if (e == -2)
                    {
                        if (!((m1 == 0 && m2 != 0) || (m1 != 0 && m2 == 0)))
                            skip = true;
                        break;
                    }
                    if (e == edge)
                        break;
                }

                if (!skip && index < nodes[i].vertices.Length)
                {
                    if (nodes[i].index == 30733)
                    {
                    }
                    if (nodes[i].index == 12)
                    {
                    }
                    vertices[i] = nodes[i].vertices[index];
                    while (vertices[i].parent != null)
                        vertices[i] = vertices[i].parent;
                    if (i > v_count)
                    {
                    }
                    v_count++;
                }
            }

            if (v_count == 0)
                return;
            if (node_count != v_count)
            {
            }

            if (!(vertices[0] != vertices[1] && vertices[1] != vertices[2] && vertices[2] != vertices[3]))
            {
                //return;
            }

            int surface_index = -1;

            for (int i = 0; i < 4; i++)
            {
                Vertex v = vertices[i];
                if (v == null)
                    continue;
                //while (v != null)
                //{
                if (v.surface_index != -1)
                {
                    if (surface_index != -1 && surface_index != v.surface_index)
                    {
                        AssignSurface(collected_vertices, v.surface_index, surface_index);
                    }
                    else if (surface_index == -1)
                        surface_index = v.surface_index;
                    //break;
                }

                //break;
                //v = v.parent;
                //}
            }

            if (surface_index == -1)
                surface_index = max_surface_index++;

            for (int i = 0; i < 4; i++)
            {
                Vertex v = vertices[i];
                if (v == null)
                    continue;
                //while (v.parent != null)
                //	v = v.parent;
                //while (v != null)
                //{
                if (v.surface_index == -1)
                {
                    collected_vertices.Add(v);
                }
                v.surface_index = surface_index;
                //v = v.parent;
                //}
            }
        }
Exemple #15
0
        public static void ClusterFace(OctreeNode[] nodes, int direction, ref int surface_index, List<Vertex> collected_vertices)
        {
            if (nodes[0] == null || nodes[1] == null)
                return;

            if (nodes[0].type != NodeType.Leaf || nodes[1].type != NodeType.Leaf)
            {
                for (int i = 0; i < 4; i++)
                {
                    OctreeNode[] face_nodes = new OctreeNode[2];

                    for (int j = 0; j < 2; j++)
                    {
                        if (nodes[j] == null)
                            continue;
                        if (nodes[j].type != NodeType.Internal)
                            face_nodes[j] = nodes[j];
                        else
                            face_nodes[j] = nodes[j].children[Utilities.TFaceProcFaceMask[direction, i, j]];
                    }

                    ClusterFace(face_nodes, Utilities.TFaceProcFaceMask[direction, i, 2], ref surface_index, collected_vertices);
                }
            }

            int[,] orders =
                {
                    { 0, 0, 1, 1 },
                    { 0, 1, 0, 1 },
                };

            for (int i = 0; i < 4; i++)
            {
                OctreeNode[] edge_nodes = new OctreeNode[4];

                for (int j = 0; j < 4; j++)
                {
                    if (nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]] == null)
                        continue;
                    if (nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]].type != NodeType.Internal)
                        edge_nodes[j] = nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]];
                    else
                        edge_nodes[j] = nodes[orders[Utilities.TFaceProcEdgeMask[direction, i, 0], j]].children[Utilities.TFaceProcEdgeMask[direction, i, 1 + j]];
                }

                ClusterEdge(edge_nodes, Utilities.TFaceProcEdgeMask[direction, i, 5], ref surface_index, collected_vertices);
            }
        }
Exemple #16
0
        public void ProcessCell(List<int> indexes, List<int> tri_count, float threshold)
        {
            if (type == NodeType.Internal)
            {
                for (int i = 0; i < 8; i++)
                {
                    if (children[i] != null)
                        children[i].ProcessCell(indexes, tri_count, threshold);
                }

                if (index == 31681)
                {
                }
                for (int i = 0; i < 12; i++)
                {
                    OctreeNode[] face_nodes = new OctreeNode[2];

                    int c1 = Utilities.TEdgePairs[i, 0];
                    int c2 = Utilities.TEdgePairs[i, 1];

                    face_nodes[0] = children[c1];
                    face_nodes[1] = children[c2];

                    ProcessFace(face_nodes, Utilities.TEdgePairs[i, 2], indexes, tri_count, threshold);
                }

                for (int i = 0; i < 6; i++)
                {
                    OctreeNode[] edge_nodes =
                    {
                        children[Utilities.TCellProcEdgeMask[i, 0]],
                        children[Utilities.TCellProcEdgeMask[i, 1]],
                        children[Utilities.TCellProcEdgeMask[i, 2]],
                        children[Utilities.TCellProcEdgeMask[i, 3]]
                    };

                    ProcessEdge(edge_nodes, Utilities.TCellProcEdgeMask[i, 4], indexes, tri_count, threshold);
                }
            }
        }