Compare commits

...

10 Commits

34 changed files with 170 additions and 336 deletions

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_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. * Tag mesh vertex and face normals to be recalculated when/if they are needed later.
* *
@@ -418,6 +420,8 @@ void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh);
*/ */
void BKE_mesh_poly_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. * 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. * This can be used to help decide whether to transfer them when copying a mesh.
@@ -430,6 +434,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_poly_normals_are_dirty(const struct Mesh *mesh);
bool BKE_mesh_corner_normals_are_dirty(const struct Mesh *mesh);
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly, void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly,
const struct MLoop *loopstart, const struct MLoop *loopstart,
const struct MVert *mvarray, const struct MVert *mvarray,
@@ -668,18 +674,6 @@ void BKE_mesh_normals_loop_to_vertex(int numVerts,
*/ */
bool BKE_mesh_has_custom_loop_normals(struct Mesh *me); 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.
*
* \param r_lnors_spacearr: Allows to get computed loop normal space array.
* That data, among other things, contains 'smooth fan' info, useful e.g.
* to split geometry along sharp edges.
*/
void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh,
struct MLoopNorSpaceArray *r_lnors_spacearr,
float (*r_corner_normals)[3]);
/** /**
* Higher level functions hiding most of the code needed around call to * Higher level functions hiding most of the code needed around call to
* #BKE_mesh_normals_loop_custom_set(). * #BKE_mesh_normals_loop_custom_set().

View File

@@ -157,8 +157,10 @@ struct MeshRuntime {
*/ */
bool vert_normals_dirty = true; bool vert_normals_dirty = true;
bool poly_normals_dirty = true; bool poly_normals_dirty = true;
bool corner_normals_dirty = false;
float (*vert_normals)[3] = nullptr; float (*vert_normals)[3] = nullptr;
float (*poly_normals)[3] = nullptr; float (*poly_normals)[3] = nullptr;
float (*corner_normals)[3] = nullptr;
/** /**
* A cache of data about the loose edges. Can be shared with other data-blocks with unchanged * A cache of data about the loose edges. Can be shared with other data-blocks with unchanged

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 /* 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. */ * of deferred CPU subdivision, this will be computed when the wrapper is generated. */
if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
BKE_mesh_calc_normals_split(mesh_final); BKE_mesh_corner_normals_ensure(mesh_final);
} }
} }
else { else {
@@ -559,13 +559,6 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
* which deals with drawing differently. */ * which deals with drawing differently. */
BKE_mesh_ensure_normals_for_display(mesh_final); 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);
}
} }
} }
@@ -1215,18 +1208,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 /* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the
* wrapper is generated. */ * wrapper is generated. */
if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
BKE_mesh_calc_normals_split(mesh_final); BKE_mesh_corner_normals_ensure(mesh_final);
} }
} }
else { else {
/* Same as mesh_calc_modifiers. If using loop normals, poly nors have already been computed. */ /* Same as mesh_calc_modifiers. If using loop normals, poly nors have already been computed. */
BKE_mesh_ensure_normals_for_display(mesh_final); 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

@@ -1564,20 +1564,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); BKE_mesh_tag_coords_changed(me);
} }
@@ -1777,65 +1763,6 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
BKE_mesh_tag_coords_changed(mesh); BKE_mesh_tag_coords_changed(mesh);
} }
static float (*ensure_corner_normal_layer(Mesh &mesh))[3]
{
float(*r_loopnors)[3];
if (CustomData_has_layer(&mesh.ldata, CD_NORMAL)) {
r_loopnors = (float(*)[3])CustomData_get_layer(&mesh.ldata, CD_NORMAL);
memset(r_loopnors, 0, sizeof(float[3]) * mesh.totloop);
}
else {
r_loopnors = (float(*)[3])CustomData_add_layer(
&mesh.ldata, CD_NORMAL, CD_SET_DEFAULT, nullptr, mesh.totloop);
CustomData_set_layer_flag(&mesh.ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
return r_loopnors;
}
void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
MLoopNorSpaceArray *r_lnors_spacearr,
float (*r_corner_normals)[3])
{
short(*clnors)[2] = nullptr;
/* Note that we enforce computing clnors when the clnor space array is requested by caller here.
* However, we obviously only use the auto-smooth angle threshold
* only in case auto-smooth is enabled. */
const bool use_split_normals = (r_lnors_spacearr != nullptr) ||
((mesh->flag & ME_AUTOSMOOTH) != 0);
const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI);
/* may be nullptr */
clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
const Span<MVert> verts = mesh->verts();
const Span<MEdge> edges = mesh->edges();
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
BKE_mesh_normals_loop_split(verts.data(),
BKE_mesh_vertex_normals_ensure(mesh),
verts.size(),
edges.data(),
edges.size(),
loops.data(),
r_corner_normals,
loops.size(),
polys.data(),
BKE_mesh_poly_normals_ensure(mesh),
polys.size(),
use_split_normals,
split_angle,
nullptr,
r_lnors_spacearr,
clnors);
}
void BKE_mesh_calc_normals_split(Mesh *mesh)
{
BKE_mesh_calc_normals_split_ex(mesh, nullptr, ensure_corner_normal_layer(*mesh));
}
/* **** Depsgraph evaluation **** */ /* **** Depsgraph evaluation **** */
void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh) void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)

View File

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

View File

@@ -101,6 +101,7 @@ void BKE_mesh_normals_tag_dirty(Mesh *mesh)
{ {
mesh->runtime->vert_normals_dirty = true; mesh->runtime->vert_normals_dirty = true;
mesh->runtime->poly_normals_dirty = true; mesh->runtime->poly_normals_dirty = true;
mesh->runtime->corner_normals_dirty = true;
} }
float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3] float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3]
@@ -139,6 +140,18 @@ void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0); BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0);
} }
void BKE_mesh_corner_normals_clear_dirty(Mesh *mesh)
{
mesh->runtime->corner_normals_dirty = false;
BLI_assert(mesh->runtime->corner_normals || mesh->totloop == 0);
}
void BKE_mesh_corner_normals_clear_dirty(Mesh *mesh)
{
mesh->runtime->corner_normals_dirty = false;
BLI_assert(mesh->runtime->corner_normals || mesh->totloop == 0);
}
bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh) bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
{ {
return mesh->runtime->vert_normals_dirty; return mesh->runtime->vert_normals_dirty;
@@ -499,6 +512,65 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
return poly_normals; 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->totloop == 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();
if (mesh_mutable.runtime->corner_normals == nullptr) {
mesh_mutable.runtime->corner_normals = (float(*)[3])MEM_malloc_arrayN(
mesh_mutable.totloop, sizeof(float[3]), __func__);
}
const short(*custom_normals)[2] = (const short(*)[2])CustomData_get_layer(&mesh->ldata,
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(),
true,
mesh->smoothresh,
nullptr,
custom_normals,
nullptr);
BKE_mesh_corner_normals_clear_dirty(&mesh_mutable);
});
}
void BKE_mesh_ensure_normals_for_display(Mesh *mesh) void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
{ {
switch (mesh->runtime->wrapper_type) { switch (mesh->runtime->wrapper_type) {

View File

@@ -1291,7 +1291,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const float(*poly_nors_src)[3] = nullptr; const float(*poly_nors_src)[3] = nullptr;
const float(*loop_nors_src)[3] = nullptr; const float(*loop_nors_src)[3] = nullptr;
const float(*poly_nors_dst)[3] = nullptr; const float(*poly_nors_dst)[3] = nullptr;
float(*loop_nors_dst)[3] = nullptr; const float(*loop_nors_dst)[3] = nullptr;
float(*poly_cents_src)[3] = nullptr; float(*poly_cents_src)[3] = nullptr;
@@ -1355,45 +1355,13 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst); poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst);
} }
if (need_lnors_dst) { if (need_lnors_dst) {
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>( loop_nors_dst = BKE_mesh_corner_normals_ensure(mesh_dst);
CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL));
/* Cache loop normals into a temporary custom data layer. */
loop_nors_dst = static_cast<float(*)[3]>(CustomData_get_layer(ldata_dst, CD_NORMAL));
const bool do_loop_nors_dst = (loop_nors_dst == nullptr);
if (!loop_nors_dst) {
loop_nors_dst = static_cast<float(*)[3]>(
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, 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,
nullptr,
nullptr,
custom_nors_dst);
}
} }
if (need_pnors_src || need_lnors_src) { if (need_pnors_src) {
if (need_pnors_src) { poly_nors_src = BKE_mesh_poly_normals_ensure(me_src);
poly_nors_src = BKE_mesh_poly_normals_ensure(me_src); }
} if (need_lnors_src) {
if (need_lnors_src) { loop_nors_src = BKE_mesh_corner_normals_ensure(me_src);
loop_nors_src = static_cast<const float(*)[3]>(
CustomData_get_layer(&me_src->ldata, CD_NORMAL));
BLI_assert(loop_nors_src != nullptr);
}
} }
} }

View File

@@ -133,19 +133,11 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
return; 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), BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_verts(mesh),
mesh->totvert, mesh->totvert,
BKE_mesh_loops(mesh), BKE_mesh_loops(mesh),
r_looptangents, r_looptangents,
loopnors, BKE_mesh_corner_normals_ensure(mesh),
loopuvs, loopuvs,
mesh->totloop, mesh->totloop,
BKE_mesh_polys(mesh), BKE_mesh_polys(mesh),
@@ -585,7 +577,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
tangent_names_len, tangent_names_len,
BKE_mesh_vertex_normals_ensure(me_eval), BKE_mesh_vertex_normals_ensure(me_eval),
BKE_mesh_poly_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 */ /* may be nullptr */
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->vdata, CD_ORCO)), static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->vdata, CD_ORCO)),
/* result */ /* result */

View File

@@ -331,22 +331,14 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
if (use_clnors) { if (use_clnors) {
/* If custom normals are present and the option is turned on calculate the split /* 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. */ * 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); CustomData_clear_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
} }
Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me); Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me);
if (use_clnors) { if (use_clnors) {
float(*lnors)[3] = static_cast<float(*)[3]>( const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(subdiv_mesh);
CustomData_get_layer(&subdiv_mesh->ldata, CD_NORMAL));
BLI_assert(lnors != nullptr);
BKE_mesh_set_custom_normals(subdiv_mesh, lnors); 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);
} }
if (subdiv != runtime_data->subdiv) { if (subdiv != runtime_data->subdiv) {

View File

@@ -136,7 +136,7 @@ bool BKE_shrinkwrap_init_tree(
if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) { if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
data->pnors = BKE_mesh_poly_normals_ensure(mesh); data->pnors = BKE_mesh_poly_normals_ensure(mesh);
if ((mesh->flag & ME_AUTOSMOOTH) != 0) { 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

@@ -364,26 +364,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
mr->poly_normals = BKE_mesh_poly_normals_ensure(mr->me); mr->poly_normals = BKE_mesh_poly_normals_ensure(mr->me);
} }
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
mr->loop_normals = static_cast<float(*)[3]>( mr->loop_normals = BKE_mesh_corner_normals_ensure(mr->me);
MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__));
short(*clnors)[2] = static_cast<short(*)[2]>(
CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL));
BKE_mesh_normals_loop_split(mr->mvert,
mr->vert_normals,
mr->vert_len,
mr->medge,
mr->edge_len,
mr->mloop,
mr->loop_normals,
mr->loop_len,
mr->mpoly,
mr->poly_normals,
mr->poly_len,
is_auto_smooth,
split_angle,
nullptr,
nullptr,
clnors);
} }
} }
else { else {
@@ -403,8 +384,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
poly_normals = mr->bm_poly_normals; poly_normals = mr->bm_poly_normals;
} }
mr->loop_normals = static_cast<float(*)[3]>( mr->bm_loop_normals = static_cast<float(*)[3]>(
MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__)); MEM_mallocN(sizeof(*mr->bm_loop_normals) * mr->loop_len, __func__));
const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL); const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(mr->bm, BM_loops_calc_normal_vcos(mr->bm,
vert_coords, vert_coords,
@@ -412,11 +393,12 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
poly_normals, poly_normals,
is_auto_smooth, is_auto_smooth,
split_angle, split_angle,
mr->loop_normals, mr->bm_loop_normals,
nullptr, nullptr,
nullptr, nullptr,
clnors_offset, clnors_offset,
false); false);
mr->loop_normals = mr->bm_loop_normals;
} }
} }
} }
@@ -601,7 +583,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
void mesh_render_data_free(MeshRenderData *mr) void mesh_render_data_free(MeshRenderData *mr)
{ {
MEM_SAFE_FREE(mr->loop_normals); MEM_SAFE_FREE(mr->bm_loop_normals);
/* Loose geometry are owned by #MeshBufferCache. */ /* Loose geometry are owned by #MeshBufferCache. */
mr->ledges = nullptr; mr->ledges = nullptr;

View File

@@ -91,7 +91,8 @@ struct MeshRenderData {
const bool *select_vert; const bool *select_vert;
const bool *select_edge; const bool *select_edge;
const bool *select_poly; const bool *select_poly;
float (*loop_normals)[3]; const float (*loop_normals)[3];
float (*bm_loop_normals)[3];
int *lverts, *ledges; int *lverts, *ledges;
const char *active_color_name; const char *active_color_name;

View File

@@ -264,9 +264,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
if (subdiv_cache->use_custom_loop_normals) { if (subdiv_cache->use_custom_loop_normals) {
Mesh *coarse_mesh = subdiv_cache->mesh; Mesh *coarse_mesh = subdiv_cache->mesh;
const float(*lnors)[3] = static_cast<const float(*)[3]>( const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(coarse_mesh);
CustomData_get_layer(&coarse_mesh->ldata, CD_NORMAL));
BLI_assert(lnors != nullptr);
GPUVertBuf *src_custom_normals = GPU_vertbuf_calloc(); GPUVertBuf *src_custom_normals = GPU_vertbuf_calloc();
GPU_vertbuf_init_with_format(src_custom_normals, get_custom_normals_format()); 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); transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface);
Object &surface_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) { if (surface_orig.totpoly == 0) {
report_empty_original_surface(stroke_extension.reports); report_empty_original_surface(stroke_extension.reports);
return; return;
@@ -206,13 +206,8 @@ struct AddOperationExecutor {
} }
const Span<MLoopTri> surface_looptris_orig = surface_orig.looptris(); 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 = { 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}; surface_orig.totloop};
const geometry::ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_looptris_orig}; 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); 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 = { 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}; surface_orig_->totloop};
const Span<MLoopTri> surface_looptris_orig = surface_orig_->looptris(); const Span<MLoopTri> surface_looptris_orig = surface_orig_->looptris();

View File

@@ -112,11 +112,8 @@ struct PuffOperationExecutor {
transforms_ = CurvesSurfaceTransforms(*object_, surface_ob_); transforms_ = CurvesSurfaceTransforms(*object_, surface_ob_);
if (!CustomData_has_layer(&surface_->ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(surface_);
}
corner_normals_su_ = { 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_->totloop};
surface_verts_ = surface_->verts(); surface_verts_ = surface_->verts();

View File

@@ -177,11 +177,8 @@ struct SlideOperationExecutor {
report_missing_uv_map_on_original_surface(stroke_extension.reports); report_missing_uv_map_on_original_surface(stroke_extension.reports);
return; return;
} }
if (!CustomData_has_layer(&surface_orig_->ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(surface_orig_);
}
corner_normals_orig_su_ = { 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_orig_->totloop};
surface_ob_eval_ = DEG_get_evaluated_object(ctx_.depsgraph, surface_ob_orig_); 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); mesh_loops.data(), mesh_polys.data(), mesh_verts.data(), me->totloop, me->totpoly, mlooptri);
// Compute loop normals // Compute loop normals
BKE_mesh_calc_normals_split(me); /* TODO: Only retrieve loop normals when necessary. */
const float(*lnors)[3] = nullptr; const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me);
if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
}
// Get other mesh data // Get other mesh data
const FreestyleEdge *fed = (FreestyleEdge *)CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE); 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; return;
} }
BKE_mesh_calc_normals_split(mesh); const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(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");
normals.resize(mesh->totloop); normals.resize(mesh->totloop);

View File

@@ -621,14 +621,9 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me); const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
const Span<MPoly> polys = me->polys(); const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops(); const Span<MLoop> loops = me->loops();
const float(*lnors)[3] = nullptr; /* TODO: Only retrieve when necessary. */
bool use_custom_normals = false; const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me);
bool use_custom_normals = true;
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;
}
for (const int poly_index : polys.index_range()) { for (const int poly_index : polys.index_range()) {
const MPoly *mpoly = &polys[poly_index]; 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) void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh)
{ {
pxr::UsdTimeCode timecode = get_export_time_code(); 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<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops(); const Span<MLoop> loops = mesh->loops();

View File

@@ -181,12 +181,6 @@ int OBJMesh::ith_smooth_group(const int poly_index) const
return poly_smooth_groups_[poly_index]; return poly_smooth_groups_[poly_index];
} }
void OBJMesh::ensure_mesh_normals() const
{
/* Const cast can be removed when calculating face corner normals lazily is possible. */
BKE_mesh_calc_normals_split(const_cast<Mesh *>(export_mesh_));
}
void OBJMesh::calc_smooth_groups(const bool use_bitflags) void OBJMesh::calc_smooth_groups(const bool use_bitflags)
{ {
poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(mesh_edges_.data(), poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(mesh_edges_.data(),
@@ -385,8 +379,8 @@ void OBJMesh::store_normal_coords_and_indices()
normal_to_index.reserve(export_mesh_->totpoly); normal_to_index.reserve(export_mesh_->totpoly);
loop_to_normal_index_.resize(export_mesh_->totloop); loop_to_normal_index_.resize(export_mesh_->totloop);
loop_to_normal_index_.fill(-1); loop_to_normal_index_.fill(-1);
const float(*lnors)[3] = static_cast<const float(*)[3]>( /* TODO: Only retrieve when necessary. */
CustomData_get_layer(&export_mesh_->ldata, CD_NORMAL)); const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(export_mesh_);
for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) { for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) {
const MPoly &mpoly = mesh_polys_[poly_index]; const MPoly &mpoly = mesh_polys_[poly_index];
bool need_per_loop_normals = lnors != nullptr || (mpoly.flag & ME_SMOOTH); bool need_per_loop_normals = lnors != nullptr || (mpoly.flag & ME_SMOOTH);

View File

@@ -121,8 +121,6 @@ class OBJMesh : NonCopyable {
*/ */
const Material *get_object_material(int16_t mat_nr) const; const Material *get_object_material(int16_t mat_nr) const;
void ensure_mesh_normals() const;
/** /**
* Calculate smooth groups of a smooth-shaded object. * Calculate smooth groups of a smooth-shaded object.
* \return A polygon aligned array of smooth group numbers. * \return A polygon aligned array of smooth group numbers.

View File

@@ -157,9 +157,6 @@ static void write_mesh_objects(Vector<std::unique_ptr<OBJMesh>> exportable_as_me
if (mtl_writer) { if (mtl_writer) {
mtlindices.append(mtl_writer->add_materials(obj)); mtlindices.append(mtl_writer->add_materials(obj));
} }
if (export_params.export_normals) {
obj.ensure_mesh_normals();
}
} }
/* Parallel over meshes: store normal coords & indices, uv coords and indices. */ /* Parallel over meshes: store normal coords & indices, uv coords and indices. */

View File

@@ -104,7 +104,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest {
const Span<MVert> verts = mesh->verts(); const Span<MVert> verts = mesh->verts();
EXPECT_V3_NEAR(verts.first().co, exp.vert_first, 0.0001f); EXPECT_V3_NEAR(verts.first().co, exp.vert_first, 0.0001f);
EXPECT_V3_NEAR(verts.last().co, exp.vert_last, 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); float3 normal_first = lnors != nullptr ? lnors[0] : float3(0, 0, 0);
EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f); EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f);
const MLoopUV *mloopuv = static_cast<const MLoopUV *>( 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); Mesh *me = rna_mesh(ptr);
const int index = rna_MeshLoop_index_get(ptr); const int index = rna_MeshLoop_index_get(ptr);
const float(*vec)[3] = CustomData_get(&me->ldata, index, CD_NORMAL); const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me);
copy_v3_v3(values, loop_normals[index]);
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);
}
} }
static void rna_MeshLoop_tangent_get(PointerRNA *ptr, float *values) 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); Mesh *me = rna_mesh(ptr);
const int index = rna_MeshLoop_index_get(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); const float(*vec)[4] = CustomData_get(&me->ldata, index, CD_MLOOPTANGENT);
if (nor && vec) { if (nor && vec) {
@@ -744,19 +728,11 @@ static void rna_MeshLoopTriangle_normal_get(PointerRNA *ptr, float *values)
static void rna_MeshLoopTriangle_split_normals_get(PointerRNA *ptr, float *values) static void rna_MeshLoopTriangle_split_normals_get(PointerRNA *ptr, float *values)
{ {
Mesh *me = rna_mesh(ptr); Mesh *me = rna_mesh(ptr);
const float(*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL); const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me);
const MLoopTri *lt = (const MLoopTri *)ptr->data;
if (!lnors) { copy_v3_v3(values + 0, loop_normals[lt->tri[0]]);
zero_v3(values + 0); copy_v3_v3(values + 3, loop_normals[lt->tri[1]]);
zero_v3(values + 3); copy_v3_v3(values + 6, loop_normals[lt->tri[2]]);
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]]);
}
} }
static float rna_MeshLoopTriangle_area_get(PointerRNA *ptr) static float rna_MeshLoopTriangle_area_get(PointerRNA *ptr)
@@ -2458,9 +2434,10 @@ static void rna_def_mloop(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Index", "Index of this loop"); RNA_def_property_ui_text(prop, "Index", "Index of this loop");
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION); prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_array(prop, 3); RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -1.0f, 1.0f); 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( RNA_def_property_ui_text(
prop, prop,
"Normal", "Normal",

View File

@@ -44,15 +44,14 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh,
static void rna_Mesh_create_normals_split(Mesh *mesh) static void rna_Mesh_create_normals_split(Mesh *mesh)
{ {
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { /* TODO: Deprecation? */
CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_SET_DEFAULT, NULL, mesh->totloop); BKE_mesh_corner_normals_ensure(mesh);
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
} }
static void rna_Mesh_free_normals_split(Mesh *mesh) static void rna_Mesh_free_normals_split(Mesh *mesh)
{ {
CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop); /* TODO: Deprecation? */
BKE_mesh_normals_tag_dirty(mesh);
} }
static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap) static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap)
@@ -69,11 +68,6 @@ static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *
CustomData_set_layer_flag(&mesh->ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY); 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); BKE_mesh_calc_loop_tangent_single(mesh, uvmap, r_looptangents, reports);
} }
@@ -225,7 +219,7 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split"); func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split");
RNA_def_function_ui_description(func, "Empty split vertex normals"); 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, RNA_def_function_ui_description(func,
"Calculate split vertex normals, which preserve sharp edges"); "Calculate split vertex normals, which preserve sharp edges");

View File

@@ -305,18 +305,14 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
} }
if (direction == MOD_DISP_DIR_CLNOR) { if (direction == MOD_DISP_DIR_CLNOR) {
CustomData *ldata = &mesh->ldata; if (CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)) {
if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) {
if (!CustomData_has_layer(ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(mesh);
}
float(*clnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(ldata, CD_NORMAL));
vert_clnors = static_cast<float(*)[3]>( vert_clnors = static_cast<float(*)[3]>(
MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__)); MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__));
BKE_mesh_normals_loop_to_vertex( BKE_mesh_normals_loop_to_vertex(verts_num,
verts_num, BKE_mesh_loops(mesh), mesh->totloop, (const float(*)[3])clnors, vert_clnors); BKE_mesh_loops(mesh),
mesh->totloop,
BKE_mesh_corner_normals_ensure(mesh),
vert_clnors);
} }
else { else {
direction = MOD_DISP_DIR_NOR; direction = MOD_DISP_DIR_NOR;

View File

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

View File

@@ -53,10 +53,11 @@ static Mesh *triangulate_mesh(Mesh *mesh,
bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0; bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0;
if (keep_clnors) { if (keep_clnors) {
BKE_mesh_calc_normals_split(mesh); CustomData_add_layer(&mesh->ldata,
/* We need that one to 'survive' to/from BMesh conversions. */ CD_NORMAL,
CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); CD_DUPLICATE,
cd_mask_extra.lmask |= CD_MASK_NORMAL; const_cast<float(*)[3]>(BKE_mesh_corner_normals_ensure(mesh)),
mesh->totloop);
} }
BMeshCreateParams bmesh_create_params{}; BMeshCreateParams bmesh_create_params{};
@@ -75,13 +76,8 @@ static Mesh *triangulate_mesh(Mesh *mesh,
if (keep_clnors) { if (keep_clnors) {
float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&result->ldata, CD_NORMAL)); 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); BKE_mesh_set_custom_normals(result, lnors);
CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop);
/* 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);
} }
edges_num = result->totedge; edges_num = result->totedge;

View File

@@ -322,14 +322,13 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Retrieve face corner normals from each mesh. It's necessary to use face corner normals /* 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 * 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 * some cases. */
* const mesh, so they are calculated here every time. */ const Span<float3> corner_normals_orig(
Array<float3> corner_normals_orig(surface_mesh_orig->totloop); reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_mesh_orig)),
Array<float3> corner_normals_eval(surface_mesh_eval->totloop); surface_mesh_orig->totloop);
BKE_mesh_calc_normals_split_ex( const Span<float3> corner_normals_eval(
surface_mesh_orig, nullptr, reinterpret_cast<float(*)[3]>(corner_normals_orig.data())); reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_mesh_eval)),
BKE_mesh_calc_normals_split_ex( surface_mesh_eval->totloop);
surface_mesh_eval, nullptr, reinterpret_cast<float(*)[3]>(corner_normals_eval.data()));
std::atomic<int> invalid_uv_count = 0; std::atomic<int> invalid_uv_count = 0;

View File

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

View File

@@ -515,7 +515,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
0, 0,
vert_normals, vert_normals,
poly_normals, poly_normals,
(const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL), BKE_mesh_corner_normals_ensure(temp_mesh),
(const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* May be nullptr. */ (const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* May be nullptr. */
/* result */ /* result */
&dm->loopData, &dm->loopData,