static void mesh_calc_edges(Mesh *mesh) { CustomData edata; EdgeHashIterator *ehi; MFace *mf = mesh->mface; MEdge *med; EdgeHash *eh = BLI_edgehash_new(); int i, *index, totedge, totface = mesh->totface; for (i = 0; i < totface; i++, mf++) { if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); if (mf->v4) { if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); } else { if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); } } totedge = BLI_edgehash_size(eh); /* write new edges into a temporary CustomData */ memset(&edata, 0, sizeof(edata)); CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); ehi = BLI_edgehashIterator_new(eh); med = CustomData_get_layer(&edata, CD_MEDGE); for(i = 0; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) { BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); med->flag = ME_EDGEDRAW|ME_EDGERENDER; } BLI_edgehashIterator_free(ehi); /* free old CustomData and assign new one */ CustomData_free(&mesh->edata, mesh->totedge); mesh->edata = edata; mesh->totedge = totedge; mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE); BLI_edgehash_free(eh, NULL); }
/** * The intention is that this calculates the output of #BLI_polyfill_calc * * * \note assumes the \a coords form a boundary, * so any edges running along contiguous (wrapped) indices, * are ignored since the edges wont share 2 faces. */ void BLI_polyfill_beautify( const float (*coords)[2], const unsigned int coords_tot, unsigned int (*tris)[3], /* structs for reuse */ MemArena *arena, Heap *eheap, EdgeHash *ehash) { const unsigned int coord_last = coords_tot - 1; const unsigned int tris_tot = coords_tot - 2; /* internal edges only (between 2 tris) */ const unsigned int edges_tot = tris_tot - 1; unsigned int edges_tot_used = 0; unsigned int i; HeapNode **eheap_table; struct PolyEdge *edges = BLI_memarena_alloc(arena, edges_tot * sizeof(*edges)); BLI_assert(BLI_heap_size(eheap) == 0); BLI_assert(BLI_edgehash_size(ehash) == 0); /* first build edges */ for (i = 0; i < tris_tot; i++) { unsigned int j_prev, j_curr, j_next; j_prev = 2; j_next = 1; for (j_curr = 0; j_curr < 3; j_next = j_prev, j_prev = j_curr++) { int e_index; unsigned int e_pair[2] = { tris[i][j_prev], tris[i][j_curr], }; if (e_pair[0] > e_pair[1]) { SWAP(unsigned int, e_pair[0], e_pair[1]); e_index = 1; } else { e_index = 0; } if (!is_boundary_edge(e_pair[0], e_pair[1], coord_last)) { struct PolyEdge *e; void **val_p; if (!BLI_edgehash_ensure_p(ehash, e_pair[0], e_pair[1], &val_p)) { e = &edges[edges_tot_used++]; *val_p = e; memcpy(e->verts, e_pair, sizeof(e->verts)); #ifndef NDEBUG e->faces[!e_index] = (unsigned int)-1; #endif } else { e = *val_p; /* ensure each edge only ever has 2x users */ #ifndef NDEBUG BLI_assert(e->faces[e_index] == (unsigned int)-1); BLI_assert((e->verts[0] == e_pair[0]) && (e->verts[1] == e_pair[1])); #endif } e->faces[e_index] = i; e->faces_other_v[e_index] = j_next; } } } /* now perform iterative rotations */ eheap_table = BLI_memarena_alloc(arena, sizeof(HeapNode *) * (size_t)edges_tot); // for (i = 0; i < tris_tot; i++) { polyfill_validate_tri(tris, i, eh); } /* build heap */ for (i = 0; i < edges_tot; i++) { struct PolyEdge *e = &edges[i]; const float cost = polyedge_rotate_beauty_calc(coords, (const unsigned int (*)[3])tris, e); if (cost < 0.0f) { eheap_table[i] = BLI_heap_insert(eheap, cost, e); } else { eheap_table[i] = NULL; } } while (BLI_heap_is_empty(eheap) == false) { struct PolyEdge *e = BLI_heap_popmin(eheap); i = (unsigned int)(e - edges); eheap_table[i] = NULL; polyedge_rotate(tris, e, ehash); /* recalculate faces connected on the heap */ polyedge_beauty_cost_update( coords, (const unsigned int (*)[3])tris, edges, e, eheap, eheap_table, ehash); } BLI_heap_clear(eheap, NULL); BLI_edgehash_clear_ex(ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE); /* MEM_freeN(eheap_table); */ /* arena */ }
/** * Calculate edges from polygons * * \param mesh The mesh to add edges into * \param update When true create new edges co-exist */ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select) { CustomData edata; EdgeHashIterator *ehi; MPoly *mp; MEdge *med, *med_orig; EdgeHash *eh = BLI_edgehash_new(); int i, totedge, totpoly = mesh->totpoly; int med_index; /* select for newly created meshes which are selected [#25595] */ const short ed_flag = (ME_EDGEDRAW | ME_EDGERENDER) | (select ? SELECT : 0); if (mesh->totedge == 0) update = false; if (update) { /* assume existing edges are valid * useful when adding more faces and generating edges from them */ med = mesh->medge; for (i = 0; i < mesh->totedge; i++, med++) BLI_edgehash_insert(eh, med->v1, med->v2, med); } /* mesh loops (bmesh only) */ for (mp = mesh->mpoly, i = 0; i < totpoly; mp++, i++) { MLoop *l = &mesh->mloop[mp->loopstart]; int j, l_prev = (l + (mp->totloop - 1))->v; for (j = 0; j < mp->totloop; j++, l++) { if (!BLI_edgehash_haskey(eh, l_prev, l->v)) { BLI_edgehash_insert(eh, l_prev, l->v, NULL); } l_prev = l->v; } } totedge = BLI_edgehash_size(eh); /* write new edges into a temporary CustomData */ CustomData_reset(&edata); CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); med = CustomData_get_layer(&edata, CD_MEDGE); for (ehi = BLI_edgehashIterator_new(eh), i = 0; BLI_edgehashIterator_isDone(ehi) == FALSE; BLI_edgehashIterator_step(ehi), ++i, ++med) { if (update && (med_orig = BLI_edgehashIterator_getValue(ehi))) { *med = *med_orig; /* copy from the original */ } else { BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); med->flag = ed_flag; } /* store the new edge index in the hash value */ BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); } BLI_edgehashIterator_free(ehi); if (mesh->totpoly) { /* second pass, iterate through all loops again and assign * the newly created edges to them. */ for (mp = mesh->mpoly, i = 0; i < mesh->totpoly; mp++, i++) { MLoop *l = &mesh->mloop[mp->loopstart]; MLoop *l_prev = (l + (mp->totloop - 1)); int j; for (j = 0; j < mp->totloop; j++, l++) { /* lookup hashed edge index */ med_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, l_prev->v, l->v)); l_prev->e = med_index; l_prev = l; } } } /* free old CustomData and assign new one */ CustomData_free(&mesh->edata, mesh->totedge); mesh->edata = edata; mesh->totedge = totedge; mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE); BLI_edgehash_free(eh, NULL); }
void BKE_mesh_calc_edges(Mesh *mesh, int update) { CustomData edata; EdgeHashIterator *ehi; MFace *mf = mesh->mface; MEdge *med, *med_orig; EdgeHash *eh = BLI_edgehash_new(); int i, totedge, totface = mesh->totface; if(mesh->totedge==0) update= 0; if(update) { /* assume existing edges are valid * useful when adding more faces and generating edges from them */ med= mesh->medge; for(i= 0; i<mesh->totedge; i++, med++) BLI_edgehash_insert(eh, med->v1, med->v2, med); } for (i = 0; i < totface; i++, mf++) { if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); if (mf->v4) { if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); } else { if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); } } totedge = BLI_edgehash_size(eh); /* write new edges into a temporary CustomData */ memset(&edata, 0, sizeof(edata)); CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); ehi = BLI_edgehashIterator_new(eh); med = CustomData_get_layer(&edata, CD_MEDGE); for(i = 0; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi), ++i, ++med) { if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) { *med= *med_orig; /* copy from the original */ } else { BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */ } } BLI_edgehashIterator_free(ehi); /* free old CustomData and assign new one */ CustomData_free(&mesh->edata, mesh->totedge); mesh->edata = edata; mesh->totedge = totedge; mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE); BLI_edgehash_free(eh, NULL); }