Mesh *BKE_mesh_add(Main *bmain, const char *name) { Mesh *me; me = BKE_libblock_alloc(&bmain->mesh, ID_ME, name); me->size[0] = me->size[1] = me->size[2] = 1.0; me->smoothresh = 30; me->texflag = ME_AUTOSPACE; me->flag = ME_TWOSIDED; me->drawflag = ME_DRAWEDGES | ME_DRAWFACES | ME_DRAWCREASES; CustomData_reset(&me->vdata); CustomData_reset(&me->edata); CustomData_reset(&me->fdata); CustomData_reset(&me->pdata); CustomData_reset(&me->ldata); return me; }
static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata) { if (free_customdata) { CustomData_free(&mesh->fdata, mesh->totface); } else { CustomData_reset(&mesh->fdata); } mesh->mface = NULL; mesh->mtface = NULL; mesh->mcol = NULL; mesh->totface = 0; }
/** * 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); }
/* This is a Mesh-based copy of DM_to_mesh() */ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership) { /* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */ /* TODO(Sybren): the above claim came from DM_to_mesh(); * check whether it is still true with Mesh */ Mesh tmp = *mesh_dst; int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; int did_shapekeys = 0; eCDAllocType alloctype = CD_DUPLICATE; if (take_ownership /* && dm->type == DM_TYPE_CDDM && dm->needsFree */) { bool has_any_referenced_layers = CustomData_has_referenced(&mesh_src->vdata) || CustomData_has_referenced(&mesh_src->edata) || CustomData_has_referenced(&mesh_src->ldata) || CustomData_has_referenced(&mesh_src->fdata) || CustomData_has_referenced(&mesh_src->pdata); if (!has_any_referenced_layers) { alloctype = CD_ASSIGN; } } CustomData_reset(&tmp.vdata); CustomData_reset(&tmp.edata); CustomData_reset(&tmp.fdata); CustomData_reset(&tmp.ldata); CustomData_reset(&tmp.pdata); BKE_mesh_ensure_normals(mesh_src); totvert = tmp.totvert = mesh_src->totvert; totedge = tmp.totedge = mesh_src->totedge; totloop = tmp.totloop = mesh_src->totloop; totpoly = tmp.totpoly = mesh_src->totpoly; tmp.totface = 0; CustomData_copy(&mesh_src->vdata, &tmp.vdata, mask->vmask, alloctype, totvert); CustomData_copy(&mesh_src->edata, &tmp.edata, mask->emask, alloctype, totedge); CustomData_copy(&mesh_src->ldata, &tmp.ldata, mask->lmask, alloctype, totloop); CustomData_copy(&mesh_src->pdata, &tmp.pdata, mask->pmask, alloctype, totpoly); tmp.cd_flag = mesh_src->cd_flag; tmp.runtime.deformed_only = mesh_src->runtime.deformed_only; if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) { KeyBlock *kb; int uid; if (ob) { kb = BLI_findlink(&mesh_dst->key->block, ob->shapenr - 1); if (kb) { uid = kb->uid; } else { CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1); uid = INT_MAX; } } else { /* if no object, set to INT_MAX so we don't mess up any shapekey layers */ uid = INT_MAX; } shapekey_layers_to_keyblocks(mesh_src, mesh_dst, uid); did_shapekeys = 1; } /* copy texture space */ if (ob) { BKE_mesh_texspace_copy_from_object(&tmp, ob); } /* not all DerivedMeshes store their verts/edges/faces in CustomData, so * we set them here in case they are missing */ /* TODO(Sybren): we could probably replace CD_ASSIGN with alloctype and * always directly pass mesh_src->mxxx, instead of using a ternary operator. */ if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) { CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN, (alloctype == CD_ASSIGN) ? mesh_src->mvert : MEM_dupallocN(mesh_src->mvert), totvert); } if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) { CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, (alloctype == CD_ASSIGN) ? mesh_src->medge : MEM_dupallocN(mesh_src->medge), totedge); } if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) { /* TODO(Sybren): assignment to tmp.mxxx is probably not necessary due to the * BKE_mesh_update_customdata_pointers() call below. */ tmp.mloop = (alloctype == CD_ASSIGN) ? mesh_src->mloop : MEM_dupallocN(mesh_src->mloop); tmp.mpoly = (alloctype == CD_ASSIGN) ? mesh_src->mpoly : MEM_dupallocN(mesh_src->mpoly); CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop); CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly); } /* object had got displacement layer, should copy this layer to save sculpted data */ /* NOTE: maybe some other layers should be copied? nazgul */ if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) { if (totloop == mesh_dst->totloop) { MDisps *mdisps = CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS); CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop); } } /* yes, must be before _and_ after tessellate */ BKE_mesh_update_customdata_pointers(&tmp, false); /* since 2.65 caller must do! */ // BKE_mesh_tessface_calc(&tmp); CustomData_free(&mesh_dst->vdata, mesh_dst->totvert); CustomData_free(&mesh_dst->edata, mesh_dst->totedge); CustomData_free(&mesh_dst->fdata, mesh_dst->totface); CustomData_free(&mesh_dst->ldata, mesh_dst->totloop); CustomData_free(&mesh_dst->pdata, mesh_dst->totpoly); /* ok, this should now use new CD shapekey data, * which should be fed through the modifier * stack */ if (tmp.totvert != mesh_dst->totvert && !did_shapekeys && mesh_dst->key) { CLOG_ERROR(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name); if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) { id_us_min(&tmp.key->id); } tmp.key = NULL; } /* Clear selection history */ MEM_SAFE_FREE(tmp.mselect); tmp.totselect = 0; BLI_assert(ELEM(tmp.bb, NULL, mesh_dst->bb)); if (mesh_dst->bb) { MEM_freeN(mesh_dst->bb); tmp.bb = NULL; } /* skip the listbase */ MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev); if (take_ownership) { if (alloctype == CD_ASSIGN) { CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask); CustomData_free_typemask(&mesh_src->edata, mesh_src->totedge, ~mask->emask); CustomData_free_typemask(&mesh_src->ldata, mesh_src->totloop, ~mask->lmask); CustomData_free_typemask(&mesh_src->pdata, mesh_src->totpoly, ~mask->pmask); } BKE_id_free(NULL, mesh_src); } }