1
1

Compare commits

...

19 Commits

Author SHA1 Message Date
01f509232b Merge branch 'master' into refactor-mesh-sharp-edge-generic 2023-01-10 13:05:56 -05:00
5609f61bb3 Merge branch 'master' into refactor-mesh-sharp-edge-generic 2023-01-09 13:16:58 -05:00
a357adf6cd Remove dot from attribute name 2023-01-04 23:58:13 -05:00
b18fd83883 Cleanup: Use static cast 2023-01-04 22:54:43 -05:00
4c2c114324 Use VArraySpan for sharp edge face set conversion 2023-01-04 22:54:35 -05:00
e31f5fde34 Fix sharp edge data transfer modifier 2023-01-04 22:47:20 -05:00
cbbab81b9e Cleanup: Use helper variable for better formatting 2023-01-04 22:47:06 -05:00
5fce94f825 Move code to make diff smaller 2023-01-04 22:46:50 -05:00
2e87364e3c Fix sharp tagging in Curve to Mesh conversion 2023-01-04 22:18:18 -05:00
8fa7bcb59a Fix bad BMesh Mesh conversion logic 2023-01-04 22:18:05 -05:00
d9f71d3133 Fix crash in BMesh Mesh conversion 2023-01-04 20:55:38 -05:00
892fbf5ab6 Merge branch 'master' into refactor-mesh-sharp-edge-generic 2023-01-04 20:27:53 -05:00
c998d56b1e Add missing sharp edge handling when converting to and from BMesh 2023-01-03 22:34:26 -05:00
0178d3e4bb Add missing attribute provider 2023-01-03 22:32:35 -05:00
8e81e3b229 Fix variable name 2023-01-03 22:32:22 -05:00
155ec559fb Merge branch 'master' into refactor-mesh-sharp-edge-generic 2023-01-03 20:29:16 -05:00
f4292febb4 Various fixes 2023-01-03 20:28:02 -05:00
c5331f134d Merge branch 'master' into refactor-mesh-sharp-edge-generic 2023-01-03 20:04:51 -05:00
4e3b1ef861 Mesh: Move sharp edges to generic attribute
Initial compiling version, many tests don't pass yet.
2023-01-03 17:22:19 -05:00
29 changed files with 368 additions and 125 deletions

View File

@@ -472,14 +472,14 @@ void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
* Used when defining an empty custom loop normals data layer,
* to keep same shading as with auto-smooth!
*/
void BKE_edges_sharp_from_angle_set(struct MEdge *medges,
int numEdges,
void BKE_edges_sharp_from_angle_set(int numEdges,
const struct MLoop *mloops,
int numLoops,
const struct MPoly *mpolys,
const float (*poly_normals)[3],
int numPolys,
float split_angle);
float split_angle,
bool *sharp_edges);
/**
* References a contiguous loop-fan with normal offset vars.
@@ -592,6 +592,8 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
* (splitting edges).
*
* \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
* each side of the edge.
*/
void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
const float (*vert_normals)[3],
@@ -606,6 +608,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
int numPolys,
bool use_split_normals,
float split_angle,
const bool *sharp_edges,
const int *loop_to_poly_map,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2]);
@@ -613,7 +616,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
int numVerts,
struct MEdge *medges,
const struct MEdge *medges,
int numEdges,
const struct MLoop *mloops,
float (*r_custom_loop_normals)[3],
@@ -621,18 +624,20 @@ void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
const struct MPoly *mpolys,
const float (*poly_normals)[3],
int numPolys,
bool *sharp_edges,
short (*r_clnors_data)[2]);
void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
float (*r_custom_vert_normals)[3],
int numVerts,
struct MEdge *medges,
const struct MEdge *medges,
int numEdges,
const struct MLoop *mloops,
int numLoops,
const struct MPoly *mpolys,
const float (*poly_normals)[3],
int numPolys,
bool *sharp_edges,
short (*r_clnors_data)[2]);
/**

View File

@@ -95,6 +95,9 @@ void BKE_mesh_legacy_convert_loose_edges_to_flag(struct Mesh *mesh);
void BKE_mesh_legacy_attribute_flags_to_strings(struct Mesh *mesh);
void BKE_mesh_legacy_attribute_strings_to_flags(struct Mesh *mesh);
void BKE_mesh_sharp_edges_to_flags(struct Mesh *mesh);
void BKE_mesh_sharp_edges_from_flags(struct Mesh *mesh);
struct MVert *BKE_mesh_legacy_convert_positions_to_verts(
Mesh *mesh,
blender::ResourceScope &temp_arrays_for_convert,

View File

@@ -322,6 +322,7 @@ int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge,
int totpoly,
const struct MLoop *mloop,
int totloop,
const bool *sharp_edges,
int *r_totgroup,
bool use_bitflags);

View File

@@ -17,13 +17,6 @@
namespace blender::bke {
static void mark_edges_sharp(MutableSpan<MEdge> edges)
{
for (MEdge &edge : edges) {
edge.flag |= ME_SHARP;
}
}
static void fill_mesh_topology(const int vert_offset,
const int edge_offset,
const int poly_offset,
@@ -155,9 +148,6 @@ static void fill_mesh_topology(const int vert_offset,
loop_end.v = last_ring_vert_offset + i;
loop_end.e = last_ring_edge_offset + i;
}
mark_edges_sharp(edges.slice(profile_edges_start, profile_segment_num));
mark_edges_sharp(edges.slice(last_ring_edge_offset, profile_segment_num));
}
}
@@ -166,17 +156,17 @@ static void mark_bezier_vector_edges_sharp(const int profile_point_num,
const Span<int> control_point_offsets,
const Span<int8_t> handle_types_left,
const Span<int8_t> handle_types_right,
MutableSpan<MEdge> edges)
MutableSpan<bool> sharp_edges)
{
const int main_edges_start = 0;
if (curves::bezier::point_is_sharp(handle_types_left, handle_types_right, 0)) {
mark_edges_sharp(edges.slice(main_edges_start, main_segment_num));
sharp_edges.slice(main_edges_start, main_segment_num).fill(true);
}
for (const int i : IndexRange(profile_point_num).drop_front(1)) {
if (curves::bezier::point_is_sharp(handle_types_left, handle_types_right, i)) {
mark_edges_sharp(edges.slice(
main_edges_start + main_segment_num * control_point_offsets[i - 1], main_segment_num));
const int offset = main_edges_start + main_segment_num * control_point_offsets[i - 1];
sharp_edges.slice(offset, main_segment_num).fill(true);
}
}
}
@@ -624,6 +614,38 @@ static void copy_curve_domain_attribute_to_mesh(const ResultOffsets &mesh_offset
});
}
static void write_sharp_bezier_edges(const CurvesInfo &curves_info,
const ResultOffsets &offsets,
MutableAttributeAccessor mesh_attributes,
SpanAttributeWriter<bool> &sharp_edges)
{
const CurvesGeometry &profile = curves_info.profile;
if (!profile.has_curve_with_type(CURVE_TYPE_BEZIER)) {
return;
}
const VArraySpan<int8_t> handle_types_left{profile.handle_types_left()};
const VArraySpan<int8_t> handle_types_right{profile.handle_types_right()};
if (!handle_types_left.contains(BEZIER_HANDLE_VECTOR) &&
!handle_types_right.contains(BEZIER_HANDLE_VECTOR)) {
return;
}
sharp_edges = mesh_attributes.lookup_or_add_for_write_span<bool>("sharp_edge", ATTR_DOMAIN_EDGE);
const VArray<int8_t> types = profile.curve_types();
foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
if (types[info.i_profile] == CURVE_TYPE_BEZIER) {
const IndexRange points = profile.points_for_curve(info.i_profile);
mark_bezier_vector_edges_sharp(points.size(),
info.main_segment_num,
profile.bezier_evaluated_offsets_for_curve(info.i_profile),
handle_types_left.slice(points),
handle_types_right.slice(points),
sharp_edges.span.slice(info.edge_range));
}
});
}
Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
const CurvesGeometry &profile,
const bool fill_caps,
@@ -691,28 +713,34 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
positions.slice(info.vert_range));
});
if (profile.curve_type_counts()[CURVE_TYPE_BEZIER] > 0) {
const VArray<int8_t> curve_types = profile.curve_types();
const VArraySpan<int8_t> handle_types_left{profile.handle_types_left()};
const VArraySpan<int8_t> handle_types_right{profile.handle_types_right()};
MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write();
SpanAttributeWriter<bool> sharp_edges;
write_sharp_bezier_edges(curves_info, offsets, mesh_attributes, sharp_edges);
if (fill_caps) {
if (!sharp_edges) {
sharp_edges = mesh_attributes.lookup_or_add_for_write_span<bool>("sharp_edge",
ATTR_DOMAIN_EDGE);
}
foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
if (curve_types[info.i_profile] == CURVE_TYPE_BEZIER) {
const IndexRange points = profile.points_for_curve(info.i_profile);
mark_bezier_vector_edges_sharp(points.size(),
info.main_segment_num,
profile.bezier_evaluated_offsets_for_curve(info.i_profile),
handle_types_left.slice(points),
handle_types_right.slice(points),
edges.slice(info.edge_range));
if (info.main_cyclic || !info.profile_cyclic) {
return;
}
const int main_edges_start = info.edge_range.start();
const int last_ring_index = info.main_points.size() - 1;
const int profile_edges_start = main_edges_start +
info.profile_points.size() * info.main_segment_num;
const int last_ring_edge_offset = profile_edges_start +
info.profile_segment_num * last_ring_index;
sharp_edges.span.slice(profile_edges_start, info.profile_segment_num).fill(true);
sharp_edges.span.slice(last_ring_edge_offset, info.profile_segment_num).fill(true);
});
}
sharp_edges.finish();
Set<AttributeIDRef> main_attributes_set;
MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write();
main_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
if (!should_add_attribute_to_mesh(
main_attributes, mesh_attributes, id, meta_data, propagation_info)) {

View File

@@ -2300,7 +2300,8 @@ static bool attribute_stored_in_bmesh_flag(const StringRef name)
".select_vert",
".select_edge",
".select_poly",
"material_index");
"material_index",
"sharp_edge");
}
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src,

View File

@@ -20,6 +20,7 @@
#include "BLI_utildefines.h"
#include "BKE_attribute.h"
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_data_transfer.h"
#include "BKE_deform.h"
@@ -300,6 +301,8 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
num_polys_dst,
use_split_nors_dst,
split_angle_dst,
static_cast<const bool *>(CustomData_get_layer_named(
&me_dst->edata, CD_PROP_BOOL, "sharp_edge")),
nullptr,
nullptr,
custom_nors_dst);
@@ -314,6 +317,7 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
const int dtdata_type,
const bool changed)
{
using namespace blender;
if (dtdata_type == DT_TYPE_LNOR) {
if (!changed) {
return;
@@ -341,6 +345,10 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, num_loops_dst));
}
bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write();
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
/* Note loop_nors_dst contains our custom normals as transferred from source... */
BKE_mesh_normals_loop_custom_set(positions_dst,
BKE_mesh_vertex_normals_ensure(me_dst),
@@ -353,7 +361,10 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
polys_dst,
poly_nors_dst,
num_polys_dst,
sharp_edges.span.data(),
custom_nors_dst);
sharp_edges.finish();
}
}
@@ -961,11 +972,11 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
}
return true;
}
if (r_map && ELEM(cddata_type, CD_FAKE_SHARP, CD_FAKE_SEAM)) {
if (r_map && cddata_type == CD_FAKE_SEAM) {
const size_t elem_size = sizeof(*((MEdge *)nullptr));
const size_t data_size = sizeof(((MEdge *)nullptr)->flag);
const size_t data_offset = offsetof(MEdge, flag);
const uint64_t data_flag = (cddata_type == CD_FAKE_SHARP) ? ME_SHARP : ME_SEAM;
const uint64_t data_flag = ME_SEAM;
data_transfer_layersmapping_add_item(r_map,
cddata_type,
@@ -984,7 +995,23 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
interp_data);
return true;
}
if (r_map && cddata_type == CD_FAKE_SHARP) {
if (!CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge")) {
CustomData_add_layer_named(
&me_dst->edata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me_dst->totedge, "sharp_edge");
}
data_transfer_layersmapping_add_item_cd(
r_map,
CD_PROP_BOOL,
mix_mode,
mix_factor,
mix_weights,
CustomData_get_layer_named(&me_src->edata, CD_PROP_BOOL, "sharp_edge"),
CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge"),
interp,
interp_data);
return true;
}
return false;
}
else if (elem_type == ME_LOOP) {

View File

@@ -1276,6 +1276,18 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
make_derived_write_attribute<MPoly, bool, get_shade_smooth, set_shade_smooth>,
nullptr);
static BuiltinCustomDataLayerProvider sharp_edge("sharp_edge",
ATTR_DOMAIN_EDGE,
CD_PROP_BOOL,
CD_PROP_BOOL,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::Writable,
BuiltinAttributeProvider::Deletable,
edge_access,
make_array_read_attribute<bool>,
make_array_write_attribute<bool>,
nullptr);
static BuiltinCustomDataLayerProvider crease(
"crease",
ATTR_DOMAIN_EDGE,
@@ -1296,7 +1308,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static CustomDataAttributeProvider face_custom_data(ATTR_DOMAIN_FACE, face_access);
return ComponentAttributeProviders(
{&position, &id, &material_index, &shade_smooth, &normal, &crease},
{&position, &id, &material_index, &shade_smooth, &sharp_edge, &normal, &crease},
{&corner_custom_data,
&vertex_groups,
&point_custom_data,

View File

@@ -2287,6 +2287,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
mesh->totpoly,
(mesh->flag & ME_AUTOSMOOTH) != 0,
mesh->smoothresh,
static_cast<const bool *>(CustomData_get_layer_named(
&mesh->edata, CD_PROP_BOOL, "sharp_edge")),
nullptr,
nullptr,
clnors);

View File

@@ -272,6 +272,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
BKE_mesh_legacy_bevel_weight_from_layers(mesh);
BKE_mesh_legacy_face_set_from_generic(mesh, poly_layers);
BKE_mesh_legacy_edge_crease_from_layers(mesh);
BKE_mesh_sharp_edges_to_flags(mesh);
BKE_mesh_legacy_attribute_strings_to_flags(mesh);
mesh->active_color_attribute = nullptr;
mesh->default_color_attribute = nullptr;
@@ -1860,6 +1861,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
polys.size(),
use_split_normals,
split_angle,
static_cast<const bool *>(CustomData_get_layer_named(
&mesh->edata, CD_PROP_BOOL, "sharp_edge")),
nullptr,
r_lnors_spacearr,
clnors);

View File

@@ -1341,6 +1341,48 @@ void BKE_mesh_legacy_edge_crease_to_layers(Mesh *mesh)
}
}
/* -------------------------------------------------------------------- */
/** \name Sharp Edge Conversion
* \{ */
void BKE_mesh_sharp_edges_to_flags(Mesh *mesh)
{
using namespace blender;
MutableSpan<MEdge> edges = mesh->edges_for_write();
if (const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"))) {
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
SET_FLAG_FROM_TEST(edges[i].flag, sharp_edges[i], ME_SHARP);
}
});
}
else {
for (const int i : edges.index_range()) {
edges[i].flag &= ~ME_SHARP;
}
}
}
void BKE_mesh_sharp_edges_from_flags(Mesh *mesh)
{
using namespace blender;
using namespace blender::bke;
const Span<MEdge> edges = mesh->edges();
MutableAttributeAccessor attributes = mesh->attributes_for_write();
if (std::any_of(
edges.begin(), edges.end(), [](const MEdge &edge) { return edge.flag & ME_SHARP; })) {
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_only_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
sharp_edges.span[i] = edges[i].flag & ME_SHARP;
}
});
sharp_edges.finish();
}
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -632,6 +632,8 @@ Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<MLoop> loops, co
using MeshRemap_CheckIslandBoundary = bool (*)(const MPoly *mpoly,
const MLoop *mloop,
const MEdge *medge,
const int edge_index,
const bool *sharp_edges,
const int edge_user_count,
const MPoly *mpoly_array,
const MeshElemMap *edge_poly_map,
@@ -643,6 +645,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
const int totpoly,
const MLoop *mloop,
const int totloop,
const bool *sharp_edges,
MeshElemMap *edge_poly_map,
const bool use_bitflags,
MeshRemap_CheckIslandBoundary edge_boundary_check,
@@ -734,7 +737,8 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
const MeshElemMap *map_ele = &edge_poly_map[me_idx];
const int *p = map_ele->indices;
int i = map_ele->count;
if (!edge_boundary_check(mp, ml, me, i, mpoly, map_ele, edge_boundary_check_data)) {
if (!edge_boundary_check(
mp, ml, me, me_idx, sharp_edges, i, mpoly, map_ele, edge_boundary_check_data)) {
for (; i--; p++) {
/* if we meet other non initialized its a bug */
BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
@@ -834,7 +838,9 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
static bool poly_is_island_boundary_smooth_cb(const MPoly *mp,
const MLoop * /*ml*/,
const MEdge *me,
const MEdge * /*me*/,
const int edge_index,
const bool *sharp_edges,
const int edge_user_count,
const MPoly *mpoly_array,
const MeshElemMap *edge_poly_map,
@@ -842,7 +848,8 @@ static bool poly_is_island_boundary_smooth_cb(const MPoly *mp,
{
/* Edge is sharp if one of its polys is flat, or edge itself is sharp,
* or edge is not used by exactly two polygons. */
if ((mp->flag & ME_SMOOTH) && !(me->flag & ME_SHARP) && (edge_user_count == 2)) {
if ((mp->flag & ME_SMOOTH) && !(sharp_edges && sharp_edges[edge_index]) &&
(edge_user_count == 2)) {
/* In that case, edge appears to be smooth, but we need to check its other poly too. */
const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ?
&mpoly_array[edge_poly_map->indices[1]] :
@@ -858,6 +865,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge,
const int totpoly,
const MLoop *mloop,
const int totloop,
const bool *sharp_edges,
int *r_totgroup,
const bool use_bitflags)
{
@@ -869,6 +877,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge,
totpoly,
mloop,
totloop,
sharp_edges,
nullptr,
use_bitflags,
poly_is_island_boundary_smooth_cb,
@@ -1011,6 +1020,8 @@ struct MeshCheckIslandBoundaryUv {
static bool mesh_check_island_boundary_uv(const MPoly * /*mp*/,
const MLoop *ml,
const MEdge *me,
const int /*edge_index*/,
const bool * /*sharp_edges*/,
const int /*edge_user_count*/,
const MPoly * /*mpoly_array*/,
const MeshElemMap * /*edge_poly_map*/,
@@ -1109,6 +1120,7 @@ static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges,
totpoly,
loops,
totloop,
nullptr,
edge_poly_map,
false,
mesh_check_island_boundary_uv,

View File

@@ -421,6 +421,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
totpoly,
true,
mesh->smoothresh,
static_cast<const bool *>(CustomData_get_layer_named(
&result->edata, CD_PROP_BOOL, "sharp_edge")),
nullptr,
&lnors_spacearr,
clnors);

View File

@@ -30,6 +30,7 @@
#include "BLI_timeit.hh"
#include "BLI_utildefines.h"
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_editmesh_cache.h"
#include "BKE_global.h"
@@ -44,6 +45,7 @@ using blender::int2;
using blender::MutableSpan;
using blender::short2;
using blender::Span;
using blender::VArray;
// #define DEBUG_TIME
@@ -787,15 +789,15 @@ struct LoopSplitTaskDataCommon {
/* See comment about edge_to_loops below. */
#define IS_EDGE_SHARP(_e2l) ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID)
static void mesh_edges_sharp_tag(const Span<MEdge> edges,
const Span<MPoly> polys,
static void mesh_edges_sharp_tag(const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> loop_to_poly_map,
const Span<float3> poly_normals,
const Span<bool> sharp_edges_in,
const bool check_angle,
const float split_angle,
MutableSpan<int2> edge_to_loops,
BitVector<> *r_sharp_edges)
MutableSpan<bool> sharp_edges_out)
{
using namespace blender;
const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
@@ -825,15 +827,15 @@ static void mesh_edges_sharp_tag(const Span<MEdge> edges,
* or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the
* same vertex, or angle between both its polys' normals is above split_angle value.
*/
if (!(poly.flag & ME_SMOOTH) || (edges[edge_i].flag & ME_SHARP) ||
if (!(poly.flag & ME_SMOOTH) || (!sharp_edges_in.is_empty() && sharp_edges_in[edge_i]) ||
vert_i == loops[e2l[0]].v || is_angle_sharp) {
/* NOTE: we are sure that loop != 0 here ;). */
e2l[1] = INDEX_INVALID;
/* We want to avoid tagging edges as sharp when it is already defined as such by
* other causes than angle threshold. */
if (r_sharp_edges && is_angle_sharp) {
(*r_sharp_edges)[edge_i].set();
if (!sharp_edges_out.is_empty() && is_angle_sharp) {
sharp_edges_out[edge_i] = true;
}
}
else {
@@ -846,8 +848,8 @@ static void mesh_edges_sharp_tag(const Span<MEdge> edges,
/* We want to avoid tagging edges as sharp when it is already defined as such by
* other causes than angle threshold. */
if (r_sharp_edges) {
(*r_sharp_edges)[edge_i].reset();
if (!sharp_edges_out.is_empty()) {
sharp_edges_out[edge_i] = false;
}
}
/* Else, edge is already 'disqualified' (i.e. sharp)! */
@@ -855,14 +857,14 @@ static void mesh_edges_sharp_tag(const Span<MEdge> edges,
}
}
void BKE_edges_sharp_from_angle_set(MEdge *medges,
const int numEdges,
void BKE_edges_sharp_from_angle_set(const int numEdges,
const MLoop *mloops,
const int numLoops,
const MPoly *mpolys,
const float (*poly_normals)[3],
const int numPolys,
const float split_angle)
const float split_angle,
bool *r_sharp_edges)
{
using namespace blender;
using namespace blender::bke;
@@ -878,24 +880,15 @@ void BKE_edges_sharp_from_angle_set(MEdge *medges,
const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map({mpolys, numPolys},
numLoops);
BitVector<> sharp_edges(numEdges, false);
mesh_edges_sharp_tag({medges, numEdges},
{mpolys, numPolys},
mesh_edges_sharp_tag({mpolys, numPolys},
{mloops, numLoops},
loop_to_poly,
{reinterpret_cast<const float3 *>(poly_normals), numPolys},
Span<bool>(r_sharp_edges, numEdges),
true,
split_angle,
edge_to_loops,
&sharp_edges);
threading::parallel_for(IndexRange(numEdges), 4096, [&](const IndexRange range) {
for (const int edge_i : range) {
if (sharp_edges[edge_i]) {
medges[edge_i].flag |= ME_SHARP;
}
}
});
{r_sharp_edges, numEdges});
}
static void loop_manifold_fan_around_vert_next(const Span<MLoop> loops,
@@ -1455,6 +1448,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
const int numPolys,
const bool use_split_normals,
const float split_angle,
const bool *sharp_edges,
const int *loop_to_poly_map,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2])
@@ -1565,15 +1559,15 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
});
/* This first loop check which edges are actually smooth, and compute edge vectors. */
mesh_edges_sharp_tag({medges, numEdges},
polys,
mesh_edges_sharp_tag(polys,
loops,
loop_to_poly,
{reinterpret_cast<const float3 *>(poly_normals), numPolys},
Span<bool>(sharp_edges, sharp_edges ? numEdges : 0),
check_angle,
split_angle,
edge_to_loops,
nullptr);
{});
if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
/* Not enough loops to be worth the whole threading overhead. */
@@ -1612,7 +1606,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
static void mesh_normals_loop_custom_set(const float (*positions)[3],
const float (*vert_normals)[3],
const int numVerts,
MEdge *medges,
const MEdge *medges,
const int numEdges,
const MLoop *mloops,
float (*r_custom_loop_normals)[3],
@@ -1620,6 +1614,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
const MPoly *mpolys,
const float (*poly_normals)[3],
const int numPolys,
MutableSpan<bool> sharp_edges,
short (*r_clnors_data)[2],
const bool use_vertices)
{
@@ -1658,6 +1653,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
numPolys,
use_split_normals,
split_angle,
sharp_edges.data(),
loop_to_poly.data(),
&lnors_spacearr,
nullptr);
@@ -1740,7 +1736,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
const MPoly *mp = &mpolys[loop_to_poly[lidx]];
const MLoop *mlp =
&mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true;
org_nor = nor;
}
@@ -1765,7 +1761,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
const MPoly *mp = &mpolys[loop_to_poly[lidx]];
const MLoop *mlp =
&mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true;
}
}
}
@@ -1785,6 +1781,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
numPolys,
use_split_normals,
split_angle,
sharp_edges.data(),
loop_to_poly.data(),
&lnors_spacearr,
nullptr);
@@ -1852,7 +1849,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
const int numVerts,
MEdge *medges,
const MEdge *medges,
const int numEdges,
const MLoop *mloops,
float (*r_custom_loop_normals)[3],
@@ -1860,6 +1857,7 @@ void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
const MPoly *mpolys,
const float (*poly_normals)[3],
const int numPolys,
bool *sharp_edges,
short (*r_clnors_data)[2])
{
mesh_normals_loop_custom_set(vert_positions,
@@ -1873,6 +1871,7 @@ void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
mpolys,
poly_normals,
numPolys,
{sharp_edges, numEdges},
r_clnors_data,
false);
}
@@ -1881,13 +1880,14 @@ void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3
const float (*vert_normals)[3],
float (*r_custom_vert_normals)[3],
const int numVerts,
MEdge *medges,
const MEdge *medges,
const int numEdges,
const MLoop *mloops,
const int numLoops,
const MPoly *mpolys,
const float (*poly_normals)[3],
const int numPolys,
bool *sharp_edges,
short (*r_clnors_data)[2])
{
mesh_normals_loop_custom_set(vert_positions,
@@ -1901,12 +1901,15 @@ void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3
mpolys,
poly_normals,
numPolys,
{sharp_edges, numEdges},
r_clnors_data,
true);
}
static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const bool use_vertices)
{
using namespace blender;
using namespace blender::bke;
short(*clnors)[2];
const int numloops = mesh->totloop;
@@ -1922,6 +1925,9 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
MutableSpan<MEdge> edges = mesh->edges_for_write();
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
mesh_normals_loop_custom_set(reinterpret_cast<const float(*)[3]>(positions.data()),
BKE_mesh_vertex_normals_ensure(mesh),
@@ -1934,8 +1940,10 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
polys.data(),
BKE_mesh_poly_normals_ensure(mesh),
polys.size(),
sharp_edges.span,
clnors,
use_vertices);
sharp_edges.finish();
}
void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loop_normals)[3])

View File

@@ -1381,6 +1381,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
numpolys_dst,
use_split_nors_dst,
split_angle_dst,
static_cast<const bool *>(CustomData_get_layer_named(
&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge")),
nullptr,
nullptr,
custom_nors_dst);

View File

@@ -999,7 +999,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
if (edgeFlags) {
if (edgeIdx != -1) {
ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW);
ed_flag |= ((edgeFlags[index] & ME_SEAM) | ME_EDGEDRAW);
}
}
else {

View File

@@ -32,6 +32,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh)
BKE_mesh_legacy_convert_uvs_to_generic(&mesh);
BKE_mesh_legacy_convert_mpoly_to_material_indices(&mesh);
BKE_mesh_legacy_bevel_weight_to_layers(&mesh);
BKE_mesh_sharp_edges_from_flags(&mesh);
BKE_mesh_legacy_face_set_to_generic(&mesh);
BKE_mesh_legacy_edge_crease_to_layers(&mesh);
BKE_mesh_legacy_convert_verts_to_positions(&mesh);

View File

@@ -718,8 +718,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
char BM_edge_flag_from_mflag(const short mflag)
{
return (((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0));
return (((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0));
}
char BM_face_flag_from_mflag(const char mflag)
{
@@ -730,8 +729,7 @@ short BM_edge_flag_to_mflag(BMEdge *e)
{
const char hflag = e->head.hflag;
return (((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0));
return (((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0));
}
char BM_face_flag_to_mflag(BMFace *f)
{

View File

@@ -336,6 +336,8 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
&me->pdata, CD_PROP_BOOL, ".hide_poly");
const int *material_indices = (const int *)CustomData_get_layer_named(
&me->pdata, CD_PROP_INT32, "material_index");
const bool *sharp_edges = (const bool *)CustomData_get_layer_named(
&me->edata, CD_PROP_BOOL, "sharp_edge");
const Span<float3> positions = me->vert_positions();
Array<BMVert *> vtable(me->totvert);
@@ -390,6 +392,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
if (select_edge && select_edge[i]) {
BM_edge_select_set(bm, e, true);
}
if (!(sharp_edges && sharp_edges[i])) {
BM_elem_flag_enable(e, BM_ELEM_SMOOTH);
}
/* Copy Custom Data */
CustomData_to_bmesh_block(&mesh_edata, &bm->edata, i, &e->head.data, true);
@@ -1063,6 +1068,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
bool need_hide_edge = false;
bool need_hide_poly = false;
bool need_material_index = false;
bool need_sharp_edge = false;
i = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -1098,6 +1104,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
need_select_edge = true;
}
if (!BM_elem_flag_test(e, BM_ELEM_SMOOTH)) {
need_sharp_edge = true;
}
BM_elem_index_set(e, i); /* set_inline */
@@ -1158,6 +1167,13 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
ATTR_DOMAIN_FACE,
[&](const int i) { return int(BM_face_at_index(bm, i)->mat_nr); });
}
if (need_sharp_edge) {
BM_mesh_elem_table_ensure(bm, BM_EDGE);
write_fn_to_attribute<bool>(
me->attributes_for_write(), "sharp_edge", ATTR_DOMAIN_EDGE, [&](const int i) {
return !BM_elem_flag_test(BM_edge_at_index(bm, i), BM_ELEM_SMOOTH);
});
}
/* Patch hook indices and vertex parents. */
if (params->calc_object_remap && (ototvert > 0)) {
@@ -1352,6 +1368,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
bke::SpanAttributeWriter<bool> hide_edge_attribute;
bke::SpanAttributeWriter<bool> select_edge_attribute;
bke::SpanAttributeWriter<bool> sharp_edge_attribute;
BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
MEdge *med = &medge[i];
@@ -1375,6 +1392,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
}
select_edge_attribute.span[i] = true;
}
if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH)) {
if (!sharp_edge_attribute) {
sharp_edge_attribute = mesh_attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
}
sharp_edge_attribute.span[i] = true;
}
CustomData_from_bmesh_block(&bm->edata, &me->edata, eed->head.data, i);
}
@@ -1442,4 +1466,5 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
select_vert_attribute.finish();
select_edge_attribute.finish();
select_poly_attribute.finish();
sharp_edge_attribute.finish();
}

View File

@@ -381,6 +381,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
mr->poly_len,
is_auto_smooth,
split_angle,
static_cast<const bool *>(CustomData_get_layer_named(
&mr->me->edata, CD_PROP_BOOL, "sharp_edge")),
nullptr,
nullptr,
clnors);

View File

@@ -843,6 +843,7 @@ void MESH_OT_customdata_skin_clear(wmOperatorType *ot)
/* Clear custom loop normals */
static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator * /*op*/)
{
using namespace blender;
Mesh *me = ED_mesh_context(C);
if (BKE_mesh_has_custom_loop_normals(me)) {
return OPERATOR_CANCELLED;
@@ -862,18 +863,20 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
/* Tag edges as sharp according to smooth threshold if needed,
* to preserve auto-smooth shading. */
if (me->flag & ME_AUTOSMOOTH) {
MutableSpan<MEdge> edges = me->edges_for_write();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
BKE_edges_sharp_from_angle_set(edges.data(),
edges.size(),
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
BKE_edges_sharp_from_angle_set(me->totedge,
loops.data(),
loops.size(),
polys.data(),
BKE_mesh_poly_normals_ensure(me),
polys.size(),
me->smoothresh);
me->smoothresh,
sharp_edges.span.data());
sharp_edges.finish();
}
CustomData_add_layer(&me->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, me->totloop);
@@ -1532,36 +1535,34 @@ Mesh *ED_mesh_context(bContext *C)
void ED_mesh_split_faces(Mesh *mesh)
{
using namespace blender;
Array<MEdge> edges(mesh->edges());
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI);
BKE_edges_sharp_from_angle_set(edges.data(),
edges.size(),
Array<bool> sharp_edges(mesh->totedge, false);
BKE_edges_sharp_from_angle_set(mesh->totedge,
loops.data(),
loops.size(),
polys.data(),
BKE_mesh_poly_normals_ensure(mesh),
polys.size(),
split_angle);
split_angle,
sharp_edges.data());
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int poly_i : range) {
const MPoly &poly = polys[poly_i];
if (!(poly.flag & ME_SMOOTH)) {
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
edges[loop.e].flag |= ME_SHARP;
sharp_edges[loop.e] = true;
}
}
}
});
Vector<int64_t> split_indices;
const IndexMask split_mask = index_mask_ops::find_indices_based_on_predicate(
edges.index_range(), 4096, split_indices, [&](const int64_t i) {
return edges[i].flag & ME_SHARP;
});
const IndexMask split_mask = index_mask_ops::find_indices_from_virtual_array(
sharp_edges.index_range(), VArray<bool>::ForSpan(sharp_edges), 4096, split_indices);
if (split_mask.is_empty()) {
return;
}

View File

@@ -697,10 +697,11 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
break;
}
case SCULPT_FACE_SETS_FROM_SHARP_EDGES: {
const Span<MEdge> edges = mesh->edges();
const VArraySpan<bool> sharp_edges = mesh->attributes().lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
sculpt_face_sets_init_flood_fill(
ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
return (edges[edge].flag & ME_SHARP) == 0;
return !sharp_edges[edge];
});
break;
}

View File

@@ -17,6 +17,7 @@
#include "PIL_time.h"
#include "BKE_attribute.hh"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_customdata.h"
@@ -1477,6 +1478,7 @@ struct EdgeFeatData {
blender::Span<MLoop> loops;
blender::Span<MPoly> polys;
LineartTriangle *tri_array;
blender::VArray<bool> sharp_edges;
LineartVert *v_array;
float crease_threshold;
bool use_auto_smooth;
@@ -1682,9 +1684,8 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
e_feat_data->edges.data(), e_feat_data->loops.data(), &mlooptri[i / 3], real_edges);
if (real_edges[i % 3] >= 0) {
const MEdge *medge = &e_feat_data->edges[real_edges[i % 3]];
if (ld->conf.use_crease && ld->conf.sharp_as_crease && (medge->flag & ME_SHARP)) {
if (ld->conf.use_crease && ld->conf.sharp_as_crease &&
e_feat_data->sharp_edges[real_edges[i % 3]]) {
edge_flag_result |= LRT_EDGE_FLAG_CREASE;
}
@@ -2068,6 +2069,10 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info,
edge_feat_settings.userdata_chunk_size = sizeof(EdgeFeatReduceData);
edge_feat_settings.func_reduce = feat_data_sum_reduce;
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> sharp_edges = attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
EdgeFeatData edge_feat_data = {nullptr};
edge_feat_data.ld = la_data;
edge_feat_data.me = me;
@@ -2077,6 +2082,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info,
edge_feat_data.edges = me->edges();
edge_feat_data.polys = me->polys();
edge_feat_data.loops = me->loops();
edge_feat_data.sharp_edges = sharp_edges;
edge_feat_data.edge_nabr = lineart_build_edge_neighbor(me, total_edges);
edge_feat_data.tri_array = la_tri_arr;
edge_feat_data.v_array = la_v_arr;

View File

@@ -192,14 +192,17 @@ void OBJMesh::ensure_mesh_normals() const
void OBJMesh::calc_smooth_groups(const bool use_bitflags)
{
poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(mesh_edges_.data(),
mesh_edges_.size(),
mesh_polys_.data(),
mesh_polys_.size(),
mesh_loops_.data(),
mesh_loops_.size(),
&tot_smooth_groups_,
use_bitflags);
poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(
mesh_edges_.data(),
mesh_edges_.size(),
mesh_polys_.data(),
mesh_polys_.size(),
mesh_loops_.data(),
mesh_loops_.size(),
static_cast<const bool *>(
CustomData_get_layer_named(&export_mesh_->edata, CD_PROP_BOOL, "sharp_edge")),
&tot_smooth_groups_,
use_bitflags);
}
void OBJMesh::calc_poly_order()

View File

@@ -46,8 +46,9 @@ enum {
#ifdef DNA_DEPRECATED_ALLOW
/** Deprecated loose edge status. Now stored in #Mesh::loose_edges() runtime cache. */
ME_LOOSEEDGE = (1 << 7),
/** Deprecated sharp edge status. Now stored in "sharp_edge" attribute. */
ME_SHARP = (1 << 9),
#endif
ME_SHARP = (1 << 9), /* only reason this flag remains a 'short' */
};
/**

View File

@@ -1506,6 +1506,32 @@ static void rna_MeshEdge_select_set(PointerRNA *ptr, bool value)
select_edge[index] = value;
}
static bool rna_MeshEdge_use_edge_sharp_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
const bool *sharp_edge = (const bool *)CustomData_get_layer_named(
&mesh->edata, CD_PROP_BOOL, "sharp_edge");
const int index = rna_MeshEdge_index_get(ptr);
return sharp_edge == NULL ? false : sharp_edge[index];
}
static void rna_MeshEdge_use_edge_sharp_set(PointerRNA *ptr, bool value)
{
Mesh *mesh = rna_mesh(ptr);
bool *sharp_edge = (bool *)CustomData_duplicate_referenced_layer_named(
&mesh->edata, CD_PROP_BOOL, "sharp_edge", mesh->totedge);
if (!sharp_edge) {
if (!value) {
/* Skip adding layer if it doesn't exist already anyway and we're not hiding an element. */
return;
}
sharp_edge = (bool *)CustomData_add_layer_named(
&mesh->edata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totedge, "sharp_edge");
}
const int index = rna_MeshEdge_index_get(ptr);
sharp_edge[index] = value;
}
static bool rna_MeshEdge_is_loose_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
@@ -2476,8 +2502,9 @@ static void rna_def_medge(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
prop = RNA_def_property(srna, "use_edge_sharp", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_SHARP);
RNA_def_property_ui_text(prop, "Sharp", "Sharp edge for the Edge Split modifier");
RNA_def_property_boolean_funcs(
prop, "rna_MeshEdge_use_edge_sharp_get", "rna_MeshEdge_use_edge_sharp_set");
RNA_def_property_ui_text(prop, "Sharp", "Sharp edge for shading");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all");
prop = RNA_def_property(srna, "is_loose", PROP_BOOLEAN, PROP_NONE);

View File

@@ -91,14 +91,16 @@ static void rna_Mesh_calc_smooth_groups(
Mesh *mesh, bool use_bitflags, int *r_poly_group_len, int **r_poly_group, int *r_group_total)
{
*r_poly_group_len = mesh->totpoly;
*r_poly_group = BKE_mesh_calc_smoothgroups(BKE_mesh_edges(mesh),
mesh->totedge,
BKE_mesh_polys(mesh),
mesh->totpoly,
BKE_mesh_loops(mesh),
mesh->totloop,
r_group_total,
use_bitflags);
*r_poly_group = BKE_mesh_calc_smoothgroups(
BKE_mesh_edges(mesh),
mesh->totedge,
BKE_mesh_polys(mesh),
mesh->totpoly,
BKE_mesh_loops(mesh),
mesh->totloop,
(const bool *)CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"),
r_group_total,
use_bitflags);
}
static void rna_Mesh_normals_split_custom_do(Mesh *mesh,

View File

@@ -21,6 +21,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "BKE_attribute.hh"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_lib_id.h"
@@ -224,8 +225,9 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
const bool use_invert_vgroup,
const float (*vert_positions)[3],
const int verts_num,
MEdge *medge,
const MEdge *medge,
const int edges_num,
bool *sharp_edges,
MLoop *mloop,
const int loops_num,
const MPoly *mpoly,
@@ -341,6 +343,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
mpoly,
poly_normals,
polys_num,
sharp_edges,
clnors);
MEM_freeN(cos);
@@ -363,8 +366,9 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
const bool use_invert_vgroup,
const float (*positions)[3],
const int verts_num,
MEdge *medge,
const MEdge *medge,
const int edges_num,
bool *sharp_edges,
MLoop *mloop,
const int loops_num,
const MPoly *mpoly,
@@ -457,6 +461,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
mpoly,
poly_normals,
polys_num,
sharp_edges,
clnors);
MEM_freeN(nos);
@@ -487,6 +492,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
Object *ob,
Mesh *mesh)
{
using namespace blender;
const bool use_invert_vgroup = ((enmd->flag & MOD_NORMALEDIT_INVERT_VGROUP) != 0);
const bool use_current_clnors = !((enmd->mix_mode == MOD_NORMALEDIT_MIX_COPY) &&
(enmd->mix_factor == 1.0f) && (enmd->defgrp_name[0] == '\0') &&
@@ -529,7 +535,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
const int loops_num = result->totloop;
const int polys_num = result->totpoly;
const float(*positions)[3] = BKE_mesh_vert_positions(result);
MEdge *edges = BKE_mesh_edges_for_write(result);
const MEdge *edges = BKE_mesh_edges(result);
const MPoly *polys = BKE_mesh_polys(result);
MLoop *loops = BKE_mesh_loops_for_write(result);
@@ -543,6 +549,10 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(result);
const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(result);
bke::MutableAttributeAccessor attributes = result->attributes_for_write();
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
short(*clnors)[2] = static_cast<short(*)[2]>(CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL));
if (use_current_clnors) {
clnors = static_cast<short(*)[2]>(
@@ -563,6 +573,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
polys_num,
true,
result->smoothresh,
sharp_edges.span.data(),
nullptr,
nullptr,
clnors);
@@ -593,6 +604,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
verts_num,
edges,
edges_num,
sharp_edges.span.data(),
loops,
loops_num,
polys,
@@ -616,6 +628,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
verts_num,
edges,
edges_num,
sharp_edges.span.data(),
loops,
loops_num,
polys,
@@ -626,6 +639,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
result->runtime->is_original_bmesh = false;
sharp_edges.finish();
return result;
}

View File

@@ -2204,7 +2204,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
medge[edge_index].v1 = last_g->new_vert;
medge[edge_index].v2 = g->new_vert;
medge[edge_index].flag = ME_EDGEDRAW | ((last_flag | flag) & (ME_SEAM | ME_SHARP));
medge[edge_index].flag = ME_EDGEDRAW | ((last_flag | flag) & ME_SEAM);
if (result_edge_crease) {
result_edge_crease[edge_index] = max_ff(mv_crease,
min_ff(last_max_crease, max_crease));
@@ -2237,8 +2237,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
last_g->open_face_edge = edge_index;
medge[edge_index].v1 = last_g->new_vert;
medge[edge_index].v2 = first_g->new_vert;
medge[edge_index].flag = ME_EDGEDRAW |
((last_flag | first_flag) & (ME_SEAM | ME_SHARP));
medge[edge_index].flag = ME_EDGEDRAW | ((last_flag | first_flag) & ME_SEAM);
if (result_edge_crease) {
result_edge_crease[edge_index] = max_ff(mv_crease,
min_ff(last_max_crease, first_max_crease));

View File

@@ -19,6 +19,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "BKE_attribute.hh"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_lib_id.h"
@@ -74,7 +75,8 @@ struct WeightedNormalData {
const float (*vert_positions)[3];
const float (*vert_normals)[3];
MEdge *medge;
const MEdge *medge;
bool *sharp_edges;
const MLoop *mloop;
blender::Span<int> loop_to_poly;
@@ -188,7 +190,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
const int polys_num = wn_data->polys_num;
const float(*positions)[3] = wn_data->vert_positions;
MEdge *medge = wn_data->medge;
const MEdge *medge = wn_data->medge;
const MLoop *mloop = wn_data->mloop;
short(*clnors)[2] = wn_data->clnors;
@@ -236,6 +238,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
polys_num,
true,
split_angle,
wn_data->sharp_edges,
loop_to_poly.data(),
&lnors_spacearr,
has_clnors ? clnors : nullptr);
@@ -366,6 +369,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
mpoly,
poly_normals,
polys_num,
wn_data->sharp_edges,
clnors);
}
else {
@@ -397,6 +401,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
mpoly,
poly_normals,
polys_num,
wn_data->sharp_edges,
clnors);
MEM_freeN(vert_normals);
@@ -418,6 +423,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
polys_num,
true,
split_angle,
wn_data->sharp_edges,
loop_to_poly.data(),
nullptr,
has_clnors ? clnors : nullptr);
@@ -440,6 +446,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
mpoly,
poly_normals,
polys_num,
wn_data->sharp_edges,
clnors);
}
}
@@ -584,7 +591,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
const int loops_num = result->totloop;
const int polys_num = result->totpoly;
const float(*positions)[3] = BKE_mesh_vert_positions(result);
MEdge *medge = BKE_mesh_edges_for_write(result);
const MEdge *medge = BKE_mesh_edges(result);
const MPoly *mpoly = BKE_mesh_polys(result);
const MLoop *mloop = BKE_mesh_loops(result);
@@ -624,6 +631,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
const Array<int> loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(result->polys(),
result->totloop);
bke::MutableAttributeAccessor attributes = result->attributes_for_write();
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
WeightedNormalData wn_data{};
wn_data.verts_num = verts_num;
wn_data.edges_num = edges_num;
@@ -633,6 +644,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
wn_data.vert_positions = positions;
wn_data.vert_normals = BKE_mesh_vertex_normals_ensure(result);
wn_data.medge = medge;
wn_data.sharp_edges = sharp_edges.span.data();
wn_data.mloop = mloop;
wn_data.loop_to_poly = loop_to_poly_map;
@@ -669,6 +681,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
result->runtime->is_original_bmesh = false;
sharp_edges.finish();
return result;
}