diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2014-02-12 23:48:09 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2014-02-12 23:48:09 +0400 |
commit | 70905a6e02a05b650acfb894265b3a2d201f193b (patch) | |
tree | 3dc7ae6303823cabc6364c059939f7fc0406f6f8 /source/blender | |
parent | f9a60ecacd9754f6673e2dc9775d6bb1cb89033e (diff) |
Fix Editderivedmeshes vertices normals computation.
Those derived meshes (used in Edit mode) were using simple sum of neighbor poly normals to get vertex normals,
while everywhere else in Blender we use weighted sum of such poly normals.
Patch: D311
Reviewed and enhanced by Campbell, thanks!
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/editderivedmesh.c | 25 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.c | 159 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.h | 1 |
3 files changed, 112 insertions, 73 deletions
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 308838c3b8f..0b89e6c0960 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -92,35 +92,16 @@ static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm) const float (*vertexCos)[3], (*polyNos)[3]; float (*vertexNos)[3]; - BMFace *efa; - BMVert *eve; - BMIter fiter; - BMIter viter; - int i; - - vertexCos = bmdm->vertexCos; - vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__); - /* calculate vertex normals from poly normals */ emDM_ensurePolyNormals(bmdm); BM_mesh_elem_index_ensure(bm, BM_FACE); - vertexCos = bmdm->vertexCos; polyNos = bmdm->polyNos; + vertexCos = bmdm->vertexCos; + vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__); - BM_ITER_MESH_INDEX (eve, &viter, bm, BM_VERTS_OF_MESH, i) { - float *no = vertexNos[i]; - BM_ITER_ELEM (efa, &fiter, eve, BM_FACES_OF_VERT) { - add_v3_v3(no, polyNos[BM_elem_index_get(efa)]); - } - - /* following Mesh convention; we use vertex coordinate itself - * for normal in this case */ - if (UNLIKELY(normalize_v3(no) == 0.0f)) { - normalize_v3_v3(no, vertexCos[i]); - } - } + BM_verts_calc_normal_vcos(bm, polyNos, vertexCos, vertexNos); bmdm->vertexNos = (const float (*)[3])vertexNos; } diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 175ef21953d..7a0c12793f3 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -272,71 +272,55 @@ void BM_mesh_free(BMesh *bm) } /** - * \brief BMesh Compute Normals - * - * Updates the normals of a mesh. + * Helpers for #BM_mesh_normals_update and #BM_verts_calc_normal_vcos */ -void BM_mesh_normals_update(BMesh *bm) +static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const float (*vcos)[3]) { - float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__); + BMIter eiter; + BMEdge *e; + int index; -#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) - { -#pragma omp section - { - /* calculate all face normals */ - BMIter fiter; - BMFace *f; + if (vcos) { + BM_mesh_elem_index_ensure(bm, BM_VERT); + } - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - BM_face_normal_update(f); - } - } -#pragma omp section - { - /* Zero out vertex normals */ - BMIter viter; - BMVert *v; - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - zero_v3(v->no); - } + BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, index) { + BM_elem_index_set(e, index); /* set_inline */ + + if (e->l) { + const float *v1_co = vcos ? vcos[BM_elem_index_get(e->v1)] : e->v1->co; + const float *v2_co = vcos ? vcos[BM_elem_index_get(e->v2)] : e->v2->co; + sub_v3_v3v3(edgevec[index], v2_co, v1_co); + normalize_v3(edgevec[index]); } -#pragma omp section - { - /* compute normalized direction vectors for each edge. directions will be - * used below for calculating the weights of the face normals on the vertex - * normals */ - BMIter eiter; - BMEdge *e; - int index; - BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, index) { - BM_elem_index_set(e, index); /* set_inline */ - - if (e->l) { - sub_v3_v3v3(edgevec[index], e->v2->co, e->v1->co); - normalize_v3(edgevec[index]); - } - else { - /* the edge vector will not be needed when the edge has no radial */ - } - } - bm->elem_index_dirty &= ~BM_EDGE; + else { + /* the edge vector will not be needed when the edge has no radial */ } } - /* end omp */ + bm->elem_index_dirty &= ~BM_EDGE; +} +static void bm_mesh_verts_calc_normals(BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3], + const float (*vcos)[3], float (*vnos)[3]) +{ + BM_mesh_elem_index_ensure(bm, (vnos) ? (BM_EDGE | BM_VERT) : BM_EDGE); /* add weighted face normals to vertices */ { BMIter fiter; BMFace *f; - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + int i; + + BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { BMLoop *l_first, *l_iter; + const float *f_no = fnos ? fnos[i] : f->no; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const float *e1diff, *e2diff; float dotprod; float fac; + float *v_no = vnos ? vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no; /* calculate the dot product of the two edges that * meet at the loop's vertex */ @@ -354,10 +338,9 @@ void BM_mesh_normals_update(BMesh *bm) fac = saacos(-dotprod); /* accumulate weighted face normal into the vertex's normal */ - madd_v3_v3fl(l_iter->v->no, f->no, fac); + madd_v3_v3fl(v_no, f_no, fac); } while ((l_iter = l_iter->next) != l_first); } - MEM_freeN(edgevec); } @@ -365,13 +348,87 @@ void BM_mesh_normals_update(BMesh *bm) { BMIter viter; BMVert *v; + int i; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + float *v_no = vnos ? vnos[i] : v->no; + if (UNLIKELY(normalize_v3(v_no) == 0.0f)) { + const float *v_co = vcos ? vcos[i] : v->co; + normalize_v3_v3(v_no, v_co); + } + } + } +} - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - if (UNLIKELY(normalize_v3(v->no) == 0.0f)) { - normalize_v3_v3(v->no, v->co); +/** + * \brief BMesh Compute Normals + * + * Updates the normals of a mesh. + */ +void BM_mesh_normals_update(BMesh *bm) +{ + float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__); + +#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) + { +#pragma omp section + { + /* calculate all face normals */ + BMIter fiter; + BMFace *f; + int i; + + BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { + BM_elem_index_set(f, i); /* set_inline */ + BM_face_normal_update(f); + } + bm->elem_index_dirty &= ~BM_FACE; + } +#pragma omp section + { + /* Zero out vertex normals */ + BMIter viter; + BMVert *v; + int i; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + BM_elem_index_set(v, i); /* set_inline */ + zero_v3(v->no); } + bm->elem_index_dirty &= ~BM_VERT; + } +#pragma omp section + { + /* Compute normalized direction vectors for each edge. + * Directions will be used for calculating the weights of the face normals on the vertex normals. + */ + bm_mesh_edges_calc_vectors(bm, edgevec, NULL); } } + /* end omp */ + + /* Add weighted face normals to vertices, and normalize vert normals. */ + bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, NULL, NULL, NULL); + MEM_freeN(edgevec); +} + +/** + * \brief BMesh Compute Normals from/to external data. + * + * Computes the vertex normals of a mesh into vnos, 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]) +{ + float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__); + + /* Compute normalized direction vectors for each edge. + * Directions will be used for calculating the weights of the face normals on the vertex normals. + */ + bm_mesh_edges_calc_vectors(bm, edgevec, vcos); + + /* Add weighted face normals to vertices, and normalize vert normals. */ + bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, fnos, vcos, vnos); + MEM_freeN(edgevec); } static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from, int to) diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 33431714660..cba4260eaea 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -38,6 +38,7 @@ void BM_mesh_data_free(BMesh *bm); void BM_mesh_clear(BMesh *bm); void BM_mesh_normals_update(BMesh *bm); +void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*vcos)[3], float (*vnos)[3]); void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag); void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag); |