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:
@@ -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. */
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()});
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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__);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user