/*merge these functions*/ static void BME_DMcorners_to_loops(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f, int numCol, int numTex){ int i, j; BME_Loop *l; MTFace *texface; MTexPoly *texpoly; MCol *mcol; MLoopCol *mloopcol; MLoopUV *mloopuv; for(i=0; i< numTex; i++){ texface = CustomData_get_layer_n(facedata, CD_MTFACE, i); texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); texpoly->tpage = texface[index].tpage; texpoly->flag = texface[index].flag; texpoly->transp = texface[index].transp; texpoly->mode = texface[index].mode; texpoly->tile = texface[index].tile; texpoly->unwrap = texface[index].unwrap; j = 0; l = f->loopbase; do{ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); mloopuv->uv[0] = texface[index].uv[j][0]; mloopuv->uv[1] = texface[index].uv[j][1]; j++; l = l->next; }while(l!=f->loopbase); } for(i=0; i < numCol; i++){ mcol = CustomData_get_layer_n(facedata, CD_MCOL, i); j = 0; l = f->loopbase; do{ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); mloopcol->r = mcol[(index*4)+j].r; mloopcol->g = mcol[(index*4)+j].g; mloopcol->b = mcol[(index*4)+j].b; mloopcol->a = mcol[(index*4)+j].a; j++; l = l->next; }while(l!=f->loopbase); } }
static void BME_loops_to_corners(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){ int i, j; BME_Loop *l; MTFace *texface; MTexPoly *texpoly; MCol *mcol; MLoopCol *mloopcol; MLoopUV *mloopuv; for(i=0; i < numTex; i++){ texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i); texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); texface->tpage = texpoly->tpage; texface->flag = texpoly->flag; texface->transp = texpoly->transp; texface->mode = texpoly->mode; texface->tile = texpoly->tile; texface->unwrap = texpoly->unwrap; j = 0; l = f->loopbase; do{ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); texface->uv[j][0] = mloopuv->uv[0]; texface->uv[j][1] = mloopuv->uv[1]; j++; l = l->next; }while(l!=f->loopbase); } for(i=0; i < numCol; i++){ mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i); j = 0; l = f->loopbase; do{ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); mcol[j].r = mloopcol->r; mcol[j].g = mloopcol->g; mcol[j].b = mloopcol->b; mcol[j].a = mloopcol->a; j++; l = l->next; }while(l!=f->loopbase); } }
/** * helper function for get/set, NULL return means the error is set */ static void *bpy_bmlayeritem_ptr_get(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer) { void *value; BMElem *ele = py_ele->ele; CustomData *data; /* error checking */ if (UNLIKELY(!BPy_BMLayerItem_Check(py_layer))) { PyErr_SetString(PyExc_AttributeError, "BMElem[key]: invalid key, must be a BMLayerItem"); return NULL; } else if (UNLIKELY(py_ele->bm != py_layer->bm)) { PyErr_SetString(PyExc_ValueError, "BMElem[layer]: layer is from another mesh"); return NULL; } else if (UNLIKELY(ele->head.htype != py_layer->htype)) { char namestr_1[32], namestr_2[32]; PyErr_Format(PyExc_ValueError, "Layer/Element type mismatch, expected %.200s got layer type %.200s", BPy_BMElem_StringFromHType_ex(ele->head.htype, namestr_1), BPy_BMElem_StringFromHType_ex(py_layer->htype, namestr_2)); return NULL; } data = bpy_bm_customdata_get(py_layer->bm, py_layer->htype); value = CustomData_bmesh_get_n(data, ele->head.data, py_layer->type, py_layer->index); if (UNLIKELY(value == NULL)) { /* this should be fairly unlikely but possible if layers move about after we get them */ PyErr_SetString(PyExc_KeyError, "BMElem[key]: layer not found"); return NULL; } else { return value; } }
/* calculates offset for co, based on fractal, sphere or smooth settings */ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc, BMVert *vsta, BMVert *vend) { float tvec[3], prev_co[3], fac; float *co = NULL; int i, totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY); BM_vert_normal_update_all(v); co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, params->origkey); copy_v3_v3(co, v->co); copy_v3_v3(prev_co, co); if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */ normalize_v3(co); mul_v3_fl(co, params->smooth); } else if (params->use_smooth) { /* we calculate an offset vector vec1[], to be added to *co */ float len, nor[3], nor1[3], nor2[3], val; sub_v3_v3v3(nor, vsta->co, vend->co); len = 0.5f * normalize_v3(nor); copy_v3_v3(nor1, vsta->no); copy_v3_v3(nor2, vend->no); /* cosine angle */ fac = dot_v3v3(nor, nor1); mul_v3_v3fl(tvec, nor1, fac); /* cosine angle */ fac = -dot_v3v3(nor, nor2); madd_v3_v3fl(tvec, nor2, fac); /* falloff for multi subdivide */ val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc)); switch (params->smooth_falloff) { case SUBD_FALLOFF_SMOOTH: val = 3.0f * val * val - 2.0f * val * val * val; break; case SUBD_FALLOFF_SPHERE: val = sqrtf(2.0f * val - val * val); break; case SUBD_FALLOFF_ROOT: val = sqrtf(val); break; case SUBD_FALLOFF_SHARP: val = val * val; break; case SUBD_FALLOFF_LIN: break; default: BLI_assert(0); } mul_v3_fl(tvec, params->smooth * val * len); add_v3_v3(co, tvec); } if (params->use_fractal) { float len = len_v3v3(vsta->co, vend->co); float normal[3] = {0.0f, 0.0f, 0.0f}, co2[3], base1[3], base2[3]; fac = params->fractal * len; mid_v3_v3v3(normal, vsta->no, vend->no); ortho_basis_v3v3_v3(base1, base2, normal); add_v3_v3v3(co2, v->co, params->fractal_ofs); mul_v3_fl(co2, 10.0f); tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f); tvec[1] = fac * (BLI_gTurbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f); tvec[2] = fac * (BLI_gTurbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f); /* add displacement */ madd_v3_v3fl(co, normal, tvec[0]); madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal)); madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal)); } /* apply the new difference to the rest of the shape keys, * note that this doesn't take rotations into account, we _could_ support * this by getting the normals and coords for each shape key and * re-calculate the smooth value for each but this is quite involved. * for now its ok to simply apply the difference IMHO - campbell */ sub_v3_v3v3(tvec, prev_co, co); for (i = 0; i < totlayer; i++) { if (params->origkey != i) { co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i); sub_v3_v3(co, tvec); } } }
/** * \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); }