Exemple #1
0
static void bm_subdivide_multicut(
    BMesh *bm, BMEdge *edge, const SubDParams *params, BMVert *v_a, BMVert *v_b)
{
  BMEdge *eed = edge, *e_new, e_tmp = *edge;
  BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
  int i, numcuts = params->numcuts;

  e_tmp.v1 = &v1_tmp;
  e_tmp.v2 = &v2_tmp;

  for (i = 0; i < numcuts; i++) {
    v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new);

    BMO_vert_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT);
    BMO_edge_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT);
    BMO_edge_flag_enable(bm, e_new, SUBD_SPLIT | ELE_SPLIT);

    BM_CHECK_ELEMENT(v);
    if (v->e) {
      BM_CHECK_ELEMENT(v->e);
    }
    if (v->e && v->e->l) {
      BM_CHECK_ELEMENT(v->e->l->f);
    }
  }

  alter_co(v1, &e_tmp, params, 0, &v1_tmp, &v2_tmp);
  alter_co(v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp);
}
Exemple #2
0
/**
 * \note This function sets the edge indices to invalid values.
 */
void BM_mesh_beautify_fill(
        BMesh *bm, BMEdge **edge_array, const int edge_array_len,
        const short flag, const short method,
        const short oflag_edge, const short oflag_face)
{
	Heap *eheap;             /* edge heap */
	HeapNode **eheap_table;  /* edge index aligned table pointing to the eheap */

	GSet       **edge_state_arr  = MEM_callocN((size_t)edge_array_len * sizeof(GSet *), __func__);
	BLI_mempool *edge_state_pool = BLI_mempool_create(sizeof(EdRotState), 0, 512, BLI_MEMPOOL_NOP);
	int i;

#ifdef DEBUG_TIME
	TIMEIT_START(beautify_fill);
#endif

	eheap = BLI_heap_new_ex((uint)edge_array_len);
	eheap_table = MEM_mallocN(sizeof(HeapNode *) * (size_t)edge_array_len, __func__);

	/* build heap */
	for (i = 0; i < edge_array_len; i++) {
		BMEdge *e = edge_array[i];
		const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
		if (cost < 0.0f) {
			eheap_table[i] = BLI_heap_insert(eheap, cost, e);
		}
		else {
			eheap_table[i] = NULL;
		}

		BM_elem_index_set(e, i);  /* set_dirty */
	}
	bm->elem_index_dirty |= BM_EDGE;

	while (BLI_heap_is_empty(eheap) == false) {
		BMEdge *e = BLI_heap_popmin(eheap);
		i = BM_elem_index_get(e);
		eheap_table[i] = NULL;

		BLI_assert(BM_edge_face_count_is_equal(e, 2));

		e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);

		BLI_assert(e == NULL || BM_edge_face_count_is_equal(e, 2));

		if (LIKELY(e)) {
			GSet *e_state_set = edge_state_arr[i];

			/* add the new state into the set so we don't move into this state again
			 * note: we could add the previous state too but this isn't essential)
			 *       for avoiding eternal loops */
			EdRotState *e_state = BLI_mempool_alloc(edge_state_pool);
			erot_state_current(e, e_state);
			if (UNLIKELY(e_state_set == NULL)) {
				edge_state_arr[i] = e_state_set = erot_gset_new();  /* store previous state */
			}
			BLI_assert(BLI_gset_haskey(e_state_set, (void *)e_state) == false);
			BLI_gset_insert(e_state_set, e_state);


			// printf("  %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2));

			/* maintain the index array */
			edge_array[i] = e;
			BM_elem_index_set(e, i);

			/* recalculate faces connected on the heap */
			bm_edge_update_beauty_cost(e, eheap, eheap_table, edge_state_arr,
			                           (const BMEdge **)edge_array, edge_array_len,
			                           flag, method);

			/* update flags */
			if (oflag_edge) {
				BMO_edge_flag_enable(bm, e, oflag_edge);
			}

			if (oflag_face) {
				BMO_face_flag_enable(bm, e->l->f, oflag_face);
				BMO_face_flag_enable(bm, e->l->radial_next->f, oflag_face);
			}
		}
	}

	BLI_heap_free(eheap, NULL);
	MEM_freeN(eheap_table);

	for (i = 0; i < edge_array_len; i++) {
		if (edge_state_arr[i]) {
			BLI_gset_free(edge_state_arr[i], NULL);
		}
	}

	MEM_freeN(edge_state_arr);
	BLI_mempool_destroy(edge_state_pool);

#ifdef DEBUG_TIME
	TIMEIT_END(beautify_fill);
#endif
}
Exemple #3
0
/**
 * <pre>
 *         v5
 *        / \
 *   s v6/---\ v4 s
 *      / \ / \
 *  sv7/---v---\ v3 s
 *    /  \/  \/ \
 *   v8--v0--v1--v2
 *      s    s
 * </pre>
 */
static void tri_3edge_subdivide(BMesh *bm,
                                BMFace *UNUSED(face),
                                BMVert **verts,
                                const SubDParams *params)
{
  BMFace *f_new;
  BMEdge *e, *e_new, e_tmp;
  BMVert ***lines, *v, v1_tmp, v2_tmp;
  void *stackarr[1];
  int i, j, a, b, numcuts = params->numcuts;

  /* number of verts in each lin */
  lines = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table");

  lines[0] = (BMVert **)stackarr;
  lines[0][0] = verts[numcuts * 2 + 1];

  lines[numcuts + 1] = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table 2");
  for (i = 0; i < numcuts; i++) {
    lines[numcuts + 1][i + 1] = verts[i];
  }
  lines[numcuts + 1][0] = verts[numcuts * 3 + 2];
  lines[numcuts + 1][numcuts + 1] = verts[numcuts];

  for (i = 0; i < numcuts; i++) {
    lines[i + 1] = MEM_callocN(sizeof(void *) * (2 + i), "triangle vert table row");
    a = numcuts * 2 + 2 + i;
    b = numcuts + numcuts - i;
    e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
    if (!e) {
      goto cleanup;
    }

    BMO_edge_flag_enable(bm, e, ELE_INNER);
    BMO_face_flag_enable(bm, f_new, ELE_INNER);

    lines[i + 1][0] = verts[a];
    lines[i + 1][i + 1] = verts[b];

    e_tmp = *e;
    v1_tmp = *verts[a];
    v2_tmp = *verts[b];
    e_tmp.v1 = &v1_tmp;
    e_tmp.v2 = &v2_tmp;
    for (j = 0; j < i; j++) {
      v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new);
      lines[i + 1][j + 1] = v;

      BMO_edge_flag_enable(bm, e_new, ELE_INNER);
    }
  }

  /**
   * <pre>
   *         v5
   *        / \
   *   s v6/---\ v4 s
   *      / \ / \
   *  sv7/---v---\ v3 s
   *    /  \/  \/ \
   *   v8--v0--v1--v2
   *      s    s
   * </pre>
   */
  for (i = 1; i <= numcuts; i++) {
    for (j = 0; j < i; j++) {
      e = connect_smallest_face(bm, lines[i][j], lines[i + 1][j + 1], &f_new);

      BMO_edge_flag_enable(bm, e, ELE_INNER);
      BMO_face_flag_enable(bm, f_new, ELE_INNER);

      e = connect_smallest_face(bm, lines[i][j + 1], lines[i + 1][j + 1], &f_new);

      BMO_edge_flag_enable(bm, e, ELE_INNER);
      BMO_face_flag_enable(bm, f_new, ELE_INNER);
    }
  }

cleanup:
  for (i = 1; i < numcuts + 2; i++) {
    if (lines[i]) {
      MEM_freeN(lines[i]);
    }
  }

  MEM_freeN(lines);
}
Exemple #4
0
/**
 * <pre>
 *            v8--v7-v6--v5
 *            |     s    |
 *            |v9 s     s|v4
 * first line |          |   last line
 *            |v10s s   s|v3
 *            v11-v0--v1-v2
 *
 *            it goes from bottom up
 * </pre>
 */
static void quad_4edge_subdivide(BMesh *bm,
                                 BMFace *UNUSED(face),
                                 BMVert **verts,
                                 const SubDParams *params)
{
  BMFace *f_new;
  BMVert *v, *v1, *v2;
  BMEdge *e, *e_new, e_tmp;
  BMVert **lines;
  int numcuts = params->numcuts;
  int i, j, a, b, s = numcuts + 2 /* , totv = numcuts * 4 + 4 */;

  lines = MEM_callocN(sizeof(BMVert *) * (numcuts + 2) * (numcuts + 2), "q_4edge_split");
  /* build a 2-dimensional array of verts,
   * containing every vert (and all new ones)
   * in the face */

  /* first line */
  for (i = 0; i < numcuts + 2; i++) {
    lines[i] = verts[numcuts * 3 + 2 + (numcuts - i + 1)];
  }

  /* last line */
  for (i = 0; i < numcuts + 2; i++) {
    lines[(s - 1) * s + i] = verts[numcuts + i];
  }

  /* first and last members of middle lines */
  for (i = 0; i < numcuts; i++) {
    a = i;
    b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);

    e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
    if (!e) {
      continue;
    }

    BMO_edge_flag_enable(bm, e, ELE_INNER);
    BMO_face_flag_enable(bm, f_new, ELE_INNER);

    v1 = lines[(i + 1) * s] = verts[a];
    v2 = lines[(i + 1) * s + s - 1] = verts[b];

    e_tmp = *e;
    for (a = 0; a < numcuts; a++) {
      v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new);

      BMESH_ASSERT(v != NULL);

      BMO_edge_flag_enable(bm, e_new, ELE_INNER);
      lines[(i + 1) * s + a + 1] = v;
    }
  }

  for (i = 1; i < numcuts + 2; i++) {
    for (j = 1; j <= numcuts; j++) {
      a = i * s + j;
      b = (i - 1) * s + j;
      e = connect_smallest_face(bm, lines[a], lines[b], &f_new);
      if (!e) {
        continue;
      }

      BMO_edge_flag_enable(bm, e, ELE_INNER);
      BMO_face_flag_enable(bm, f_new, ELE_INNER);
    }
  }

  MEM_freeN(lines);
}