Cleanup: Use C++ Span, float3 for BMesh normals API

This commit is contained in:
Hans Goudey 2024-04-02 17:04:13 -04:00
parent 768c68f19b
commit a4b4f0116c
6 changed files with 119 additions and 150 deletions

View File

@ -36,10 +36,7 @@ void BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMe
int i;
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
BM_elem_index_set(efa, i); /* set_inline */
BM_face_calc_normal_vcos(bm,
efa,
emd.face_normals[i],
reinterpret_cast<const float(*)[3]>(emd.vert_positions.data()));
BM_face_calc_normal_vcos(bm, efa, emd.face_normals[i], emd.vert_positions);
}
bm->elem_index_dirty &= ~BM_FACE;
}
@ -57,10 +54,7 @@ void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMe
emd.vert_normals.reinitialize(bm->totvert);
BM_mesh_elem_index_ensure(bm, BM_FACE);
BM_verts_calc_normal_vcos(bm,
reinterpret_cast<const float(*)[3]>(emd.face_normals.data()),
reinterpret_cast<const float(*)[3]>(emd.vert_positions.data()),
reinterpret_cast<float(*)[3]>(emd.vert_normals.data()));
BM_verts_calc_normal_vcos(bm, emd.face_normals, emd.vert_positions, emd.vert_normals);
}
void BKE_editmesh_cache_ensure_face_centers(BMEditMesh &em, blender::bke::EditMeshData &emd)

View File

@ -14,6 +14,7 @@
#include "DNA_scene_types.h"
#include "BLI_array.hh"
#include "BLI_bitmap.h"
#include "BLI_linklist_stack.h"
#include "BLI_math_base.hh"
@ -29,15 +30,18 @@
#include "intern/bmesh_private.hh"
using blender::Array;
using blender::float3;
using blender::MutableSpan;
using blender::Span;
/* Smooth angle to use when tagging edges is disabled entirely. */
#define EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS -FLT_MAX
static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
static void bm_edge_tag_from_smooth_and_set_sharp(Span<float3> fnos,
BMEdge *e,
const float split_angle_cos);
static void bm_edge_tag_from_smooth(const float (*fnos)[3],
BMEdge *e,
const float split_angle_cos);
static void bm_edge_tag_from_smooth(Span<float3> fnos, BMEdge *e, const float split_angle_cos);
/* -------------------------------------------------------------------- */
/** \name Update Vertex & Face Normals
@ -53,11 +57,11 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3],
struct BMVertsCalcNormalsWithCoordsData {
/* Read-only data. */
const float (*fnos)[3];
const float (*vcos)[3];
Span<float3> fnos;
Span<float3> vcos;
/* Write data. */
float (*vnos)[3];
MutableSpan<float3> vnos;
};
BLI_INLINE void bm_vert_calc_normals_accum_loop(const BMLoop *l_iter,
@ -204,21 +208,21 @@ static void bm_vert_calc_normals_with_coords_cb(void *userdata,
}
static void bm_mesh_verts_calc_normals(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],
float (*vnos)[3])
const Span<float3> fnos,
const Span<float3> vcos,
MutableSpan<float3> vnos)
{
BM_mesh_elem_index_ensure(bm, BM_FACE | ((vnos || vcos) ? BM_VERT : 0));
BM_mesh_elem_index_ensure(bm, BM_FACE | ((!vnos.is_empty() || !vcos.is_empty()) ? BM_VERT : 0));
TaskParallelSettings settings;
BLI_parallel_mempool_settings_defaults(&settings);
settings.use_threading = bm->totvert >= BM_THREAD_LIMIT;
if (vcos == nullptr) {
if (vcos.is_empty()) {
BM_iter_parallel(bm, BM_VERTS_OF_MESH, bm_vert_calc_normals_cb, nullptr, &settings);
}
else {
BLI_assert(!ELEM(nullptr, fnos, vnos));
BLI_assert(!fnos.is_empty() || !vnos.is_empty());
BMVertsCalcNormalsWithCoordsData data{};
data.fnos = fnos;
data.vcos = vcos;
@ -248,7 +252,7 @@ void BM_mesh_normals_update_ex(BMesh *bm, const BMeshNormalsUpdate_Params *param
}
/* Add weighted face normals to vertices, and normalize vert normals. */
bm_mesh_verts_calc_normals(bm, nullptr, nullptr, nullptr);
bm_mesh_verts_calc_normals(bm, {}, {}, {});
}
void BM_mesh_normals_update(BMesh *bm)
@ -321,9 +325,9 @@ void BM_mesh_normals_update_with_partial(BMesh *bm, const BMPartialUpdate *bmpin
* \{ */
void BM_verts_calc_normal_vcos(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],
float (*vnos)[3])
const Span<float3> fnos,
const Span<float3> vcos,
MutableSpan<float3> vnos)
{
/* Add weighted face normals to vertices, and normalize vert normals. */
bm_mesh_verts_calc_normals(bm, fnos, vcos, vnos);
@ -374,7 +378,7 @@ void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges)
* Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normal_vcos
*/
static void bm_mesh_edges_sharp_tag(BMesh *bm,
const float (*fnos)[3],
const Span<float3> fnos,
float split_angle_cos,
const bool do_sharp_edges_tag)
{
@ -382,7 +386,7 @@ static void bm_mesh_edges_sharp_tag(BMesh *bm,
BMEdge *e;
int i;
if (fnos) {
if (!fnos.is_empty()) {
BM_mesh_elem_index_ensure(bm, BM_FACE);
}
@ -413,7 +417,7 @@ void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
return;
}
bm_mesh_edges_sharp_tag(bm, nullptr, cosf(split_angle), true);
bm_mesh_edges_sharp_tag(bm, {}, cosf(split_angle), true);
}
/** \} */
@ -467,8 +471,8 @@ bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
* \return The number of loops that were handled (for early exit when all have been handled).
*/
static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
const bool has_clnors,
@ -477,12 +481,12 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
/* Iterate. */
BMLoop *l_curr,
/* Result. */
float (*r_lnos)[3],
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr)
{
BLI_assert((bm->elem_index_dirty & BM_LOOP) == 0);
BLI_assert((fnos == nullptr) || ((bm->elem_index_dirty & BM_FACE) == 0));
BLI_assert((vcos == nullptr) || ((bm->elem_index_dirty & BM_VERT) == 0));
BLI_assert(fnos.is_empty() || ((bm->elem_index_dirty & BM_FACE) == 0));
BLI_assert(vcos.is_empty() || ((bm->elem_index_dirty & BM_VERT) == 0));
UNUSED_VARS_NDEBUG(bm);
int handled = 0;
@ -514,7 +518,8 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
* this vertex just takes its face normal.
*/
const int l_curr_index = BM_elem_index_get(l_curr);
const float *no = fnos ? fnos[BM_elem_index_get(l_curr->f)] : l_curr->f->no;
const float3 no = !fnos.is_empty() ? fnos[BM_elem_index_get(l_curr->f)] :
float3(l_curr->f->no);
copy_v3_v3(r_lnos[l_curr_index], no);
/* If needed, generate this (simple!) lnor space. */
@ -524,11 +529,12 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
{
const BMVert *v_pivot = l_curr->v;
const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
const float3 co_pivot = !vcos.is_empty() ? vcos[BM_elem_index_get(v_pivot)] :
float3(v_pivot->co);
const BMVert *v_1 = l_curr->next->v;
const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co;
const float3 co_1 = !vcos.is_empty() ? vcos[BM_elem_index_get(v_1)] : float3(v_1->co);
const BMVert *v_2 = l_curr->prev->v;
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
const float3 co_2 = !vcos.is_empty() ? vcos[BM_elem_index_get(v_2)] : float3(v_2->co);
BLI_assert(v_1 == BM_edge_other_vert(l_curr->e, v_pivot));
BLI_assert(v_2 == BM_edge_other_vert(l_curr->prev->e, v_pivot));
@ -586,7 +592,8 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
int clnors_count = 0;
bool clnors_invalid = false;
const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
const float3 co_pivot = !vcos.is_empty() ? vcos[BM_elem_index_get(v_pivot)] :
float3(v_pivot->co);
MLoopNorSpace *lnor_space = r_lnors_spacearr ? BKE_lnor_space_create(r_lnors_spacearr) :
nullptr;
@ -601,7 +608,7 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
* then we can just reuse old current one! */
{
const BMVert *v_2 = lfan_pivot->next->v;
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
const float3 co_2 = !vcos.is_empty() ? vcos[BM_elem_index_get(v_2)] : float3(v_2->co);
BLI_assert(v_2 == BM_edge_other_vert(e_next, v_pivot));
@ -633,7 +640,7 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
*/
{
const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot);
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
const float3 co_2 = !vcos.is_empty() ? vcos[BM_elem_index_get(v_2)] : float3(v_2->co);
sub_v3_v3v3(vec_next, co_2, co_pivot);
normalize_v3(vec_next);
@ -644,7 +651,7 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
/* Calculate angle between the two face edges incident on this vertex. */
const BMFace *f = lfan_pivot->f;
const float fac = blender::math::safe_acos_approx(dot_v3v3(vec_next, vec_curr));
const float *no = fnos ? fnos[BM_elem_index_get(f)] : f->no;
const float3 no = !fnos.is_empty() ? fnos[BM_elem_index_get(f)] : float3(f->no);
/* Accumulate */
madd_v3_v3fl(lnor, no, fac);
@ -795,16 +802,18 @@ BLI_INLINE bool bm_edge_is_smooth_no_angle_test(const BMEdge *e,
BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH));
}
static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const float split_angle_cos)
static void bm_edge_tag_from_smooth(const Span<float3> fnos,
BMEdge *e,
const float split_angle_cos)
{
BLI_assert(e->l != nullptr);
BMLoop *l_a = e->l, *l_b = l_a->radial_next;
bool is_smooth = false;
if (bm_edge_is_smooth_no_angle_test(e, l_a, l_b)) {
if (split_angle_cos != -1.0f) {
const float dot = (fnos == nullptr) ? dot_v3v3(l_a->f->no, l_b->f->no) :
dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
fnos[BM_elem_index_get(l_b->f)]);
const float dot = fnos.is_empty() ? dot_v3v3(l_a->f->no, l_b->f->no) :
dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
fnos[BM_elem_index_get(l_b->f)]);
if (dot >= split_angle_cos) {
is_smooth = true;
}
@ -834,7 +843,7 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const flo
* \note This doesn't have the same atomic requirement as #bm_edge_tag_from_smooth
* since it isn't run from multiple threads at once.
*/
static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
static void bm_edge_tag_from_smooth_and_set_sharp(const Span<float3> fnos,
BMEdge *e,
const float split_angle_cos)
{
@ -843,9 +852,9 @@ static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
bool is_smooth = false;
if (bm_edge_is_smooth_no_angle_test(e, l_a, l_b)) {
if (split_angle_cos != -1.0f) {
const float dot = (fnos == nullptr) ? dot_v3v3(l_a->f->no, l_b->f->no) :
dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
fnos[BM_elem_index_get(l_b->f)]);
const float dot = fnos.is_empty() ? dot_v3v3(l_a->f->no, l_b->f->no) :
dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
fnos[BM_elem_index_get(l_b->f)]);
if (dot >= split_angle_cos) {
is_smooth = true;
}
@ -871,9 +880,9 @@ static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
*/
static void bm_mesh_loops_calc_normals_for_vert_with_clnors(
BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
const bool do_rebuild,
@ -993,9 +1002,9 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(
*/
static void bm_mesh_loops_calc_normals_for_vert_without_clnors(
BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
const bool do_rebuild,
const float split_angle_cos,
/* TLS */
@ -1070,9 +1079,9 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors(
* we could add a low-level API flag for this, see #BM_ELEM_API_FLAG_ENABLE and friends.
*/
static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1091,7 +1100,7 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
{
char htype = 0;
if (vcos) {
if (!vcos.is_empty()) {
htype |= BM_VERT;
}
/* Face/Loop indices are set inline below. */
@ -1164,8 +1173,8 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
struct BMLoopsCalcNormalsWithCoordsData {
/* Read-only data. */
const float (*fnos)[3];
const float (*vcos)[3];
Span<float3> vcos;
Span<float3> fnos;
BMesh *bm;
const short (*clnors_data)[2];
int cd_loop_clnors_offset;
@ -1173,7 +1182,7 @@ struct BMLoopsCalcNormalsWithCoordsData {
float split_angle_cos;
/* Output. */
float (*r_lnos)[3];
MutableSpan<float3> r_lnos;
MLoopNorSpaceArray *r_lnors_spacearr;
};
@ -1272,9 +1281,9 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors_fn(
}
static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1286,10 +1295,10 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm,
{
char htype = BM_LOOP;
if (vcos) {
if (!vcos.is_empty()) {
htype |= BM_VERT;
}
if (fnos) {
if (!fnos.is_empty()) {
htype |= BM_FACE;
}
/* Face/Loop indices are set inline below. */
@ -1347,9 +1356,9 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm,
}
static void bm_mesh_loops_calc_normals(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1572,8 +1581,8 @@ static void bm_mesh_loops_assign_normal_data(BMesh *bm,
* instead, depending on the do_split_fans parameter.
*/
static void bm_mesh_loops_custom_normals_set(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*r_clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1584,8 +1593,7 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm,
BMFace *f;
BMLoop *l;
BMIter liter, fiter;
float(*cur_lnors)[3] = static_cast<float(*)[3]>(
MEM_mallocN(sizeof(*cur_lnors) * bm->totloop, __func__));
Array<float3> cur_lnors(bm->totloop);
BKE_lnor_spacearr_clear(r_lnors_spacearr);
@ -1653,27 +1661,25 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm,
bm_mesh_loops_assign_normal_data(
bm, r_lnors_spacearr, r_clnors_data, cd_loop_clnors_offset, custom_lnors);
MEM_freeN(cur_lnors);
if (custom_lnors != new_lnors) {
MEM_freeN(custom_lnors);
}
}
static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm,
const float (*vnos)[3],
const float (*fnos)[3],
float (*r_lnos)[3])
const Span<float3> vnos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos)
{
BMIter fiter;
BMFace *f_curr;
{
char htype = BM_LOOP;
if (vnos) {
if (!vnos.is_empty()) {
htype |= BM_VERT;
}
if (fnos) {
if (!fnos.is_empty()) {
htype |= BM_FACE;
}
BM_mesh_elem_index_ensure(bm, htype);
@ -1685,8 +1691,10 @@ static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm,
l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
do {
const float *no = is_face_flat ? (fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no) :
(vnos ? vnos[BM_elem_index_get(l_curr->v)] : l_curr->v->no);
const float3 no = is_face_flat ? (!fnos.is_empty() ? fnos[BM_elem_index_get(f_curr)] :
float3(f_curr->no)) :
(!vnos.is_empty() ? vnos[BM_elem_index_get(l_curr->v)] :
float3(l_curr->v->no));
copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no);
} while ((l_curr = l_curr->next) != l_first);
@ -1694,11 +1702,11 @@ static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm,
}
void BM_loops_calc_normal_vcos(BMesh *bm,
const float (*vcos)[3],
const float (*vnos)[3],
const float (*fnos)[3],
const Span<float3> vcos,
const Span<float3> vnos,
const Span<float3> fnos,
const bool use_split_normals,
float (*r_lnos)[3],
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1728,7 +1736,7 @@ void BM_loops_calc_normal_vcos(BMesh *bm,
/** \name Loop Normal Space API
* \{ */
void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3])
void BM_lnorspacearr_store(BMesh *bm, MutableSpan<float3> r_lnors)
{
BLI_assert(bm->lnor_spacearr != nullptr);
@ -1738,16 +1746,8 @@ void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3])
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(bm,
nullptr,
nullptr,
nullptr,
true,
r_lnors,
bm->lnor_spacearr,
nullptr,
cd_loop_clnors_offset,
false);
BM_loops_calc_normal_vcos(
bm, {}, {}, {}, true, r_lnors, bm->lnor_spacearr, nullptr, cd_loop_clnors_offset, false);
bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
}
@ -1834,10 +1834,8 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
BMLoop *l;
BMIter fiter, liter;
float(*r_lnors)[3] = static_cast<float(*)[3]>(
MEM_callocN(sizeof(*r_lnors) * bm->totloop, __func__));
float(*oldnors)[3] = static_cast<float(*)[3]>(
preserve_clnor ? MEM_mallocN(sizeof(*oldnors) * bm->totloop, __func__) : nullptr);
Array<float3> r_lnors(bm->totloop, float3(0));
Array<float3> oldnors(preserve_clnor ? bm->totloop : 0, float3(0));
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
@ -1865,17 +1863,8 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
BKE_lnor_spacearr_clear(bm->lnor_spacearr);
}
BM_loops_calc_normal_vcos(bm,
nullptr,
nullptr,
nullptr,
true,
r_lnors,
bm->lnor_spacearr,
nullptr,
cd_loop_clnors_offset,
true);
MEM_freeN(r_lnors);
BM_loops_calc_normal_vcos(
bm, {}, {}, {}, true, r_lnors, bm->lnor_spacearr, nullptr, cd_loop_clnors_offset, true);
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@ -1894,7 +1883,6 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
}
}
MEM_SAFE_FREE(oldnors);
bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
#ifndef NDEBUG
@ -1908,12 +1896,8 @@ void BM_lnorspace_update(BMesh *bm)
bm->lnor_spacearr = MEM_cnew<MLoopNorSpaceArray>(__func__);
}
if (bm->lnor_spacearr->lspacearr == nullptr) {
float(*lnors)[3] = static_cast<float(*)[3]>(
MEM_callocN(sizeof(*lnors) * bm->totloop, __func__));
Array<float3> lnors(bm->totloop, float3(0));
BM_lnorspacearr_store(bm, lnors);
MEM_freeN(lnors);
}
else if (bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL)) {
BM_lnorspace_rebuild(bm, false);
@ -1945,9 +1929,9 @@ void BM_lnorspace_err(BMesh *bm)
BKE_lnor_spacearr_init(temp, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
float(*lnors)[3] = static_cast<float(*)[3]>(MEM_callocN(sizeof(*lnors) * bm->totloop, __func__));
Array<float3> lnors(bm->totloop, float3(0));
BM_loops_calc_normal_vcos(
bm, nullptr, nullptr, nullptr, true, lnors, temp, nullptr, cd_loop_clnors_offset, true);
bm, {}, {}, {}, true, lnors, temp, nullptr, cd_loop_clnors_offset, true);
for (int i = 0; i < bm->totloop; i++) {
int j = 0;
@ -1969,7 +1953,6 @@ void BM_lnorspace_err(BMesh *bm)
}
BKE_lnor_spacearr_free(temp);
MEM_freeN(temp);
MEM_freeN(lnors);
BLI_assert(clear);
bm->spacearr_dirty &= ~BM_SPACEARR_DIRTY_ALL;
@ -2268,8 +2251,8 @@ void BM_custom_loop_normals_from_vector_layer(BMesh *bm, bool add_sharp_edges)
}
bm_mesh_loops_custom_normals_set(bm,
nullptr,
nullptr,
{},
{},
bm->lnor_spacearr,
nullptr,
cd_custom_normal_offset,

View File

@ -43,9 +43,9 @@ void BM_mesh_normals_update_with_partial(BMesh *bm, const BMPartialUpdate *bmpin
* using given vertex coordinates (vcos) and polygon normals (fnos).
*/
void BM_verts_calc_normal_vcos(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],
float (*vnos)[3]);
blender::Span<blender::float3> fnos,
blender::Span<blender::float3> vcos,
blender::MutableSpan<blender::float3> vnos);
/**
* \brief BMesh Compute Loop Normals from/to external data.
*
@ -54,11 +54,11 @@ void BM_verts_calc_normal_vcos(BMesh *bm,
* (splitting edges).
*/
void BM_loops_calc_normal_vcos(BMesh *bm,
const float (*vcos)[3],
const float (*vnos)[3],
const float (*fnos)[3],
blender::Span<blender::float3> vcos,
blender::Span<blender::float3> vnos,
blender::Span<blender::float3> fnos,
bool use_split_normals,
float (*r_lnos)[3],
blender::MutableSpan<blender::float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2],
int cd_loop_clnors_offset,
@ -70,7 +70,7 @@ void BM_loops_calc_normal_vcos(BMesh *bm,
* and yet we need to walk them once, and only once.
*/
bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr);
void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3]);
void BM_lnorspacearr_store(BMesh *bm, blender::MutableSpan<blender::float3> r_lnors);
void BM_lnorspace_invalidate(BMesh *bm, bool do_invalidate_all);
void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor);
/**

View File

@ -31,6 +31,9 @@
#include "intern/bmesh_private.hh"
using blender::float3;
using blender::Span;
/**
* \brief COMPUTE POLY NORMAL (BMFace)
*
@ -66,7 +69,7 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3])
*/
static float bm_face_calc_poly_normal_vertex_cos(const BMFace *f,
float r_no[3],
float const (*vertexCos)[3])
const Span<float3> vertexCos)
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter = l_first;
@ -742,7 +745,7 @@ void BM_face_normal_update(BMFace *f)
float BM_face_calc_normal_vcos(const BMesh *bm,
const BMFace *f,
float r_no[3],
float const (*vertexCos)[3])
const Span<float3> vertexCos)
{
BMLoop *l;

View File

@ -46,7 +46,7 @@ float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
float BM_face_calc_normal_vcos(const BMesh *bm,
const BMFace *f,
float r_no[3],
float const (*vertexCos)[3]) ATTR_NONNULL();
blender::Span<blender::float3> vertexCos) ATTR_NONNULL();
/**
* Calculate a normal from a vertex cloud.

View File

@ -501,25 +501,14 @@ void mesh_render_data_update_normals(MeshRenderData &mr, const eMRDataType data_
mr.normals_domain == bke::MeshNormalDomain::Corner) ||
(data_flag & MR_DATA_TAN_LOOP_NOR))
{
const float(*vert_coords)[3] = nullptr;
const float(*vert_normals)[3] = nullptr;
const float(*face_normals)[3] = nullptr;
if (mr.edit_data && !mr.edit_data->vert_positions.is_empty()) {
vert_coords = reinterpret_cast<const float(*)[3]>(mr.bm_vert_coords.data());
vert_normals = reinterpret_cast<const float(*)[3]>(mr.bm_vert_normals.data());
face_normals = reinterpret_cast<const float(*)[3]>(mr.bm_face_normals.data());
}
mr.bm_loop_normals.reinitialize(mr.corners_num);
const int clnors_offset = CustomData_get_offset(&mr.bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(mr.bm,
vert_coords,
vert_normals,
face_normals,
mr.bm_vert_coords,
mr.bm_vert_normals,
mr.bm_face_normals,
true,
reinterpret_cast<float(*)[3]>(mr.bm_loop_normals.data()),
mr.bm_loop_normals,
nullptr,
nullptr,
clnors_offset,