/** * Duplicate of BM_mesh_cd_validate() for Mesh data. */ void BKE_mesh_cd_validate(Mesh *me) { int totlayer_mtex = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); int totlayer_uv = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); int mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY); int uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV); int i; /* XXX For now, do not delete those, just warn they are not really usable. */ if (UNLIKELY(totlayer_mtex > MAX_MTFACE)) { printf("WARNING! More UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n", MAX_MTFACE, totlayer_mtex - MAX_MTFACE); } if (UNLIKELY(totlayer_uv > MAX_MTFACE)) { printf("WARNING! More UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n", MAX_MTFACE, totlayer_uv - MAX_MTFACE); } if (UNLIKELY(totlayer_mcol > MAX_MCOL)) { printf("WARNING! More VCol layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n", MAX_MCOL, totlayer_mcol - MAX_MCOL); } if (LIKELY(totlayer_mtex == totlayer_uv)) { /* pass */ } else if (totlayer_mtex < totlayer_uv) { do { const char *from_name = me->ldata.layers[uv_index + totlayer_mtex].name; CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, from_name); CustomData_set_layer_unique_name(&me->pdata, totlayer_mtex); } while (totlayer_uv != ++totlayer_mtex); mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY); } else if (totlayer_uv < totlayer_mtex) { do { const char *from_name = me->pdata.layers[mtex_index + totlayer_uv].name; CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, from_name); CustomData_set_layer_unique_name(&me->ldata, totlayer_uv); } while (totlayer_mtex != ++totlayer_uv); uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV); } BLI_assert(totlayer_mtex == totlayer_uv); /* Check uv/tex names match as well!!! */ for (i = 0; i < totlayer_mtex; i++, mtex_index++, uv_index++) { const char *name_src = me->pdata.layers[mtex_index].name; const char *name_dst = me->ldata.layers[uv_index].name; if (!STREQ(name_src, name_dst)) { BKE_mesh_uv_cdlayer_rename_index(me, mtex_index, uv_index, -1, name_src, false); } } }
int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mesh *me, const char *name, int active_set) { EditMesh *em; MCol *mcol; int layernum; if(me->edit_mesh) { em= me->edit_mesh; layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL); if(layernum >= MAX_MCOL) return 0; EM_add_data_layer(em, &em->fdata, CD_MCOL, name); if(layernum) /* copy data from active vertex color layer */ copy_editface_active_customdata(em, CD_MCOL, layernum); if(active_set || layernum==0) CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum); } else { layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL); if(layernum >= MAX_MCOL) return 0; mcol= me->mcol; if(me->mcol) CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name); else CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name); if(active_set || layernum==0) CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum); mesh_update_customdata_pointers(me); } DAG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, me); return 1; }
int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_set) { EditMesh *em; int layernum; if(me->edit_mesh) { em= me->edit_mesh; layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE); if(layernum >= MAX_MTFACE) return 0; EM_add_data_layer(em, &em->fdata, CD_MTFACE, name); if(layernum) /* copy data from active UV */ copy_editface_active_customdata(em, CD_MTFACE, layernum); if(active_set || layernum==0) CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum); } else { layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE); if(layernum >= MAX_MTFACE) return 0; if(me->mtface) CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name); else CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name); if(active_set || layernum==0) CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum); mesh_update_customdata_pointers(me); } DAG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, me); return 1; }
/** * Duplicate of BM_mesh_cd_validate() for Mesh data. */ void BKE_mesh_cd_validate(Mesh *me) { int totlayer_mtex = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); int totlayer_uv = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); int mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY); int uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV); int i; if (LIKELY(totlayer_mtex == totlayer_uv)) { /* pass */ } else if (totlayer_mtex < totlayer_uv) { do { const char *from_name = me->ldata.layers[uv_index + totlayer_mtex].name; CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, from_name); CustomData_set_layer_unique_name(&me->pdata, totlayer_mtex); } while (totlayer_uv != ++totlayer_mtex); mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY); } else if (totlayer_uv < totlayer_mtex) { do { const char *from_name = me->pdata.layers[mtex_index + totlayer_uv].name; CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, from_name); CustomData_set_layer_unique_name(&me->ldata, totlayer_uv); } while (totlayer_mtex != ++totlayer_uv); uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV); } BLI_assert(totlayer_mtex == totlayer_uv); /* Check uv/tex names match as well!!! */ for (i = 0; i < totlayer_mtex; i++, mtex_index++, uv_index++) { const char *name_src = me->pdata.layers[mtex_index].name; const char *name_dst = me->ldata.layers[uv_index].name; if (!STREQ(name_src, name_dst)) { BKE_mesh_uv_cdlayer_rename_index(me, mtex_index, uv_index, -1, name_src, false); } } }
Mesh *BKE_mesh_new_nomain_from_curve_displist(Object *ob, ListBase *dispbase) { Curve *cu = ob->data; Mesh *mesh; MVert *allvert; MEdge *alledge; MLoop *allloop; MPoly *allpoly; MLoopUV *alluv = NULL; int totvert, totedge, totloop, totpoly; bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0; if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert, &alledge, &totedge, &allloop, &allpoly, (use_orco_uv) ? &alluv : NULL, &totloop, &totpoly) != 0) { /* Error initializing mdata. This often happens when curve is empty */ return BKE_mesh_new_nomain(0, 0, 0, 0, 0); } mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly); mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; memcpy(mesh->mvert, allvert, totvert * sizeof(MVert)); memcpy(mesh->medge, alledge, totedge * sizeof(MEdge)); memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop)); memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly)); if (alluv) { const char *uvname = "Orco"; CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname); } MEM_freeN(allvert); MEM_freeN(alledge); MEM_freeN(allloop); MEM_freeN(allpoly); return mesh; }
static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src) { KeyBlock *kb; Key *key = mesh_src->key; int i; if (!mesh_src->key) { return; } /* ensure we can use mesh vertex count for derived mesh custom data */ if (mesh_src->totvert != mesh_dest->totvert) { CLOG_ERROR(&LOG, "vertex size mismatch (mesh/dm) '%s' (%d != %d)", mesh_src->id.name + 2, mesh_src->totvert, mesh_dest->totvert); return; } for (i = 0, kb = key->block.first; kb; kb = kb->next, i++) { int ci; float *array; if (mesh_src->totvert != kb->totelem) { CLOG_ERROR(&LOG, "vertex size mismatch (Mesh '%s':%d != KeyBlock '%s':%d)", mesh_src->id.name + 2, mesh_src->totvert, kb->name, kb->totelem); array = MEM_calloc_arrayN((size_t)mesh_src->totvert, 3 * sizeof(float), __func__); } else { array = MEM_malloc_arrayN((size_t)mesh_src->totvert, 3 * sizeof(float), __func__); memcpy(array, kb->data, (size_t)mesh_src->totvert * 3 * sizeof(float)); } CustomData_add_layer_named( &mesh_dest->vdata, CD_SHAPEKEY, CD_ASSIGN, array, mesh_dest->totvert, kb->name); ci = CustomData_get_layer_index_n(&mesh_dest->vdata, CD_SHAPEKEY, i); mesh_dest->vdata.layers[ci].uid = kb->uid; } }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; DerivedMesh *dm = derivedData; MDeformVert *dvert = NULL; MDeformWeight **dw1, **tdw1, **dw2, **tdw2; int numVerts; int defgrp_idx, defgrp_idx2 = -1; float *org_w; float *new_w; int *tidx, *indices = NULL; int numIdx = 0; int i; /* Flags. */ #if 0 int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); #endif /* Get number of verts. */ numVerts = dm->getNumVerts(dm); /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ if ((numVerts == 0) || (ob->defbase.first == NULL)) return dm; /* Get vgroup idx from its name. */ defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name_a); if (defgrp_idx < 0) return dm; /* Get seconf vgroup idx from its name, if given. */ if (wmd->defgrp_name_b[0] != (char)0) { defgrp_idx2 = defgroup_name_index(ob, wmd->defgrp_name_b); if (defgrp_idx2 < 0) return dm; } dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts); /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ if (!dvert) { /* If not affecting all vertices, just return. */ if (wmd->mix_set != MOD_WVG_SET_ALL) return dm; /* Else, add a valid data layer! */ dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts, wmd->defgrp_name_a); /* Ultimate security check. */ if (!dvert) return dm; } /* Find out which vertices to work on. */ tidx = MEM_mallocN(sizeof(int) * numVerts, "WeightVGMix Modifier, tidx"); tdw1 = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGMix Modifier, tdw1"); tdw2 = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGMix Modifier, tdw2"); switch (wmd->mix_set) { case MOD_WVG_SET_A: /* All vertices in first vgroup. */ for (i = 0; i < numVerts; i++) { MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx); if (dw) { tdw1[numIdx] = dw; tdw2[numIdx] = defvert_find_index(&dvert[i], defgrp_idx2); tidx[numIdx++] = i; } } break; case MOD_WVG_SET_B: /* All vertices in second vgroup. */ for (i = 0; i < numVerts; i++) { MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx2); if (dw) { tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_idx); tdw2[numIdx] = dw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_OR: /* All vertices in one vgroup or the other. */ for (i = 0; i < numVerts; i++) { MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx); MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2); if (adw || bdw) { tdw1[numIdx] = adw; tdw2[numIdx] = bdw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_AND: /* All vertices in both vgroups. */ for (i = 0; i < numVerts; i++) { MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx); MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2); if (adw && bdw) { tdw1[numIdx] = adw; tdw2[numIdx] = bdw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_ALL: default: /* Use all vertices. */ for (i = 0; i < numVerts; i++) { tdw1[i] = defvert_find_index(&dvert[i], defgrp_idx); tdw2[i] = defvert_find_index(&dvert[i], defgrp_idx2); } numIdx = -1; break; } if (numIdx == 0) { /* Use no vertices! Hence, return org data. */ MEM_freeN(tdw1); MEM_freeN(tdw2); MEM_freeN(tidx); return dm; } if (numIdx != -1) { indices = MEM_mallocN(sizeof(int) * numIdx, "WeightVGMix Modifier, indices"); memcpy(indices, tidx, sizeof(int) * numIdx); dw1 = MEM_mallocN(sizeof(MDeformWeight *) * numIdx, "WeightVGMix Modifier, dw1"); memcpy(dw1, tdw1, sizeof(MDeformWeight *) * numIdx); MEM_freeN(tdw1); dw2 = MEM_mallocN(sizeof(MDeformWeight *) * numIdx, "WeightVGMix Modifier, dw2"); memcpy(dw2, tdw2, sizeof(MDeformWeight *) * numIdx); MEM_freeN(tdw2); } else { /* Use all vertices. */ numIdx = numVerts; /* Just copy MDeformWeight pointers arrays, they will be freed at the end. */ dw1 = tdw1; dw2 = tdw2; } MEM_freeN(tidx); org_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, org_w"); new_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, new_w"); /* Mix weights. */ for (i = 0; i < numIdx; i++) { float weight2 = 0.0; org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a; weight2 = dw2[i] ? dw2[i]->weight : wmd->default_weight_b; new_w[i] = mix_weight(org_w[i], weight2, wmd->mix_mode); } /* Do masking. */ weightvg_do_mask(numIdx, indices, org_w, new_w, ob, dm, wmd->mask_constant, wmd->mask_defgrp_name, wmd->modifier.scene, wmd->mask_texture, wmd->mask_tex_use_channel, wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name); /* Update (add to) vgroup. * XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup. */ weightvg_update_vg(dvert, defgrp_idx, dw1, numIdx, indices, org_w, TRUE, -FLT_MAX, FALSE, 0.0f); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ if (do_prev) DM_update_weight_mcol(ob, dm, 0, org_w, numIdx, indices); #endif /* Freeing stuff. */ MEM_freeN(org_w); MEM_freeN(new_w); MEM_freeN(dw1); MEM_freeN(dw2); if (indices) MEM_freeN(indices); /* Return the vgroup-modified mesh. */ return dm; }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md; DerivedMesh *dm = derivedData; MDeformVert *dvert = NULL; MDeformWeight **dw = NULL; float *org_w; /* Array original weights. */ float *new_w; /* Array new weights. */ int numVerts; int defgrp_index; int i; /* Flags. */ int do_add = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0; int do_rem = (wmd->edit_flags & MOD_WVG_EDIT_REMFVG) != 0; /* Only do weight-preview in Object, Sculpt and Pose modes! */ #if 0 int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); #endif /* Get number of verts. */ numVerts = dm->getNumVerts(dm); /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ if ((numVerts == 0) || (ob->defbase.first == NULL)) return dm; /* Get vgroup idx from its name. */ defgrp_index = defgroup_name_index(ob, wmd->defgrp_name); if (defgrp_index == -1) return dm; dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts); /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ if (!dvert) { /* If this modifier is not allowed to add vertices, just return. */ if (!do_add) return dm; /* Else, add a valid data layer! */ dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts, wmd->defgrp_name); /* Ultimate security check. */ if (!dvert) return dm; } /* Get org weights, assuming 0.0 for vertices not in given vgroup. */ org_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, org_w"); new_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, new_w"); dw = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGEdit Modifier, dw"); for (i = 0; i < numVerts; i++) { dw[i] = defvert_find_index(&dvert[i], defgrp_index); if (dw[i]) { org_w[i] = new_w[i] = dw[i]->weight; } else { org_w[i] = new_w[i] = wmd->default_weight; } } /* Do mapping. */ if (wmd->falloff_type != MOD_WVG_MAPPING_NONE) { RNG *rng = NULL; if (wmd->falloff_type == MOD_WVG_MAPPING_RANDOM) rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ob->id.name + 2)); weightvg_do_map(numVerts, new_w, wmd->falloff_type, wmd->cmap_curve, rng); if (rng) BLI_rng_free(rng); } /* Do masking. */ weightvg_do_mask(numVerts, NULL, org_w, new_w, ob, dm, wmd->mask_constant, wmd->mask_defgrp_name, wmd->modifier.scene, wmd->mask_texture, wmd->mask_tex_use_channel, wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name); /* Update/add/remove from vgroup. */ weightvg_update_vg(dvert, defgrp_index, dw, numVerts, NULL, org_w, do_add, wmd->add_threshold, do_rem, wmd->rem_threshold); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ if (do_prev) DM_update_weight_mcol(ob, dm, 0, org_w, 0, NULL); #endif /* Freeing stuff. */ MEM_freeN(org_w); MEM_freeN(new_w); MEM_freeN(dw); /* Return the vgroup-modified mesh. */ return dm; }
static DerivedMesh *doOcean(ModifierData *md, Object *ob, DerivedMesh *derivedData, int UNUSED(useRenderParams)) { OceanModifierData *omd = (OceanModifierData *) md; DerivedMesh *dm = NULL; OceanResult ocr; MVert *mverts, *mv; MLoop *mloops; int i, j; int num_verts; int num_faces; int cfra; /* use cached & inverted value for speed * expanded this would read... * * (axis / (omd->size * omd->spatial_size)) + 0.5f) */ #define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f) const float size_co_inv = 1.0f / (omd->size * omd->spatial_size); /* can happen in when size is small, avoid bad array lookups later and quit now */ if (!finite(size_co_inv)) { return derivedData; } /* update modifier */ if (omd->refresh & MOD_OCEAN_REFRESH_ADD) omd->ocean = BKE_ocean_add(); if (omd->refresh & MOD_OCEAN_REFRESH_RESET) init_ocean_modifier(omd); if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) clear_cache_data(omd); omd->refresh = 0; /* do ocean simulation */ if (omd->cached == true) { if (!omd->oceancache) init_cache_data(ob, omd); BKE_ocean_simulate_cache(omd->oceancache, md->scene->r.cfra); } else { simulate_ocean_modifier(omd); } if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) { dm = generate_ocean_geometry(omd); DM_ensure_normals(dm); } else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) { dm = CDDM_copy(derivedData); } cfra = md->scene->r.cfra; CLAMP(cfra, omd->bakestart, omd->bakeend); cfra -= omd->bakestart; /* shift to 0 based */ num_verts = dm->getNumVerts(dm); num_faces = dm->getNumPolys(dm); mverts = dm->getVertArray(dm); mloops = dm->getLoopArray(dm); /* add vcols before displacement - allows lookup based on position */ if (omd->flag & MOD_OCEAN_GENERATE_FOAM) { int cdlayer = CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL); if (cdlayer < MAX_MCOL) { MLoopCol *mloopcols = CustomData_add_layer_named(&dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, num_faces * 4, omd->foamlayername); if (mloopcols) { /* unlikely to fail */ MLoopCol *mlcol; MPoly *mpolys = dm->getPolyArray(dm); MPoly *mp; float foam; for (i = 0, mp = mpolys; i < num_faces; i++, mp++) { j = mp->totloop - 1; /* highly unlikely */ if (j <= 0) continue; do { const float *co = mverts[mloops[mp->loopstart + j].v].co; const float u = OCEAN_CO(size_co_inv, co[0]); const float v = OCEAN_CO(size_co_inv, co[1]); if (omd->oceancache && omd->cached == true) { BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); foam = ocr.foam; CLAMP(foam, 0.0f, 1.0f); } else { BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage); } mlcol = &mloopcols[mp->loopstart + j]; mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255); /* This needs to be set (render engine uses) */ mlcol->a = 255; } while (j--); } } } } /* displace the geometry */ /* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */ for (i = 0, mv = mverts; i < num_verts; i++, mv++) { const float u = OCEAN_CO(size_co_inv, mv->co[0]); const float v = OCEAN_CO(size_co_inv, mv->co[1]); if (omd->oceancache && omd->cached == true) BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v); else BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); mv->co[2] += ocr.disp[1]; if (omd->chop_amount > 0.0f) { mv->co[0] += ocr.disp[0]; mv->co[1] += ocr.disp[2]; } } #undef OCEAN_CO return dm; }
/** * \brief Mesh -> BMesh * \param bm: The mesh to write into, while this is typically a newly created BMesh, * merging into existing data is supported. * Note the custom-data layout isn't used. * If more comprehensive merging is needed we should move this into a separate function * since this should be kept fast for edit-mode switching and storing undo steps. * * \warning This function doesn't calculate face normals. */ void BM_mesh_bm_from_me( BMesh *bm, Mesh *me, const struct BMeshFromMeshParams *params) { const bool is_new = !(bm->totvert || (bm->vdata.totlayer || bm->edata.totlayer || bm->pdata.totlayer || bm->ldata.totlayer)); MVert *mvert; MEdge *medge; MLoop *mloop; MPoly *mp; KeyBlock *actkey, *block; BMVert *v, **vtable = NULL; BMEdge *e, **etable = NULL; BMFace *f, **ftable = NULL; float (*keyco)[3] = NULL; int totuv, totloops, i; if (!me || !me->totvert) { if (me && is_new) { /*no verts? still copy customdata layout*/ CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_ASSIGN, 0); CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_ASSIGN, 0); CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_ASSIGN, 0); CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_ASSIGN, 0); CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); } return; /* sanity check */ } if (is_new) { CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); /* make sure uv layer names are consisten */ totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); for (i = 0; i < totuv; i++) { int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i); CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name); } } /* -------------------------------------------------------------------- */ /* Shape Key */ int tot_shape_keys = me->key ? BLI_listbase_count(&me->key->block) : 0; if (is_new == false) { tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY)); } const float (**shape_key_table)[3] = tot_shape_keys ? BLI_array_alloca(shape_key_table, tot_shape_keys) : NULL; if ((params->active_shapekey != 0) && (me->key != NULL)) { actkey = BLI_findlink(&me->key->block, params->active_shapekey - 1); } else { actkey = NULL; } if (is_new) { if (tot_shape_keys || params->add_key_index) { CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0); } } if (tot_shape_keys) { if (is_new) { /* check if we need to generate unique ids for the shapekeys. * this also exists in the file reading code, but is here for * a sanity check */ if (!me->key->uidgen) { fprintf(stderr, "%s had to generate shape key uid's in a situation we shouldn't need to! " "(bmesh internal error)\n", __func__); me->key->uidgen = 1; for (block = me->key->block.first; block; block = block->next) { block->uid = me->key->uidgen++; } } } if (actkey && actkey->totelem == me->totvert) { keyco = params->use_shapekey ? actkey->data : NULL; if (is_new) { bm->shapenr = params->active_shapekey; } } for (i = 0, block = me->key->block.first; i < tot_shape_keys; block = block->next, i++) { if (is_new) { CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY, CD_ASSIGN, NULL, 0, block->name); int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i); bm->vdata.layers[j].uid = block->uid; } shape_key_table[i] = (const float (*)[3])block->data; } } if (is_new) { CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); BM_mesh_cd_flag_apply(bm, me->cd_flag); } const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); const int cd_shape_key_offset = me->key ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) : -1; const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ? CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : -1; vtable = MEM_mallocN(sizeof(BMVert **) * me->totvert, __func__); for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(v, i); /* set_ok */ /* transfer flag */ v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT); /* this is necessary for selection counts to work properly */ if (mvert->flag & SELECT) { BM_vert_select_set(bm, v, true); } normal_short_to_float_v3(v->no, mvert->no); /* Copy Custom Data */ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true); if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f); /* set shape key original index */ if (cd_shape_keyindex_offset != -1) BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i); /* set shapekey data */ if (tot_shape_keys) { float (*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset); for (int j = 0; j < tot_shape_keys; j++, co_dst++) { copy_v3_v3(*co_dst, shape_key_table[j][i]); } } } if (is_new) { bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */ } etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__); medge = me->medge; for (i = 0; i < me->totedge; i++, medge++) { e = etable[i] = BM_edge_create(bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(e, i); /* set_ok */ /* transfer flags */ e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT); /* this is necessary for selection counts to work properly */ if (medge->flag & SELECT) { BM_edge_select_set(bm, e, true); } /* Copy Custom Data */ CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true); if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f); if (cd_edge_crease_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge->crease / 255.0f); } if (is_new) { bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */ } /* only needed for selection. */ if (me->mselect && me->totselect != 0) { ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__); } mloop = me->mloop; mp = me->mpoly; for (i = 0, totloops = 0; i < me->totpoly; i++, mp++) { BMLoop *l_iter; BMLoop *l_first; f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart, bm, vtable, etable); if (ftable != NULL) { ftable[i] = f; } if (UNLIKELY(f == NULL)) { printf("%s: Warning! Bad face in mesh" " \"%s\" at index %d!, skipping\n", __func__, me->id.name + 2, i); continue; } /* don't use 'i' since we may have skipped the face */ BM_elem_index_set(f, bm->totface - 1); /* set_ok */ /* transfer flag */ f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL); /* this is necessary for selection counts to work properly */ if (mp->flag & ME_FACE_SEL) { BM_face_select_set(bm, f, true); } f->mat_nr = mp->mat_nr; if (i == me->act_face) bm->act_face = f; int j = mp->loopstart; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { /* don't use 'j' since we may have skipped some faces, hence some loops. */ BM_elem_index_set(l_iter, totloops++); /* set_ok */ /* Save index of correspsonding MLoop */ CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true); } while ((l_iter = l_iter->next) != l_first); /* Copy Custom Data */ CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true); if (params->calc_face_normal) { BM_face_normal_update(f); } } if (is_new) { bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */ } /* -------------------------------------------------------------------- */ /* MSelect clears the array elements (avoid adding multiple times). * * Take care to keep this last and not use (v/e/ftable) after this. */ if (me->mselect && me->totselect != 0) { MSelect *msel; for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) { BMElem **ele_p; switch (msel->type) { case ME_VSEL: ele_p = (BMElem **)&vtable[msel->index]; break; case ME_ESEL: ele_p = (BMElem **)&etable[msel->index]; break; case ME_FSEL: ele_p = (BMElem **)&ftable[msel->index]; break; default: continue; } if (*ele_p != NULL) { BM_select_history_store_notest(bm, *ele_p); *ele_p = NULL; } } } else { BM_select_history_clear(bm); } MEM_freeN(vtable); MEM_freeN(etable); if (ftable) { MEM_freeN(ftable); } }
static bool data_transfer_layersmapping_cdlayers( ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, const int num_elem_dst, const bool use_create, const bool use_delete, CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, const int fromlayers, const int tolayers) { int idx_src, idx_dst; void *data_src, *data_dst = NULL; if (CustomData_layertype_is_singleton(cddata_type)) { if (!(data_src = CustomData_get_layer(cd_src, cddata_type))) { if (use_delete) { CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, 0); } return true; } data_dst = CustomData_get_layer(cd_dst, cddata_type); if (!data_dst) { if (!use_create) { return true; } data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); } else if (use_dupref_dst && r_map) { /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */ data_dst = CustomData_duplicate_referenced_layer(cd_dst, cddata_type, num_elem_dst); } if (r_map) { data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst); } } else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) { /* Note: use_delete has not much meaning in this case, ignored. */ if (fromlayers >= 0) { /* Real-layer index */ idx_src = fromlayers; } else { if ((idx_src = CustomData_get_active_layer(cd_src, cddata_type)) == -1) { return true; } } data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); if (!data_src) { return true; } if (tolayers >= 0) { /* Real-layer index */ idx_dst = tolayers; /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */ if (use_dupref_dst && r_map) { data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); } else { data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); } } else if (tolayers == DT_LAYERS_ACTIVE_DST) { if ((idx_dst = CustomData_get_active_layer(cd_dst, cddata_type)) == -1) { if (!use_create) { return true; } data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); } else { /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */ if (use_dupref_dst && r_map) { data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); } else { data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); } } } else if (tolayers == DT_LAYERS_INDEX_DST) { int num = CustomData_number_of_layers(cd_dst, cddata_type); idx_dst = idx_src; if (num <= idx_dst) { if (!use_create) { return true; } /* Create as much data layers as necessary! */ for (; num <= idx_dst; num++) { CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); } } /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */ if (use_dupref_dst && r_map) { data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); } else { data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); } } else if (tolayers == DT_LAYERS_NAME_DST) { const char *name = CustomData_get_layer_name(cd_src, cddata_type, idx_src); if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) { if (!use_create) { return true; } CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name); idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name); } /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */ if (use_dupref_dst && r_map) { data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); } else { data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); } } else { return false; } if (!data_dst) { return false; } if (r_map) { data_transfer_layersmapping_add_item_cd( r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst); } } else if (fromlayers == DT_LAYERS_ALL_SRC) { int num_src = CustomData_number_of_layers(cd_src, cddata_type); bool *use_layers_src = num_src ? MEM_mallocN(sizeof(*use_layers_src) * (size_t)num_src, __func__) : NULL; bool ret; if (use_layers_src) { memset(use_layers_src, true, sizeof(*use_layers_src) * num_src); } ret = data_transfer_layersmapping_cdlayers_multisrc_to_dst( r_map, cddata_type, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete, cd_src, cd_dst, use_dupref_dst, tolayers, use_layers_src, num_src); if (use_layers_src) { MEM_freeN(use_layers_src); } return ret; } else { return false; } return true; }
static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst( ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, const int num_elem_dst, const bool use_create, const bool use_delete, CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, const int tolayers, bool *use_layers_src, const int num_layers_src) { void *data_src, *data_dst = NULL; int idx_src = num_layers_src; int idx_dst, tot_dst = CustomData_number_of_layers(cd_dst, cddata_type); bool *data_dst_to_delete = NULL; if (!use_layers_src) { /* No source at all, we can only delete all dest if requested... */ if (use_delete) { idx_dst = tot_dst; while (idx_dst--) { CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); } } return true; } switch (tolayers) { case DT_LAYERS_INDEX_DST: idx_dst = tot_dst; /* Find last source actually used! */ while (idx_src-- && !use_layers_src[idx_src]); idx_src++; if (idx_dst < idx_src) { if (!use_create) { return true; } /* Create as much data layers as necessary! */ for (; idx_dst < idx_src; idx_dst++) { CustomData_add_layer(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst); } } else if (use_delete && idx_dst > idx_src) { while (idx_dst-- > idx_src) { CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); } } if (r_map) { while (idx_src--) { if (!use_layers_src[idx_src]) { continue; } data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */ if (use_dupref_dst) { data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_src, num_elem_dst); } else { data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_src); } data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst); } } break; case DT_LAYERS_NAME_DST: if (use_delete) { if (tot_dst) { data_dst_to_delete = MEM_mallocN(sizeof(*data_dst_to_delete) * (size_t)tot_dst, __func__); memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * (size_t)tot_dst); } } while (idx_src--) { const char *name; if (!use_layers_src[idx_src]) { continue; } name = CustomData_get_layer_name(cd_src, cddata_type, idx_src); data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src); if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) { if (!use_create) { if (r_map) { BLI_freelistN(r_map); } return true; } CustomData_add_layer_named(cd_dst, cddata_type, CD_CALLOC, NULL, num_elem_dst, name); idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name); } else if (data_dst_to_delete) { data_dst_to_delete[idx_dst] = false; } if (r_map) { /* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */ if (use_dupref_dst) { data_dst = CustomData_duplicate_referenced_layer_n(cd_dst, cddata_type, idx_dst, num_elem_dst); } else { data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst); } data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst); } } if (data_dst_to_delete) { /* Note: This won't affect newly created layers, if any, since tot_dst has not been updated! * Also, looping backward ensures us we do not suffer from index shifting when deleting a layer. */ for (idx_dst = tot_dst; idx_dst--;) { if (data_dst_to_delete[idx_dst]) { CustomData_free_layer(cd_dst, cddata_type, num_elem_dst, idx_dst); } } MEM_freeN(data_dst_to_delete); } break; default: return false; } return true; }
// ================================================================= // Return the number of faces by summing up // the facecounts of the parts. // hint: This is done because mesh->getFacesCount() does // count loose edges as extra faces, which is not what we want here. // ================================================================= void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) { COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives(); int total_poly_count = 0; int total_loop_count = 0; // collect edge_count and face_count from all parts for (int i = 0; i < prim_arr.getCount(); i++) { COLLADAFW::MeshPrimitive *mp = prim_arr[i]; int type = mp->getPrimitiveType(); switch (type) { case COLLADAFW::MeshPrimitive::TRIANGLES: case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: case COLLADAFW::MeshPrimitive::POLYLIST: case COLLADAFW::MeshPrimitive::POLYGONS: { COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; size_t prim_poly_count = mpvc->getFaceCount(); size_t prim_loop_count = 0; for (int index=0; index < prim_poly_count; index++) { prim_loop_count += get_vertex_count(mpvc, index); } total_poly_count += prim_poly_count; total_loop_count += prim_loop_count; break; } default: break; } } // Add the data containers if (total_poly_count > 0) { me->totpoly = total_poly_count; me->totloop = total_loop_count; me->mpoly = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, me->totpoly); me->mloop = (MLoop *)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, me->totloop); unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount(); for (int i = 0; i < totuvset; i++) { if (collada_mesh->getUVCoords().getLength(i) == 0) { totuvset = 0; break; } } if (totuvset > 0) { for (int i = 0; i < totuvset; i++) { COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i]; COLLADAFW::String &uvname = info->mName; // Allocate space for UV_data CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname.c_str()); CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str()); } // activate the first uv map me->mtpoly = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0); me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0); } int totcolset = collada_mesh->getColors().getInputInfosArray().getCount(); if (totcolset > 0) { for (int i = 0; i < totcolset; i++) { COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getColors().getInputInfosArray()[i]; COLLADAFW::String colname = extract_vcolname(info->mName); CustomData_add_layer_named(&me->ldata,CD_MLOOPCOL,CD_DEFAULT,NULL,me->totloop, colname.c_str()); } me->mloopcol = (MLoopCol *) CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0); } } }
/** * \brief Mesh -> BMesh * * \warning This function doesn't calculate face normals. */ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, const bool calc_face_normal, const bool set_key, int act_key_nr) { MVert *mvert; MEdge *medge; MLoop *mloop; MPoly *mp; KeyBlock *actkey, *block; BMVert *v, **vtable = NULL; BMEdge *e, **etable = NULL; BMFace *f; float (*keyco)[3] = NULL; int *keyi; int totuv, i, j; int cd_vert_bweight_offset; int cd_edge_bweight_offset; int cd_edge_crease_offset; /* free custom data */ /* this isnt needed in most cases but do just incase */ CustomData_free(&bm->vdata, bm->totvert); CustomData_free(&bm->edata, bm->totedge); CustomData_free(&bm->ldata, bm->totloop); CustomData_free(&bm->pdata, bm->totface); if (!me || !me->totvert) { if (me) { /*no verts? still copy customdata layout*/ CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_ASSIGN, 0); CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_ASSIGN, 0); CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_ASSIGN, 0); CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_ASSIGN, 0); CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); } return; /* sanity check */ } vtable = MEM_mallocN(sizeof(void **) * me->totvert, "mesh to bmesh vtable"); CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); /* make sure uv layer names are consisten */ totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); for (i = 0; i < totuv; i++) { int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i); CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name); } if ((act_key_nr != 0) && (me->key != NULL)) { actkey = BLI_findlink(&me->key->block, act_key_nr - 1); } else { actkey = NULL; } if (me->key) { CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0); /* check if we need to generate unique ids for the shapekeys. * this also exists in the file reading code, but is here for * a sanity check */ if (!me->key->uidgen) { fprintf(stderr, "%s had to generate shape key uid's in a situation we shouldn't need to! " "(bmesh internal error)\n", __func__); me->key->uidgen = 1; for (block = me->key->block.first; block; block = block->next) { block->uid = me->key->uidgen++; } } if (actkey && actkey->totelem == me->totvert) { keyco = actkey->data; bm->shapenr = act_key_nr; } for (i = 0, block = me->key->block.first; block; block = block->next, i++) { CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY, CD_ASSIGN, NULL, 0, block->name); j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i); bm->vdata.layers[j].uid = block->uid; } } CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); BM_mesh_cd_flag_apply(bm, me->cd_flag); cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { v = vtable[i] = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(v, i); /* set_ok */ /* transfer flag */ v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT); /* this is necessary for selection counts to work properly */ if (mvert->flag & SELECT) { BM_vert_select_set(bm, v, true); } normal_short_to_float_v3(v->no, mvert->no); /* Copy Custom Data */ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true); if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f); /* set shapekey data */ if (me->key) { /* set shape key original index */ keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); if (keyi) { *keyi = i; } for (block = me->key->block.first, j = 0; block; block = block->next, j++) { float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, j); if (co) { copy_v3_v3(co, ((float *)block->data) + 3 * i); } } } } bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */ if (!me->totedge) { MEM_freeN(vtable); return; } etable = MEM_mallocN(sizeof(void **) * me->totedge, "mesh to bmesh etable"); medge = me->medge; for (i = 0; i < me->totedge; i++, medge++) { e = etable[i] = BM_edge_create(bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(e, i); /* set_ok */ /* transfer flags */ e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT); /* this is necessary for selection counts to work properly */ if (medge->flag & SELECT) { BM_edge_select_set(bm, e, true); } /* Copy Custom Data */ CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true); if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f); if (cd_edge_crease_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge->crease / 255.0f); } bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */ mloop = me->mloop; mp = me->mpoly; for (i = 0; i < me->totpoly; i++, mp++) { BMLoop *l_iter; BMLoop *l_first; f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart, bm, vtable, etable); if (UNLIKELY(f == NULL)) { printf("%s: Warning! Bad face in mesh" " \"%s\" at index %d!, skipping\n", __func__, me->id.name + 2, i); continue; } /* don't use 'i' since we may have skipped the face */ BM_elem_index_set(f, bm->totface - 1); /* set_ok */ /* transfer flag */ f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL); /* this is necessary for selection counts to work properly */ if (mp->flag & ME_FACE_SEL) { BM_face_select_set(bm, f, true); } f->mat_nr = mp->mat_nr; if (i == me->act_face) bm->act_face = f; j = mp->loopstart; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { /* Save index of correspsonding MLoop */ CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true); } while ((l_iter = l_iter->next) != l_first); /* Copy Custom Data */ CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true); if (calc_face_normal) { BM_face_normal_update(f); } } bm->elem_index_dirty &= ~BM_FACE; /* added in order, clear dirty flag */ if (me->mselect && me->totselect != 0) { BMVert **vert_array = MEM_mallocN(sizeof(BMVert *) * bm->totvert, "VSelConv"); BMEdge **edge_array = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, "ESelConv"); BMFace **face_array = MEM_mallocN(sizeof(BMFace *) * bm->totface, "FSelConv"); MSelect *msel; #pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) { #pragma omp section { BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)vert_array, bm->totvert); } #pragma omp section { BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edge_array, bm->totedge); } #pragma omp section { BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)face_array, bm->totface); } } for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) { switch (msel->type) { case ME_VSEL: BM_select_history_store(bm, (BMElem *)vert_array[msel->index]); break; case ME_ESEL: BM_select_history_store(bm, (BMElem *)edge_array[msel->index]); break; case ME_FSEL: BM_select_history_store(bm, (BMElem *)face_array[msel->index]); break; } } MEM_freeN(vert_array); MEM_freeN(edge_array); MEM_freeN(face_array); } else { me->totselect = 0; if (me->mselect) { MEM_freeN(me->mselect); me->mselect = NULL; } } MEM_freeN(vtable); MEM_freeN(etable); }
/* this may fail replacing ob->data, be sure to check ob->type */ void BKE_mesh_from_nurbs_displist(Main *bmain, Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name, bool temporary) { Object *ob1; Mesh *me_eval = ob->runtime.mesh_eval; Mesh *me; Curve *cu; MVert *allvert = NULL; MEdge *alledge = NULL; MLoop *allloop = NULL; MLoopUV *alluv = NULL; MPoly *allpoly = NULL; int totvert, totedge, totloop, totpoly; cu = ob->data; if (me_eval == NULL) { if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert, &alledge, &totedge, &allloop, &allpoly, (use_orco_uv) ? &alluv : NULL, &totloop, &totpoly) != 0) { /* Error initializing */ return; } /* make mesh */ me = BKE_mesh_add(bmain, obdata_name); me->totvert = totvert; me->totedge = totedge; me->totloop = totloop; me->totpoly = totpoly; me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert); me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge); me->mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop); me->mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly); if (alluv) { const char *uvname = "Orco"; me->mloopuv = CustomData_add_layer_named( &me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname); } BKE_mesh_calc_normals(me); } else { me = BKE_mesh_add(bmain, obdata_name); ob->runtime.mesh_eval = NULL; BKE_mesh_nomain_to_mesh(me_eval, me, ob, &CD_MASK_MESH, true); } me->totcol = cu->totcol; me->mat = cu->mat; /* Copy evaluated texture space from curve to mesh. * * Note that we disable auto texture space feature since that will cause * texture space to evaluate differently for curve and mesh, since curve * uses CV to calculate bounding box, and mesh uses what is coming from * tessellated curve. */ me->texflag = cu->texflag & ~CU_AUTOSPACE; copy_v3_v3(me->loc, cu->loc); copy_v3_v3(me->size, cu->size); copy_v3_v3(me->rot, cu->rot); BKE_mesh_texspace_calc(me); cu->mat = NULL; cu->totcol = 0; /* Do not decrement ob->data usercount here, * it's done at end of func with BKE_id_free_us() call. */ ob->data = me; ob->type = OB_MESH; /* other users */ ob1 = bmain->objects.first; while (ob1) { if (ob1->data == cu) { ob1->type = OB_MESH; id_us_min((ID *)ob1->data); ob1->data = ob->data; id_us_plus((ID *)ob1->data); } ob1 = ob1->id.next; } if (temporary) { /* For temporary objects in BKE_mesh_new_from_object don't remap * the entire scene with associated depsgraph updates, which are * problematic for renderers exporting data. */ BKE_id_free(NULL, cu); } else { BKE_id_free_us(bmain, cu); } }
static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, Base* base) { float co[3], rot[3]; EditMesh *em; int i,j, k; unsigned short* v; int face[3]; Scene *scene= CTX_data_scene(C); Object* obedit; int createob= base==NULL; int nverts, nmeshes, nvp; unsigned short *verts, *polys; unsigned int *meshes; float bmin[3], cs, ch, *dverts; unsigned char *tris; zero_v3(co); zero_v3(rot); if(createob) { /* create new object */ obedit= ED_object_add_type(C, OB_MESH, co, rot, FALSE, 1); } else { obedit= base->object; scene_select_base(scene, base); copy_v3_v3(obedit->loc, co); copy_v3_v3(obedit->rot, rot); } ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); if(!createob) { /* clear */ if(em->verts.first) free_vertlist(em, &em->verts); if(em->edges.first) free_edgelist(em, &em->edges); if(em->faces.first) free_facelist(em, &em->faces); if(em->selected.first) BLI_freelistN(&(em->selected)); } /* create verts for polygon mesh */ verts= recast_polyMeshGetVerts(pmesh, &nverts); recast_polyMeshGetBoundbox(pmesh, bmin, NULL); recast_polyMeshGetCell(pmesh, &cs, &ch); for(i= 0; i<nverts; i++) { v= &verts[3*i]; co[0]= bmin[0] + v[0]*cs; co[1]= bmin[1] + v[1]*ch; co[2]= bmin[2] + v[2]*cs; SWAP(float, co[1], co[2]); addvertlist(em, co, NULL); } /* create custom data layer to save polygon idx */ CustomData_add_layer_named(&em->fdata, CD_RECAST, CD_CALLOC, NULL, 0, "createRepresentation recastData"); /* create verts and faces for detailed mesh */ meshes= recast_polyMeshDetailGetMeshes(dmesh, &nmeshes); polys= recast_polyMeshGetPolys(pmesh, NULL, &nvp); dverts= recast_polyMeshDetailGetVerts(dmesh, NULL); tris= recast_polyMeshDetailGetTris(dmesh, NULL); for(i= 0; i<nmeshes; i++) { int uniquevbase= em->totvert; unsigned int vbase= meshes[4*i+0]; unsigned short ndv= meshes[4*i+1]; unsigned short tribase= meshes[4*i+2]; unsigned short trinum= meshes[4*i+3]; const unsigned short* p= &polys[i*nvp*2]; int nv= 0; for(j= 0; j < nvp; ++j) { if(p[j]==0xffff) break; nv++; } /* create unique verts */ for(j= nv; j<ndv; j++) { copy_v3_v3(co, &dverts[3*(vbase + j)]); SWAP(float, co[1], co[2]); addvertlist(em, co, NULL); } EM_init_index_arrays(em, 1, 0, 0); /* create faces */ for(j= 0; j<trinum; j++) { unsigned char* tri= &tris[4*(tribase+j)]; EditFace* newFace; int* polygonIdx; for(k= 0; k<3; k++) { if(tri[k]<nv) face[k]= p[tri[k]]; /* shared vertex */ else face[k]= uniquevbase+tri[k]-nv; /* unique vertex */ } newFace= addfacelist(em, EM_get_vert_for_index(face[0]), EM_get_vert_for_index(face[2]), EM_get_vert_for_index(face[1]), NULL, NULL, NULL); /* set navigation polygon idx to the custom layer */ polygonIdx= (int*)CustomData_em_get(&em->fdata, newFace->data, CD_RECAST); *polygonIdx= i+1; /* add 1 to avoid zero idx */ } EM_free_index_arrays(); } recast_destroyPolyMesh(pmesh); recast_destroyPolyMeshDetail(dmesh); BKE_mesh_end_editmesh((Mesh*)obedit->data, em); DAG_id_tag_update((ID*)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); ED_object_exit_editmode(C, EM_FREEDATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); if(createob) { obedit->gameflag&= ~OB_COLLISION; obedit->gameflag|= OB_NAVMESH; obedit->body_type= OB_BODY_TYPE_NAVMESH; rename_id((ID *)obedit, "Navmesh"); } BKE_mesh_ensure_navmesh(obedit->data); return obedit; }