Fix T58450: Skin modifier not working if applied after subsurf
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 12 Dec 2018 14:06:39 +0000 (15:06 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 12 Dec 2018 14:07:03 +0000 (15:07 +0100)
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/subdiv_mesh.c
source/blender/modifiers/intern/MOD_skin.c

index 84864411360c11d93481d87670cc5b8f68301e60..64a3cbe09354cf6a0800c8b8a9cdabc3e08135e9 100644 (file)
@@ -1194,6 +1194,12 @@ static void layerDefault_mvert_skin(void *data, int count)
        }
 }
 
+static void layerCopy_mvert_skin(const void *source, void *dest,
+                                 int count)
+{
+       memcpy(dest, source, sizeof (MVertSkin) * count);
+}
+
 static void layerInterp_mvert_skin(
         const void **sources, const float *weights,
         const float *UNUSED(sub_weights),
@@ -1342,7 +1348,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
        {sizeof(GridPaintMask), "GridPaintMask", 1, NULL, layerCopy_grid_paint_mask,
         layerFree_grid_paint_mask, NULL, NULL, NULL},
        /* 36: CD_MVERT_SKIN */
-       {sizeof(MVertSkin), "MVertSkin", 1, NULL, NULL, NULL,
+       {sizeof(MVertSkin), "MVertSkin", 1, NULL, layerCopy_mvert_skin, NULL,
         layerInterp_mvert_skin, NULL, layerDefault_mvert_skin},
        /* 37: CD_FREESTYLE_EDGE */
        {sizeof(FreestyleEdge), "FreestyleEdge", 1, NULL, NULL, NULL, NULL, NULL, NULL},
index 4d9e8998cf05353dcc5de6bcd37ac73a8e797426..4d1b436ca1664ea9178dab0f78e9484c97b06089 100644 (file)
@@ -1032,6 +1032,41 @@ static void points_for_loose_edges_interpolation_get(
        }
 }
 
+static void subdiv_mesh_vertex_of_loose_edge_interpolate(
+        SubdivMeshContext *ctx,
+        const MEdge *coarse_edge,
+        const float u,
+        const int subdiv_vertex_index)
+{
+       const Mesh *coarse_mesh = ctx->coarse_mesh;
+       Mesh *subdiv_mesh = ctx->subdiv_mesh;
+       if (u == 0.0f) {
+               CustomData_copy_data(&coarse_mesh->vdata,
+                                    &subdiv_mesh->vdata,
+                                    coarse_edge->v1,
+                                    subdiv_vertex_index,
+                                    1);
+       }
+       else if (u == 1.0f) {
+               CustomData_copy_data(&coarse_mesh->vdata,
+                                    &subdiv_mesh->vdata,
+                                    coarse_edge->v2,
+                                    subdiv_vertex_index,
+                                    1);
+       }
+       else {
+               BLI_assert(u > 0.0f);
+               BLI_assert(u < 1.0f);
+               const float interpolation_weights[2] = {1.0f - u, u};
+               const int coarse_vertex_indices[2] = {coarse_edge->v1, coarse_edge->v2};
+               CustomData_interp(&coarse_mesh->vdata,
+                                 &subdiv_mesh->vdata,
+                                 coarse_vertex_indices,
+                                 interpolation_weights, NULL,
+                                 2, subdiv_vertex_index);
+       }
+}
+
 static void subdiv_mesh_vertex_of_loose_edge(
         const struct SubdivForeachContext *foreach_context,
         void *UNUSED(tls),
@@ -1055,6 +1090,10 @@ static void subdiv_mesh_vertex_of_loose_edge(
        float weights[4];
        key_curve_position_weights(u, weights, KEY_BSPLINE);
 
+       /* Interpolate custom data. */
+       subdiv_mesh_vertex_of_loose_edge_interpolate(
+               ctx, coarse_edge, u, subdiv_vertex_index);
+       /* Initialize  */
        MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
        interp_v3_v3v3v3v3(subdiv_vertex->co,
                           points[0],
@@ -1064,11 +1103,12 @@ static void subdiv_mesh_vertex_of_loose_edge(
                           weights);
        /* Reset flags and such. */
        subdiv_vertex->flag = 0;
+       /* TODO(sergey): This matches old behavior, but we can as well interpolate
+        * it. Maybe even using vertex varying attributes. */
        subdiv_vertex->bweight = 0.0f;
-       /* Reset normal. */
-       subdiv_vertex->no[0] = 0.0f;
-       subdiv_vertex->no[1] = 0.0f;
-       subdiv_vertex->no[2] = 1.0f;
+       /* Reset normal, initialize it in a similar way as edit mode does for a
+        * vertices adjacent to a loose edges. */
+       normal_float_to_short_v3(subdiv_vertex->no, subdiv_vertex->co);
 }
 
 /* =============================================================================
index 87d47769cdbe57cf94fed72ab16490ad1a17f695..b31167152b8d9f01b37ee3139f9f18cd56e64ac2 100644 (file)
@@ -859,6 +859,7 @@ static Mesh *subdivide_base(Mesh *orig)
        for (i = 0, totsubd = 0; i < totorigedge; i++) {
                edge_subd[i] += calc_edge_subdivisions(origvert, orignode,
                                                       &origedge[i], degree);
+               BLI_assert(edge_subd[i] >= 0);
                totsubd += edge_subd[i];
        }