Mesh: Move custom normals to a generic attribute

Move `CD_CUSTOMLOOPNORMAL` to the newly added
`CD_PROP_INT16_2D` generic attribute type. This is similar to
previous commits moving specific custom data types.

The attribute name is `custom_normal`. When the attribute with
that name is on the face corner domain, the code will interpret it
as stored in the existing deformation-invariant spherical coordinate
space.

The API remains the same, with the additional opportunity to edit
custom normal data as an attribute directly (which admittedly is fairly
unintuitive currently).

See #130484.

Pull Request: https://projects.blender.org/blender/blender/pulls/130689
This commit is contained in:
Hans Goudey
2024-12-04 16:06:36 +01:00
committed by Hans Goudey
parent f7d271dd92
commit f9b627d29c
31 changed files with 200 additions and 184 deletions

View File

@@ -699,8 +699,7 @@ enum {
CD_FAKE |
CD_PROP_FLOAT2, /* UV flag, because we handle both loop's UVs and face's textures. */
CD_FAKE_LNOR = CD_FAKE |
CD_CUSTOMLOOPNORMAL, /* Because we play with clnor and temp lnor layers here. */
CD_FAKE_LNOR = CD_FAKE | 500,
CD_FAKE_SHARP = CD_FAKE | 200, /* Sharp flag for edges, smooth flag for faces. */

View File

@@ -180,7 +180,7 @@ void normals_calc_corners(Span<float3> vert_positions,
Span<float3> face_normals,
Span<bool> sharp_edges,
Span<bool> sharp_faces,
const short2 *clnors_data,
Span<short2> custom_normals,
CornerNormalSpaceArray *r_lnors_spacearr,
MutableSpan<float3> r_corner_normals);

View File

@@ -18,8 +18,13 @@ struct Mesh;
struct MFace;
namespace blender::bke {
void mesh_custom_normals_to_legacy(MutableSpan<CustomDataLayer> corner_layers);
void mesh_custom_normals_to_generic(Mesh &mesh);
void mesh_sculpt_mask_to_legacy(MutableSpan<CustomDataLayer> vert_layers);
void mesh_sculpt_mask_to_generic(Mesh &mesh);
} // namespace blender::bke
void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh);

View File

@@ -2000,17 +2000,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
nullptr,
layerSwap_flnor,
nullptr},
/* 41: CD_CUSTOMLOOPNORMAL */
{sizeof(short[2]),
alignof(short[2]),
"vec2s",
1,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr},
/* 41: CD_CUSTOMLOOPNORMAL */ /* DEPRECATED */
{sizeof(short[2]), alignof(short[2]), "vec2s", 1},
/* 42: CD_SCULPT_FACE_SETS */ /* DEPRECATED */
{sizeof(int), alignof(int), ""},
/* 43: CD_LOCATION */
@@ -2238,7 +2229,7 @@ const CustomData_MeshMasks CD_MASK_MESH = {
/*pmask*/
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
(CD_MASK_MDISPS | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
/*vmask*/ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
@@ -2249,8 +2240,7 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
/*pmask*/
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_ORIGSPACE_MLOOP |
CD_MASK_PROP_ALL), /* XXX: MISSING #CD_MASK_MLOOPTANGENT ? */
(CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PROP_ALL), /* XXX: MISSING #CD_MASK_MLOOPTANGENT ? */
};
const CustomData_MeshMasks CD_MASK_BMESH = {
/*vmask*/ (CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
@@ -2260,7 +2250,7 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
/*pmask*/
(CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
(CD_MASK_MDISPS | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_EVERYTHING = {
/*vmask*/ (CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT |
@@ -2274,8 +2264,8 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
/*pmask*/
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_MLOOPTANGENT | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_MLOOPTANGENT |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
static const LayerTypeInfo *layerType_getInfo(const eCustomDataType type)

View File

@@ -68,9 +68,6 @@ void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types,
else if (cddata_type == CD_FAKE_UV) {
r_data_masks->lmask |= CD_MASK_PROP_FLOAT2;
}
else if (cddata_type == CD_FAKE_LNOR) {
r_data_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
}
}
}
@@ -366,15 +363,13 @@ static void data_transfer_dtdata_type_postprocess(Mesh *me_dst,
blender::float3 *loop_nors_dst = static_cast<blender::float3 *>(
CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, me_dst->corners_num));
blender::short2 *custom_nors_dst = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->corners_num));
if (!custom_nors_dst) {
custom_nors_dst = static_cast<blender::short2 *>(CustomData_add_layer(
ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, me_dst->corners_num));
}
bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write();
bke::SpanAttributeWriter custom_nors_dst = attributes.lookup_or_add_for_write_span<short2>(
"custom_normal", bke::AttrDomain::Corner);
if (!custom_nors_dst) {
return;
}
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", bke::AttrDomain::Edge);
const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
@@ -389,7 +384,8 @@ static void data_transfer_dtdata_type_postprocess(Mesh *me_dst,
sharp_faces,
sharp_edges.span,
{loop_nors_dst, me_dst->corners_num},
{custom_nors_dst, me_dst->corners_num});
custom_nors_dst.span);
custom_nors_dst.finish();
sharp_edges.finish();
CustomData_free_layers(ldata_dst, CD_NORMAL, me_dst->corners_num);
}
@@ -1054,7 +1050,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
else if (cddata_type == CD_FAKE_LNOR) {
if (r_map) {
/* Use #CD_NORMAL as a temporary storage for custom normals in 3D vector form.
* A post-process step will convert this layer to #CD_CUSTOMLOOPNORMAL. */
* A post-process step will convert this layer to "custom_normal". */
float3 *dst_data = static_cast<float3 *>(
CustomData_get_layer_for_write(&me_dst->corner_data, CD_NORMAL, me_dst->corners_num));
if (!dst_data) {
@@ -1064,7 +1060,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
if (mix_factor != 1.0f || mix_weights) {
MutableSpan(dst_data, me_dst->corners_num).copy_from(me_dst->corner_normals());
}
/* Post-process will convert it back to CD_CUSTOMLOOPNORMAL. */
/* Post-process will convert it back to "custom_normal". */
data_transfer_layersmapping_add_item_cd(r_map,
CD_NORMAL,
mix_mode,

View File

@@ -2263,11 +2263,11 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
{reinterpret_cast<blender::float3 *>(vert_normals), mesh->verts_num});
}
if (loop_normals_needed) {
const blender::short2 *clnors = static_cast<const blender::short2 *>(
CustomData_get_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL));
const AttributeAccessor attributes = mesh->attributes();
const VArraySpan sharp_edges = *attributes.lookup<bool>("sharp_edge", AttrDomain::Edge);
const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", AttrDomain::Face);
const VArraySpan custom_normals = *attributes.lookup<short2>("custom_normal",
AttrDomain::Corner);
mesh::normals_calc_corners(
positions,
edges,
@@ -2279,7 +2279,7 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
{reinterpret_cast<blender::float3 *>(face_normals), faces.size()},
sharp_edges,
sharp_faces,
clnors,
custom_normals,
nullptr,
{reinterpret_cast<blender::float3 *>(r_loop_normals), corner_verts.size()});
}

View File

@@ -302,6 +302,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
CustomData_blend_write_prepare(mesh->face_data, face_layers, {});
if (!is_undo) {
mesh_sculpt_mask_to_legacy(vert_layers);
mesh_custom_normals_to_legacy(loop_layers);
}
}
@@ -471,10 +472,11 @@ void BKE_mesh_ensure_skin_customdata(Mesh *mesh)
bool BKE_mesh_has_custom_loop_normals(Mesh *mesh)
{
if (mesh->runtime->edit_mesh) {
return CustomData_has_layer(&mesh->runtime->edit_mesh->bm->ldata, CD_CUSTOMLOOPNORMAL);
return CustomData_has_layer_named(
&mesh->runtime->edit_mesh->bm->ldata, CD_PROP_INT16_2D, "custom_normal");
}
return CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL);
return mesh->attributes().contains("custom_normal");
}
namespace blender::bke {

View File

@@ -837,6 +837,9 @@ static std::function<void()> get_tag_modified_function(void *owner, const String
if (name.startswith(".hide")) {
return [owner]() { (static_cast<Mesh *>(owner))->tag_visibility_changed(); };
}
if (name == "custom_normal") {
return [owner]() { (static_cast<Mesh *>(owner))->tag_custom_normals_changed(); };
}
return {};
}

View File

@@ -59,7 +59,6 @@ void mesh_flip_faces(Mesh &mesh, const IndexMask &selection)
flip_custom_data_type<float4>(faces, mesh.corner_data, selection, CD_TANGENT);
flip_custom_data_type<float4>(faces, mesh.corner_data, selection, CD_MLOOPTANGENT);
flip_custom_data_type<short2>(faces, mesh.corner_data, selection, CD_CUSTOMLOOPNORMAL);
flip_custom_data_type<GridPaintMask>(faces, mesh.corner_data, selection, CD_GRID_PAINT_MASK);
flip_custom_data_type<OrigSpaceLoop>(faces, mesh.corner_data, selection, CD_ORIGSPACE_MLOOP);
flip_custom_data_type<MDisps>(faces, mesh.corner_data, selection, CD_MDISPS);

View File

@@ -2395,7 +2395,9 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
/* Auto-smooth disabled sharp edge tagging when the evaluated mesh had custom normals.
* When the original mesh has custom normals, that's a good sign the evaluated mesh will
* have custom normals as well. */
bool has_custom_normals = CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL);
bool has_custom_normals = CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL) ||
CustomData_has_layer_named(
&mesh->corner_data, CD_PROP_INT16_2D, "custom_normal");
if (has_custom_normals) {
continue;
}
@@ -2509,6 +2511,58 @@ void mesh_sculpt_mask_to_generic(Mesh &mesh)
}
}
void mesh_custom_normals_to_legacy(MutableSpan<CustomDataLayer> corner_layers)
{
bool changed = false;
for (CustomDataLayer &layer : corner_layers) {
if (StringRef(layer.name) == "custom_normal" && layer.type == CD_PROP_INT16_2D) {
layer.type = CD_CUSTOMLOOPNORMAL;
layer.name[0] = '\0';
changed = true;
break;
}
}
if (!changed) {
return;
}
/* #CustomData expects the layers to be sorted in increasing order based on type. */
std::stable_sort(
corner_layers.begin(),
corner_layers.end(),
[](const CustomDataLayer &a, const CustomDataLayer &b) { return a.type < b.type; });
}
void mesh_custom_normals_to_generic(Mesh &mesh)
{
if (mesh.attributes().contains("custom_normal")) {
return;
}
void *data = nullptr;
const ImplicitSharingInfo *sharing_info = nullptr;
for (const int i : IndexRange(mesh.corner_data.totlayer)) {
CustomDataLayer &layer = mesh.corner_data.layers[i];
if (layer.type == CD_CUSTOMLOOPNORMAL) {
data = layer.data;
sharing_info = layer.sharing_info;
layer.data = nullptr;
layer.sharing_info = nullptr;
CustomData_free_layer(&mesh.corner_data, CD_CUSTOMLOOPNORMAL, mesh.corners_num, i);
break;
}
}
if (data != nullptr) {
CustomData_add_layer_named_with_data(&mesh.corner_data,
CD_PROP_INT16_2D,
data,
mesh.corners_num,
"custom_normal",
sharing_info);
}
if (sharing_info != nullptr) {
sharing_info->remove_user_and_delete_if_last();
}
}
//
} // namespace blender::bke

View File

@@ -390,12 +390,13 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
}
/* handle custom split normals */
if (ob->type == OB_MESH && CustomData_has_layer(&result->corner_data, CD_CUSTOMLOOPNORMAL) &&
result->faces_num > 0)
bke::MutableAttributeAccessor attributes = result->attributes_for_write();
bke::GAttributeWriter custom_normals = attributes.lookup_for_write("custom_normal");
if (ob->type == OB_MESH && custom_normals && custom_normals.domain == bke::AttrDomain::Corner &&
custom_normals.varray.type().is<short2>() && result->faces_num > 0)
{
blender::Array<blender::float3> corner_normals(result_corner_verts.size());
blender::short2 *clnors = static_cast<blender::short2 *>(CustomData_get_layer_for_write(
&result->corner_data, CD_CUSTOMLOOPNORMAL, result->corners_num));
MutableVArraySpan clnors(custom_normals.varray.typed<short2>());
blender::bke::mesh::CornerNormalSpaceArray lnors_spacearr;
/* The transform matrix of a normal must be
@@ -405,7 +406,6 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
transpose_m4(mtx_nor);
/* calculate custom normals into corner_normals, then mirror first half into second half */
const bke::AttributeAccessor attributes = result->attributes();
const VArraySpan sharp_edges = *attributes.lookup<bool>("sharp_edge", AttrDomain::Edge);
const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", AttrDomain::Face);
blender::bke::mesh::normals_calc_corners(result->vert_positions(),
@@ -441,7 +441,10 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
lnors_spacearr.spaces[space_index], corner_normals[mirrorj]);
}
}
clnors.save();
}
custom_normals.finish();
/* handle vgroup stuff */
if (BKE_object_supports_vertex_groups(ob)) {

View File

@@ -202,11 +202,22 @@ blender::bke::MeshNormalDomain Mesh::normals_domain(const bool support_sharp_fac
return MeshNormalDomain::Point;
}
if (CustomData_has_layer(&this->corner_data, CD_CUSTOMLOOPNORMAL)) {
return MeshNormalDomain::Corner;
const bke::AttributeAccessor attributes = this->attributes();
if (const std::optional<AttributeMetaData> custom = attributes.lookup_meta_data("custom_normal"))
{
switch (custom->domain) {
case AttrDomain::Point:
case AttrDomain::Edge:
case AttrDomain::Face:
/* Not supported yet. */
break;
case AttrDomain::Corner:
return MeshNormalDomain::Corner;
default:
BLI_assert_unreachable();
}
}
const AttributeAccessor attributes = this->attributes();
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", AttrDomain::Face, false);
@@ -288,8 +299,8 @@ blender::Span<blender::float3> Mesh::corner_normals() const
const AttributeAccessor attributes = this->attributes();
const VArraySpan sharp_edges = *attributes.lookup<bool>("sharp_edge", AttrDomain::Edge);
const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", AttrDomain::Face);
const short2 *custom_normals = static_cast<const short2 *>(
CustomData_get_layer(&this->corner_data, CD_CUSTOMLOOPNORMAL));
const VArraySpan custom_normals = *attributes.lookup<short2>("custom_normal",
AttrDomain::Corner);
mesh::normals_calc_corners(this->vert_positions(),
this->edges(),
this->faces(),
@@ -1173,7 +1184,7 @@ void normals_calc_corners(const Span<float3> vert_positions,
const Span<float3> face_normals,
const Span<bool> sharp_edges,
const Span<bool> sharp_faces,
const short2 *clnors_data,
const Span<short2> custom_normals,
CornerNormalSpaceArray *r_lnors_spacearr,
MutableSpan<float3> r_corner_normals)
{
@@ -1199,7 +1210,7 @@ void normals_calc_corners(const Span<float3> vert_positions,
SCOPED_TIMER_AVERAGED(__func__);
#endif
if (!r_lnors_spacearr && clnors_data) {
if (!r_lnors_spacearr && !custom_normals.is_empty()) {
/* We need to compute lnor spacearr if some custom lnor data are given to us! */
r_lnors_spacearr = &_lnors_spacearr;
}
@@ -1208,7 +1219,7 @@ void normals_calc_corners(const Span<float3> vert_positions,
CornerSplitTaskDataCommon common_data;
common_data.lnors_spacearr = r_lnors_spacearr;
common_data.corner_normals = r_corner_normals;
common_data.clnors_data = {clnors_data, clnors_data ? corner_verts.size() : 0};
common_data.clnors_data = custom_normals;
common_data.positions = vert_positions;
common_data.edges = edges;
common_data.faces = faces;
@@ -1306,7 +1317,7 @@ static void mesh_normals_corner_custom_set(const Span<float3> positions,
face_normals,
sharp_edges,
sharp_faces,
r_clnors_data.data(),
r_clnors_data,
&lnors_spacearr,
corner_normals);
@@ -1427,7 +1438,7 @@ static void mesh_normals_corner_custom_set(const Span<float3> positions,
face_normals,
sharp_edges,
sharp_faces,
r_clnors_data.data(),
r_clnors_data,
&lnors_spacearr,
corner_normals);
}
@@ -1529,16 +1540,12 @@ void normals_corner_custom_set_from_verts(const Span<float3> vert_positions,
static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const bool use_vertices)
{
short2 *clnors = static_cast<short2 *>(
CustomData_get_layer_for_write(&mesh->corner_data, CD_CUSTOMLOOPNORMAL, mesh->corners_num));
if (clnors != nullptr) {
memset(clnors, 0, sizeof(*clnors) * mesh->corners_num);
}
else {
clnors = static_cast<short2 *>(CustomData_add_layer(
&mesh->corner_data, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, mesh->corners_num));
}
MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter custom_normals = attributes.lookup_or_add_for_write_span<short2>(
"custom_normal", AttrDomain::Corner);
if (!custom_normals) {
return;
}
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", AttrDomain::Edge);
const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", AttrDomain::Face);
@@ -1555,9 +1562,10 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
{reinterpret_cast<float3 *>(r_custom_nors),
use_vertices ? mesh->verts_num : mesh->corners_num},
sharp_edges.span,
{clnors, mesh->corners_num});
custom_normals.span);
sharp_edges.finish();
custom_normals.finish();
}
} // namespace blender::bke::mesh

View File

@@ -11,6 +11,7 @@
#include "DNA_object_types.h"
#include "DNA_userdef_types.h"
#include "BKE_attribute.hh"
#include "BKE_customdata.hh"
#include "BKE_mesh.hh"
#include "BKE_modifier.hh"
@@ -84,8 +85,13 @@ static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene,
bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh)
{
return smd->flags & eSubsurfModifierFlag_UseCustomNormals &&
CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL);
if ((smd->flags & eSubsurfModifierFlag_UseCustomNormals) == 0) {
return false;
}
const std::optional<AttributeMetaData> meta_data = mesh->attributes().lookup_meta_data(
"custom_normal");
return meta_data && meta_data->domain == AttrDomain::Corner &&
meta_data->data_type == CD_PROP_INT16_2D;
}
bool BKE_subsurf_modifier_has_split_normals(const SubsurfModifierData *smd, const Mesh *mesh)

View File

@@ -5187,6 +5187,7 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
* breaking release. */
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
blender::bke::mesh_sculpt_mask_to_generic(*mesh);
blender::bke::mesh_custom_normals_to_generic(*mesh);
}
/**

View File

@@ -1740,11 +1740,10 @@ void BM_lnorspacearr_store(BMesh *bm, MutableSpan<float3> r_lnors)
{
BLI_assert(bm->lnor_spacearr != nullptr);
if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
}
BM_data_layer_ensure_named(bm, &bm->ldata, CD_PROP_INT16_2D, "custom_normal");
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
int cd_loop_clnors_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
BM_loops_calc_normal_vcos(
bm, {}, {}, {}, true, r_lnors, bm->lnor_spacearr, nullptr, cd_loop_clnors_offset, false);
@@ -1837,7 +1836,8 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
Array<float3> r_lnors(bm->totloop, float3(0));
Array<float3> oldnors(preserve_clnor ? bm->totloop : 0, float3(0));
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
int cd_loop_clnors_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
BM_mesh_elem_index_ensure(bm, BM_LOOP);
@@ -1928,7 +1928,8 @@ void BM_lnorspace_err(BMesh *bm)
BKE_lnor_spacearr_init(temp, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
int cd_loop_clnors_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
Array<float3> lnors(bm->totloop, float3(0));
BM_loops_calc_normal_vcos(
bm, {}, {}, {}, true, lnors, temp, nullptr, cd_loop_clnors_offset, true);
@@ -2151,10 +2152,9 @@ BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm,
BMLoopNorEditDataArray *lnors_ed_arr = MEM_cnew<BMLoopNorEditDataArray>(__func__);
lnors_ed_arr->lidx_to_lnor_editdata = MEM_cnew_array<BMLoopNorEditData *>(bm->totloop, __func__);
if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
}
const int cd_custom_normal_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_data_layer_ensure_named(bm, &bm->ldata, CD_PROP_INT16_2D, "custom_normal");
const int cd_custom_normal_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
BM_mesh_elem_index_ensure(bm, BM_LOOP);
@@ -2203,7 +2203,7 @@ bool BM_custom_loop_normals_to_vector_layer(BMesh *bm)
BMLoop *l;
BMIter liter, fiter;
if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
if (!CustomData_has_layer_named(&bm->ldata, CD_PROP_INT16_2D, "custom_normal")) {
return false;
}
@@ -2216,7 +2216,8 @@ bool BM_custom_loop_normals_to_vector_layer(BMesh *bm)
CustomData_set_layer_flag(&bm->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
const int cd_custom_normal_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
const int cd_custom_normal_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
const int cd_normal_offset = CustomData_get_offset(&bm->ldata, CD_NORMAL);
int l_index = 0;
@@ -2237,14 +2238,15 @@ bool BM_custom_loop_normals_to_vector_layer(BMesh *bm)
void BM_custom_loop_normals_from_vector_layer(BMesh *bm, bool add_sharp_edges)
{
if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL) ||
!CustomData_has_layer(&bm->ldata, CD_NORMAL))
{
const int cd_custom_normal_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
if (cd_custom_normal_offset == -1) {
return;
}
const int cd_custom_normal_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
const int cd_normal_offset = CustomData_get_offset(&bm->ldata, CD_NORMAL);
if (cd_normal_offset == -1) {
return;
}
if (bm->lnor_spacearr == nullptr) {
bm->lnor_spacearr = MEM_cnew<MLoopNorSpaceArray>(__func__);

View File

@@ -2464,7 +2464,8 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
/* I suspect this is not necessary. TODO: test that guess. */
BM_mesh_normals_update(bm);
int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
int cd_clnors_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
/* If there is not already a custom split normal layer then making one
* (with #BM_lnorspace_update) will not respect the auto-smooth angle between smooth faces.
@@ -2479,7 +2480,7 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
BM_lnorspace_update(bm);
if (cd_clnors_offset == -1) {
cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
cd_clnors_offset = CustomData_get_offset_named(&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
}
BMIter fiter;

View File

@@ -1505,11 +1505,6 @@ void DepsgraphRelationBuilder::build_constraints(ID *id,
/* Add dependency on normal layers if necessary. */
if (ct->tar->type == OB_MESH && scon->shrinkType != MOD_SHRINKWRAP_NEAREST_VERTEX) {
bool track = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0;
if (track || BKE_shrinkwrap_needs_normals(scon->shrinkType, scon->shrinkMode)) {
add_customdata_mask(ct->tar,
DEGCustomDataMeshMasks::MaskLoop(CD_MASK_CUSTOMLOOPNORMAL));
}
if (scon->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
add_special_eval_flag(&ct->tar->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
}

View File

@@ -456,7 +456,7 @@ static bke::MeshNormalDomain bmesh_normals_domain(BMesh *bm)
return bke::MeshNormalDomain::Point;
}
if (CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
if (CustomData_has_layer_named(&bm->ldata, CD_PROP_INT16_2D, "custom_normal")) {
return bke::MeshNormalDomain::Corner;
}
@@ -492,7 +492,8 @@ void mesh_render_data_update_corner_normals(MeshRenderData &mr)
}
else {
mr.bm_loop_normals.reinitialize(mr.corners_num);
const int clnors_offset = CustomData_get_offset(&mr.bm->ldata, CD_CUSTOMLOOPNORMAL);
const int clnors_offset = CustomData_get_offset_named(
&mr.bm->ldata, CD_PROP_INT16_2D, "custom_normal");
BM_loops_calc_normal_vcos(mr.bm,
mr.bm_vert_coords,
mr.bm_vert_normals,

View File

@@ -2206,8 +2206,7 @@ static bool draw_subdiv_create_requested_buffers(Object &ob,
runtime_data->stats_totloop = draw_cache.num_subdiv_loops;
draw_cache.use_custom_loop_normals = (runtime_data->use_loop_normals) &&
CustomData_has_layer(&mesh_eval->corner_data,
CD_CUSTOMLOOPNORMAL);
mesh_eval->attributes().contains("custom_normal");
if (DRW_ibo_requested(mbc.buff.ibo.tris)) {
draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache.mat_len);

View File

@@ -2062,7 +2062,7 @@ void MESH_OT_duplicate(wmOperatorType *ot)
static BMLoopNorEditDataArray *flip_custom_normals_init_data(BMesh *bm)
{
BMLoopNorEditDataArray *lnors_ed_arr = nullptr;
if (CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
if (CustomData_has_layer_named(&bm->ldata, CD_PROP_INT16_2D, "custom_normal")) {
/* The mesh has custom normal data, update these too.
* Otherwise they will be left in a mangled state.
*/
@@ -2155,7 +2155,7 @@ static bool flip_custom_normals(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr)
static void edbm_flip_normals_custom_loop_normals(Object *obedit, BMEditMesh *em)
{
if (!CustomData_has_layer(&em->bm->ldata, CD_CUSTOMLOOPNORMAL)) {
if (!CustomData_has_layer_named(&em->bm->ldata, CD_PROP_INT16_2D, "custom_normal")) {
return;
}
@@ -8616,7 +8616,8 @@ static void normals_split(BMesh *bm)
BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
const int cd_clnors_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
@@ -8830,7 +8831,8 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
BKE_editmesh_lnorspace_update(em);
const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
const int cd_clnors_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
float weight = absweight / 50.0f;
if (absweight == 100.0f) {
@@ -9310,7 +9312,8 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op)
}
BLI_bitmap *loop_set = BLI_BITMAP_NEW(bm->totloop, __func__);
const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
const int cd_clnors_offset = CustomData_get_offset_named(
&bm->ldata, CD_PROP_INT16_2D, "custom_normal");
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) {

View File

@@ -719,11 +719,14 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
if (mesh->runtime->edit_mesh) {
BMesh &bm = *mesh->runtime->edit_mesh->bm;
BM_data_layer_add(&bm, &bm.ldata, CD_CUSTOMLOOPNORMAL);
BM_data_layer_ensure_named(&bm, &bm.ldata, CD_PROP_INT16_2D, "custom_normal");
}
else {
CustomData_add_layer(
&mesh->corner_data, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, mesh->corners_num);
if (!mesh->attributes_for_write().add<short2>(
"custom_normal", bke::AttrDomain::Corner, bke::AttributeInitDefaultValue()))
{
return OPERATOR_CANCELLED;
}
}
DEG_id_tag_update(&mesh->id, 0);
@@ -753,19 +756,18 @@ static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperato
if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
BMesh &bm = *em->bm;
if (!CustomData_has_layer(&bm.ldata, CD_CUSTOMLOOPNORMAL)) {
if (!CustomData_has_layer_named(&bm.ldata, CD_PROP_INT16_2D, "custom_normal")) {
return OPERATOR_CANCELLED;
}
BM_data_layer_free(&bm, &bm.ldata, CD_CUSTOMLOOPNORMAL);
BM_data_layer_free_named(&bm, &bm.ldata, "custom_normal");
if (bm.lnor_spacearr) {
BKE_lnor_spacearr_clear(bm.lnor_spacearr);
}
}
else {
if (!CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL)) {
if (!mesh->attributes_for_write().remove("custom_normal")) {
return OPERATOR_CANCELLED;
}
CustomData_free_layers(&mesh->corner_data, CD_CUSTOMLOOPNORMAL, mesh->corners_num);
}
mesh->tag_custom_normals_changed();

View File

@@ -152,8 +152,8 @@ typedef enum eCustomDataType {
CD_FREESTYLE_FACE = 38,
CD_MLOOPTANGENT = 39,
CD_TESSLOOPNORMAL = 40,
CD_CUSTOMLOOPNORMAL = 41,
#ifdef DNA_DEPRECATED_ALLOW
CD_CUSTOMLOOPNORMAL = 41,
CD_SCULPT_FACE_SETS = 42,
#endif
@@ -207,7 +207,6 @@ using eCustomDataMask = uint64_t;
#define CD_MASK_FREESTYLE_FACE (1LL << CD_FREESTYLE_FACE)
#define CD_MASK_MLOOPTANGENT (1LL << CD_MLOOPTANGENT)
#define CD_MASK_TESSLOOPNORMAL (1LL << CD_TESSLOOPNORMAL)
#define CD_MASK_CUSTOMLOOPNORMAL (1LL << CD_CUSTOMLOOPNORMAL)
#define CD_MASK_PROP_COLOR (1ULL << CD_PROP_COLOR)
#define CD_MASK_PROP_FLOAT3 (1ULL << CD_PROP_FLOAT3)
#define CD_MASK_PROP_FLOAT2 (1ULL << CD_PROP_FLOAT2)

View File

@@ -419,7 +419,7 @@ typedef struct Mesh {
void tag_positions_changed_no_normals();
/** Call when changing "sharp_face" or "sharp_edge" data. */
void tag_sharpness_changed();
/** Call when changing #CD_CUSTOMLOOPNORMAL data. */
/** Call when changing "custom_normal" data. */
void tag_custom_normals_changed();
/** Call when face vertex order has changed but positions and faces haven't changed. */
void tag_face_winding_changed();

View File

@@ -20,6 +20,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "BKE_attribute.hh"
#include "BKE_customdata.hh"
#include "BKE_deform.hh"
#include "BKE_image.hh"
@@ -68,10 +69,6 @@ static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_
if (dmd->texmapping == MOD_DISP_MAP_UV) {
r_cddata_masks->fmask |= CD_MASK_MTFACE;
}
if (dmd->direction == MOD_DISP_DIR_CLNOR) {
r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
}
}
static bool depends_on_time(Scene * /*scene*/, ModifierData *md)
@@ -296,7 +293,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
}
if (direction == MOD_DISP_DIR_CLNOR) {
if (CustomData_has_layer(&mesh->corner_data, CD_CUSTOMLOOPNORMAL)) {
if (mesh->attributes().contains("custom_normal")) {
vert_clnors = static_cast<float(*)[3]>(
MEM_malloc_arrayN(positions.size(), sizeof(*vert_clnors), __func__));
BKE_mesh_normals_loop_to_vertex(

View File

@@ -107,18 +107,12 @@ static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_re
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
auto *smd = reinterpret_cast<GreasePencilShrinkwrapModifierData *>(md);
CustomData_MeshMasks mask = {0};
if (BKE_shrinkwrap_needs_normals(smd->shrink_type, smd->shrink_mode)) {
mask.lmask |= CD_MASK_CUSTOMLOOPNORMAL;
}
if (smd->target != nullptr) {
DEG_add_object_relation(
ctx->node, smd->target, DEG_OB_COMP_TRANSFORM, "Grease Pencil Shrinkwrap Modifier");
DEG_add_object_relation(
ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Grease Pencil Shrinkwrap Modifier");
DEG_add_customdata_mask(ctx->node, smd->target, &mask);
if (smd->shrink_type == MOD_SHRINKWRAP_TARGET_PROJECT) {
DEG_add_special_eval_flag(ctx->node, &smd->target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
}
@@ -128,7 +122,6 @@ static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphCont
ctx->node, smd->aux_target, DEG_OB_COMP_TRANSFORM, "Grease Pencil Shrinkwrap Modifier");
DEG_add_object_relation(
ctx->node, smd->aux_target, DEG_OB_COMP_GEOMETRY, "Grease Pencil Shrinkwrap Modifier");
DEG_add_customdata_mask(ctx->node, smd->aux_target, &mask);
if (smd->shrink_type == MOD_SHRINKWRAP_TARGET_PROJECT) {
DEG_add_special_eval_flag(
ctx->node, &smd->aux_target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);

View File

@@ -60,14 +60,6 @@ static void init_data(ModifierData *md)
md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1;
}
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
{
MultiresModifierData *mmd = (MultiresModifierData *)md;
if (mmd->flags & eMultiresModifierFlag_UseCustomNormals) {
r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
}
}
static void copy_data(const ModifierData *md_src, ModifierData *md_dst, const int flag)
{
BKE_modifier_copydata_generic(md_src, md_dst, flag);
@@ -484,7 +476,7 @@ ModifierTypeInfo modifierType_Multires = {
/*modify_geometry_set*/ nullptr,
/*init_data*/ init_data,
/*required_data_mask*/ required_data_mask,
/*required_data_mask*/ nullptr,
/*free_data*/ free_data,
/*is_disabled*/ nullptr,
/*update_depsgraph*/ nullptr,

View File

@@ -497,17 +497,16 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
blender::Array<blender::float3> corner_normals;
CustomData *ldata = &result->corner_data;
bke::MutableAttributeAccessor attributes = result->attributes_for_write();
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", bke::AttrDomain::Edge);
blender::short2 *clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size()));
bke::SpanAttributeWriter custom_nors_dst = attributes.lookup_or_add_for_write_span<short2>(
"custom_normal", bke::AttrDomain::Corner);
if (!custom_nors_dst) {
return result;
}
if (use_current_clnors) {
clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size()));
corner_normals.reinitialize(corner_verts.size());
const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
blender::bke::mesh::normals_calc_corners(positions,
@@ -520,16 +519,11 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
result->face_normals(),
sharp_edges.span,
sharp_faces,
clnors,
custom_nors_dst.span,
nullptr,
corner_normals);
}
if (clnors == nullptr) {
clnors = static_cast<blender::short2 *>(
CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, corner_verts.size()));
}
MOD_get_vgroup(ob, result, enmd->defgrp_name, &dvert, &defgrp_index);
if (enmd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
@@ -537,7 +531,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
ctx,
ob,
result,
{clnors, result->corners_num},
custom_nors_dst.span,
corner_normals,
enmd->mix_mode,
enmd->mix_factor,
@@ -557,7 +551,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
ctx,
ob,
result,
{clnors, result->corners_num},
custom_nors_dst.span,
corner_normals,
enmd->mix_mode,
enmd->mix_factor,
@@ -575,6 +569,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
result->runtime->is_original_bmesh = false;
custom_nors_dst.finish();
sharp_edges.finish();
return result;
@@ -593,8 +588,6 @@ static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_
{
NormalEditModifierData *enmd = (NormalEditModifierData *)md;
r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
/* Ask for vertex-groups if we need them. */
if (enmd->defgrp_name[0] != '\0') {
r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;

View File

@@ -102,16 +102,9 @@ static void deform_verts(ModifierData *md,
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
CustomData_MeshMasks mask = {0};
if (BKE_shrinkwrap_needs_normals(smd->shrinkType, smd->shrinkMode)) {
mask.lmask |= CD_MASK_CUSTOMLOOPNORMAL;
}
if (smd->target != nullptr) {
DEG_add_object_relation(ctx->node, smd->target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
DEG_add_object_relation(ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
DEG_add_customdata_mask(ctx->node, smd->target, &mask);
if (smd->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
DEG_add_special_eval_flag(ctx->node, &smd->target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
}
@@ -121,7 +114,6 @@ static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphCont
ctx->node, smd->auxTarget, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
DEG_add_object_relation(
ctx->node, smd->auxTarget, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
DEG_add_customdata_mask(ctx->node, smd->auxTarget, &mask);
if (smd->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
DEG_add_special_eval_flag(ctx->node, &smd->auxTarget->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
}

View File

@@ -59,14 +59,6 @@ static void init_data(ModifierData *md)
MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SubsurfModifierData), modifier);
}
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
{
SubsurfModifierData *smd = (SubsurfModifierData *)md;
if (smd->flags & eSubsurfModifierFlag_UseCustomNormals) {
r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
}
}
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
{
#if 0
@@ -497,7 +489,7 @@ ModifierTypeInfo modifierType_Subsurf = {
/*modify_geometry_set*/ nullptr,
/*init_data*/ init_data,
/*required_data_mask*/ required_data_mask,
/*required_data_mask*/ nullptr,
/*free_data*/ free_data,
/*is_disabled*/ is_disabled,
/*update_depsgraph*/ nullptr,

View File

@@ -82,7 +82,6 @@ struct WeightedNormalData {
blender::Span<int> corner_edges;
blender::Span<int> loop_to_face;
blender::MutableSpan<blender::short2> clnors;
bool has_clnors; /* True if clnors already existed, false if we had to create them. */
blender::OffsetIndices<int> faces;
blender::Span<blender::float3> face_normals;
@@ -206,7 +205,6 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
const short mode = wn_data->mode;
ModePair *mode_pair = wn_data->mode_pair;
const bool has_clnors = wn_data->has_clnors;
bke::mesh::CornerNormalSpaceArray lnors_spacearr;
const bool keep_sharp = (wnmd->flag & MOD_WEIGHTEDNORMAL_KEEP_SHARP) != 0;
@@ -231,7 +229,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
wn_data->face_normals,
wn_data->sharp_edges,
wn_data->sharp_faces,
has_clnors ? clnors.data() : nullptr,
clnors,
&lnors_spacearr,
corner_normals);
@@ -359,7 +357,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
face_normals,
wn_data->sharp_edges,
wn_data->sharp_faces,
has_clnors ? clnors.data() : nullptr,
clnors,
nullptr,
corner_normals);
@@ -504,17 +502,6 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
weight = (weight - 1) * 25;
}
blender::short2 *clnors = static_cast<blender::short2 *>(CustomData_get_layer_for_write(
&result->corner_data, CD_CUSTOMLOOPNORMAL, mesh->corners_num));
/* Keep info whether we had clnors,
* it helps when generating clnor spaces and default normals. */
const bool has_clnors = clnors != nullptr;
if (!clnors) {
clnors = static_cast<blender::short2 *>(CustomData_add_layer(
&result->corner_data, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, corner_verts.size()));
}
const MDeformVert *dvert;
int defgrp_index;
MOD_get_vgroup(ctx->object, mesh, wnmd->defgrp_name, &dvert, &defgrp_index);
@@ -524,6 +511,11 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
bke::MutableAttributeAccessor attributes = result->attributes_for_write();
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", bke::AttrDomain::Edge);
bke::SpanAttributeWriter clnors = attributes.lookup_or_add_for_write_span<short2>(
"custom_normal", bke::AttrDomain::Corner);
if (!clnors) {
return result;
}
WeightedNormalData wn_data{};
wn_data.verts_num = verts_num;
@@ -536,8 +528,7 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
wn_data.corner_verts = corner_verts;
wn_data.corner_edges = corner_edges;
wn_data.loop_to_face = loop_to_face_map;
wn_data.clnors = {clnors, mesh->corners_num};
wn_data.has_clnors = has_clnors;
wn_data.clnors = clnors.span;
wn_data.faces = faces;
wn_data.face_normals = mesh->face_normals();
@@ -569,6 +560,7 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
result->runtime->is_original_bmesh = false;
sharp_edges.finish();
clnors.finish();
return result;
}
@@ -586,8 +578,6 @@ static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_
{
WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md;
r_cddata_masks->lmask = CD_MASK_CUSTOMLOOPNORMAL;
if (wnmd->defgrp_name[0] != '\0') {
r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
}

View File

@@ -125,7 +125,6 @@ static void remove_unsupported_corner_data(Mesh &mesh)
CustomData_free_layers(&mesh.corner_data, CD_TANGENT, mesh.corners_num);
CustomData_free_layers(&mesh.corner_data, CD_MLOOPTANGENT, mesh.corners_num);
CustomData_free_layers(&mesh.corner_data, CD_GRID_PAINT_MASK, mesh.corners_num);
CustomData_free_layers(&mesh.corner_data, CD_CUSTOMLOOPNORMAL, mesh.corners_num);
}
static void expand_mesh(Mesh &mesh,