/** * Given an array of faces, recalculate their normals. * this functions assumes all faces in the array are connected by edges. * * \param bm: * \param faces: Array of connected faces. * \param faces_len: Length of \a faces * \param oflag: Flag to check before doing the actual face flipping. */ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int faces_len, const short oflag) { int i, f_start_index; const short oflag_flip = oflag | FACE_FLIP; bool is_flip; BMFace *f; BLI_LINKSTACK_DECLARE(fstack, BMFace *); f_start_index = recalc_face_normals_find_index(bm, faces, faces_len, &is_flip); if (is_flip) { BMO_face_flag_enable(bm, faces[f_start_index], FACE_FLIP); } /* now that we've found our starting face, make all connected faces * have the same winding. this is done recursively, using a manual * stack (if we use simple function recursion, we'd end up overloading * the stack on large meshes). */ BLI_LINKSTACK_INIT(fstack); BLI_LINKSTACK_PUSH(fstack, faces[f_start_index]); BMO_face_flag_enable(bm, faces[f_start_index], FACE_TEMP); while ((f = BLI_LINKSTACK_POP(fstack))) { const bool flip_state = BMO_face_flag_test_bool(bm, f, FACE_FLIP); BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { BMLoop *l_other = l_iter->radial_next; if ((l_other != l_iter) && bmo_recalc_normal_loop_filter_cb(l_iter, NULL)) { if (!BMO_face_flag_test(bm, l_other->f, FACE_TEMP)) { BMO_face_flag_enable(bm, l_other->f, FACE_TEMP); BMO_face_flag_set(bm, l_other->f, FACE_FLIP, (l_other->v == l_iter->v) != flip_state); BLI_LINKSTACK_PUSH(fstack, l_other->f); } } } while ((l_iter = l_iter->next) != l_first); } BLI_LINKSTACK_FREE(fstack); /* apply flipping to oflag'd faces */ for (i = 0; i < faces_len; i++) { if (BMO_face_flag_test(bm, faces[i], oflag_flip) == oflag_flip) { BM_face_normal_flip(bm, faces[i]); } BMO_face_flag_disable(bm, faces[i], FACE_TEMP); } }
static PyObject *bpy_bm_utils_face_flip(PyObject *UNUSED(self), BPy_BMFace *value) { if (!BPy_BMFace_Check(value)) { PyErr_Format(PyExc_TypeError, "face_flip(face): BMFace expected, not '%.200s'", Py_TYPE(value)->tp_name); return NULL; } BPY_BM_CHECK_OBJ(value); BM_face_normal_flip(value->bm, value->f); Py_RETURN_NONE; }