示例#1
0
        /*
         * /// <summary>
         * /// Applies a single iteration of Catmull-Clark subdivision to the given mesh.
         * /// http://rosettacode.org/wiki/Catmull%E2%80%93Clark_subdivision_surface
         * /// http://w3.impa.br/~lcruz/courses/cma/surfaces.html
         * /// </summary>
         * /// <typeparam name="V"></typeparam>
         * /// <typeparam name="E"></typeparam>
         * /// <typeparam name="F"></typeparam>
         * /// <param name="mesh"></param>
         * /// <param name="position"></param>
         * /// <param name="boundaryType"></param>
         * public static void CatmullClark<V, E, F>(HeMesh<V, E, F> mesh, Property<V, Vec3d> position, SmoothBoundaryType boundaryType, bool parallel)
         *  where V : HeVertex<V, E, F>
         *  where E : Halfedge<V, E, F>
         *  where F : HeFace<V, E, F>
         * {
         *  CatmullClarkGeometry(mesh, position, boundaryType, parallel);
         *  QuadSplitTopology(mesh);
         * }
         *
         *
         * /// <summary>
         * ///
         * /// </summary>
         * private static void CatmullClarkGeometry<V, E, F>(HeMesh<V, E, F> mesh, Property<V, Vec3d> position, SmoothBoundaryType boundaryType, bool parallel)
         * where V : HeVertex<V, E, F>
         * where E : Halfedge<V, E, F>
         * where F : HeFace<V, E, F>
         * {
         *  var verts = mesh.Vertices;
         *  var edges = mesh.Edges;
         *  var faces = mesh.Faces;
         *
         *  int fv0 = verts.Count; // index of first face vertex
         *  int ev0 = verts.Count + faces.Count;
         *
         *  // add all new vertices
         *  mesh.AddVertices(faces.Count);
         *  mesh.AddVertices(edges.Count);
         *
         *  // set attributes of face vertices
         *  Action<Tuple<int, int>> setFaceVerts = range =>
         *   {
         *       for (int i = range.Item1; i < range.Item2; i++)
         *       {
         *           var f = faces[i];
         *
         *           if (!f.IsRemoved)
         *               position.Set(verts[i + fv0], f.Vertices.Mean(position.Get));
         *       }
         *   };
         *
         *  // set attributes of edge vertices
         *  Action<Tuple<int, int>> setEdgeVerts = range =>
         *  {
         *      for (int i = range.Item1; i < range.Item2; i++)
         *      {
         *          var he0 = edges[i];
         *          if (he0.IsRemoved) continue;
         *
         *          if (he0.IsBoundary)
         *          {
         *              position.Set(verts[i + ev0], he0.Lerp(position.Get, 0.5));
         *              continue;
         *          }
         *
         *          var he1 = he0.Twin;
         *          var p0 = position.Get(he0.Start);
         *          var p1 = position.Get(he1.Start);
         *          var p2 = position.Get(verts[he0.Face.Index + fv0]);
         *          var p3 = position.Get(verts[he1.Face.Index + fv0]);
         *          position.Set(verts[i + ev0], (p0 + p1 + p2 + p3) * 0.25);
         *      }
         *  };
         *
         *  // set attributes of old vertices
         *  //CatmullClarkSmooth(mesh, position, boundaryType);
         *  Action<Tuple<int, int>> setOldVerts = range =>
         *  {
         *      for (int i = range.Item1; i < range.Item2; i++)
         *      {
         *          var v = verts[i];
         *          if (v.IsRemoved) continue;
         *
         *          if (v.IsBoundary)
         *          {
         *              var he0 = v.FirstOut;
         *              var he1 = he0.PrevInFace;
         *              var p0 = position.Get(verts[(he0.Index >> 1) + ev0]);
         *              var p1 = position.Get(verts[(he1.Index >> 1) + ev0]);
         *              position.Set(v, position.Get(v) * 0.5 + (p0 + p1) * 0.25);
         *          }
         *          else
         *          {
         *              Vec3d fsum = new Vec3d();
         *              Vec3d esum = new Vec3d();
         *              int n = 0;
         *
         *              foreach (var he in v.OutgoingHalfedges)
         *              {
         *                  fsum += position.Get(verts[he.Face.Index + fv0]);
         *                  esum += position.Get(verts[(he.Index >> 1) + ev0]);
         *                  n++;
         *              }
         *
         *              double t = 1.0 / n;
         *              position.Set(v, (position.Get(v) * (n - 3) + fsum * t + 2 * esum * t) * t);
         *          }
         *      }
         *  };
         *
         *
         *  if (parallel)
         *  {
         *      Parallel.ForEach(Partitioner.Create(0, faces.Count), setFaceVerts);
         *      Parallel.ForEach(Partitioner.Create(0, edges.Count), setEdgeVerts);
         *      Parallel.ForEach(Partitioner.Create(0, verts.Count), setOldVerts);
         *  }
         *  else
         *  {
         *      setFaceVerts(Tuple.Create(0, faces.Count));
         *      setEdgeVerts(Tuple.Create(0, edges.Count));
         *      setOldVerts(Tuple.Create(0, verts.Count));
         *  }
         * }
         */

        #endregion


        /// <summary>
        /// If using external buffers to store vertex attributes, the number of vertices after subdivision equals the sum of the number of vertices and faces in the initial mesh.
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <typeparam name="F"></typeparam>
        /// <param name="mesh"></param>
        /// <param name="position"></param>
        /// <param name="skipBoundary"></param>
        public static void Diagonalize <V, E, F>(HeMeshBase <V, E, F> mesh, Property <V, Vec3d> position, bool skipBoundary)
            where V : HeVertex <V, E, F>
            where E : Halfedge <V, E, F>
            where F : HeFace <V, E, F>
        {
            var edges = mesh.Edges;
            var faces = mesh.Faces;

            int ne = edges.Count;
            int nf = faces.Count;

            // stellate faces
            for (int i = 0; i < nf; i++)
            {
                var f = faces[i];
                if (f.IsRemoved)
                {
                    continue;
                }

                var v = mesh.AddVertex();
                position.Set(v, f.GetBarycenter(position.Get));
                mesh.PokeFaceImpl(f.First, v);
            }

            // merge faces
            if (skipBoundary)
            {
                for (int i = 0; i < ne; i++)
                {
                    var he = edges[i];
                    if (he.IsRemoved || he.IsBoundary)
                    {
                        continue;
                    }
                    mesh.MergeFaces(he);
                }
            }
            else
            {
                for (int i = 0; i < ne; i++)
                {
                    var he = edges[i];
                    if (he.IsRemoved)
                    {
                        continue;
                    }
                    mesh.MergeFaces(he);
                }
            }
        }