Compare commits
19 Commits
asset-shel
...
refactor-m
Author | SHA1 | Date | |
---|---|---|---|
01f509232b | |||
5609f61bb3 | |||
a357adf6cd | |||
b18fd83883 | |||
4c2c114324 | |||
e31f5fde34 | |||
cbbab81b9e | |||
5fce94f825 | |||
2e87364e3c | |||
8fa7bcb59a | |||
d9f71d3133 | |||
892fbf5ab6 | |||
c998d56b1e | |||
0178d3e4bb | |||
8e81e3b229 | |||
155ec559fb | |||
f4292febb4 | |||
c5331f134d | |||
4e3b1ef861 |
@@ -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]);
|
||||
|
||||
/**
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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)) {
|
||||
|
@@ -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,
|
||||
|
@@ -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) {
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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])
|
||||
|
@@ -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);
|
||||
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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()
|
||||
|
@@ -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' */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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));
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user