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
32 changed files with 168 additions and 291 deletions
Showing only changes of commit 172a976273 - Show all commits

View File

@ -372,6 +372,8 @@ const float (*BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3];
*/
const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3];
const float (*BKE_mesh_corner_normals_ensure(const struct Mesh *mesh))[3];
/**
* Tag mesh vertex and face normals to be recalculated when/if they are needed later.
*
@ -434,6 +436,8 @@ void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh);
*/
void BKE_mesh_poly_normals_clear_dirty(struct Mesh *mesh);
void BKE_mesh_corner_normals_clear_dirty(struct Mesh *mesh);
/**
* Return true if the mesh vertex normals either are not stored or are dirty.
* This can be used to help decide whether to transfer them when copying a mesh.
@ -446,6 +450,8 @@ bool BKE_mesh_vertex_normals_are_dirty(const struct Mesh *mesh);
*/
bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
bool BKE_mesh_corner_normals_are_dirty(const struct Mesh *mesh);
/**
* Calculate face normals directly into a result array.
*
@ -690,7 +696,6 @@ void BKE_mesh_normals_loop_to_vertex(int numVerts,
*/
bool BKE_mesh_has_custom_loop_normals(struct Mesh *me);
void BKE_mesh_calc_normals_split(struct Mesh *mesh);
/**
* Compute 'split' (aka loop, or per face corner's) normals.
*

View File

@ -141,8 +141,10 @@ struct MeshRuntime {
*/
bool vert_normals_dirty = false;
bool poly_normals_dirty = false;
bool corner_normals_dirty = false;
float (*vert_normals)[3] = nullptr;
float (*poly_normals)[3] = nullptr;
float (*corner_normals)[3] = nullptr;
/**
* A #BLI_bitmap containing tags for the center vertices of subdivided polygons, set by the

View File

@ -547,7 +547,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
/* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case
* of deferred CPU subdivision, this will be computed when the wrapper is generated. */
if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
BKE_mesh_calc_normals_split(mesh_final);
BKE_mesh_corner_normals_ensure(mesh_final);
}
}
else {
@ -560,12 +560,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
BKE_mesh_ensure_normals_for_display(mesh_final);
}
/* Some modifiers, like data-transfer, may generate those data as temp layer,
* we do not want to keep them, as they are used by display code when available
* (i.e. even if auto-smooth is disabled). */
if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
}
}
}
@ -1216,18 +1211,12 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
/* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the
* wrapper is generated. */
if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
BKE_mesh_calc_normals_split(mesh_final);
BKE_mesh_corner_normals_ensure(mesh_final);
}
}
else {
/* Same as mesh_calc_modifiers. If using loop normals, poly nors have already been computed. */
BKE_mesh_ensure_normals_for_display(mesh_final);
/* Some modifiers, like data-transfer, may generate those data, we do not want to keep them,
* as they are used by display code when available (i.e. even if autosmooth is disabled). */
if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
}
}
}

View File

@ -247,65 +247,6 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
/* ********** */
/* Generic pre/post processing, only used by custom loop normals currently. */
static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
Mesh *me_dst,
const int dtdata_type,
const bool dirty_nors_dst)
{
if (dtdata_type == DT_TYPE_LNOR) {
/* Compute custom normals into regular loop normals, which will be used for the transfer. */
const MVert *verts_dst = BKE_mesh_verts(me_dst);
const int num_verts_dst = me_dst->totvert;
const MEdge *edges_dst = BKE_mesh_edges(me_dst);
const int num_edges_dst = me_dst->totedge;
const MPoly *polys_dst = BKE_mesh_polys(me_dst);
const int num_polys_dst = me_dst->totpoly;
const MLoop *loops_dst = BKE_mesh_loops(me_dst);
const int num_loops_dst = me_dst->totloop;
CustomData *ldata_dst = &me_dst->ldata;
const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0;
const float split_angle_dst = me_dst->smoothresh;
/* This should be ensured by cddata_masks we pass to code generating/giving us me_src now. */
BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != NULL);
(void)me_src;
float(*loop_nors_dst)[3];
short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
/* Cache loop nors into a temp CDLayer. */
loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
const bool do_loop_nors_dst = (loop_nors_dst == NULL);
if (do_loop_nors_dst) {
loop_nors_dst = CustomData_add_layer(
ldata_dst, CD_NORMAL, CD_SET_DEFAULT, NULL, num_loops_dst);
CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
}
if (dirty_nors_dst || do_loop_nors_dst) {
BKE_mesh_normals_loop_split(verts_dst,
BKE_mesh_vertex_normals_ensure(me_dst),
num_verts_dst,
edges_dst,
num_edges_dst,
loops_dst,
loop_nors_dst,
num_loops_dst,
polys_dst,
BKE_mesh_poly_normals_ensure(me_dst),
num_polys_dst,
use_split_nors_dst,
split_angle_dst,
NULL,
custom_nors_dst,
NULL);
}
}
}
static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src),
Object *UNUSED(ob_dst),
Mesh *UNUSED(me_src),
@ -330,7 +271,6 @@ static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src),
CustomData *ldata_dst = &me_dst->ldata;
const float(*poly_nors_dst)[3] = BKE_mesh_poly_normals_ensure(me_dst);
float(*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL);
short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
if (!custom_nors_dst) {
@ -345,7 +285,7 @@ static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src),
edges_dst,
num_edges_dst,
loops_dst,
loop_nors_dst,
BKE_mesh_corner_normals_ensure(me_dst),
num_loops_dst,
polys_dst,
poly_nors_dst,
@ -1323,8 +1263,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
continue;
}
data_transfer_dtdata_type_preprocess(me_src, me_dst, dtdata_type, dirty_nors_dst);
cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type);

View File

@ -1567,20 +1567,6 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)
}
}
/* don't update normals, caller can do this explicitly.
* We do update loop normals though, those may not be auto-generated
* (see e.g. STL import script)! */
float(*lnors)[3] = (float(*)[3])CustomData_duplicate_referenced_layer(
&me->ldata, CD_NORMAL, me->totloop);
if (lnors) {
float m3[3][3];
copy_m3_m4(m3, mat);
normalize_m3(m3);
for (int i = 0; i < me->totloop; i++, lnors++) {
mul_m3_v3(m3, *lnors);
}
}
BKE_mesh_tag_coords_changed(me);
}
@ -1836,10 +1822,6 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
}
void BKE_mesh_calc_normals_split(Mesh *mesh)
{
BKE_mesh_calc_normals_split_ex(mesh, nullptr, ensure_corner_normal_layer(*mesh));
}
/* Split faces helper functions. */

View File

@ -164,8 +164,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
/* XXX: investigate using EditMesh data. */
const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
static_cast<const float(*)[3]>(
CustomData_get_layer(&mesh->ldata, CD_NORMAL)) :
BKE_mesh_corner_normals_ensure(mesh) :
nullptr;
int f_idx;
@ -186,8 +185,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
}
else {
const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
static_cast<const float(*)[3]>(
CustomData_get_layer(&mesh->ldata, CD_NORMAL)) :
BKE_mesh_corner_normals_ensure(mesh) :
nullptr;
const MVert *mv = BKE_mesh_verts(mesh);

View File

@ -123,6 +123,18 @@ float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3]
return mesh->runtime->poly_normals;
}
float (*BKE_mesh_corner_normals_for_write(Mesh *mesh))[3]
{
if (mesh->runtime->corner_normals == nullptr) {
mesh->runtime->corner_normals = (float(*)[3])MEM_malloc_arrayN(
mesh->totloop, sizeof(float[3]), __func__);
}
BLI_assert(MEM_allocN_len(mesh->runtime->corner_normals) >= sizeof(float[3]) * mesh->totloop);
return mesh->runtime->corner_normals;
}
void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh)
{
mesh->runtime->vert_normals_dirty = false;
@ -135,6 +147,12 @@ void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
}
void BKE_mesh_corner_normals_clear_dirty(Mesh *mesh)
{
mesh->runtime->corner_normals_dirty = false;
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
}
bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
{
return mesh->runtime->vert_normals_dirty;
@ -145,13 +163,20 @@ bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
return mesh->runtime->poly_normals_dirty;
}
bool BKE_mesh_corner_normals_are_dirty(const Mesh *mesh)
{
return mesh->runtime->corner_normals_dirty;
}
void BKE_mesh_clear_derived_normals(Mesh *mesh)
{
MEM_SAFE_FREE(mesh->runtime->vert_normals);
MEM_SAFE_FREE(mesh->runtime->poly_normals);
MEM_SAFE_FREE(mesh->runtime->corner_normals);
mesh->runtime->vert_normals_dirty = true;
mesh->runtime->poly_normals_dirty = true;
mesh->runtime->corner_normals_dirty = true;
}
void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh)
@ -162,6 +187,9 @@ void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh)
if (!mesh->runtime->poly_normals_dirty) {
BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0);
}
if (!mesh->runtime->corner_normals_dirty) {
BLI_assert(mesh->runtime->corner_normals || mesh->totloop == 0);
}
}
/** \} */
@ -433,6 +461,60 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
return poly_normals;
}
const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3]
{
if (!BKE_mesh_corner_normals_are_dirty(mesh)) {
BLI_assert(mesh->runtime->corner_normals != nullptr || mesh->totcorner == 0);
return mesh->runtime->corner_normals;
}
if (mesh->totpoly == 0) {
return nullptr;
}
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(mesh);
std::lock_guard lock{mesh->runtime->normals_mutex};
if (!BKE_mesh_corner_normals_are_dirty(mesh)) {
BLI_assert(mesh->runtime->corner_normals != nullptr);
return mesh->runtime->corner_normals;
}
float(*corner_normals)[3];
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
blender::threading::isolate_task([&]() {
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
const Span<MVert> verts = mesh_mutable.verts();
const Span<MEdge> edges = mesh_mutable.edges();
const Span<MPoly> polys = mesh_mutable.polys();
const Span<MLoop> loops = mesh_mutable.loops();
corner_normals = BKE_mesh_corner_normals_for_write(&mesh_mutable);
const short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
BKE_mesh_normals_loop_split(verts.data(),
vert_normals,
verts.size(),
edges.data(),
edges.size(),
loops.data(),
corner_normals,
loops.size(),
polys.data(),
poly_normals,
polys.size(),
use_split_normals,
split_angle,
r_lnors_spacearr,
clnors,
nullptr);
BKE_mesh_corner_normals_clear_dirty(&mesh_mutable);
});
}
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
{
switch (mesh->runtime->wrapper_type) {

View File

@ -1347,43 +1347,13 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst);
}
if (need_lnors_dst) {
short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
/* Cache loop normals into a temporary custom data layer. */
loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
const bool do_loop_nors_dst = (loop_nors_dst == NULL);
if (!loop_nors_dst) {
loop_nors_dst = CustomData_add_layer(
ldata_dst, CD_NORMAL, CD_SET_DEFAULT, NULL, numloops_dst);
CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
}
if (dirty_nors_dst || do_loop_nors_dst) {
BKE_mesh_normals_loop_split(verts_dst,
BKE_mesh_vertex_normals_ensure(mesh_dst),
numverts_dst,
edges_dst,
numedges_dst,
loops_dst,
loop_nors_dst,
numloops_dst,
polys_dst,
poly_nors_dst,
numpolys_dst,
use_split_nors_dst,
split_angle_dst,
NULL,
custom_nors_dst,
NULL);
}
loop_nors_dst = BKE_mesh_corner_normals_ensure(mesh_dst);
}
if (need_pnors_src || need_lnors_src) {
if (need_pnors_src) {
poly_nors_src = BKE_mesh_poly_normals_ensure(me_src);
}
if (need_lnors_src) {
loop_nors_src = CustomData_get_layer(&me_src->ldata, CD_NORMAL);
BLI_assert(loop_nors_src != NULL);
}
if (need_pnors_src) {
poly_nors_src = BKE_mesh_poly_normals_ensure(me_src);
}
if (need_lnors_src) {
loop_nors_src = BKE_mesh_corner_normals_ensure(me_src);
}
}

View File

@ -133,19 +133,11 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
return;
}
const float(*loopnors)[3] = static_cast<const float(*)[3]>(
CustomData_get_layer(&mesh->ldata, CD_NORMAL));
if (!loopnors) {
BKE_report(
reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting");
return;
}
BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_verts(mesh),
mesh->totvert,
BKE_mesh_loops(mesh),
r_looptangents,
loopnors,
BKE_mesh_corner_normals_ensure(mesh),
loopuvs,
mesh->totloop,
BKE_mesh_polys(mesh),
@ -585,7 +577,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
tangent_names_len,
BKE_mesh_vertex_normals_ensure(me_eval),
BKE_mesh_poly_normals_ensure(me_eval),
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->ldata, CD_NORMAL)),
BKE_mesh_corner_normals_ensure(me_eval),
/* may be nullptr */
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->vdata, CD_ORCO)),
/* result */

View File

@ -331,22 +331,17 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
if (use_clnors) {
/* If custom normals are present and the option is turned on calculate the split
* normals and clear flag so the normals get interpolated to the result mesh. */
BKE_mesh_calc_normals_split(me);
CustomData_clear_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me);
if (use_clnors) {
float(*lnors)[3] = static_cast<float(*)[3]>(
CustomData_get_layer(&subdiv_mesh->ldata, CD_NORMAL));
BLI_assert(lnors != nullptr);
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(subdiv_mesh);
BKE_mesh_set_custom_normals(subdiv_mesh, lnors);
CustomData_set_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_set_layer_flag(&subdiv_mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
else if (runtime_data->calc_loop_normals) {
BKE_mesh_calc_normals_split(subdiv_mesh);
BKE_mesh_corner_normals_ensure(subdiv_mesh);
}
if (subdiv != runtime_data->subdiv) {

View File

@ -135,7 +135,7 @@ bool BKE_shrinkwrap_init_tree(
if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
data->pnors = BKE_mesh_poly_normals_ensure(mesh);
if ((mesh->flag & ME_AUTOSMOOTH) != 0) {
data->clnors = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
data->clnors = BKE_mesh_corner_normals_ensure(mesh);
}
}

View File

@ -235,9 +235,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
if (subdiv_cache->use_custom_loop_normals) {
Mesh *coarse_mesh = subdiv_cache->mesh;
const float(*lnors)[3] = static_cast<const float(*)[3]>(
CustomData_get_layer(&coarse_mesh->ldata, CD_NORMAL));
BLI_assert(lnors != nullptr);
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(coarse_mesh);
GPUVertBuf *src_custom_normals = GPU_vertbuf_calloc();
GPU_vertbuf_init_with_format(src_custom_normals, get_custom_normals_format());

View File

@ -127,7 +127,7 @@ struct AddOperationExecutor {
transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface);
Object &surface_ob_orig = *curves_id_orig_->surface;
Mesh &surface_orig = *static_cast<Mesh *>(surface_ob_orig.data);
const Mesh &surface_orig = *static_cast<Mesh *>(surface_ob_orig.data);
if (surface_orig.totpoly == 0) {
report_empty_original_surface(stroke_extension.reports);
return;
@ -206,13 +206,8 @@ struct AddOperationExecutor {
}
const Span<MLoopTri> surface_looptris_orig = surface_orig.looptris();
/* Find normals. */
if (!CustomData_has_layer(&surface_orig.ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(&surface_orig);
}
const Span<float3> corner_normals_su = {
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_orig.ldata, CD_NORMAL)),
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(&surface_orig)),
surface_orig.totloop};
const geometry::ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_looptris_orig};

View File

@ -256,12 +256,8 @@ struct DensityAddOperationExecutor {
}
self_->new_deformed_root_positions_.extend(new_positions_cu);
/* Find normals. */
if (!CustomData_has_layer(&surface_orig_->ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(surface_orig_);
}
const Span<float3> corner_normals_su = {
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_orig_->ldata, CD_NORMAL)),
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_orig_)),
surface_orig_->totloop};
const Span<MLoopTri> surface_looptris_orig = surface_orig_->looptris();

View File

@ -112,11 +112,8 @@ struct PuffOperationExecutor {
transforms_ = CurvesSurfaceTransforms(*object_, surface_ob_);
if (!CustomData_has_layer(&surface_->ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(surface_);
}
corner_normals_su_ = {
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_->ldata, CD_NORMAL)),
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_)),
surface_->totloop};
surface_verts_ = surface_->verts();

View File

@ -177,11 +177,8 @@ struct SlideOperationExecutor {
report_missing_uv_map_on_original_surface(stroke_extension.reports);
return;
}
if (!CustomData_has_layer(&surface_orig_->ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(surface_orig_);
}
corner_normals_orig_su_ = {
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_orig_->ldata, CD_NORMAL)),
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_orig_)),
surface_orig_->totloop};
surface_ob_eval_ = DEG_get_evaluated_object(ctx_.depsgraph, surface_ob_orig_);

View File

@ -412,12 +412,8 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
mesh_loops.data(), mesh_polys.data(), mesh_verts.data(), me->totloop, me->totpoly, mlooptri);
// Compute loop normals
BKE_mesh_calc_normals_split(me);
const float(*lnors)[3] = nullptr;
if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
}
/* TODO: Only retrieve loop normals when necessary. */
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me);
// Get other mesh data
const FreestyleEdge *fed = (FreestyleEdge *)CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE);

View File

@ -534,9 +534,7 @@ static void get_loop_normals(struct Mesh *mesh,
return;
}
BKE_mesh_calc_normals_split(mesh);
const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
BLI_assert_msg(lnors != nullptr, "BKE_mesh_calc_normals_split() should have computed CD_NORMAL");
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(mesh);
normals.resize(mesh->totloop);

View File

@ -619,14 +619,9 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const float(*lnors)[3] = nullptr;
bool use_custom_normals = false;
BKE_mesh_calc_normals_split(me);
if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
use_custom_normals = true;
}
/* TODO: Only retrieve when necessary. */
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me);
bool use_custom_normals = true;
for (const int poly_index : polys.index_range()) {
const MPoly *mpoly = &polys[poly_index];

View File

@ -398,7 +398,8 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context,
void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh)
{
pxr::UsdTimeCode timecode = get_export_time_code();
const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
/* TODO: Only when necessary. */
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(mesh);
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();

View File

@ -176,11 +176,6 @@ int OBJMesh::ith_smooth_group(const int poly_index) const
return poly_smooth_groups_[poly_index];
}
void OBJMesh::ensure_mesh_normals() const
{
BKE_mesh_calc_normals_split(export_mesh_eval_);
}
void OBJMesh::ensure_mesh_edges() const
{
BKE_mesh_calc_edges_loose(export_mesh_eval_);
@ -397,8 +392,8 @@ void OBJMesh::store_normal_coords_and_indices()
normal_to_index.reserve(export_mesh_eval_->totpoly);
loop_to_normal_index_.resize(export_mesh_eval_->totloop);
loop_to_normal_index_.fill(-1);
const float(*lnors)[3] = static_cast<const float(*)[3]>(
CustomData_get_layer(&export_mesh_eval_->ldata, CD_NORMAL));
/* TODO: Only get loop normals when they're necessary. */
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(export_mesh_eval_);
for (int poly_index = 0; poly_index < export_mesh_eval_->totpoly; ++poly_index) {
const MPoly &mpoly = polys[poly_index];
bool need_per_loop_normals = lnors != nullptr || (mpoly.flag & ME_SMOOTH);

View File

@ -131,7 +131,6 @@ class OBJMesh : NonCopyable {
*/
const Material *get_object_material(int16_t mat_nr) const;
void ensure_mesh_normals() const;
void ensure_mesh_edges() const;
/**

View File

@ -104,7 +104,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest {
const Span<MVert> verts = mesh->verts();
EXPECT_V3_NEAR(verts.first().co, exp.vert_first, 0.0001f);
EXPECT_V3_NEAR(verts.last().co, exp.vert_last, 0.0001f);
const float3 *lnors = (const float3 *)CustomData_get_layer(&mesh->ldata, CD_NORMAL);
const float3 *lnors = (const float3 *)BKE_mesh_corner_normals_ensure(mesh);
float3 normal_first = lnors != nullptr ? lnors[0] : float3(0, 0, 0);
EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f);
const MLoopUV *mloopuv = static_cast<const MLoopUV *>(

View File

@ -554,25 +554,8 @@ static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values)
{
Mesh *me = rna_mesh(ptr);
const int index = rna_MeshLoop_index_get(ptr);
const float(*vec)[3] = CustomData_get(&me->ldata, index, CD_NORMAL);
if (!vec) {
zero_v3(values);
}
else {
copy_v3_v3(values, (const float *)vec);
}
}
static void rna_MeshLoop_normal_set(PointerRNA *ptr, const float *values)
{
Mesh *me = rna_mesh(ptr);
const int index = rna_MeshLoop_index_get(ptr);
float(*vec)[3] = CustomData_get(&me->ldata, index, CD_NORMAL);
if (vec) {
normalize_v3_v3(*vec, values);
}
const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me);
copy_v3_v3(values, loop_normals[index]);
}
static void rna_MeshLoop_tangent_get(PointerRNA *ptr, float *values)
@ -602,7 +585,8 @@ static void rna_MeshLoop_bitangent_get(PointerRNA *ptr, float *values)
{
Mesh *me = rna_mesh(ptr);
const int index = rna_MeshLoop_index_get(ptr);
const float(*nor)[3] = CustomData_get(&me->ldata, index, CD_NORMAL);
const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me);
const float(*nor)[3] = loop_normals[index];
const float(*vec)[4] = CustomData_get(&me->ldata, index, CD_MLOOPTANGENT);
if (nor && vec) {
@ -745,19 +729,11 @@ static void rna_MeshLoopTriangle_normal_get(PointerRNA *ptr, float *values)
static void rna_MeshLoopTriangle_split_normals_get(PointerRNA *ptr, float *values)
{
Mesh *me = rna_mesh(ptr);
const float(*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL);
if (!lnors) {
zero_v3(values + 0);
zero_v3(values + 3);
zero_v3(values + 6);
}
else {
MLoopTri *lt = (MLoopTri *)ptr->data;
copy_v3_v3(values + 0, lnors[lt->tri[0]]);
copy_v3_v3(values + 3, lnors[lt->tri[1]]);
copy_v3_v3(values + 6, lnors[lt->tri[2]]);
}
const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me);
const MLoopTri *lt = (const MLoopTri *)ptr->data;
copy_v3_v3(values + 0, loop_normals[lt->tri[0]]);
copy_v3_v3(values + 3, loop_normals[lt->tri[1]]);
copy_v3_v3(values + 6, loop_normals[lt->tri[2]]);
}
static float rna_MeshLoopTriangle_area_get(PointerRNA *ptr)
@ -2453,7 +2429,7 @@ static void rna_def_mloop(BlenderRNA *brna)
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -1.0f, 1.0f);
RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", "rna_MeshLoop_normal_set", NULL);
RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", NULL, NULL);
RNA_def_property_ui_text(
prop,
"Normal",

View File

@ -44,15 +44,13 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh,
static void rna_Mesh_create_normals_split(Mesh *mesh)
{
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_SET_DEFAULT, NULL, mesh->totloop);
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
/* TODO: Proper deprecation. */
}
static void rna_Mesh_free_normals_split(Mesh *mesh)
{
CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
/* TODO: Deprecation? */
BKE_mesh_clear_derived_normals(mesh);
}
static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap)
@ -69,11 +67,6 @@ static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *
CustomData_set_layer_flag(&mesh->ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY);
}
/* Compute loop normals if needed. */
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(mesh);
}
BKE_mesh_calc_loop_tangent_single(mesh, uvmap, r_looptangents, reports);
}
@ -226,7 +219,7 @@ void RNA_api_mesh(StructRNA *srna)
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", "BKE_mesh_calc_normals_split");
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");

View File

@ -307,11 +307,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
CustomData *ldata = &mesh->ldata;
if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) {
if (!CustomData_has_layer(ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(mesh);
}
float(*clnors)[3] = CustomData_get_layer(ldata, CD_NORMAL);
const float(*clnors)[3] = BKE_mesh_corner_normals_ensure(mesh);
vert_clnors = MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__);
BKE_mesh_normals_loop_to_vertex(
verts_num, BKE_mesh_loops(mesh), mesh->totloop, (const float(*)[3])clnors, vert_clnors);

View File

@ -252,20 +252,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
else {
if (use_clnors) {
/* If custom normals are present and the option is turned on calculate the split
* normals and clear flag so the normals get interpolated to the result mesh. */
BKE_mesh_calc_normals_split(mesh);
CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_add_layer(&mesh->ldata,
CD_NORMAL,
CD_DUPLICATE,
const_cast<float(*)[3]>(BKE_mesh_corner_normals_ensure(mesh)),
mesh->totloop);
}
result = multires_as_mesh(mmd, ctx, mesh, subdiv);
if (use_clnors) {
float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&result->ldata, CD_NORMAL));
BLI_assert(lnors != nullptr);
BKE_mesh_set_custom_normals(result, lnors);
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop);
}
// BKE_subdiv_stats_print(&subdiv->stats);
if (subdiv != runtime_data->subdiv) {

View File

@ -250,10 +250,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh);
if (use_clnors) {
/* If custom normals are present and the option is turned on calculate the split
* normals and clear flag so the normals get interpolated to the result mesh. */
BKE_mesh_calc_normals_split(mesh);
CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_add_layer(&mesh->ldata,
CD_NORMAL,
CD_DUPLICATE,
const_cast<float(*)[3]>(BKE_mesh_corner_normals_ensure(mesh)),
mesh->totloop);
}
/* TODO(sergey): Decide whether we ever want to use CCG for subsurf,
* maybe when it is a last modifier in the stack? */
@ -266,10 +267,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
if (use_clnors) {
float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&result->ldata, CD_NORMAL));
BLI_assert(lnors != nullptr);
BKE_mesh_set_custom_normals(result, lnors);
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop);
}
// BKE_subdiv_stats_print(&subdiv->stats);
if (subdiv != runtime_data->subdiv) {

View File

@ -51,9 +51,11 @@ static Mesh *triangulate_mesh(Mesh *mesh,
bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0;
if (keep_clnors) {
BKE_mesh_calc_normals_split(mesh);
/* We need that one to 'survive' to/from BMesh conversions. */
CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_add_layer(&mesh->ldata,
CD_NORMAL,
CD_DUPLICATE,
(float(*)[3])BKE_mesh_corner_normals_ensure(mesh),
mesh->totloop);
cd_mask_extra.lmask |= CD_MASK_NORMAL;
}
@ -71,14 +73,8 @@ static Mesh *triangulate_mesh(Mesh *mesh,
BM_mesh_free(bm);
if (keep_clnors) {
float(*lnors)[3] = CustomData_get_layer(&result->ldata, CD_NORMAL);
BLI_assert(lnors != NULL);
BKE_mesh_set_custom_normals(result, lnors);
/* Do some cleanup, we do not want those temp data to stay around. */
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
BKE_mesh_set_custom_normals(result, CustomData_get_layer(&result->ldata, CD_NORMAL));
CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop);
}
edges_num = result->totedge;

View File

@ -320,14 +320,13 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Retrieve face corner normals from each mesh. It's necessary to use face corner normals
* because face normals or vertex normals may lose information (custom normals, auto smooth) in
* some cases. It isn't yet possible to retrieve lazily calculated face corner normals from a
* const mesh, so they are calculated here every time. */
Array<float3> corner_normals_orig(surface_mesh_orig->totloop);
Array<float3> corner_normals_eval(surface_mesh_eval->totloop);
BKE_mesh_calc_normals_split_ex(
surface_mesh_orig, nullptr, reinterpret_cast<float(*)[3]>(corner_normals_orig.data()));
BKE_mesh_calc_normals_split_ex(
surface_mesh_eval, nullptr, reinterpret_cast<float(*)[3]>(corner_normals_eval.data()));
* some cases. */
const Span<float3> corner_normals_orig(
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_mesh_orig)),
surface_mesh_orig->totloop);
const Span<float3> corner_normals_eval(
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_mesh_eval)),
surface_mesh_eval->totloop);
std::atomic<int> invalid_uv_count = 0;

View File

@ -482,14 +482,12 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
const TSpace *tspace = NULL;
const float(*loop_normals)[3] = NULL;
if (tangent) {
BKE_mesh_ensure_normals_for_display(me_eval);
BKE_mesh_calc_normals_split(me_eval);
BKE_mesh_calc_loop_tangents(me_eval, true, NULL, 0);
tspace = CustomData_get_layer(&me_eval->ldata, CD_TANGENT);
BLI_assert(tspace);
loop_normals = CustomData_get_layer(&me_eval->ldata, CD_NORMAL);
loop_normals = BKE_mesh_corner_normals_ensure(me_eval);
}
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);

View File

@ -499,6 +499,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
temp_mesh->totloop * sizeof(MLoop));
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(temp_mesh);
const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(temp_mesh);
const float(*corner_normals)[3] = BKE_mesh_corner_normals_ensure(temp_mesh);
if (require_tangent) {
if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
@ -515,7 +516,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
0,
vert_normals,
poly_normals,
(const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL),
corner_normals,
(const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* may be nullptr */
/* result */
&dm->loopData,