Exemplo n.º 1
0
        /// <summary>
        /// Generate the dual of this geometry. ( The dual mesh translates vertices to faces, and faces to vertices ).
        /// Used for rendering the world.
        /// </summary>
        /// <typeparam name="AltVertex">The dual's vertex format</typeparam>
        /// <param name="colorProvider">A system for coloring the vertices of the dual</param>
        /// <returns></returns>
        public Geometry <AltVertex> GenerateDual <AltVertex>(IColorProvider colorProvider) where AltVertex : struct, IVertex
        {
            // For each edge,
            //   get centroids of triangles each side
            //   make 2 new triangles from verts of edge + centroids

            List <AltVertex> newVerts = new List <AltVertex>(mesh.vertices.Length + Topology.Edges.Count * 2);

            // Initialize the first V verts
            for (int i = 0; i < mesh.vertices.Length; ++i)
            {
                newVerts.Add(new AltVertex());
            }

            List <uint> newIndices = new List <uint>();

            foreach (var iter in Topology.Edges)
            {
                Int64 key    = iter.Key;
                int   index1 = (int)(key & 0xffffffff);
                int   index2 = (int)((key >> 32) & 0xffffffff);
                Edge  e      = iter.Value;

                Vector3 centroid1 = Topology.Centroids[e.triangle1].position;
                Vector3 centroid2 = Topology.Centroids[e.triangle2].position;

                // To find which order of vertices to use;
                // if triangle1 contains index1 followed by index2,
                // new tris are index1, c2, c1; index2, c1, c2
                // otherwise, the opposite order.

                bool edgeOrderIsAnticlockwise = false;
                for (int i = 0; i < 3; i++)
                {
                    if (indices[e.triangle1 * 3 + i] == index1)
                    {
                        if (indices[e.triangle1 * 3 + (i + 1) % 3] == index2)
                        {
                            edgeOrderIsAnticlockwise = true;
                        }
                        break;
                    }
                }
                // Get the color of the face from the color provider for the vertex in the primary mesh
                Vector4 c1 = colorProvider.GetColor(index1);
                Vector4 c2 = colorProvider.GetColor(index2);
                if (edgeOrderIsAnticlockwise)
                {
                    AddTriangle2(ref newVerts, ref newIndices, index1, ref centroid2, ref centroid1, c1);
                    AddTriangle2(ref newVerts, ref newIndices, index2, ref centroid1, ref centroid2, c2);
                }
                else
                {
                    AddTriangle2(ref newVerts, ref newIndices, index1, ref centroid1, ref centroid2, c1);
                    AddTriangle2(ref newVerts, ref newIndices, index2, ref centroid2, ref centroid1, c2);
                }
            }

            var newMesh = new Mesh <AltVertex>(newVerts.ToArray());
            var newGeom = new Geometry <AltVertex>(newMesh, newIndices.ToArray());

            return(newGeom);
        }
Exemplo n.º 2
0
        public void TweakTriangles(float ratio, Random rand)
        {
            NeedsUpdate = true;

            // Assumptions: minimised mesh. Shared edges won't work without shared verts.
            Topology.GenerateEdges();

            // How many edges do we have? exchange some percentage of them...
            int          numPerturbations = (int)((float)Topology.Edges.Count * ratio);
            int          numTriangles     = mesh.vertices.Length;
            List <Int64> keys             = new List <Int64>(Topology.Edges.Keys);

            List <int> visitedTris = new List <int>();

            for (int i = 0; i < numPerturbations; ++i)
            {
                // Choose a random edge:
                int edgeIndex = rand.Next(Topology.Edges.Count);
                // Check out the tris around the edge.
                Int64 key  = keys[edgeIndex];
                Edge  edge = Topology.Edges[key];

                // TODO - add flag to triangle to avoid n2/2 lookup.
                bool r = false;
                foreach (var visited in visitedTris)
                {
                    if (edge.triangle1 == visited || edge.triangle2 == visited)
                    {
                        r = true;
                        break;
                    }
                }
                if (r)
                {
                    continue;
                }

                visitedTris.Add(edge.triangle1);
                visitedTris.Add(edge.triangle2);

                if (IsObtuse(edge.triangle1) || IsObtuse(edge.triangle2))
                {
                    continue;
                }

                uint index1 = (uint)(key & 0xffffffff);
                uint index2 = (uint)((key >> 32) & 0xffffffff);
                uint index3;
                uint index4;
                uint a = index1;

                int cornerA = GetTriOffset(edge.triangle1, a);
                // get the next coord in the triangle (in ccw order)
                uint b = indices[edge.triangle1 * 3 + ((cornerA + 1) % 3)];
                uint c = indices[edge.triangle1 * 3 + ((cornerA + 2) % 3)];
                uint d = 0;
                if (b == index2)
                {
                    d      = indices[edge.triangle2 * 3 + ((GetTriOffset(edge.triangle2, a) + 1) % 3)];
                    index3 = c;
                    index4 = d;
                }
                else
                {
                    d      = indices[edge.triangle2 * 3 + ((GetTriOffset(edge.triangle2, a) + 2) % 3)];
                    index3 = b;
                    index4 = d;
                }

                if (Topology.TrianglesPerVertex[index1] <= 5 || Topology.TrianglesPerVertex[index2] <= 5 ||
                    Topology.TrianglesPerVertex[index3] >= 7 || Topology.TrianglesPerVertex[index4] >= 7)
                {
                    continue;
                }
                // Check edge lengths
                Vector3 pos1 = MeshAttr.GetPosition(ref mesh.vertices[index1]);
                Vector3 pos2 = MeshAttr.GetPosition(ref mesh.vertices[index2]);
                Vector3 pos3 = MeshAttr.GetPosition(ref mesh.vertices[index3]);
                Vector3 pos4 = MeshAttr.GetPosition(ref mesh.vertices[index4]);

                float oldLength = new Vector3(pos2 - pos1).Length;
                float newLength = new Vector3(pos4 - pos3).Length;
                if (oldLength / newLength >= 2 || oldLength / newLength <= 0.5f)
                {
                    continue;
                }

                Topology.TrianglesPerVertex[index1]--;
                Topology.TrianglesPerVertex[index2]--;
                Topology.TrianglesPerVertex[index3]++;
                Topology.TrianglesPerVertex[index4]++;

                // Need to keep tris in CCW order.
                if (b == index2)
                {
                    // order is a b c; c is the non-shared vertex.
                    // new tris are: ADC, DBC
                    // tri2 order is a d b
                    indices[edge.triangle1 * 3]     = a;
                    indices[edge.triangle1 * 3 + 1] = d;
                    indices[edge.triangle1 * 3 + 2] = c;
                    indices[edge.triangle2 * 3]     = d;
                    indices[edge.triangle2 * 3 + 1] = b;
                    indices[edge.triangle2 * 3 + 2] = c;
                }
                else
                {
                    // order is a b c; b is the non-shared value
                    // new tris are ACD, CBD
                    // tri2 order is a b d
                    indices[edge.triangle1 * 3]     = a;
                    indices[edge.triangle1 * 3 + 1] = b;
                    indices[edge.triangle1 * 3 + 2] = d;
                    indices[edge.triangle2 * 3]     = c;
                    indices[edge.triangle2 * 3 + 1] = d;
                    indices[edge.triangle2 * 3 + 2] = b;
                }
            }

            Topology.Regenerate();
        }