Mesh: Replace auto smooth with node group #108014

Merged
Hans Goudey merged 149 commits from HooglyBoogly/blender:refactor-mesh-corner-normals-lazy into main 2023-10-20 16:54:20 +02:00
21 changed files with 46 additions and 68 deletions
Showing only changes of commit cb2220999e - Show all commits

View File

@ -998,7 +998,8 @@ static void create_mesh(Scene *scene,
const int polys_num = b_mesh.polygons.length();
int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
const int numcorners = b_mesh.loops.length();
bool use_loop_normals = b_mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT &&
bool use_loop_normals = b_mesh.normal_domain_all_info() ==
BL::Mesh::normal_domain_all_info_CORNER &&
(mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK);
/* If no faces, create empty mesh. */

View File

@ -87,8 +87,9 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
/* Make a copy to split faces if we use autosmooth, otherwise not needed.
* Also in edit mode do we need to make a copy, to ensure data layers like
* UV are not empty. */
if (mesh.is_editmode() || (mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT &&
subdivision_type == Mesh::SUBDIVISION_NONE)) {
if (mesh.is_editmode() ||
(mesh.normal_domain_all_info() == BL::Mesh::normal_domain_all_info_CORNER &&
subdivision_type == Mesh::SUBDIVISION_NONE)) {
BL::Depsgraph depsgraph(PointerRNA_NULL);
mesh = b_ob_info.real_object.to_mesh(false, depsgraph);
}
@ -112,8 +113,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
#endif
if ((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) {
if (mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT) {
mesh.calc_normals_split();
if (mesh.normal_domain_all_info() == BL::Mesh::normal_domain_all_info_CORNER) {
mesh.split_faces(false);
}

View File

@ -214,7 +214,7 @@ bool BKE_mesh_material_index_used(struct Mesh *me, short index);
void BKE_mesh_material_index_clear(struct Mesh *me);
void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
void BKE_mesh_smooth_flag_set(struct Mesh *me, bool use_smooth);
void BKE_mesh_sharp_edges_set_from_angle(struct Mesh *me, float auto_smooth_angle);
void BKE_mesh_sharp_edges_set_from_angle(struct Mesh *me, float angle);
/**
* Used for unit testing; compares two meshes, checking only

View File

@ -757,8 +757,6 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph,
if (geometry_set.has_mesh()) {
Mesh *final_mesh = geometry_set.get_mesh_for_write();
BLI_strncpy(final_mesh->id.name, cu->id.name, sizeof(final_mesh->id.name));
*((short *)final_mesh->id.name) = ID_ME;
}

View File

@ -2276,9 +2276,9 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
}
if (loop_normals_needed) {
const blender::bke::AttributeAccessor attributes = mesh->attributes();
const blender::VArray<bool> sharp_edges = attributes.lookup_or_default<bool>(
const blender::VArray<bool> sharp_edges = *attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
const blender::VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const blender::VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
const blender::short2 *custom_normals = static_cast<const blender::short2 *>(
CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL));

View File

@ -1554,21 +1554,21 @@ void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth)
}
}
void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float auto_smooth_angle)
void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float angle)
{
using namespace blender;
using namespace blender::bke;
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);
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
bke::mesh::edges_sharp_from_angle_set(me->polys(),
me->corner_verts(),
me->corner_edges(),
me->poly_normals(),
sharp_faces,
auto_smooth_angle,
angle,
sharp_edges.span);
sharp_edges.finish();
}

View File

@ -392,9 +392,9 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* calculate custom normals into loop_normals, then mirror first half into second half */
const blender::bke::AttributeAccessor attributes = result->attributes();
const blender::VArray<bool> sharp_edges = attributes.lookup_or_default<bool>(
const blender::VArray<bool> sharp_edges = *attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
const blender::VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const blender::VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
blender::bke::mesh::normals_calc_loop(result->vert_positions(),
result_edges,

View File

@ -293,14 +293,16 @@ void normals_calc_poly_vert(const Span<float3> positions,
}
}
/** \} */
} // namespace blender::bke::mesh
/** \} */
/* -------------------------------------------------------------------- */
/** \name Mesh Normal Calculation
* \{ */
namespace blender::bke {
enum class BoolArrayMix {
None,
AllFalse,
@ -365,6 +367,8 @@ static BoolArrayMix bool_array_mix_calc(const VArray<bool> &varray)
return bool_array_mix_calc(varray, varray.index_range());
}
} // namespace blender::bke
eAttrDomain Mesh::normal_domain_all_info() const
{
using namespace blender;
@ -378,7 +382,7 @@ eAttrDomain Mesh::normal_domain_all_info() const
}
const AttributeAccessor attributes = this->attributes();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
const BoolArrayMix face_mix = bool_array_mix_calc(sharp_faces);
@ -386,7 +390,7 @@ eAttrDomain Mesh::normal_domain_all_info() const
return ATTR_DOMAIN_FACE;
}
const VArray<bool> sharp_edges = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_edges = *attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
const BoolArrayMix edge_mix = bool_array_mix_calc(sharp_edges);
if (edge_mix == BoolArrayMix::AllTrue) {
@ -507,9 +511,9 @@ blender::Span<blender::float3> Mesh::corner_normals() const
}
case ATTR_DOMAIN_CORNER: {
const AttributeAccessor attributes = this->attributes();
const VArray<bool> sharp_edges = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_edges = *attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
const short2 *custom_normals = static_cast<const short2 *>(
CustomData_get_layer(&this->ldata, CD_CUSTOMLOOPNORMAL));
@ -925,8 +929,7 @@ static void build_edge_to_loop_map(const OffsetIndices<int> polys,
/* Second loop using this edge, time to test its sharpness.
* An edge is sharp if it is tagged as such, or its face is not smooth,
* 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.
*/
* same vertex. */
if (sharp_faces[poly_i] || sharp_edges[edge_i] || vert_i == corner_verts[e2l[0]]) {
/* NOTE: we are sure that loop != 0 here ;). */
e2l[1] = INDEX_INVALID;
@ -1814,7 +1817,7 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
mesh_normals_loop_custom_set(

View File

@ -24,8 +24,7 @@ BLI_NOINLINE static void sample_point_attribute(const Span<int> corner_verts,
{
for (const int i : mask) {
const MLoopTri &tri = looptris[looptri_indices[i]];
const float3 &bary_coord = bary_coords[i];
dst[i] = attribute_math::mix3(bary_coord,
dst[i] = attribute_math::mix3(bary_coords[i],
src[corner_verts[tri.tri[0]]],
src[corner_verts[tri.tri[1]]],
src[corner_verts[tri.tri[2]]]);
@ -42,8 +41,7 @@ void sample_point_normals(const Span<int> corner_verts,
{
for (const int i : mask) {
const MLoopTri &tri = looptris[looptri_indices[i]];
const float3 &bary_coord = bary_coords[i];
const float3 value = attribute_math::mix3(bary_coord,
const float3 value = attribute_math::mix3(bary_coords[i],
src[corner_verts[tri.tri[0]]],
src[corner_verts[tri.tri[1]]],
src[corner_verts[tri.tri[2]]]);

View File

@ -333,8 +333,6 @@ static bool edbm_bevel_calc(wmOperator *op)
const int material = CLAMPIS(material_init, -1, obedit->totcol - 1);
Mesh *me = obedit->data;
EDBM_op_init(em,
&bmop,
op,

View File

@ -1462,7 +1462,7 @@ void ED_mesh_split_faces(Mesh *mesh)
const bke::AttributeAccessor attributes = mesh->attributes();
const VArray<bool> mesh_sharp_edges = *attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
Array<bool> sharp_edges(mesh->totedge);

View File

@ -125,7 +125,7 @@ struct AddOperationExecutor {
transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface);
Object &surface_ob_orig = *curves_id_orig_->surface;
const Mesh &surface_orig = *static_cast<Mesh *>(surface_ob_orig.data);
const Mesh &surface_orig = *static_cast<const Mesh *>(surface_ob_orig.data);
if (surface_orig.totpoly == 0) {
report_empty_original_surface(stroke_extension.reports);
return;

View File

@ -73,7 +73,7 @@ struct DensityAddOperationExecutor {
CurvesGeometry *curves_orig_ = nullptr;
Object *surface_ob_orig_ = nullptr;
Mesh *surface_orig_ = nullptr;
const Mesh *surface_orig_ = nullptr;
Object *surface_ob_eval_ = nullptr;
Mesh *surface_eval_ = nullptr;
@ -112,7 +112,7 @@ struct DensityAddOperationExecutor {
}
surface_ob_orig_ = curves_id_orig_->surface;
surface_orig_ = static_cast<Mesh *>(surface_ob_orig_->data);
surface_orig_ = static_cast<const Mesh *>(surface_ob_orig_->data);
if (surface_orig_->totpoly == 0) {
report_empty_original_surface(stroke_extension.reports);
return;

View File

@ -71,8 +71,8 @@ struct PuffOperationExecutor {
CurvesSurfaceTransforms transforms_;
Object *surface_ob_ = nullptr;
Mesh *surface_ = nullptr;
const Object *surface_ob_ = nullptr;
const Mesh *surface_ = nullptr;
Span<float3> surface_positions_;
Span<int> surface_corner_verts_;
Span<MLoopTri> surface_looptris_;
@ -111,7 +111,7 @@ struct PuffOperationExecutor {
falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape);
surface_ob_ = curves_id_->surface;
surface_ = static_cast<Mesh *>(surface_ob_->data);
surface_ = static_cast<const Mesh *>(surface_ob_->data);
transforms_ = CurvesSurfaceTransforms(*object_, surface_ob_);

View File

@ -97,7 +97,7 @@ struct SlideOperationExecutor {
CurvesGeometry *curves_orig_ = nullptr;
Object *surface_ob_orig_ = nullptr;
Mesh *surface_orig_ = nullptr;
const Mesh *surface_orig_ = nullptr;
Span<MLoopTri> surface_looptris_orig_;
VArraySpan<float2> surface_uv_map_orig_;
Span<float3> corner_normals_orig_su_;
@ -164,7 +164,7 @@ struct SlideOperationExecutor {
transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface);
surface_ob_orig_ = curves_id_orig_->surface;
surface_orig_ = static_cast<Mesh *>(surface_ob_orig_->data);
surface_orig_ = static_cast<const Mesh *>(surface_ob_orig_->data);
if (surface_orig_->totpoly == 0) {
report_empty_original_surface(stroke_extension.reports);
return;

View File

@ -503,8 +503,7 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_
switch (mesh->normal_domain_all_info()) {
case ATTR_DOMAIN_POINT: {
const Span<int> corner_verts = mesh->corner_verts();
array_utils::gather(mesh->vert_normals(), corner_verts, dst_normals);
array_utils::gather(mesh->vert_normals(), mesh->corner_verts(), dst_normals);
break;
}
case ATTR_DOMAIN_FACE: {

View File

@ -381,7 +381,6 @@ void MeshFromGeometry::create_normals(Mesh *mesh)
tot_loop_idx++;
}
}
BKE_mesh_set_custom_normals(mesh, loop_normals);
MEM_freeN(loop_normals);
}

View File

@ -4242,7 +4242,10 @@ static void rna_def_mesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "normal_domain_all_info", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_attribute_domain_only_mesh_no_edge_items);
RNA_def_property_ui_text(prop, "Normal Domain ALl Info", "");
RNA_def_property_ui_text(
prop,
"Normal Domain All Info",
"The attribute domain that gives enough information to represent the mesh's normals");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_funcs(prop, "rna_Mesh_normal_domain_all_info_get", NULL, NULL);

View File

@ -42,17 +42,6 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh,
return ret;
}
static void rna_Mesh_create_normals_split(Mesh *mesh)
{
/* TODO: Deprecation? */
BKE_mesh_corner_normals_ensure(mesh);
}
static void rna_Mesh_free_normals_split(Mesh *UNUSED(mesh))
{
/* TODO: Deprecation? */
}
static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap)
{
float(*r_looptangents)[4];
@ -226,16 +215,6 @@ void RNA_api_mesh(StructRNA *srna)
RNA_def_function_ui_description(
func, "Deprecated. Has no effect. Normals are calculated upon retrieval");
func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split");
RNA_def_function_ui_description(func, "Empty split vertex normals");
func = RNA_def_function(srna, "calc_normals_split", "rna_Mesh_create_normals_split");
RNA_def_function_ui_description(func,
"Calculate split vertex normals, which preserve sharp edges");
func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
RNA_def_function_ui_description(func, "Free split vertex normals");
func = RNA_def_function(srna, "split_faces", "rna_Mesh_split_faces");
RNA_def_function_ui_description(func, "Split faces based on the edge angle");
/* TODO: This parameter has no effect anymore, since the internal code does not need to

View File

@ -331,7 +331,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
corner_verts, corner_edges, nos.data(), &mesh->ldata, polys, mesh->poly_normals())) {
BKE_mesh_tag_face_winding_changed(mesh);
}
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
blender::bke::mesh::normals_loop_custom_set(vert_positions,
edges,
@ -440,7 +440,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
corner_verts, corner_edges, nos.data(), &mesh->ldata, polys, mesh->poly_normals())) {
BKE_mesh_tag_face_winding_changed(mesh);
}
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
blender::bke::mesh::normals_loop_custom_set(positions,
edges,
@ -525,7 +525,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size()));
loop_normals.reinitialize(corner_verts.size());
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces =* attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
blender::bke::mesh::normals_calc_loop(positions,
edges,

View File

@ -573,7 +573,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
wn_data.polys = polys;
wn_data.poly_normals = mesh->poly_normals();
wn_data.sharp_faces = attributes.lookup_or_default<bool>("sharp_face", ATTR_DOMAIN_FACE, false);
wn_data.sharp_faces = *attributes.lookup_or_default<bool>("sharp_face", ATTR_DOMAIN_FACE, false);
wn_data.poly_strength = static_cast<const int *>(CustomData_get_layer_named(
&result->pdata, CD_PROP_INT32, MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID));