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_corner_normals_ensure(const struct Mesh *mesh))[3];
/**
* 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_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.
@@ -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_corner_normals_are_dirty(const struct Mesh *mesh);
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly,
const struct MLoop *loopstart,
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);
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
* #BKE_mesh_normals_loop_custom_set().

View File

@@ -157,8 +157,10 @@ struct MeshRuntime {
*/
bool vert_normals_dirty = true;
bool poly_normals_dirty = true;
bool corner_normals_dirty = false;
float (*vert_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

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 {
@@ -559,13 +559,6 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
* which deals with drawing differently. */
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
* 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

@@ -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);
}
@@ -1777,65 +1763,6 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *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 **** */
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. */
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

@@ -101,6 +101,7 @@ void BKE_mesh_normals_tag_dirty(Mesh *mesh)
{
mesh->runtime->vert_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]
@@ -139,6 +140,18 @@ void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
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)
{
return mesh->runtime->vert_normals_dirty;
@@ -499,6 +512,65 @@ 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->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)
{
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(*loop_nors_src)[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;
@@ -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);
}
if (need_lnors_dst) {
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>(
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);
loop_nors_dst = BKE_mesh_corner_normals_ensure(mesh_dst);
}
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) {
poly_nors_src = BKE_mesh_poly_normals_ensure(me_src);
}
if (need_lnors_src) {
loop_nors_src = static_cast<const float(*)[3]>(
CustomData_get_layer(&me_src->ldata, CD_NORMAL));
BLI_assert(loop_nors_src != nullptr);
}
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,14 @@ 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);
}
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)) {
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

@@ -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);
}
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
mr->loop_normals = static_cast<float(*)[3]>(
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);
mr->loop_normals = BKE_mesh_corner_normals_ensure(mr->me);
}
}
else {
@@ -403,8 +384,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
poly_normals = mr->bm_poly_normals;
}
mr->loop_normals = static_cast<float(*)[3]>(
MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__));
mr->bm_loop_normals = static_cast<float(*)[3]>(
MEM_mallocN(sizeof(*mr->bm_loop_normals) * mr->loop_len, __func__));
const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(mr->bm,
vert_coords,
@@ -412,11 +393,12 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
poly_normals,
is_auto_smooth,
split_angle,
mr->loop_normals,
mr->bm_loop_normals,
nullptr,
nullptr,
clnors_offset,
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)
{
MEM_SAFE_FREE(mr->loop_normals);
MEM_SAFE_FREE(mr->bm_loop_normals);
/* Loose geometry are owned by #MeshBufferCache. */
mr->ledges = nullptr;

View File

@@ -91,7 +91,8 @@ struct MeshRenderData {
const bool *select_vert;
const bool *select_edge;
const bool *select_poly;
float (*loop_normals)[3];
const float (*loop_normals)[3];
float (*bm_loop_normals)[3];
int *lverts, *ledges;
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) {
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

@@ -621,14 +621,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

@@ -181,12 +181,6 @@ int OBJMesh::ith_smooth_group(const int poly_index) const
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)
{
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);
loop_to_normal_index_.resize(export_mesh_->totloop);
loop_to_normal_index_.fill(-1);
const float(*lnors)[3] = static_cast<const float(*)[3]>(
CustomData_get_layer(&export_mesh_->ldata, CD_NORMAL));
/* TODO: Only retrieve when necessary. */
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(export_mesh_);
for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) {
const MPoly &mpoly = mesh_polys_[poly_index];
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;
void ensure_mesh_normals() const;
/**
* Calculate smooth groups of a smooth-shaded object.
* \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) {
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. */

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) {
@@ -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)
{
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)
@@ -2458,9 +2434,10 @@ static void rna_def_mloop(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Index", "Index of this loop");
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_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,14 @@ 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: Deprecation? */
BKE_mesh_corner_normals_ensure(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)
@@ -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);
}
/* 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);
}
@@ -225,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

@@ -305,18 +305,14 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
}
if (direction == MOD_DISP_DIR_CLNOR) {
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] = static_cast<float(*)[3]>(CustomData_get_layer(ldata, CD_NORMAL));
if (CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)) {
vert_clnors = static_cast<float(*)[3]>(
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);
BKE_mesh_normals_loop_to_vertex(verts_num,
BKE_mesh_loops(mesh),
mesh->totloop,
BKE_mesh_corner_normals_ensure(mesh),
vert_clnors);
}
else {
direction = MOD_DISP_DIR_NOR;

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

@@ -53,10 +53,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);
cd_mask_extra.lmask |= CD_MASK_NORMAL;
CustomData_add_layer(&mesh->ldata,
CD_NORMAL,
CD_DUPLICATE,
const_cast<float(*)[3]>(BKE_mesh_corner_normals_ensure(mesh)),
mesh->totloop);
}
BMeshCreateParams bmesh_create_params{};
@@ -75,13 +76,8 @@ static Mesh *triangulate_mesh(Mesh *mesh,
if (keep_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);
/* 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);
CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop);
}
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
* 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

@@ -483,15 +483,12 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
const TSpace *tspace = nullptr;
const float(*loop_normals)[3] = nullptr;
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, nullptr, 0);
BKE_mesh_calc_loop_tangents(me_eval, true, NULL, 0);
tspace = static_cast<const TSpace *>(CustomData_get_layer(&me_eval->ldata, CD_TANGENT));
BLI_assert(tspace);
loop_normals = static_cast<const float(*)[3]>(
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

@@ -515,7 +515,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
0,
vert_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. */
/* result */
&dm->loopData,