From a42553f986baa8f457b2b9db0b97d8e86bfca1cf Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 6 Feb 2015 20:14:18 +0100 Subject: [PATCH] Fix T43579: FBX Export shading issue (Broken normals?) Error in custom split normals work, non-autosmooth normals != vertex normals! Loops from flat faces shall take normal of their face, not their vertex. Tsst... --- .../blender/blenkernel/intern/mesh_evaluate.c | 25 +++++++++++++++---- source/blender/bmesh/intern/bmesh_mesh.c | 14 ++++++++--- .../modifiers/intern/MOD_normal_edit.c | 2 +- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index f12fdeb7a80..5520653d3de 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -1062,18 +1062,33 @@ void BKE_mesh_normals_loop_split( { /* For now this is not supported. If we do not use split normals, we do not generate anything fancy! */ - BLI_assert(use_split_normals || !(r_lnors_spacearr || r_loop_to_poly)); + BLI_assert(use_split_normals || !(r_lnors_spacearr)); if (!use_split_normals) { - /* In this case, we simply fill lnors with vnors, quite simple! + /* In this case, we simply fill lnors with vnors (or fnors for flat faces), quite simple! * Note this is done here to keep some logic and consistency in this quite complex code, * since we may want to use lnors even when mesh's 'autosmooth' is disabled (see e.g. mesh mapping code). * As usual, we could handle that on case-by-case basis, but simpler to keep it well confined here. */ - int i; + int mp_index; - for (i = 0; i < numLoops; i++) { - normal_short_to_float_v3(r_loopnors[i], mverts[mloops[i].v].no); + for (mp_index = 0; mp_index < numPolys; mp_index++) { + MPoly *mp = &mpolys[mp_index]; + int ml_index = mp->loopstart; + const int ml_index_end = ml_index + mp->totloop; + const bool is_poly_flat = ((mp->flag & ME_SMOOTH) == 0); + + for (; ml_index < ml_index_end; ml_index++) { + if (r_loop_to_poly) { + r_loop_to_poly[ml_index] = mp_index; + } + if (is_poly_flat) { + copy_v3_v3(r_loopnors[ml_index], polynors[mp_index]); + } + else { + normal_short_to_float_v3(r_loopnors[ml_index], mverts[mloops[ml_index].v].no); + } + } } return; } diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 6700ffe314e..9a2869b64ef 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -815,7 +815,8 @@ static void bm_mesh_loops_calc_normals( } } -static void bm_mesh_loops_from_vert_normals(BMesh *bm, const float (*vnos)[3], float (*r_lnos)[3]) +static void bm_mesh_loops_calc_normals_no_autosmooth( + BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float (*r_lnos)[3]) { BMIter fiter; BMFace *f_curr; @@ -825,15 +826,20 @@ static void bm_mesh_loops_from_vert_normals(BMesh *bm, const float (*vnos)[3], f if (vnos) { htype |= BM_VERT; } + if (fnos) { + htype |= BM_FACE; + } BM_mesh_elem_index_ensure(bm, htype); } BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) { BMLoop *l_curr, *l_first; + const bool is_face_flat = !BM_elem_flag_test(f_curr, BM_ELEM_SMOOTH); l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); do { - const float *no = vnos ? vnos[BM_elem_index_get(l_curr->v)] : l_curr->v->no; + 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); copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no); } while ((l_curr = l_curr->next) != l_first); @@ -863,7 +869,7 @@ void BM_mesh_loop_normals_update( } else { BLI_assert(!r_lnors_spacearr); - bm_mesh_loops_from_vert_normals(bm, NULL, r_lnos); + bm_mesh_loops_calc_normals_no_autosmooth(bm, NULL, NULL, r_lnos); } } #endif @@ -891,7 +897,7 @@ void BM_loops_calc_normal_vcos( } else { BLI_assert(!r_lnors_spacearr); - bm_mesh_loops_from_vert_normals(bm, vnos, r_lnos); + bm_mesh_loops_calc_normals_no_autosmooth(bm, vnos, fnos, r_lnos); } } diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 3bf60519530..58ef850bb4f 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -362,7 +362,7 @@ static void normalEditModifier_do(NormalEditModifierData *smd, Object *ob, Deriv if (use_current_clnors) { - dm->calcLoopNormals(dm, (me->flag & ME_AUTOSMOOTH) != 0, me->smoothresh); + dm->calcLoopNormals(dm, true, me->smoothresh); loopnors = dm->getLoopDataArray(dm, CD_NORMAL); }