diff options
Diffstat (limited to 'source/blender')
35 files changed, 526 insertions, 92 deletions
diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h index 0237661cd16..697b3e9ace7 100644 --- a/source/blender/blenkernel/BKE_subdiv.h +++ b/source/blender/blenkernel/BKE_subdiv.h @@ -306,8 +306,8 @@ BLI_INLINE void BKE_subdiv_rotate_grid_to_quad( int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v); /* Convert Blender edge crease value to OpenSubdiv sharpness. */ -BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_f(float edge_crease); -BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_char(char edge_crease); +BLI_INLINE float BKE_subdiv_crease_to_sharpness_f(float edge_crease); +BLI_INLINE float BKE_subdiv_crease_to_sharpness_char(char edge_crease); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index feb5ecb8f04..e1bc025efd2 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -1692,7 +1692,9 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 29: CD_BWEIGHT */ {sizeof(float), "", 0, N_("BevelWeight"), nullptr, nullptr, layerInterp_bweight}, /* 30: CD_CREASE */ - {sizeof(float), "", 0, N_("SubSurfCrease"), nullptr, nullptr, layerInterp_bweight}, + /* NOTE: we do not interpolate crease data as it should be either inherited for subdivided + * edges, or for vertex creases, only present on the original vertex. */ + {sizeof(float), "", 0, N_("SubSurfCrease"), nullptr, nullptr, nullptr}, /* 31: CD_ORIGSPACE_MLOOP */ {sizeof(OrigSpaceLoop), "OrigSpaceLoop", @@ -1938,7 +1940,7 @@ const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = { }; const CustomData_MeshMasks CD_MASK_MESH = { /* vmask */ (CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK | - CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR), + CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_CREASE), /* emask */ (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), /* fmask */ 0, /* pmask */ @@ -1950,7 +1952,7 @@ const CustomData_MeshMasks CD_MASK_MESH = { }; const CustomData_MeshMasks CD_MASK_EDITMESH = { /* vmask */ (CD_MASK_MDEFORMVERT | CD_MASK_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY | - CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR), + CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_CREASE), /* emask */ (CD_MASK_PROP_ALL), /* fmask */ 0, /* pmask */ (CD_MASK_FACEMAP | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS), @@ -1961,7 +1963,7 @@ const CustomData_MeshMasks CD_MASK_EDITMESH = { const CustomData_MeshMasks CD_MASK_DERIVEDMESH = { /* vmask */ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL | - CD_MASK_PROP_COLOR), + CD_MASK_PROP_COLOR | CD_MASK_CREASE), /* emask */ (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), /* fmask */ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT), /* pmask */ @@ -1974,7 +1976,7 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = { const CustomData_MeshMasks CD_MASK_BMESH = { /* vmask */ (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | - CD_MASK_PROP_COLOR), + CD_MASK_PROP_COLOR | CD_MASK_CREASE), /* emask */ (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), /* fmask */ 0, /* pmask */ @@ -2001,7 +2003,7 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = { /* vmask */ (CD_MASK_MVERT | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_NORMAL | CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | - CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR), + CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_CREASE), /* emask */ (CD_MASK_MEDGE | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), @@ -4409,7 +4411,12 @@ bool CustomData_verify_versions(struct CustomData *data, int index) /* 0 structnum is used in writing code to tag layer types that should not be written. */ else if (typeInfo->structnum == 0 && /* XXX Not sure why those three are exception, maybe that should be fixed? */ - !ELEM(layer->type, CD_PAINT_MASK, CD_FACEMAP, CD_MTEXPOLY, CD_SCULPT_FACE_SETS)) { + !ELEM(layer->type, + CD_PAINT_MASK, + CD_FACEMAP, + CD_MTEXPOLY, + CD_SCULPT_FACE_SETS, + CD_CREASE)) { keeplayer = false; CLOG_WARN(&LOG, ".blend file read: removing a data layer that should not have been written"); } @@ -5080,6 +5087,10 @@ void CustomData_blend_write(BlendWriter *writer, const bool *layer_data = static_cast<const bool *>(layer->data); BLO_write_raw(writer, sizeof(*layer_data) * count, layer_data); } + else if (layer->type == CD_CREASE) { + const float *layer_data = static_cast<const float *>(layer->data); + BLO_write_raw(writer, sizeof(*layer_data) * count, layer_data); + } else { const char *structname; int structnum; diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h index 8a37d0ea785..a038ce5f108 100644 --- a/source/blender/blenkernel/intern/multires_reshape.h +++ b/source/blender/blenkernel/intern/multires_reshape.h @@ -106,6 +106,9 @@ typedef struct MultiresReshapeContext { /* Indexed by base face index, returns first ptex face index corresponding * to that base face. */ int *face_ptex_offset; + + /* Vertex crease custom data layer, null if none is present. */ + const float *cd_vertex_crease; } MultiresReshapeContext; /** diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c index 50b4410a28e..839c457dd84 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.c +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c @@ -75,6 +75,7 @@ typedef struct Vertex { int num_grid_coords; GridCoord *grid_coords; + float sharpness; bool is_infinite_sharp; } Vertex; @@ -489,19 +490,33 @@ static int get_reshape_level_resolution(const MultiresReshapeContext *reshape_co return (1 << reshape_context->reshape.level) + 1; } +static bool is_crease_supported(const MultiresReshapeSmoothContext *reshape_smooth_context) +{ + return !ELEM(reshape_smooth_context->smoothing_type, + MULTIRES_SUBDIVIDE_LINEAR, + MULTIRES_SUBDIVIDE_SIMPLE); +} + /* Get crease which will be used for communication to OpenSubdiv topology. * Note that simple subdivision treats all base edges as infinitely sharp. */ -static char get_effective_edge_crease_char( - const MultiresReshapeSmoothContext *reshape_smooth_context, const MEdge *base_edge) +static char get_effective_crease_char(const MultiresReshapeSmoothContext *reshape_smooth_context, + const MEdge *base_edge) { - if (ELEM(reshape_smooth_context->smoothing_type, - MULTIRES_SUBDIVIDE_LINEAR, - MULTIRES_SUBDIVIDE_SIMPLE)) { + if (!is_crease_supported(reshape_smooth_context)) { return 255; } return base_edge->crease; } +static float get_effective_crease_float(const MultiresReshapeSmoothContext *reshape_smooth_context, + const float crease) +{ + if (!is_crease_supported(reshape_smooth_context)) { + return 1.0f; + } + return crease; +} + static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context, const MultiresReshapeContext *reshape_context, const eMultiresSubdivideModeType mode) @@ -596,6 +611,7 @@ static bool foreach_topology_info(const SubdivForeachContext *foreach_context, static void foreach_single_vertex(const SubdivForeachContext *foreach_context, const GridCoord *grid_coord, + const int coarse_vertex_index, const int subdiv_vertex_index) { const MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data; @@ -608,11 +624,32 @@ static void foreach_single_vertex(const SubdivForeachContext *foreach_context, sizeof(Vertex) * (vertex->num_grid_coords + 1)); vertex->grid_coords[vertex->num_grid_coords] = *grid_coord; ++vertex->num_grid_coords; + + if (coarse_vertex_index == -1) { + return; + } + + const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; + const float *cd_vertex_crease = reshape_context->cd_vertex_crease; + + if (cd_vertex_crease == NULL) { + return; + } + + float crease = cd_vertex_crease[coarse_vertex_index]; + + if (crease == 0.0f) { + return; + } + + crease = get_effective_crease_float(reshape_smooth_context, crease); + vertex->sharpness = BKE_subdiv_crease_to_sharpness_f(crease); } /* TODO(sergey): De-duplicate with similar function in multires_reshape_vertcos.c */ static void foreach_vertex(const SubdivForeachContext *foreach_context, const PTexCoord *ptex_coord, + const int coarse_vertex_index, const int subdiv_vertex_index) { const MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data; @@ -632,12 +669,13 @@ static void foreach_vertex(const SubdivForeachContext *foreach_context, for (int current_corner = 0; current_corner < num_corners; ++current_corner) { GridCoord corner_grid_coord = grid_coord; corner_grid_coord.grid_index = start_grid_index + current_corner; - foreach_single_vertex(foreach_context, &corner_grid_coord, subdiv_vertex_index); + foreach_single_vertex( + foreach_context, &corner_grid_coord, coarse_vertex_index, subdiv_vertex_index); } return; } - foreach_single_vertex(foreach_context, &grid_coord, subdiv_vertex_index); + foreach_single_vertex(foreach_context, &grid_coord, coarse_vertex_index, subdiv_vertex_index); if (grid_coord.u == 0.0f) { GridCoord prev_grid_coord; @@ -645,7 +683,8 @@ static void foreach_vertex(const SubdivForeachContext *foreach_context, prev_grid_coord.u = grid_coord.v; prev_grid_coord.v = 0.0f; - foreach_single_vertex(foreach_context, &prev_grid_coord, subdiv_vertex_index); + foreach_single_vertex( + foreach_context, &prev_grid_coord, coarse_vertex_index, subdiv_vertex_index); } if (grid_coord.v == 0.0f) { @@ -654,7 +693,8 @@ static void foreach_vertex(const SubdivForeachContext *foreach_context, next_grid_coord.u = 0.0f; next_grid_coord.v = grid_coord.u; - foreach_single_vertex(foreach_context, &next_grid_coord, subdiv_vertex_index); + foreach_single_vertex( + foreach_context, &next_grid_coord, coarse_vertex_index, subdiv_vertex_index); } } @@ -672,7 +712,7 @@ static void foreach_vertex_inner(const struct SubdivForeachContext *foreach_cont .u = ptex_face_u, .v = ptex_face_v, }; - foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index); + foreach_vertex(foreach_context, &ptex_coord, -1, subdiv_vertex_index); } static void foreach_vertex_every_corner(const struct SubdivForeachContext *foreach_context, @@ -680,7 +720,7 @@ static void foreach_vertex_every_corner(const struct SubdivForeachContext *forea const int ptex_face_index, const float ptex_face_u, const float ptex_face_v, - const int UNUSED(coarse_vertex_index), + const int coarse_vertex_index, const int UNUSED(coarse_face_index), const int UNUSED(coarse_face_corner), const int subdiv_vertex_index) @@ -690,7 +730,7 @@ static void foreach_vertex_every_corner(const struct SubdivForeachContext *forea .u = ptex_face_u, .v = ptex_face_v, }; - foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index); + foreach_vertex(foreach_context, &ptex_coord, coarse_vertex_index, subdiv_vertex_index); } static void foreach_vertex_every_edge(const struct SubdivForeachContext *foreach_context, @@ -708,7 +748,7 @@ static void foreach_vertex_every_edge(const struct SubdivForeachContext *foreach .u = ptex_face_u, .v = ptex_face_v, }; - foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index); + foreach_vertex(foreach_context, &ptex_coord, -1, subdiv_vertex_index); } static void foreach_loop(const struct SubdivForeachContext *foreach_context, @@ -778,7 +818,7 @@ static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context, Edge *edge = &reshape_smooth_context->geometry.edges[edge_index]; edge->v1 = subdiv_v1; edge->v2 = subdiv_v2; - edge->sharpness = BKE_subdiv_edge_crease_to_sharpness_char(crease); + edge->sharpness = BKE_subdiv_crease_to_sharpness_char(crease); } static void foreach_edge(const struct SubdivForeachContext *foreach_context, @@ -809,7 +849,7 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context, /* Edges without crease are to be ignored as well. */ const Mesh *base_mesh = reshape_context->base_mesh; const MEdge *base_edge = &base_mesh->medge[coarse_edge_index]; - const char crease = get_effective_edge_crease_char(reshape_smooth_context, base_edge); + const char crease = get_effective_crease_char(reshape_smooth_context, base_edge); if (crease == 0) { return; } @@ -835,8 +875,7 @@ static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshap if (!BLI_BITMAP_TEST_BOOL(reshape_smooth_context->non_loose_base_edge_map, loop->e)) { BLI_BITMAP_ENABLE(reshape_smooth_context->non_loose_base_edge_map, loop->e); - const char crease = get_effective_edge_crease_char(reshape_smooth_context, - &base_edge[loop->e]); + const char crease = get_effective_crease_char(reshape_smooth_context, &base_edge[loop->e]); if (crease != 0) { ++num_used_edges; } @@ -979,6 +1018,15 @@ static float get_edge_sharpness(const OpenSubdiv_Converter *converter, const int return edge->sharpness; } +static float get_vertex_sharpness(const OpenSubdiv_Converter *converter, const int vertex_index) +{ + const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data; + BLI_assert(vertex_index < reshape_smooth_context->geometry.num_vertices); + + const Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index]; + return vertex->sharpness; +} + static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter, int vertex_index) { const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data; @@ -1015,7 +1063,7 @@ static void converter_init(const MultiresReshapeSmoothContext *reshape_smooth_co converter->getNumVertexFaces = NULL; converter->getVertexFaces = NULL; converter->isInfiniteSharpVertex = is_infinite_sharp_vertex; - converter->getVertexSharpness = NULL; + converter->getVertexSharpness = get_vertex_sharpness; converter->getNumUVLayers = NULL; converter->precalcUVLayer = NULL; diff --git a/source/blender/blenkernel/intern/multires_reshape_util.c b/source/blender/blenkernel/intern/multires_reshape_util.c index 49d880e04cc..810cf328531 100644 --- a/source/blender/blenkernel/intern/multires_reshape_util.c +++ b/source/blender/blenkernel/intern/multires_reshape_util.c @@ -211,6 +211,8 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape reshape_context->top.level = mmd->totlvl; reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level); + reshape_context->cd_vertex_crease = CustomData_get_layer(&base_mesh->vdata, CD_CREASE); + context_init_commoon(reshape_context); return context_verify_or_free(reshape_context); diff --git a/source/blender/blenkernel/intern/subdiv_converter_mesh.c b/source/blender/blenkernel/intern/subdiv_converter_mesh.c index 41fc28c5d52..fc7ef887879 100644 --- a/source/blender/blenkernel/intern/subdiv_converter_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_converter_mesh.c @@ -40,6 +40,8 @@ #include "opensubdiv_capi.h" #include "opensubdiv_converter_capi.h" +#include "bmesh_class.h" + /* Enable work-around for non-working CPU evaluator when using bilinear scheme. * This forces Catmark scheme with all edges marked as infinitely sharp. */ #define BUGGY_SIMPLE_SCHEME_WORKAROUND 1 @@ -47,6 +49,8 @@ typedef struct ConverterStorage { SubdivSettings settings; const Mesh *mesh; + /* CustomData layer for vertex sharpnesses. */ + const float *cd_vertex_crease; /* Indexed by loop index, value denotes index of face-varying vertex * which corresponds to the UV coordinate. */ @@ -168,7 +172,7 @@ static float get_edge_sharpness(const OpenSubdiv_Converter *converter, int manif } const int edge_index = storage->manifold_edge_index_reverse[manifold_edge_index]; const MEdge *medge = storage->mesh->medge; - return BKE_subdiv_edge_crease_to_sharpness_char(medge[edge_index].crease); + return BKE_subdiv_crease_to_sharpness_char(medge[edge_index].crease); } static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter, @@ -184,14 +188,14 @@ static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter, return BLI_BITMAP_TEST_BOOL(storage->infinite_sharp_vertices_map, vertex_index); } -static float get_vertex_sharpness(const OpenSubdiv_Converter *converter, - int UNUSED(manifold_vertex_index)) +static float get_vertex_sharpness(const OpenSubdiv_Converter *converter, int manifold_vertex_index) { ConverterStorage *storage = converter->user_data; - if (!storage->settings.use_creases) { + if (!storage->settings.use_creases || storage->cd_vertex_crease == NULL) { return 0.0f; } - return 0.0f; + const int vertex_index = storage->manifold_vertex_index_reverse[manifold_vertex_index]; + return BKE_subdiv_crease_to_sharpness_f(storage->cd_vertex_crease[vertex_index]); } static int get_num_uv_layers(const OpenSubdiv_Converter *converter) @@ -393,6 +397,7 @@ static void init_user_data(OpenSubdiv_Converter *converter, ConverterStorage *user_data = MEM_mallocN(sizeof(ConverterStorage), __func__); user_data->settings = *settings; user_data->mesh = mesh; + user_data->cd_vertex_crease = CustomData_get_layer(&mesh->vdata, CD_CREASE); user_data->loop_uv_indices = NULL; initialize_manifold_indices(user_data); converter->user_data = user_data; diff --git a/source/blender/blenkernel/intern/subdiv_inline.h b/source/blender/blenkernel/intern/subdiv_inline.h index ba45d0a4997..d52adff1e61 100644 --- a/source/blender/blenkernel/intern/subdiv_inline.h +++ b/source/blender/blenkernel/intern/subdiv_inline.h @@ -103,13 +103,13 @@ BLI_INLINE void BKE_subdiv_rotate_grid_to_quad( } } -BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_f(float edge_crease) +BLI_INLINE float BKE_subdiv_crease_to_sharpness_f(float edge_crease) { return edge_crease * edge_crease * 10.0f; } -BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_char(char edge_crease) +BLI_INLINE float BKE_subdiv_crease_to_sharpness_char(char edge_crease) { const float edge_crease_f = edge_crease / 255.0f; - return BKE_subdiv_edge_crease_to_sharpness_f(edge_crease_f); + return BKE_subdiv_crease_to_sharpness_f(edge_crease_f); } diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.c b/source/blender/bmesh/intern/bmesh_mesh_convert.c index 6b44fe2c9ff..a7dd5be5cbd 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.c +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.c @@ -122,6 +122,17 @@ void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag) } } + if (cd_flag & ME_CDFLAG_VERT_CREASE) { + if (!CustomData_has_layer(&bm->vdata, CD_CREASE)) { + BM_data_layer_add(bm, &bm->vdata, CD_CREASE); + } + } + else { + if (CustomData_has_layer(&bm->vdata, CD_CREASE)) { + BM_data_layer_free(bm, &bm->vdata, CD_CREASE); + } + } + if (cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); @@ -151,6 +162,9 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm) if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { cd_flag |= ME_CDFLAG_VERT_BWEIGHT; } + if (CustomData_has_layer(&bm->vdata, CD_CREASE)) { + cd_flag |= ME_CDFLAG_VERT_CREASE; + } if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; } diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index 389704b3d66..9899dce5df6 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -323,7 +323,9 @@ GPUShader *OVERLAY_shader_edit_mesh_vert(void) datatoc_edit_mesh_common_lib_glsl, datatoc_edit_mesh_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, + .frag = (const char *[]){datatoc_common_globals_lib_glsl, + datatoc_gpu_shader_point_varying_color_frag_glsl, + NULL}, .defs = (const char *[]){sh_cfg->def, "#define VERT\n", NULL}, }); } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl index 195d2a5a7b7..418c7bceb63 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl @@ -36,7 +36,7 @@ vec4 EDIT_MESH_edge_vertex_color(int vertex_flag) return color; } -vec4 EDIT_MESH_vertex_color(int vertex_flag) +vec4 EDIT_MESH_vertex_color(int vertex_flag, float vertex_crease) { if ((vertex_flag & VERT_ACTIVE) != 0) { return vec4(colorEditMeshActive.xyz, 1.0); @@ -45,6 +45,10 @@ vec4 EDIT_MESH_vertex_color(int vertex_flag) return colorVertexSelect; } else { + /* Full crease color if not selected nor active. */ + if (vertex_crease > 0.0) { + return mix(colorVertex, colorEdgeCrease, vertex_crease); + } return colorVertex; } } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl index a3ff277b714..5cee976f9a8 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl @@ -13,6 +13,9 @@ in vec4 norAndFlag; #endif out vec4 finalColor; +#ifdef VERT +out float vertexCrease; +#endif #ifdef EDGE out vec4 finalColorOuter; #endif @@ -44,8 +47,9 @@ void main() ivec4 m_data = data & dataMask; #if defined(VERT) - finalColor = EDIT_MESH_vertex_color(m_data.y); - gl_PointSize = sizeVertex * 2.0; + vertexCrease = float(m_data.z >> 4) / 15.0; + finalColor = EDIT_MESH_vertex_color(m_data.y, vertexCrease); + gl_PointSize = sizeVertex * ((vertexCrease > 0.0) ? 3.0 : 2.0); /* Make selected and active vertex always on top. */ if ((data.x & VERT_SELECTED) != 0) { gl_Position.z -= 5e-7 * abs(gl_Position.w); @@ -65,9 +69,9 @@ void main() selectOverride = (m_data.y & EDGE_SELECTED); # endif - float crease = float(m_data.z) / 255.0; + float edge_crease = float(m_data.z & 0xF) / 15.0; float bweight = float(m_data.w) / 255.0; - finalColorOuter = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight); + finalColorOuter = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, edge_crease, bweight); if (finalColorOuter.a > 0.0) { gl_Position.z -= 5e-7 * abs(gl_Position.w); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c index df1758fc1a2..29430c46d93 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c @@ -487,7 +487,8 @@ MeshRenderData *mesh_render_data_create(Mesh *me, mr->eed_act = BM_mesh_active_edge_get(mr->bm); mr->eve_act = BM_mesh_active_vert_get(mr->bm); - mr->crease_ofs = CustomData_get_offset(&mr->bm->edata, CD_CREASE); + mr->vert_crease_ofs = CustomData_get_offset(&mr->bm->vdata, CD_CREASE); + mr->edge_crease_ofs = CustomData_get_offset(&mr->bm->edata, CD_CREASE); mr->bweight_ofs = CustomData_get_offset(&mr->bm->edata, CD_BWEIGHT); #ifdef WITH_FREESTYLE mr->freestyle_edge_ofs = CustomData_get_offset(&mr->bm->edata, CD_FREESTYLE_EDGE); diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index e975d213e22..37bc9435c76 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -1693,7 +1693,8 @@ void draw_subdiv_init_mesh_render_data(DRWSubdivCache *cache, mr->eed_act = BM_mesh_active_edge_get(bm); mr->efa_act = BM_mesh_active_face_get(bm, false, true); mr->eve_act = BM_mesh_active_vert_get(bm); - mr->crease_ofs = CustomData_get_offset(&bm->edata, CD_CREASE); + mr->edge_crease_ofs = CustomData_get_offset(&bm->edata, CD_CREASE); + mr->vert_crease_ofs = CustomData_get_offset(&bm->vdata, CD_CREASE); mr->bweight_ofs = CustomData_get_offset(&bm->edata, CD_BWEIGHT); #ifdef WITH_FREESTYLE mr->freestyle_edge_ofs = CustomData_get_offset(&bm->edata, CD_FREESTYLE_EDGE); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.h b/source/blender/draw/intern/mesh_extractors/extract_mesh.h index 834f378c07a..bb55d0c5b2c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.h +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.h @@ -84,7 +84,8 @@ typedef struct MeshRenderData { const float (*bm_poly_centers)[3]; int *v_origindex, *e_origindex, *p_origindex; - int crease_ofs; + int edge_crease_ofs; + int vert_crease_ofs; int bweight_ofs; int freestyle_edge_ofs; int freestyle_face_ofs; @@ -308,6 +309,8 @@ void mesh_render_data_update_looptris(MeshRenderData *mr, typedef struct EditLoopData { uchar v_flag; uchar e_flag; + /* This is used for both vertex and edge creases. The edge crease value is stored in the bottom 4 + * bits, while the vertex crease is stored in the upper 4 bits. */ uchar crease; uchar bweight; } EditLoopData; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc index 3cc1375329e..0002b95c867 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc @@ -72,11 +72,11 @@ static void mesh_render_data_edge_flag(const MeshRenderData *mr, } } - /* Use a byte for value range */ - if (mr->crease_ofs != -1) { - float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->crease_ofs); + /* Use half a byte for value range */ + if (mr->edge_crease_ofs != -1) { + float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->edge_crease_ofs); if (crease > 0) { - eattr->crease = (uchar)(crease * 255.0f); + eattr->crease = (uchar)ceil(crease * 15.0f); } } /* Use a byte for value range */ @@ -107,6 +107,13 @@ static void mesh_render_data_vert_flag(const MeshRenderData *mr, if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { eattr->e_flag |= VFLAG_VERT_SELECTED; } + /* Use half a byte for value range */ + if (mr->vert_crease_ofs != -1) { + float crease = BM_ELEM_CD_GET_FLOAT(eve, mr->vert_crease_ofs); + if (crease > 0) { + eattr->crease |= (uchar)ceil(crease * 15.0f) << 4; + } + } } static GPUVertFormat *get_edit_data_format() diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index b76f882e706..573f9b4939b 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -54,7 +54,8 @@ typedef enum { TFM_TILT, TFM_TRACKBALL, TFM_PUSHPULL, - TFM_CREASE, + TFM_EDGE_CREASE, + TFM_VERT_CREASE, TFM_MIRROR, TFM_BONESIZE, TFM_BONE_ENVELOPE, diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 5451aa5a2e0..243d4033cbc 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -87,7 +87,7 @@ typedef struct { } TransformMedian_Generic; typedef struct { - float location[3], bv_weight, be_weight, skin[2], crease; + float location[3], bv_weight, v_crease, be_weight, skin[2], e_crease; } TransformMedian_Mesh; typedef struct { @@ -319,6 +319,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float BMIter iter; const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + const int cd_vert_crease_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); @@ -335,6 +336,10 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float median->bv_weight += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_bweight_offset); } + if (cd_vert_crease_offset != -1) { + median->v_crease += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_crease_offset); + } + if (has_skinradius) { MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset); add_v2_v2(median->skin, vs->radius); /* Third val not used currently. */ @@ -352,7 +357,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (cd_edge_crease_offset != -1) { - median->crease += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_crease_offset); + median->e_crease += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_crease_offset); } totedgedata++; @@ -489,11 +494,12 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float if (has_meshdata) { TransformMedian_Mesh *median = &median_basis.mesh; if (totedgedata) { - median->crease /= (float)totedgedata; + median->e_crease /= (float)totedgedata; median->be_weight /= (float)totedgedata; } if (tot) { median->bv_weight /= (float)tot; + median->v_crease /= (float)tot; if (has_skinradius) { median->skin[0] /= (float)tot; median->skin[1] /= (float)tot; @@ -683,6 +689,23 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float TIP_("Vertex weight used by Bevel modifier")); UI_but_number_step_size_set(but, 1); UI_but_number_precision_set(but, 2); + /* customdata layer added on demand */ + but = uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + tot == 1 ? IFACE_("Vertex Crease:") : IFACE_("Mean Vertex Crease:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->v_crease, + 0.0, + 1.0, + 0, + 0, + TIP_("Weight used by the Subdivision Surface modifier")); + UI_but_number_step_size_set(but, 1); + UI_but_number_precision_set(but, 2); } if (has_skinradius) { UI_block_align_begin(block); @@ -761,7 +784,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float yi -= buth + but_margin, butw, buth, - &ve_median->crease, + &ve_median->e_crease, 0.0, 1.0, 0, @@ -958,8 +981,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float const bool apply_vcos = (tot == 1) || (len_squared_v3(median_basis.generic.location) != 0.0f); if ((ob->type == OB_MESH) && - (apply_vcos || median_basis.mesh.bv_weight || median_basis.mesh.skin[0] || - median_basis.mesh.skin[1] || median_basis.mesh.be_weight || median_basis.mesh.crease)) { + (apply_vcos || median_basis.mesh.bv_weight || median_basis.mesh.v_crease || + median_basis.mesh.skin[0] || median_basis.mesh.skin[1] || median_basis.mesh.be_weight || + median_basis.mesh.e_crease)) { const TransformMedian_Mesh *median = &median_basis.mesh, *ve_median = &ve_median_basis.mesh; Mesh *me = ob->data; BMEditMesh *em = me->edit_mesh; @@ -969,18 +993,21 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float BMEdge *eed; int cd_vert_bweight_offset = -1; + int cd_vert_crease_offset = -1; int cd_vert_skin_offset = -1; int cd_edge_bweight_offset = -1; int cd_edge_crease_offset = -1; float scale_bv_weight = 1.0f; + float scale_v_crease = 1.0f; float scale_skin[2] = {1.0f, 1.0f}; float scale_be_weight = 1.0f; - float scale_crease = 1.0f; + float scale_e_crease = 1.0f; /* Vertices */ - if (apply_vcos || median->bv_weight || median->skin[0] || median->skin[1]) { + if (apply_vcos || median->bv_weight || median->v_crease || median->skin[0] || + median->skin[1]) { if (median->bv_weight) { BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT); cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); @@ -989,6 +1016,14 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float scale_bv_weight = compute_scale_factor(ve_median->bv_weight, median->bv_weight); } + if (median->v_crease) { + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_CREASE); + cd_vert_crease_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); + BLI_assert(cd_vert_crease_offset != -1); + + scale_v_crease = compute_scale_factor(ve_median->v_crease, median->v_crease); + } + for (int i = 0; i < 2; i++) { if (median->skin[i]) { cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); @@ -1011,6 +1046,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float apply_scale_factor_clamp(b_weight, tot, ve_median->bv_weight, scale_bv_weight); } + if (cd_vert_crease_offset != -1) { + float *crease = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_crease_offset); + apply_scale_factor_clamp(crease, tot, ve_median->v_crease, scale_v_crease); + } + if (cd_vert_skin_offset != -1) { MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset); @@ -1033,7 +1073,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float /* Edges */ - if (median->be_weight || median->crease) { + if (median->be_weight || median->e_crease) { if (median->be_weight) { BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); @@ -1042,12 +1082,12 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float scale_be_weight = compute_scale_factor(ve_median->be_weight, median->be_weight); } - if (median->crease) { + if (median->e_crease) { BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE); cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); BLI_assert(cd_edge_crease_offset != -1); - scale_crease = compute_scale_factor(ve_median->crease, median->crease); + scale_e_crease = compute_scale_factor(ve_median->e_crease, median->e_crease); } BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { @@ -1057,9 +1097,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float apply_scale_factor_clamp(b_weight, tot, ve_median->be_weight, scale_be_weight); } - if (median->crease != 0.0f) { + if (median->e_crease != 0.0f) { float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset); - apply_scale_factor_clamp(crease, tot, ve_median->crease, scale_crease); + apply_scale_factor_clamp(crease, tot, ve_median->e_crease, scale_e_crease); } } } diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index c3d95e1ad98..55f2bfd37db 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1465,7 +1465,7 @@ static void VertsToTransData(TransInfo *t, td->ext = NULL; td->val = NULL; td->extra = eve; - if (t->mode == TFM_BWEIGHT) { + if (t->mode == TFM_BWEIGHT || t->mode == TFM_VERT_CREASE) { td->val = bweight; td->ival = *bweight; } @@ -1606,10 +1606,15 @@ void createTransEditVerts(TransInfo *t) } int cd_vert_bweight_offset = -1; + int cd_vert_crease_offset = -1; if (t->mode == TFM_BWEIGHT) { BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT); cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); } + else if (t->mode == TFM_VERT_CREASE) { + BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_CREASE); + cd_vert_crease_offset = CustomData_get_offset(&bm->vdata, CD_CREASE); + } TransData *tob = tc->data; TransDataMirror *td_mirror = tc->data_mirror; @@ -1645,6 +1650,8 @@ void createTransEditVerts(TransInfo *t) else if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : + (cd_vert_crease_offset != -1) ? + BM_ELEM_CD_GET_VOID_P(eve, cd_vert_crease_offset) : NULL; /* Do not use the island center in case we are using islands diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index 2db3e259153..2243f66cc7f 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -86,8 +86,8 @@ void createTransEdge(TransInfo *t) BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT); cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT); } - else { /* if (t->mode == TFM_CREASE) { */ - BLI_assert(t->mode == TFM_CREASE); + else { /* if (t->mode == TFM_EDGE_CREASE) { */ + BLI_assert(t->mode == TFM_EDGE_CREASE); BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_CREASE); cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 43d894d60f2..d1cbab9ff8a 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -260,7 +260,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } /* Crease needs edge flag */ - if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) { + if (ELEM(t->mode, TFM_EDGE_CREASE, TFM_BWEIGHT)) { t->options |= CTX_EDGE_DATA; } diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index 2ab4cdff5e6..e1fea62ae54 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -1135,8 +1135,11 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode) case TFM_PUSHPULL: initPushPull(t); break; - case TFM_CREASE: - initCrease(t); + case TFM_EDGE_CREASE: + initEgdeCrease(t); + break; + case TFM_VERT_CREASE: + initVertCrease(t); break; case TFM_BONESIZE: initBoneSize(t); diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h index cdcda5a8648..16b26724c67 100644 --- a/source/blender/editors/transform/transform_mode.h +++ b/source/blender/editors/transform/transform_mode.h @@ -106,7 +106,8 @@ void initCurveShrinkFatten(TransInfo *t); void initBevelWeight(TransInfo *t); /* transform_mode_edge_crease.c */ -void initCrease(TransInfo *t); +void initEgdeCrease(TransInfo *t); +void initVertCrease(TransInfo *t); /* transform_mode_edge_rotate_normal.c */ void initNormalRotation(TransInfo *t); diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c index debc2a1be3e..60b95a1d2da 100644 --- a/source/blender/editors/transform/transform_mode_edge_crease.c +++ b/source/blender/editors/transform/transform_mode_edge_crease.c @@ -157,9 +157,9 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) ED_area_status_text(t->area, str); } -void initCrease(TransInfo *t) +static void initCrease_ex(TransInfo *t, int mode) { - t->mode = TFM_CREASE; + t->mode = mode; t->transform = applyCrease; initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA); @@ -176,4 +176,13 @@ void initCrease(TransInfo *t) t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } +void initEgdeCrease(TransInfo *t) +{ + initCrease_ex(t, TFM_EDGE_CREASE); +} + +void initVertCrease(TransInfo *t) +{ + initCrease_ex(t, TFM_VERT_CREASE); +} /** \} */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 5ed340abf97..80feb934f1a 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -78,6 +78,7 @@ static const char OP_BONE_SIZE[] = "TRANSFORM_OT_bbone_resize"; static const char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide"; static const char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide"; static const char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease"; +static const char OP_VERT_CREASE[] = "TRANSFORM_OT_vert_crease"; static const char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight"; static const char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide"; static const char OP_NORMAL_ROTATION[] = "TRANSFORM_OT_rotate_normal"; @@ -98,6 +99,7 @@ static void TRANSFORM_OT_bbone_resize(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot); static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot); +static void TRANSFORM_OT_vert_crease(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot); static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot); static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot); @@ -118,7 +120,8 @@ static TransformModeItem transform_modes[] = { {OP_BONE_SIZE, TFM_BONESIZE, TRANSFORM_OT_bbone_resize}, {OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide}, {OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide}, - {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease}, + {OP_EDGE_CREASE, TFM_EDGE_CREASE, TRANSFORM_OT_edge_crease}, + {OP_VERT_CREASE, TFM_VERT_CREASE, TRANSFORM_OT_vert_crease}, {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight}, {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide}, {OP_NORMAL_ROTATION, TFM_NORMAL_ROTATION, TRANSFORM_OT_rotate_normal}, @@ -139,7 +142,8 @@ const EnumPropertyItem rna_enum_transform_mode_types[] = { {TFM_TILT, "TILT", 0, "Tilt", ""}, {TFM_TRACKBALL, "TRACKBALL", 0, "Trackball", ""}, {TFM_PUSHPULL, "PUSHPULL", 0, "Push/Pull", ""}, - {TFM_CREASE, "CREASE", 0, "Crease", ""}, + {TFM_EDGE_CREASE, "CREASE", 0, "Crease", ""}, + {TFM_VERT_CREASE, "VERTEX_CREASE", 0, "Vertex Crease", ""}, {TFM_MIRROR, "MIRROR", 0, "Mirror", ""}, {TFM_BONESIZE, "BONE_SIZE", 0, "Bone Size", ""}, {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone Envelope", ""}, @@ -1196,6 +1200,29 @@ static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) Transform_Properties(ot, P_SNAP); } +static void TRANSFORM_OT_vert_crease(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Vertex Crease"; + ot->description = "Change the crease of vertices"; + ot->idname = OP_VERT_CREASE; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* api callbacks */ + ot->invoke = transform_invoke; + ot->exec = transform_exec; + ot->modal = transform_modal; + ot->cancel = transform_cancel; + ot->poll = ED_operator_editmesh; + ot->poll_property = transform_poll_property; + + RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f); + + WM_operatortype_props_advanced_begin(ot); + + Transform_Properties(ot, P_SNAP); +} + static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot) { /* identifiers */ diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl index 119189ad29b..23e9f9bc20f 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl @@ -3,6 +3,10 @@ in vec4 finalColor; out vec4 fragColor; #endif +#if defined(VERT) +in float vertexCrease; +#endif + void main() { vec2 centered = gl_PointCoord - vec2(0.5); @@ -14,5 +18,14 @@ void main() discard; } +#if defined(VERT) + fragColor = finalColor; + + float midStroke = 0.5 * rad_squared; + if (vertexCrease > 0.0 && dist_squared > midStroke) { + fragColor.rgb = mix(finalColor.rgb, colorEdgeCrease.rgb, vertexCrease); + } +#else fragColor = finalColor; +#endif } diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 7275d0addf0..6ab4b06fba6 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -76,10 +76,13 @@ static void get_topology(struct Mesh *mesh, std::vector<int32_t> &poly_verts, std::vector<int32_t> &loop_counts, bool &r_has_flat_shaded_poly); -static void get_creases(struct Mesh *mesh, - std::vector<int32_t> &indices, - std::vector<int32_t> &lengths, - std::vector<float> &sharpnesses); +static void get_edge_creases(struct Mesh *mesh, + std::vector<int32_t> &indices, + std::vector<int32_t> &lengths, + std::vector<float> &sharpnesses); +static void get_vert_creases(struct Mesh *mesh, + std::vector<int32_t> &indices, + std::vector<float> &sharpnesses); static void get_loop_normals(struct Mesh *mesh, std::vector<Imath::V3f> &normals, bool has_flat_shaded_poly); @@ -283,15 +286,16 @@ void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *mesh) { - std::vector<float> crease_sharpness; + std::vector<float> edge_crease_sharpness, vert_crease_sharpness; std::vector<Imath::V3f> points; std::vector<int32_t> poly_verts, loop_counts; - std::vector<int32_t> crease_indices, crease_lengths; + std::vector<int32_t> edge_crease_indices, edge_crease_lengths, vert_crease_indices; bool has_flat_poly = false; get_vertices(mesh, points); get_topology(mesh, poly_verts, loop_counts, has_flat_poly); - get_creases(mesh, crease_indices, crease_lengths, crease_sharpness); + get_edge_creases(mesh, edge_crease_indices, edge_crease_lengths, edge_crease_sharpness); + get_vert_creases(mesh, vert_crease_indices, vert_crease_sharpness); if (!frame_has_been_written_ && args_.export_params->face_sets) { write_face_sets(context.object, mesh, abc_subdiv_schema_); @@ -322,10 +326,15 @@ void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *me write_generated_coordinates(abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config); } - if (!crease_indices.empty()) { - subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices)); - subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths)); - subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness)); + if (!edge_crease_indices.empty()) { + subdiv_sample.setCreaseIndices(Int32ArraySample(edge_crease_indices)); + subdiv_sample.setCreaseLengths(Int32ArraySample(edge_crease_lengths)); + subdiv_sample.setCreaseSharpnesses(FloatArraySample(edge_crease_sharpness)); + } + + if (!vert_crease_indices.empty()) { + subdiv_sample.setCornerIndices(Int32ArraySample(vert_crease_indices)); + subdiv_sample.setCornerSharpnesses(FloatArraySample(vert_crease_sharpness)); } update_bounding_box(context.object); @@ -477,10 +486,10 @@ static void get_topology(struct Mesh *mesh, } } -static void get_creases(struct Mesh *mesh, - std::vector<int32_t> &indices, - std::vector<int32_t> &lengths, - std::vector<float> &sharpnesses) +static void get_edge_creases(struct Mesh *mesh, + std::vector<int32_t> &indices, + std::vector<int32_t> &lengths, + std::vector<float> &sharpnesses) { const float factor = 1.0f / 255.0f; @@ -503,6 +512,29 @@ static void get_creases(struct Mesh *mesh, lengths.resize(sharpnesses.size(), 2); } +static void get_vert_creases(struct Mesh *mesh, + std::vector<int32_t> &indices, + std::vector<float> &sharpnesses) +{ + indices.clear(); + sharpnesses.clear(); + + const float *creases = static_cast<const float *>(CustomData_get_layer(&mesh->vdata, CD_CREASE)); + + if (!creases) { + return; + } + + for (int i = 0, v = mesh->totvert; i < v; i++) { + const float sharpness = creases[i]; + + if (sharpness != 0.0f) { + indices.push_back(i); + sharpnesses.push_back(sharpness); + } + } +} + static void get_loop_normals(struct Mesh *mesh, std::vector<Imath::V3f> &normals, bool has_flat_shaded_poly) diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 3c1ac8ceeaf..bd40eb35123 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -45,6 +45,7 @@ #include "BKE_modifier.h" #include "BKE_object.h" +using Alembic::Abc::FloatArraySamplePtr; using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::IV3fArrayProperty; using Alembic::Abc::P3fArraySamplePtr; @@ -910,6 +911,32 @@ static void read_subd_sample(const std::string &iobject_full_name, } } +static void read_vertex_creases(Mesh *mesh, + const Int32ArraySamplePtr &indices, + const FloatArraySamplePtr &sharpnesses) +{ + if (!(indices && sharpnesses && indices->size() == sharpnesses->size() && + indices->size() != 0)) { + return; + } + + float *vertex_crease_data = (float *)CustomData_add_layer( + &mesh->vdata, CD_CREASE, CD_DEFAULT, nullptr, mesh->totvert); + const int totvert = mesh->totvert; + + for (int i = 0, v = indices->size(); i < v; ++i) { + const int idx = (*indices)[i]; + + if (idx >= totvert) { + continue; + } + + vertex_crease_data[idx] = (*sharpnesses)[i]; + } + + mesh->cd_flag |= ME_CDFLAG_VERT_CREASE; +} + /* ************************************************************************** */ AbcSubDReader::AbcSubDReader(const IObject &object, ImportSettings &settings) @@ -973,6 +1000,7 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec return; } + /* Read egde creases. */ Int32ArraySamplePtr indices = sample.getCreaseIndices(); Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses(); @@ -1003,6 +1031,8 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; } + read_vertex_creases(mesh, sample.getCornerIndices(), sample.getCornerSharpnesses()); + if (m_settings->validate_meshes) { BKE_mesh_validate(mesh, false, false); } diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 53dbaac99fd..95b73c85da6 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -522,6 +522,38 @@ void USDMeshReader::read_colors(Mesh *mesh, const double motionSampleTime) } } +void USDMeshReader::read_vertex_creases(Mesh *mesh, const double motionSampleTime) +{ + pxr::VtIntArray corner_indices; + if (!mesh_prim_.GetCornerIndicesAttr().Get(&corner_indices, motionSampleTime)) { + return; + } + + pxr::VtIntArray corner_sharpnesses; + if (!mesh_prim_.GetCornerSharpnessesAttr().Get(&corner_sharpnesses, motionSampleTime)) { + return; + } + + /* It is fine to have fewer indices than vertices, but never the other way other. */ + if (corner_indices.size() > mesh->totvert) { + std::cerr << "WARNING: too many vertex crease for mesh " << prim_path_ << std::endl; + return; + } + + if (corner_indices.size() != corner_sharpnesses.size()) { + std::cerr << "WARNING: vertex crease indices and sharpnesses count mismatch for mesh " + << prim_path_ << std::endl; + return; + } + + float *creases = static_cast<float *>( + CustomData_add_layer(&mesh->vdata, CD_CREASE, CD_DEFAULT, nullptr, mesh->totvert)); + + for (size_t i = 0; i < corner_indices.size(); i++) { + creases[corner_indices[i]] = corner_sharpnesses[i]; + } +} + void USDMeshReader::process_normals_vertex_varying(Mesh *mesh) { if (!mesh) { @@ -640,6 +672,8 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings, mvert.co[1] = positions_[i][1]; mvert.co[2] = positions_[i][2]; } + + read_vertex_creases(mesh, motionSampleTime); } if (new_mesh || (settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { diff --git a/source/blender/io/usd/intern/usd_reader_mesh.h b/source/blender/io/usd/intern/usd_reader_mesh.h index 9ed73ba5a28..c5869fcbd32 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.h +++ b/source/blender/io/usd/intern/usd_reader_mesh.h @@ -86,6 +86,7 @@ class USDMeshReader : public USDGeomReader { void read_mpolys(Mesh *mesh); void read_uvs(Mesh *mesh, double motionSampleTime, bool load_uvs = false); void read_colors(Mesh *mesh, double motionSampleTime); + void read_vertex_creases(Mesh *mesh, double motionSampleTime); void read_mesh_sample(ImportSettings *settings, Mesh *mesh, diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index b21dd8ac1fd..b061a2ff795 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -110,6 +110,12 @@ struct USDMeshData { * single sharpness or a value per-edge, USD will encode either a single sharpness per crease on * a mesh, or sharpness's for all edges making up the creases on a mesh. */ pxr::VtFloatArray crease_sharpnesses; + + /* The lengths of this array specifies the number of sharp corners (or vertex crease) on the + * surface. Each value is the index of a vertex in the mesh's vertex list. */ + pxr::VtIntArray corner_indices; + /* The per-vertex sharpnesses. The lengths of this array must match that of `corner_indices`. */ + pxr::VtFloatArray corner_sharpnesses; }; void USDGenericMeshWriter::write_uv_maps(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh) @@ -214,6 +220,23 @@ void USDGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) attr_crease_sharpness, pxr::VtValue(usd_mesh_data.crease_sharpnesses), timecode); } + if (!usd_mesh_data.corner_indices.empty() && + usd_mesh_data.corner_indices.size() == usd_mesh_data.corner_sharpnesses.size()) { + pxr::UsdAttribute attr_corner_indices = usd_mesh.CreateCornerIndicesAttr(pxr::VtValue(), true); + pxr::UsdAttribute attr_corner_sharpnesses = usd_mesh.CreateCornerSharpnessesAttr( + pxr::VtValue(), true); + + if (!attr_corner_indices.HasValue()) { + attr_corner_indices.Set(usd_mesh_data.corner_indices, defaultTime); + attr_corner_sharpnesses.Set(usd_mesh_data.corner_sharpnesses, defaultTime); + } + + usd_value_writer_.SetAttribute( + attr_corner_indices, pxr::VtValue(usd_mesh_data.corner_indices), timecode); + usd_value_writer_.SetAttribute( + attr_corner_sharpnesses, pxr::VtValue(usd_mesh_data.crease_sharpnesses), timecode); + } + if (usd_export_context_.export_params.export_uvmaps) { write_uv_maps(mesh, usd_mesh); } @@ -268,7 +291,7 @@ static void get_loops_polys(const Mesh *mesh, USDMeshData &usd_mesh_data) } } -static void get_creases(const Mesh *mesh, USDMeshData &usd_mesh_data) +static void get_edge_creases(const Mesh *mesh, USDMeshData &usd_mesh_data) { const float factor = 1.0f / 255.0f; @@ -293,11 +316,30 @@ static void get_creases(const Mesh *mesh, USDMeshData &usd_mesh_data) } } +static void get_vert_creases(const Mesh *mesh, USDMeshData &usd_mesh_data) +{ + const float *creases = static_cast<const float *>(CustomData_get_layer(&mesh->vdata, CD_CREASE)); + + if (!creases) { + return; + } + + for (int i = 0, v = mesh->totvert; i < v; i++) { + const float sharpness = creases[i]; + + if (sharpness != 0.0f) { + usd_mesh_data.corner_indices.push_back(i); + usd_mesh_data.corner_sharpnesses.push_back(sharpness); + } + } +} + void USDGenericMeshWriter::get_geometry_data(const Mesh *mesh, USDMeshData &usd_mesh_data) { get_vertices(mesh, usd_mesh_data); get_loops_polys(mesh, usd_mesh_data); - get_creases(mesh, usd_mesh_data); + get_edge_creases(mesh, usd_mesh_data); + get_vert_creases(mesh, usd_mesh_data); } void USDGenericMeshWriter::assign_materials(const HierarchyContext &context, diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 787dbc23515..e1ec061f2f9 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -139,6 +139,10 @@ typedef enum CustomDataType { CD_SHAPE_KEYINDEX = 27, CD_SHAPEKEY = 28, CD_BWEIGHT = 29, + /* Usage of CD_CREASE depends on where on the Mesh the layer is added: + * - for vertex creasing, this is persistent data accross all modes and is stored in the file, + * - for egde creasing, it is runtime data which is only used in edit-mode before being copied to + * MEdge when exiting edit-mode. */ CD_CREASE = 30, CD_ORIGSPACE_MLOOP = 31, CD_PREVIEW_MLOOPCOL = 32, diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index fdd389c9c50..bf50100b302 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -428,6 +428,7 @@ enum { ME_CDFLAG_VERT_BWEIGHT = 1 << 0, ME_CDFLAG_EDGE_BWEIGHT = 1 << 1, ME_CDFLAG_EDGE_CREASE = 1 << 2, + ME_CDFLAG_VERT_CREASE = 1 << 3, }; /** #Mesh.remesh_mode */ diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 7d43d500760..552cd836d76 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -984,6 +984,30 @@ static int rna_MeshSkinVertexLayer_data_length(PointerRNA *ptr) /* End skin vertices */ +/* Vertex creases */ +DEFINE_CUSTOMDATA_LAYER_COLLECTION(vertex_crease, vdata, CD_CREASE) + +static char *rna_VertCustomData_data_path(PointerRNA *ptr, const char *collection, int type); +static char *rna_MeshVertexCreaseLayer_path(PointerRNA *ptr) +{ + return rna_VertCustomData_data_path(ptr, "vertex_creases", CD_CREASE); +} + +static void rna_MeshVertexCreaseLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Mesh *me = rna_mesh(ptr); + CustomDataLayer *layer = (CustomDataLayer *)ptr->data; + rna_iterator_array_begin(iter, layer->data, sizeof(float), me->totvert, 0, NULL); +} + +static int rna_MeshVertexCreaseLayer_data_length(PointerRNA *ptr) +{ + Mesh *me = rna_mesh(ptr); + return me->totvert; +} + +/* End vertex creases */ + /* Paint mask */ DEFINE_CUSTOMDATA_LAYER_COLLECTION(vertex_paint_mask, vdata, CD_PAINT_MASK) @@ -1675,6 +1699,7 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void) (void)rna_Mesh_face_map_active_index_set; (void)rna_Mesh_face_map_active_index_get; (void)rna_Mesh_face_map_active_set; + (void)rna_Mesh_vertex_crease_index_range; /* end unused function block */ } @@ -2907,6 +2932,40 @@ static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop)) RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all"); } +static void rna_def_vertex_creases(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MeshVertexCreaseLayer", NULL); + RNA_def_struct_ui_text(srna, "Mesh Vertex Crease Layer", "Per-vertex crease"); + RNA_def_struct_sdna(srna, "CustomDataLayer"); + RNA_def_struct_path_func(srna, "rna_MeshVertexCreaseLayer_path"); + + prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "MeshVertexCrease"); + RNA_def_property_ui_text(prop, "Data", ""); + RNA_def_property_collection_funcs(prop, + "rna_MeshVertexCreaseLayer_data_begin", + "rna_iterator_array_next", + "rna_iterator_array_end", + "rna_iterator_array_get", + "rna_MeshVertexCreaseLayer_data_length", + NULL, + NULL, + NULL); + + /* VertexCrease struct */ + srna = RNA_def_struct(brna, "MeshVertexCrease", NULL); + RNA_def_struct_sdna(srna, "MFloatProperty"); + RNA_def_struct_ui_text(srna, "Float Property", ""); + + prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f"); + RNA_def_property_ui_text(prop, "Value", ""); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all"); +} + static void rna_def_paint_mask(BlenderRNA *brna, PropertyRNA *UNUSED(cprop)) { StructRNA *srna; @@ -3322,6 +3381,24 @@ static void rna_def_mesh(BlenderRNA *brna) rna_def_skin_vertices(brna, prop); /* End skin vertices */ + /* Vertex Crease */ + prop = RNA_def_property(srna, "vertex_creases", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "MeshVertexCreaseLayer"); + RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer"); + RNA_def_property_collection_funcs(prop, + "rna_Mesh_vertex_creases_begin", + NULL, + NULL, + NULL, + "rna_Mesh_vertex_creases_length", + NULL, + NULL, + NULL); + RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); + RNA_def_property_ui_text(prop, "Vertex Creases", "Sharpness of the vertices"); + rna_def_vertex_creases(brna); + /* End vertex crease */ + /* Paint mask */ prop = RNA_def_property(srna, "vertex_paint_masks", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer"); @@ -3519,6 +3596,10 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_EDGE_BWEIGHT); RNA_def_property_ui_text(prop, "Store Edge Bevel Weight", ""); + prop = RNA_def_property(srna, "use_customdata_vertex_crease", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_VERT_CREASE); + RNA_def_property_ui_text(prop, "Store Vertex Crease", ""); + prop = RNA_def_property(srna, "use_customdata_edge_crease", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_EDGE_CREASE); RNA_def_property_ui_text(prop, "Store Edge Crease", ""); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 0f0734c8448..957b92f204a 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1741,7 +1741,7 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) prop = RNA_def_property(srna, "use_creases", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", eSubsurfModifierFlag_UseCrease); RNA_def_property_ui_text( - prop, "Use Creases", "Use mesh edge crease information to sharpen edges"); + prop, "Use Creases", "Use mesh crease information to sharpen edges or corners"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "use_custom_normals", PROP_BOOLEAN, PROP_NONE); @@ -1956,7 +1956,7 @@ static void rna_def_modifier_multires(BlenderRNA *brna) prop = RNA_def_property(srna, "use_creases", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", eMultiresModifierFlag_UseCrease); RNA_def_property_ui_text( - prop, "Use Creases", "Use mesh edge crease information to sharpen edges"); + prop, "Use Creases", "Use mesh crease information to sharpen edges or corners"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "use_custom_normals", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 00870d076ef..b77f6b7e3e2 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -85,6 +85,9 @@ static void requiredDataMask(Object *UNUSED(ob), r_cddata_masks->lmask |= CD_MASK_NORMAL; r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL; } + if (smd->flags & eSubsurfModifierFlag_UseCrease) { + r_cddata_masks->vmask |= CD_MASK_CREASE; + } } static bool dependsOnNormals(ModifierData *md) |