forked from bartvdbraak/blender
fix [#34657] Smoothing will not be updated in object mode, when hiding faces in edit mode and changing shape.
remove the option to skip hidden faces in BM_mesh_normals_update, use openmp to speedup recalculation for high poly meshes.
This commit is contained in:
parent
40c217cabd
commit
245a175a00
@ -259,96 +259,102 @@ void BM_mesh_free(BMesh *bm)
|
||||
*
|
||||
* Updates the normals of a mesh.
|
||||
*/
|
||||
void BM_mesh_normals_update(BMesh *bm, const bool skip_hidden)
|
||||
void BM_mesh_normals_update(BMesh *bm)
|
||||
{
|
||||
BMVert *v;
|
||||
BMEdge *e;
|
||||
BMFace *f;
|
||||
BMIter iter;
|
||||
int index;
|
||||
float (*edgevec)[3];
|
||||
|
||||
/* calculate all face normals */
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
if (skip_hidden && BM_elem_flag_test(f, BM_ELEM_HIDDEN))
|
||||
continue;
|
||||
#if 0 /* UNUSED */
|
||||
if (f->head.flag & BM_NONORMCALC)
|
||||
continue;
|
||||
#endif
|
||||
float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
|
||||
|
||||
BM_face_normal_update(f);
|
||||
}
|
||||
|
||||
/* Zero out vertex normals */
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
if (skip_hidden && BM_elem_flag_test(v, BM_ELEM_HIDDEN))
|
||||
continue;
|
||||
#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;
|
||||
|
||||
zero_v3(v->no);
|
||||
}
|
||||
|
||||
/* compute normalized direction vectors for each edge. directions will be
|
||||
* used below for calculating the weights of the face normals on the vertex
|
||||
* normals */
|
||||
edgevec = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
|
||||
BM_ITER_MESH_INDEX (e, &iter, 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]);
|
||||
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
|
||||
BM_face_normal_update(f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* the edge vector will not be needed when the edge has no radial */
|
||||
#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);
|
||||
}
|
||||
}
|
||||
#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;
|
||||
}
|
||||
}
|
||||
bm->elem_index_dirty &= ~BM_EDGE;
|
||||
/* end omp */
|
||||
|
||||
|
||||
/* add weighted face normals to vertices */
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
BMLoop *l_first, *l_iter;
|
||||
{
|
||||
BMIter fiter;
|
||||
BMFace *f;
|
||||
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
|
||||
BMLoop *l_first, *l_iter;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
const float *e1diff, *e2diff;
|
||||
float dotprod;
|
||||
float fac;
|
||||
|
||||
if (skip_hidden && BM_elem_flag_test(f, BM_ELEM_HIDDEN))
|
||||
continue;
|
||||
/* calculate the dot product of the two edges that
|
||||
* meet at the loop's vertex */
|
||||
e1diff = edgevec[BM_elem_index_get(l_iter->prev->e)];
|
||||
e2diff = edgevec[BM_elem_index_get(l_iter->e)];
|
||||
dotprod = dot_v3v3(e1diff, e2diff);
|
||||
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
const float *e1diff, *e2diff;
|
||||
float dotprod;
|
||||
float fac;
|
||||
/* edge vectors are calculated from e->v1 to e->v2, so
|
||||
* adjust the dot product if one but not both loops
|
||||
* actually runs from from e->v2 to e->v1 */
|
||||
if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) {
|
||||
dotprod = -dotprod;
|
||||
}
|
||||
|
||||
/* calculate the dot product of the two edges that
|
||||
* meet at the loop's vertex */
|
||||
e1diff = edgevec[BM_elem_index_get(l_iter->prev->e)];
|
||||
e2diff = edgevec[BM_elem_index_get(l_iter->e)];
|
||||
dotprod = dot_v3v3(e1diff, e2diff);
|
||||
fac = saacos(-dotprod);
|
||||
|
||||
/* edge vectors are calculated from e->v1 to e->v2, so
|
||||
* adjust the dot product if one but not both loops
|
||||
* actually runs from from e->v2 to e->v1 */
|
||||
if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) {
|
||||
dotprod = -dotprod;
|
||||
}
|
||||
|
||||
fac = saacos(-dotprod);
|
||||
|
||||
/* accumulate weighted face normal into the vertex's normal */
|
||||
madd_v3_v3fl(l_iter->v->no, f->no, fac);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
/* accumulate weighted face normal into the vertex's normal */
|
||||
madd_v3_v3fl(l_iter->v->no, f->no, fac);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
MEM_freeN(edgevec);
|
||||
}
|
||||
|
||||
/* normalize the accumulated vertex normals */
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
if (skip_hidden && BM_elem_flag_test(v, BM_ELEM_HIDDEN))
|
||||
continue;
|
||||
|
||||
if (UNLIKELY(normalize_v3(v->no) == 0.0f)) {
|
||||
normalize_v3_v3(v->no, v->co);
|
||||
|
||||
/* normalize the accumulated vertex normals */
|
||||
{
|
||||
BMIter viter;
|
||||
BMVert *v;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(edgevec);
|
||||
}
|
||||
|
||||
static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from, int to)
|
||||
@ -449,7 +455,7 @@ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
|
||||
|
||||
/* compute normals, clear temp flags and flush selections */
|
||||
if (type_flag & BMO_OPTYPE_FLAG_NORMALS_CALC) {
|
||||
BM_mesh_normals_update(bm, true);
|
||||
BM_mesh_normals_update(bm);
|
||||
}
|
||||
|
||||
if (type_flag & BMO_OPTYPE_FLAG_SELECT_FLUSH) {
|
||||
|
@ -37,7 +37,7 @@ void BM_mesh_free(BMesh *bm);
|
||||
void BM_mesh_data_free(BMesh *bm);
|
||||
void BM_mesh_clear(BMesh *bm);
|
||||
|
||||
void BM_mesh_normals_update(BMesh *bm, const bool skip_hidden);
|
||||
void BM_mesh_normals_update(BMesh *bm);
|
||||
|
||||
void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
|
||||
void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
|
||||
|
@ -2292,7 +2292,7 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh
|
||||
* since de-selecting all skips selection flushing logic */
|
||||
BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
|
||||
|
||||
BM_mesh_normals_update(bm_new, false);
|
||||
BM_mesh_normals_update(bm_new);
|
||||
|
||||
BM_mesh_bm_to_me(bm_new, base_new->object->data, false);
|
||||
|
||||
|
@ -115,7 +115,7 @@ void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em)
|
||||
|
||||
void EDBM_mesh_normals_update(BMEditMesh *em)
|
||||
{
|
||||
BM_mesh_normals_update(em->bm, true);
|
||||
BM_mesh_normals_update(em->bm);
|
||||
}
|
||||
|
||||
void EDBM_mesh_clear(BMEditMesh *em)
|
||||
@ -648,7 +648,7 @@ static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *UNUSED(obdata))
|
||||
BM_mesh_bm_from_me(bm, &um->me, false, ob->shapenr);
|
||||
|
||||
/* face normals need recalculation since we are not calling through an operator */
|
||||
BM_mesh_normals_update(bm, true);
|
||||
BM_mesh_normals_update(bm);
|
||||
|
||||
em_tmp = BKE_editmesh_create(bm, true);
|
||||
*em = *em_tmp;
|
||||
|
@ -4566,10 +4566,10 @@ void sculpt_dynamic_topology_enable(bContext *C)
|
||||
ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
|
||||
|
||||
BM_mesh_bm_from_me(ss->bm, me, TRUE, ob->shapenr);
|
||||
BM_mesh_normals_update(ss->bm, false);
|
||||
BM_mesh_normals_update(ss->bm);
|
||||
sculpt_dynamic_topology_triangulate(ss->bm);
|
||||
BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
|
||||
BM_mesh_normals_update(ss->bm, TRUE);
|
||||
BM_mesh_normals_update(ss->bm);
|
||||
|
||||
/* Enable dynamic topology */
|
||||
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
|
||||
|
@ -101,7 +101,7 @@ static void special_transvert_update(Object *obedit)
|
||||
|
||||
if (obedit->type == OB_MESH) {
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
BM_mesh_normals_update(em->bm, true); /* does face centers too */
|
||||
BM_mesh_normals_update(em->bm);
|
||||
}
|
||||
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
|
||||
Curve *cu = obedit->data;
|
||||
|
@ -1170,25 +1170,15 @@ static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
|
||||
|
||||
|
||||
PyDoc_STRVAR(bpy_bmesh_normal_update_doc,
|
||||
".. method:: normal_update(skip_hidden=False)\n"
|
||||
".. method:: normal_update()\n"
|
||||
"\n"
|
||||
" Update mesh normals.\n"
|
||||
"\n"
|
||||
" :arg skip_hidden: When True hidden elements are ignored.\n"
|
||||
" :type skip_hidden: boolean\n"
|
||||
);
|
||||
static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self, PyObject *args)
|
||||
static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self)
|
||||
{
|
||||
|
||||
int skip_hidden = false;
|
||||
|
||||
BPY_BM_CHECK_OBJ(self);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|i:normal_update", &skip_hidden)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BM_mesh_normals_update(self->bm, skip_hidden);
|
||||
BM_mesh_normals_update(self->bm);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@ -2543,7 +2533,7 @@ static struct PyMethodDef bpy_bmesh_methods[] = {
|
||||
/* meshdata */
|
||||
{"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
|
||||
{"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
|
||||
{"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc},
|
||||
{"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_NOARGS, bpy_bmesh_normal_update_doc},
|
||||
{"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_transform_doc},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user