Exemple #1
0
/**
 * 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);
  }
}
Exemple #2
0
void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op)
{
	int *groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totface, __func__);
	BMFace **faces_grp = MEM_mallocN(sizeof(*faces_grp) * bm->totface, __func__);

	int (*group_index)[2];
	const int group_tot = BM_mesh_calc_face_groups(
	        bm, groups_array, &group_index,
	        bmo_recalc_normal_loop_filter_cb, NULL,
	        0, BM_EDGE);
	int i;

	BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_FLAG);

	BM_mesh_elem_table_ensure(bm, BM_FACE);

	for (i = 0; i < group_tot; i++) {
		const int fg_sta = group_index[i][0];
		const int fg_len = group_index[i][1];
		int j;
		bool is_calc = false;

		for (j = 0; j < fg_len; j++) {
			faces_grp[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);

			if (is_calc == false) {
				is_calc = BMO_face_flag_test_bool(bm, faces_grp[j], FACE_FLAG);
			}
		}

		if (is_calc) {
			bmo_recalc_face_normals_array(bm, faces_grp, fg_len, FACE_FLAG);
		}
	}

	MEM_freeN(faces_grp);

	MEM_freeN(groups_array);
	MEM_freeN(group_index);
}