/// <summary> /// /// </summary> private static void CatmullClarkSmooth <V, E, F>(HeMeshBase <V, E, F> mesh, Property <V, Vec3d> position, SmoothBoundaryType boundaryType) where V : HeVertex <V, E, F> where E : Halfedge <V, E, F> where F : HeFace <V, E, F> { switch (boundaryType) { case SmoothBoundaryType.Fixed: CatmullClarkSmoothFixed(mesh, position); return; case SmoothBoundaryType.CornerFixed: CatmullClarkSmoothCornerFixed(mesh, position); return; case SmoothBoundaryType.Free: CatmullClarkSmoothFree(mesh, position); return; } throw new NotSupportedException(); }
/// <summary> /// Applies a single iteration of Catmull-Clark subdivision to the given mesh. /// If using external buffers to store vertex attributes, the number of vertices after subdivision equals the sum of the number of vertices edges and faces in the initial 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>(HeMeshBase <V, E, F> mesh, Property <V, Vec3d> position, SmoothBoundaryType boundaryType) where V : HeVertex <V, E, F> where E : Halfedge <V, E, F> where F : HeFace <V, E, F> { CatmullClarkGeometry(mesh, position, boundaryType); QuadSplitTopology(mesh); }
/// <summary> /// /// </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> private static void CatmullClarkGeometry <V, E, F>(HeMeshBase <V, E, F> mesh, Property <V, Vec3d> position, SmoothBoundaryType boundaryType) where V : HeVertex <V, E, F> where E : Halfedge <V, E, F> where F : HeFace <V, E, F> { var verts = mesh.Vertices; int fv0 = verts.Count; // index of first face vertex // create face vertices foreach (var f in mesh.Faces) { var v = mesh.AddVertex(); if (!f.IsRemoved) { position.Set(v, f.Vertices.Mean(position.Get)); } } // create edge vertices foreach (var he0 in mesh.Edges) { var v = mesh.AddVertex(); if (he0.IsRemoved) { continue; } if (he0.IsBoundary) { position.Set(v, 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(v, (p0 + p1 + p2 + p3) * 0.25); } // smooth old vertices CatmullClarkSmooth(mesh, position, boundaryType); }
/// <summary> /// Applies a single iteration of Catmull-Clark subdivision to the given mesh. /// If using external buffers to store vertex attributes, the number of vertices after subdivision equals the sum of the number of vertices, edges, 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="boundaryType"></param> public static void CatmullClark <V, E, F>(HeMesh <V, E, F> mesh, Property <V, Vec3d> position, SmoothBoundaryType boundaryType) where V : HeMesh <V, E, F> .Vertex where E : HeMesh <V, E, F> .Halfedge where F : HeMesh <V, E, F> .Face { // impl ref // http://rosettacode.org/wiki/Catmull%E2%80%93Clark_subdivision_surface // http://w3.impa.br/~lcruz/courses/cma/surfaces.html CatmullClarkGeometry(mesh, position, boundaryType); QuadSplitTopology(mesh); }