diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-01-03 15:44:47 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-01-03 15:44:47 +0300 |
commit | be403891652a375e5a0ac61b493342ca6d39afb7 (patch) | |
tree | ef9637103db6d66c4b311cba5b705d575562a1f8 /source/blender/blenkernel/intern/mesh_evaluate.c | |
parent | 060fdb49d64857ff1cbf9937420ed70b10b17086 (diff) | |
parent | cbc7aa80d49e3b36c9ecc0e27ec528b34c491fc1 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_evaluate.c')
-rw-r--r-- | source/blender/blenkernel/intern/mesh_evaluate.c | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index c21c16adc85..68283b4a3aa 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -173,10 +173,11 @@ typedef struct MeshCalcNormalsData { const MLoop *mloop; MVert *mverts; float (*pnors)[3]; + float (*lnors_weighted)[3]; float (*vnors)[3]; } MeshCalcNormalsData; -static void mesh_calc_normals_poly_task_cb(void *userdata, const int pidx) +static void mesh_calc_normals_poly_cb(void *userdata, const int pidx) { MeshCalcNormalsData *data = userdata; const MPoly *mp = &data->mpolys[pidx]; @@ -184,7 +185,7 @@ static void mesh_calc_normals_poly_task_cb(void *userdata, const int pidx) BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mverts, data->pnors[pidx]); } -static void mesh_calc_normals_poly_accum_task_cb(void *userdata, const int pidx) +static void mesh_calc_normals_poly_prepare_cb(void *userdata, const int pidx) { MeshCalcNormalsData *data = userdata; const MPoly *mp = &data->mpolys[pidx]; @@ -193,7 +194,7 @@ static void mesh_calc_normals_poly_accum_task_cb(void *userdata, const int pidx) float pnor_temp[3]; float *pnor = data->pnors ? data->pnors[pidx] : pnor_temp; - float (*vnors)[3] = data->vnors; + float (*lnors_weighted)[3] = data->lnors_weighted; const int nverts = mp->totloop; float (*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, (size_t)nverts); @@ -220,42 +221,62 @@ static void mesh_calc_normals_poly_accum_task_cb(void *userdata, const int pidx) v_prev = v_curr; } if (UNLIKELY(normalize_v3(pnor) == 0.0f)) { - pnor[2] = 1.0f; /* other axis set to 0.0 */ + pnor[2] = 1.0f; /* other axes set to 0.0 */ } } /* accumulate angle weighted face normal */ - /* inline version of #accumulate_vertex_normals_poly_v3 */ + /* inline version of #accumulate_vertex_normals_poly_v3, + * split between this threaded callback and #mesh_calc_normals_poly_accum_cb. */ { const float *prev_edge = edgevecbuf[nverts - 1]; for (i = 0; i < nverts; i++) { + const int lidx = mp->loopstart + i; const float *cur_edge = edgevecbuf[i]; /* calculate angle between the two poly edges incident on * this vertex */ const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); - /* accumulate */ - for (int k = 3; k--; ) { - atomic_add_and_fetch_fl(&vnors[ml[i].v][k], pnor[k] * fac); - } + /* Store for later accumulation */ + mul_v3_v3fl(lnors_weighted[lidx], pnor, fac); + prev_edge = cur_edge; } } +} + +static void mesh_calc_normals_poly_accum_cb(void *userdata, const int lidx) +{ + MeshCalcNormalsData *data = userdata; + + add_v3_v3(data->vnors[data->mloop[lidx].v], data->lnors_weighted[lidx]); +} + +static void mesh_calc_normals_poly_finalize_cb(void *userdata, const int vidx) +{ + MeshCalcNormalsData *data = userdata; + + MVert *mv = &data->mverts[vidx]; + float *no = data->vnors[vidx]; + + if (UNLIKELY(normalize_v3(no) == 0.0f)) { + /* following Mesh convention; we use vertex coordinate itself for normal in this case */ + normalize_v3_v3(no, mv->co); + } + normal_float_to_short_v3(mv->no, no); } void BKE_mesh_calc_normals_poly( MVert *mverts, float (*r_vertnors)[3], int numVerts, const MLoop *mloop, const MPoly *mpolys, - int UNUSED(numLoops), int numPolys, float (*r_polynors)[3], + int numLoops, int numPolys, float (*r_polynors)[3], const bool only_face_normals) { + const bool do_threaded = (numPolys > BKE_MESH_OMP_LIMIT); float (*pnors)[3] = r_polynors; - float (*vnors)[3] = r_vertnors; - bool free_vnors = false; - int i; if (only_face_normals) { BLI_assert((pnors != NULL) || (numPolys == 0)); @@ -265,10 +286,14 @@ void BKE_mesh_calc_normals_poly( .mpolys = mpolys, .mloop = mloop, .mverts = mverts, .pnors = pnors, }; - BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_task_cb, (numPolys > BKE_MESH_OMP_LIMIT)); + BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_cb, do_threaded); return; } + float (*vnors)[3] = r_vertnors; + float (*lnors_weighted)[3] = MEM_mallocN(sizeof(*lnors_weighted) * (size_t)numLoops, __func__); + bool free_vnors = false; + /* first go through and calculate normals for all the polys */ if (vnors == NULL) { vnors = MEM_callocN(sizeof(*vnors) * (size_t)numVerts, __func__); @@ -279,26 +304,23 @@ void BKE_mesh_calc_normals_poly( } MeshCalcNormalsData data = { - .mpolys = mpolys, .mloop = mloop, .mverts = mverts, .pnors = pnors, .vnors = vnors, + .mpolys = mpolys, .mloop = mloop, .mverts = mverts, + .pnors = pnors, .lnors_weighted = lnors_weighted, .vnors = vnors }; - BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_accum_task_cb, (numPolys > BKE_MESH_OMP_LIMIT)); - - for (i = 0; i < numVerts; i++) { - MVert *mv = &mverts[i]; - float *no = vnors[i]; + /* Compute poly normals, and prepare weighted loop normals. */ + BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, do_threaded); - if (UNLIKELY(normalize_v3(no) == 0.0f)) { - /* following Mesh convention; we use vertex coordinate itself for normal in this case */ - normalize_v3_v3(no, mv->co); - } + /* Actually accumulate weighted loop normals into vertex ones. */ + BLI_task_parallel_range(0, numLoops, &data, mesh_calc_normals_poly_accum_cb, do_threaded); - normal_float_to_short_v3(mv->no, no); - } + /* Normalize and validate computed vertex normals. */ + BLI_task_parallel_range(0, numVerts, &data, mesh_calc_normals_poly_finalize_cb, do_threaded); if (free_vnors) { MEM_freeN(vnors); } + MEM_freeN(lnors_weighted); } void BKE_mesh_calc_normals(Mesh *mesh) |