Beispiel #1
0
 public Vertex()
 {
     parent        = null;
     index         = -1;
     collapsible   = true;
     qef           = null;
     normal        = Vector3.Zero;
     surface_index = -1;
     eis           = null;
 }
Beispiel #2
0
        private void Polygonize(int x, int y, int z)
        {
            if (Cells[x, y, z] == null)
            {
                return;
            }

            int cube_index = 0;

            for (int i = 0; i < 8; i++)
            {
                if (Sampler.Sample(new Vector3(x, y, z) + CornerDeltas[i]) < 0)
                {
                    cube_index |= 1 << i;
                }
            }

            if (cube_index == 0 || cube_index == 255)
            {
                return;
            }

            Cells[x, y, z].Vertices = new Vertex[VerticesNumberTable[cube_index]];

            /*for (int i = 0; i < 12; i++)
             * {
             *      Cells[x, y, z].Edges[i].A = new Vector3(x, y, z) + CornerDeltas[EdgePairs[i, 0]];
             *      Cells[x, y, z].Edges[i].B = new Vector3(x, y, z) + CornerDeltas[EdgePairs[i, 1]];
             *
             *      Cells[x, y, z].Edges[i].ValueA = Sampler.Sample(Cells[x, y, z].Edges[i].A);
             *      Cells[x, y, z].Edges[i].ValueB = Sampler.Sample(Cells[x, y, z].Edges[i].B);
             * }*/

            int v_index = 0;

            Cells[x, y, z].Vertices[0] = new Vertex();
            for (int e = 0; e < EdgesTable.GetLength(1); e++)
            {
                if (EdgesTable[cube_index, e] == -2)
                {
                    break;
                }
                if (EdgesTable[cube_index, e] == -1)
                {
                    v_index++;
                    if (v_index < Cells[x, y, z].Vertices.Length)
                    {
                        Cells[x, y, z].Vertices[v_index] = new Vertex();
                    }
                    continue;
                }

                //Cells[x, y, z].Vertices[v_index].Index = v_index;
                Cells[x, y, z].Vertices[v_index].Edges.Add(EdgesTable[cube_index, e]);
                Cells[x, y, z].Edges[EdgesTable[cube_index, e]].Vertices.Add(Cells[x, y, z].Vertices[v_index]);
                //Cells[x, y, z].Edges[EdgesTable[cube_index, e]].Flipped = Cells[x, y, z].Edges[EdgesTable[cube_index, e]].ValueA < 0;
            }

            foreach (Vertex v in Cells[x, y, z].Vertices)
            {
                Vertex tx = v;
                if (v == null)                 //for edges 241/243, which were originally marked as having 2 vertices...?
                {
                    continue;
                }
                Vector3 point = new Vector3();

                if (VertexMode != VertexModes.Block)
                {
                    //QEF3D qef = new QEF3D();
                    QEFProper.QEFSolver qef = new QEFProper.QEFSolver();
                    VertexPlacement     qem = new VertexPlacement();
                    for (int e_i = 0; e_i < tx.Edges.Count; e_i++)
                    {
                        Edge e = Cells[x, y, z].Edges[tx.Edges[e_i]];
                        if (VertexMode == VertexModes.Edges)
                        {
                            point += e.GetIntersection();
                        }
                        else if (VertexMode == VertexModes.QEF)
                        {
                            qef.Add(e.GetIntersection() - new Vector3(x, y, z), Sampler.GetNormal(e.GetIntersection()));
                        }
                        else
                        {
                            qem.AddPlane(e.GetIntersection() - new Vector3(x, y, z), Sampler.GetNormal(e.GetIntersection()));
                        }
                    }

                    if (VertexMode == VertexModes.Edges)
                    {
                        point /= (float)tx.Edges.Count;
                    }
                    else if (VertexMode == VertexModes.QEF)
                    {
                        point = qef.Solve(1e-6f, 4, 1e-6f) + new Vector3(x, y, z);
                    }
                    else
                    {
                        point = qem.Solve() + new Vector3(x, y, z);
                    }
                }
                else
                {
                    point = new Vector3(x, y, z) + Vector3.One * 0.5f;
                }
                //point = Vector3.Clamp(point, new Vector3(x, y, z), new Vector3(x + 1, y + 1, z + 1));

                tx.Position = point;
                Vector3 norm = Sampler.GetNormal(point);
                Vector3 c_v  = norm * 0.5f + Vector3.One * 0.5f;
                c_v.Normalize();
                Color clr = new Color(c_v);
                if (!UseFlatShading)
                {
                    tx.Index = Vertices.Count;
                    VertexPositionColorNormal pv = new VertexPositionColorNormal(tx.Position, clr, norm);
                    Vertices.Add(pv);
                }
                else
                {
                    tx.Index = CalculatedVertices.Count;
                    VertexPositionColor pv = new VertexPositionColor(tx.Position, clr);
                    CalculatedVertices.Add(pv);
                }

                VertexPositionColor[] vs = new VertexPositionColor[24];
                Color c  = Color.Red;
                float vx = tx.Position.X;
                float vy = tx.Position.Y;
                float vz = tx.Position.Z;
                float r  = 0.25f;
                vs[0] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + 0)), c);
                vs[1] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + 0)), c);
                vs[2] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + 0)), c);
                vs[3] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + 0)), c);
                vs[4] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + 0)), c);
                vs[5] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + 0)), c);
                vs[6] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + 0)), c);
                vs[7] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + 0)), c);

                vs[8]  = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + r)), c);
                vs[9]  = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + r)), c);
                vs[10] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + r)), c);
                vs[11] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + r)), c);
                vs[12] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + r)), c);
                vs[13] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + r)), c);
                vs[14] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + r)), c);
                vs[15] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + r)), c);

                vs[16] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + 0)), c);
                vs[17] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + r)), c);
                vs[18] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + 0)), c);
                vs[19] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + r)), c);

                vs[20] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + 0)), c);
                vs[21] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + r)), c);
                vs[22] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + 0)), c);
                vs[23] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + r)), c);

                OutlineBuffer.SetData <VertexPositionColor>(OutlineLocation * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 24, VertexPositionColor.VertexDeclaration.VertexStride);
                OutlineLocation += 24;
            }
        }
Beispiel #3
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)
            {
            }
        }
Beispiel #4
0
        /* The following code is more or less a copy/paste cleanup of the C++ implementation
         * It's not clean, or efficient, but it works and is fairly straightforward
         */
        public bool ConstructLeaf(List <VertexPositionColorNormal> vertices, int grid_size)
        {
            if (size != 1)
            {
                return(false);
            }
            int corners = 0;

            float[, ,] samples = new float[2, 2, 2];
            for (int i = 0; i < 8; i++)
            {
                if ((samples[i / 4, i % 4 / 2, i % 2] = Sampler.Sample(position + new Vector3(i / 4, i % 4 / 2, i % 2))) < 0)
                {
                    corners |= 1 << i;
                }
            }

            if (corners == 0 || corners == 255)
            {
                return(false);
            }

            //type = OctreeNodeType.Leaf;
            //return true;

            QEF3D qef = new QEF3D();

            QEFProper.QEFSolver qefp           = new QEFProper.QEFSolver();
            Vector3             average_normal = Vector3.Zero;

            for (int i = 0; i < 12; i++)
            {
                int c1 = edgevmap[i, 0];
                int c2 = edgevmap[i, 1];

                int m1 = (corners >> c1) & 1;
                int m2 = (corners >> c2) & 1;
                if (m1 == m2)
                {
                    continue;
                }

                float d1 = samples[c1 / 4, c1 % 4 / 2, c1 % 2];
                float d2 = samples[c2 / 4, c2 % 4 / 2, c2 % 2];

                Vector3 p1 = new Vector3((float)((c1 / 4)), (float)((c1 % 4 / 2)), (float)((c1 % 2)));
                Vector3 p2 = new Vector3((float)((c2 / 4)), (float)((c2 % 4 / 2)), (float)((c2 % 2)));

                Vector3 intersection = Sampler.GetIntersection(p1, p2, d1, d2) + position;
                Vector3 normal       = Sampler.GetNormal(intersection);          //GetNormal(x, y);
                average_normal += normal;

                qef.Add(intersection, normal);
                qefp.Add(intersection, normal);
            }

            Vector3 n = average_normal / (float)qef.Intersections.Count;

            n.Normalize();
            draw_info = new OctreeDrawInfo();
            //draw_info.position = position + qef.Solve2(0, 0, 0);
            draw_info.position      = qefp.Solve(1e-6f, 4, 1e-6f);
            draw_info.corners       = corners;
            draw_info.averageNormal = n;
            draw_info.qef           = qefp;
            //vertices.Add(new VertexPositionColorNormal(position + draw_info.position, Color.LightGreen, n));

            type = OctreeNodeType.Leaf;
            return(true);
        }
Beispiel #5
0
        public void Simplify(float threshold, bool randomize = false)
        {
            if (type != OctreeNodeType.Internal)
            {
                return;
            }

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

            //QEF3D qef = new QEF3D();
            QEFProper.QEFSolver qef = new QEFProper.QEFSolver();
            Random rnd = new Random();

            float t = threshold;

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

                if (randomize)
                {
                    t = (float)rnd.NextDouble() * (float)rnd.NextDouble() * 20.0f;
                }
                children[i].Simplify(t);
                OctreeNode child = children[i];

                if (child.type == OctreeNodeType.Internal)
                {
                    is_collapsible = false;
                }
                else
                {
                    //qef.Add(child.draw_info.position, child.draw_info.averageNormal);
                    //if (child.draw_info.qef != null)
                    qef.Add(ref child.draw_info.qef.data);

                    mid_sign = (child.draw_info.corners >> (7 - i)) & 1;
                    signs[i] = (child.draw_info.corners >> i) & 1;
                }
            }

            if (size == 16)
            {
            }

            if (!is_collapsible)
            {
                return;
            }

            //Vector3 pos = qef.Solve2(0, 0, 0);
            Vector3 pos   = qef.Solve(1e-6f, 4, 1e-6f);
            float   error = qef.GetError();

            if (error > threshold)
            {
                return;
            }

            OctreeDrawInfo draw_info = new OctreeDrawInfo();

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

            Vector3 normal = new Vector3();

            for (int i = 0; i < 8; i++)
            {
                if (children[i] != null)
                {
                    OctreeNode child = children[i];
                    if (child.type == OctreeNodeType.Pseudo || child.type == OctreeNodeType.Leaf)
                    {
                        normal += child.draw_info.averageNormal;
                    }
                }
            }

            normal.Normalize();
            draw_info.averageNormal = normal;
            draw_info.position      = pos;
            draw_info.qef           = qef;

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

            type           = OctreeNodeType.Pseudo;
            this.draw_info = draw_info;
        }
Beispiel #6
0
        public void Simplify(float threshold, bool randomize = false)
        {
            if (type != OctreeNodeType.Internal)
                return;

            int[] signs = { -1, -1, -1, -1, -1, -1, -1, -1 };
            int mid_sign = -1;
            bool is_collapsible = true;
            //QEF3D qef = new QEF3D();
            QEFProper.QEFSolver qef = new QEFProper.QEFSolver();
            Random rnd = new Random();

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

                if (randomize)
                    t = (float)rnd.NextDouble() * (float)rnd.NextDouble() * 20.0f;
                children[i].Simplify(t);
                OctreeNode child = children[i];

                if (child.type == OctreeNodeType.Internal)
                    is_collapsible = false;
                else
                {
                    //qef.Add(child.draw_info.position, child.draw_info.averageNormal);
                    //if (child.draw_info.qef != null)
                        qef.Add(ref child.draw_info.qef.data);

                    mid_sign = (child.draw_info.corners >> (7 - i)) & 1;
                    signs[i] = (child.draw_info.corners >> i) & 1;
                }
            }

            if (size == 16)
            {
            }

            if (!is_collapsible)
                return;

            //Vector3 pos = qef.Solve2(0, 0, 0);
            Vector3 pos = qef.Solve(1e-6f, 4, 1e-6f);
            float error = qef.GetError();

            if (error > threshold)
                return;

            OctreeDrawInfo draw_info = new OctreeDrawInfo();

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

            Vector3 normal = new Vector3();
            for (int i = 0; i < 8; i++)
            {
                if (children[i] != null)
                {
                    OctreeNode child = children[i];
                    if (child.type == OctreeNodeType.Pseudo || child.type == OctreeNodeType.Leaf)
                        normal += child.draw_info.averageNormal;
                }
            }

            normal.Normalize();
            draw_info.averageNormal = normal;
            draw_info.position = pos;
            draw_info.qef = qef;

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

            type = OctreeNodeType.Pseudo;
            this.draw_info = draw_info;
        }
Beispiel #7
0
        /* The following code is more or less a copy/paste cleanup of the C++ implementation
         * It's not clean, or efficient, but it works and is fairly straightforward
         */
        public bool ConstructLeaf(List<VertexPositionColorNormal> vertices, int grid_size)
        {
            if (size != 1)
                return false;
            int corners = 0;
            float[, ,] samples = new float[2, 2, 2];
            for (int i = 0; i < 8; i++)
            {
                if ((samples[i / 4, i % 4 / 2, i % 2] = Sampler.Sample(position + new Vector3(i / 4, i % 4 / 2, i % 2))) < 0)
                    corners |= 1 << i;
            }

            if (corners == 0 || corners == 255)
                return false;

            //type = OctreeNodeType.Leaf;
            //return true;

            QEF3D qef = new QEF3D();
            QEFProper.QEFSolver qefp = new QEFProper.QEFSolver();
            Vector3 average_normal = Vector3.Zero;
            for (int i = 0; i < 12; i++)
            {
                int c1 = edgevmap[i, 0];
                int c2 = edgevmap[i, 1];

                int m1 = (corners >> c1) & 1;
                int m2 = (corners >> c2) & 1;
                if (m1 == m2)
                    continue;

                float d1 = samples[c1 / 4, c1 % 4 / 2, c1 % 2];
                float d2 = samples[c2 / 4, c2 % 4 / 2, c2 % 2];

                Vector3 p1 = new Vector3((float)((c1 / 4)), (float)((c1 % 4 / 2)), (float)((c1 % 2)));
                Vector3 p2 = new Vector3((float)((c2 / 4)), (float)((c2 % 4 / 2)), (float)((c2 % 2)));

                Vector3 intersection = Sampler.GetIntersection(p1, p2, d1, d2) + position;
                Vector3 normal = Sampler.GetNormal(intersection);//GetNormal(x, y);
                average_normal += normal;

                qef.Add(intersection, normal);
                qefp.Add(intersection, normal);
            }

            Vector3 n = average_normal / (float)qef.Intersections.Count;
            n.Normalize();
            draw_info = new OctreeDrawInfo();
            //draw_info.position = position + qef.Solve2(0, 0, 0);
            draw_info.position = qefp.Solve(1e-6f, 4, 1e-6f);
            draw_info.corners = corners;
            draw_info.averageNormal = n;
            draw_info.qef = qefp;
            //vertices.Add(new VertexPositionColorNormal(position + draw_info.position, Color.LightGreen, n));

            type = OctreeNodeType.Leaf;
            return true;
        }
Beispiel #8
0
        private void Polygonize(int x, int y, int z)
        {
            if (Cells[x, y, z] == null)
                return;

            int cube_index = 0;
            for (int i = 0; i < 8; i++)
            {
                if (Sampler.Sample(new Vector3(x, y, z) + CornerDeltas[i]) < 0)
                    cube_index |= 1 << i;
            }

            if (cube_index == 0 || cube_index == 255)
                return;

            Cells[x, y, z].Vertices = new Vertex[VerticesNumberTable[cube_index]];
            /*for (int i = 0; i < 12; i++)
            {
                Cells[x, y, z].Edges[i].A = new Vector3(x, y, z) + CornerDeltas[EdgePairs[i, 0]];
                Cells[x, y, z].Edges[i].B = new Vector3(x, y, z) + CornerDeltas[EdgePairs[i, 1]];

                Cells[x, y, z].Edges[i].ValueA = Sampler.Sample(Cells[x, y, z].Edges[i].A);
                Cells[x, y, z].Edges[i].ValueB = Sampler.Sample(Cells[x, y, z].Edges[i].B);
            }*/

            int v_index = 0;
            Cells[x, y, z].Vertices[0] = new Vertex();
            for (int e = 0; e < EdgesTable.GetLength(1); e++)
            {
                if (EdgesTable[cube_index, e] == -2)
                    break;
                if (EdgesTable[cube_index, e] == -1)
                {
                    v_index++;
                    if (v_index < Cells[x, y, z].Vertices.Length)
                        Cells[x, y, z].Vertices[v_index] = new Vertex();
                    continue;
                }

                //Cells[x, y, z].Vertices[v_index].Index = v_index;
                Cells[x, y, z].Vertices[v_index].Edges.Add(EdgesTable[cube_index, e]);
                Cells[x, y, z].Edges[EdgesTable[cube_index, e]].Vertices.Add(Cells[x, y, z].Vertices[v_index]);
                //Cells[x, y, z].Edges[EdgesTable[cube_index, e]].Flipped = Cells[x, y, z].Edges[EdgesTable[cube_index, e]].ValueA < 0;
            }

            foreach (Vertex v in Cells[x, y, z].Vertices)
            {
                Vertex tx = v;
                if (v == null) //for edges 241/243, which were originally marked as having 2 vertices...?
                    continue;
                Vector3 point = new Vector3();

                if (VertexMode != VertexModes.Block)
                {
                    //QEF3D qef = new QEF3D();
                    QEFProper.QEFSolver qef = new QEFProper.QEFSolver();
                    VertexPlacement qem = new VertexPlacement();
                    for (int e_i = 0; e_i < tx.Edges.Count; e_i++)
                    {
                        Edge e = Cells[x, y, z].Edges[tx.Edges[e_i]];
                        if (VertexMode == VertexModes.Edges)
                            point += e.GetIntersection();
                        else if (VertexMode == VertexModes.QEF)
                            qef.Add(e.GetIntersection() - new Vector3(x, y, z), Sampler.GetNormal(e.GetIntersection()));
                        else
                            qem.AddPlane(e.GetIntersection() - new Vector3(x, y, z), Sampler.GetNormal(e.GetIntersection()));
                    }

                    if (VertexMode == VertexModes.Edges)
                        point /= (float)tx.Edges.Count;
                    else if (VertexMode == VertexModes.QEF)
                        point = qef.Solve(1e-6f, 4, 1e-6f) + new Vector3(x, y, z);
                    else
                        point = qem.Solve() + new Vector3(x, y, z);
                }
                else
                    point = new Vector3(x, y, z) + Vector3.One * 0.5f;
                //point = Vector3.Clamp(point, new Vector3(x, y, z), new Vector3(x + 1, y + 1, z + 1));

                tx.Position = point;
                Vector3 norm = Sampler.GetNormal(point);
                Vector3 c_v = norm * 0.5f + Vector3.One * 0.5f;
                c_v.Normalize();
                Color clr = new Color(c_v);
                if (!UseFlatShading)
                {
                    tx.Index = Vertices.Count;
                    VertexPositionColorNormal pv = new VertexPositionColorNormal(tx.Position, clr, norm);
                    Vertices.Add(pv);
                }
                else
                {
                    tx.Index = CalculatedVertices.Count;
                    VertexPositionColor pv = new VertexPositionColor(tx.Position, clr);
                    CalculatedVertices.Add(pv);
                }

                VertexPositionColor[] vs = new VertexPositionColor[24];
                Color c = Color.Red;
                float vx = tx.Position.X;
                float vy = tx.Position.Y;
                float vz = tx.Position.Z;
                float r = 0.25f;
                vs[0] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + 0)), c);
                vs[1] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + 0)), c);
                vs[2] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + 0)), c);
                vs[3] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + 0)), c);
                vs[4] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + 0)), c);
                vs[5] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + 0)), c);
                vs[6] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + 0)), c);
                vs[7] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + 0)), c);

                vs[8] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + r)), c);
                vs[9] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + r)), c);
                vs[10] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + r)), c);
                vs[11] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + r)), c);
                vs[12] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + r)), c);
                vs[13] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + r)), c);
                vs[14] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + r)), c);
                vs[15] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + r)), c);

                vs[16] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + 0)), c);
                vs[17] = new VertexPositionColor(new Vector3((vx + 0), (vy + 0), (vz + r)), c);
                vs[18] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + 0)), c);
                vs[19] = new VertexPositionColor(new Vector3((vx + 0), (vy + r), (vz + r)), c);

                vs[20] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + 0)), c);
                vs[21] = new VertexPositionColor(new Vector3((vx + r), (vy + 0), (vz + r)), c);
                vs[22] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + 0)), c);
                vs[23] = new VertexPositionColor(new Vector3((vx + r), (vy + r), (vz + r)), c);

                OutlineBuffer.SetData<VertexPositionColor>(OutlineLocation * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 24, VertexPositionColor.VertexDeclaration.VertexStride);
                OutlineLocation += 24;
            }
        }
Beispiel #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)
            {
            }
        }
Beispiel #10
0
 public Vertex()
 {
     parent = null;
     index = -1;
     collapsible = true;
     qef = null;
     normal = Vector3.Zero;
     surface_index = -1;
     eis = null;
 }