int ED_mesh_uv_texture_add(bContext *C, Scene *scene, Object *ob, Mesh *me) { 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 OPERATOR_CANCELLED; EM_add_data_layer(em, &em->fdata, CD_MTFACE); CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum); } else { layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE); if(layernum >= MAX_MTFACE) return OPERATOR_CANCELLED; if(me->mtface) CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface); else CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface); CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum); mesh_update_customdata_pointers(me); } DAG_id_flush_update(&me->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, me); return 1; }
static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd) { DerivedMesh *result; GenerateOceanGeometryData gogd; int num_verts; int num_polys; const bool use_threading = omd->resolution > 4; gogd.rx = omd->resolution * omd->resolution; gogd.ry = omd->resolution * omd->resolution; gogd.res_x = gogd.rx * omd->repeat_x; gogd.res_y = gogd.ry * omd->repeat_y; num_verts = (gogd.res_x + 1) * (gogd.res_y + 1); num_polys = gogd.res_x * gogd.res_y; gogd.sx = omd->size * omd->spatial_size; gogd.sy = omd->size * omd->spatial_size; gogd.ox = -gogd.sx / 2.0f; gogd.oy = -gogd.sy / 2.0f; gogd.sx /= gogd.rx; gogd.sy /= gogd.ry; result = CDDM_new(num_verts, 0, 0, num_polys * 4, num_polys); gogd.mverts = CDDM_get_verts(result); gogd.mpolys = CDDM_get_polys(result); gogd.mloops = CDDM_get_loops(result); gogd.origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX); /* create vertices */ BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_vertices, use_threading); /* create faces */ BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_polygons, use_threading); CDDM_calc_edges(result); /* add uvs */ if (CustomData_number_of_layers(&result->loopData, CD_MLOOPUV) < MAX_MTFACE) { gogd.mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_polys * 4); CustomData_add_layer(&result->polyData, CD_MTEXPOLY, CD_CALLOC, NULL, num_polys); if (gogd.mloopuvs) { /* unlikely to fail */ gogd.ix = 1.0 / gogd.rx; gogd.iy = 1.0 / gogd.ry; BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_uvs, use_threading); } } result->dirty |= DM_DIRTY_NORMALS; return result; }
static void data_transfer_dtdata_type_preprocess( Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *dm_src, DerivedMesh *dm_dst, Mesh *me_dst, const int dtdata_type, const bool dirty_nors_dst, const bool use_split_nors_src, const float split_angle_src) { if (dtdata_type == DT_TYPE_LNOR) { /* Compute custom normals into regular loop normals, which will be used for the transfer. */ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert; const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert; MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge; const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge; MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly; const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly; MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop; const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop; CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata; CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata; const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0; const float split_angle_dst = me_dst->smoothresh; dm_src->calcLoopNormals(dm_src, use_split_nors_src, split_angle_src); if (dm_dst) { dm_dst->calcLoopNormals(dm_dst, use_split_nors_dst, split_angle_dst); } else { float (*poly_nors_dst)[3]; float (*loop_nors_dst)[3]; short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); /* Cache poly nors into a temp CDLayer. */ poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL); if (dirty_nors_dst || !poly_nors_dst) { if (!poly_nors_dst) { poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst); CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); } BKE_mesh_calc_normals_poly(verts_dst, num_verts_dst, loops_dst, polys_dst, num_loops_dst, num_polys_dst, poly_nors_dst, true); } /* Cache loop nors into a temp CDLayer. */ loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL); if (dirty_nors_dst || loop_nors_dst) { if (!loop_nors_dst) { loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, num_loops_dst); CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); } BKE_mesh_normals_loop_split(verts_dst, num_verts_dst, edges_dst, num_edges_dst, loops_dst, loop_nors_dst, num_loops_dst, polys_dst, (const float (*)[3])poly_nors_dst, num_polys_dst, use_split_nors_dst, split_angle_dst, NULL, custom_nors_dst, NULL); } } } }
static void allocate_custom_layers(CustomData *data, int type, int num_elements, int num_layers) { int i; for (i = 0; i < num_layers; i++) { CustomData_add_layer(data, type, CD_DEFAULT, NULL, num_elements); } }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { SculptSession *ss= ob->sculpt; int sculpting= (ob->mode & OB_MODE_SCULPT) && ss; MultiresModifierData *mmd = (MultiresModifierData*)md; DerivedMesh *result; Mesh *me= (Mesh*)ob->data; if(mmd->totlvl) { if(!CustomData_get_layer(&me->fdata, CD_MDISPS)) { /* multires always needs a displacement layer */ CustomData_add_layer(&me->fdata, CD_MDISPS, CD_CALLOC, NULL, me->totface); } } result = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams, isFinalCalc); if(result == dm) return dm; if(useRenderParams || !isFinalCalc) { DerivedMesh *cddm= CDDM_copy(result); result->release(result); result= cddm; } else if(sculpting) { /* would be created on the fly too, just nicer this way on first stroke after e.g. switching levels */ ss->pbvh= result->getPBVH(ob, result); } return result; }
static void mesh_add_faces(Mesh *mesh, int len) { CustomData fdata; MFace *mface; int i, totface; if(len == 0) return; totface= mesh->totface + len; /* new face count */ /* update customdata */ CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface); CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface); if(!CustomData_has_layer(&fdata, CD_MFACE)) CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface); CustomData_free(&mesh->fdata, mesh->totface); mesh->fdata= fdata; mesh_update_customdata_pointers(mesh); /* set default flags */ mface= &mesh->mface[mesh->totface]; for(i=0; i<len; i++, mface++) mface->flag= ME_FACE_SEL; mesh->totface= totface; }
static void mesh_add_verts(Mesh *mesh, int len) { CustomData vdata; MVert *mvert; int i, totvert; if(len == 0) return; totvert= mesh->totvert + len; CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert); if(!CustomData_has_layer(&vdata, CD_MVERT)) CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); CustomData_free(&mesh->vdata, mesh->totvert); mesh->vdata= vdata; mesh_update_customdata_pointers(mesh); /* scan the input list and insert the new vertices */ mvert= &mesh->mvert[mesh->totvert]; for(i=0; i<len; i++, mvert++) mvert->flag |= SELECT; /* set final vertex list size */ mesh->totvert= totvert; }
static void rna_Mesh_create_normals_split(Mesh *mesh) { if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop); CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } }
// ================================================================= // This functin is copied from source/blender/editors/mesh/mesh_data.c // // TODO: (As discussed with sergey-) : // Maybe move this function to blenderkernel/intern/mesh.c // and add definition to BKE_mesh.c // ================================================================= void MeshImporter::mesh_add_edges(Mesh *mesh, int len) { CustomData edata; MEdge *medge; int i, totedge; if (len == 0) return; totedge = mesh->totedge + len; /* update customdata */ CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge); if (!CustomData_has_layer(&edata, CD_MEDGE)) CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); CustomData_free(&mesh->edata, mesh->totedge); mesh->edata = edata; BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */ /* set default flags */ medge = &mesh->medge[mesh->totedge]; for (i = 0; i < len; i++, medge++) medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; mesh->totedge = totedge; }
int ED_mesh_color_add(bContext *C, Scene *scene, Object *ob, Mesh *me) { 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); 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(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface); else CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface); CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum); mesh_update_customdata_pointers(me); if(!mcol) shadeMeshMCol(scene, ob, me); } DAG_id_flush_update(&me->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, me); return 1; }
void ED_vgroup_data_create(ID *id) { /* create deform verts */ if(GS(id->name)==ID_ME) { Mesh *me= (Mesh *)id; me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert); } else if(GS(id->name)==ID_LT) { Lattice *lt= (Lattice *)id; lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert"); } }
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); }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag flag) { MultiresModifierData *mmd = (MultiresModifierData *)md; DerivedMesh *result; Mesh *me = (Mesh *)ob->data; const int useRenderParams = flag & MOD_APPLY_RENDER; if (mmd->totlvl) { if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) { /* multires always needs a displacement layer */ CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); } } result = multires_dm_create_from_derived(mmd, 0, dm, ob, useRenderParams); if (result == dm) return dm; if(useRenderParams || !(flag & MOD_APPLY_USECACHE)) { DerivedMesh *cddm; cddm = CDDM_copy(result); /* copy hidden flag to vertices */ if (!useRenderParams) { struct MDisps *mdisps; mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); if (mdisps) { subsurf_copy_grid_hidden(result, me->mpoly, cddm->getVertArray(cddm), mdisps); BKE_mesh_flush_hidden_from_verts(cddm->getVertArray(cddm), cddm->getLoopArray(cddm), cddm->getEdgeArray(cddm), cddm->getNumEdges(cddm), cddm->getPolyArray(cddm), cddm->getNumPolys(cddm)); } } result->release(result); result = cddm; } return result; }
void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me) { // vertices COLLADAFW::MeshVertexData& pos = mesh->getPositions(); int stride = pos.getStride(0); if (stride == 0) stride = 3; me->totvert = mesh->getPositions().getFloatValues()->getCount() / stride; me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); MVert *mvert; int i; for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { get_vector(mvert->co, pos, i, stride); } }
static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap) { float (*r_looptangents)[4]; if (CustomData_has_layer(&mesh->ldata, CD_MLOOPTANGENT)) { r_looptangents = CustomData_get_layer(&mesh->ldata, CD_MLOOPTANGENT); memset(r_looptangents, 0, sizeof(float[4]) * mesh->totloop); } else { r_looptangents = CustomData_add_layer(&mesh->ldata, CD_MLOOPTANGENT, CD_CALLOC, NULL, mesh->totloop); CustomData_set_layer_flag(&mesh->ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY); } /* Compute loop normals if needed. */ if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { BKE_mesh_calc_normals_split(mesh); } BKE_mesh_loop_tangents(mesh, uvmap, r_looptangents, reports); }
static void rna_Mesh_normals_split_custom_do(Mesh *mesh, float (*custom_loopnors)[3], const bool use_vertices) { float (*polynors)[3]; short (*clnors)[2]; const int numloops = mesh->totloop; bool free_polynors = false; clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); if (clnors) { memset(clnors, 0, sizeof(*clnors) * numloops); } else { clnors = CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, numloops); } if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL); } else { polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__); BKE_mesh_calc_normals_poly( mesh->mvert, NULL, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, polynors, false); free_polynors = true; } if (use_vertices) { BKE_mesh_normals_loop_custom_from_vertices_set( mesh->mvert, custom_loopnors, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, clnors); } else { BKE_mesh_normals_loop_custom_set( mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, custom_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, clnors); } if (free_polynors) { MEM_freeN(polynors); } }
static void data_transfer_dtdata_type_postprocess( Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *UNUSED(dm_src), DerivedMesh *dm_dst, Mesh *me_dst, const int dtdata_type, const bool changed) { if (dtdata_type == DT_TYPE_LNOR) { /* Bake edited destination loop normals into custom normals again. */ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert; const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert; MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge; const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge; MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly; const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly; MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop; const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop; CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata; CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata; const float (*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL); float (*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL); short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); BLI_assert(poly_nors_dst); if (!changed) { return; } if (!custom_nors_dst) { custom_nors_dst = CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops_dst); } /* Note loop_nors_dst contains our custom normals as transferred from source... */ BKE_mesh_normals_loop_custom_set(verts_dst, num_verts_dst, edges_dst, num_edges_dst, loops_dst, loop_nors_dst, num_loops_dst, polys_dst, poly_nors_dst, num_polys_dst, custom_nors_dst); } }
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 void update_tface_color_layer(DerivedMesh *dm) { MTFace *tface = DM_get_tessface_data_layer(dm, CD_MTFACE); MFace *mface = dm->getTessFaceArray(dm); MCol *finalCol; int i, j; MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); if (!mcol) mcol = dm->getTessFaceDataArray(dm, CD_MCOL); if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) { finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL); } else { finalCol = MEM_mallocN(sizeof(MCol) * 4 * dm->getNumTessFaces(dm), "add_tface_color_layer"); CustomData_add_layer(&dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData); } for (i = 0; i < dm->getNumTessFaces(dm); i++) { Material *ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1); if (ma && (ma->game.flag & GEMAT_INVISIBLE)) { if (mcol) memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4); else for (j = 0; j < 4; j++) { finalCol[i * 4 + j].b = 255; finalCol[i * 4 + j].g = 255; finalCol[i * 4 + j].r = 255; } } else if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) { for (j = 0; j < 4; j++) { finalCol[i * 4 + j].b = 255; finalCol[i * 4 + j].g = 0; finalCol[i * 4 + j].r = 255; } } else if (ma && (ma->shade_flag & MA_OBCOLOR)) { for (j = 0; j < 4; j++) { finalCol[i * 4 + j].b = Gtexdraw.obcol[0]; finalCol[i * 4 + j].g = Gtexdraw.obcol[1]; finalCol[i * 4 + j].r = Gtexdraw.obcol[2]; } } else if (!mcol) { if (tface) { for (j = 0; j < 4; j++) { finalCol[i * 4 + j].b = 255; finalCol[i * 4 + j].g = 255; finalCol[i * 4 + j].r = 255; } } else { float col[3]; if (ma) { if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); else copy_v3_v3(col, &ma->r); for (j = 0; j < 4; j++) { finalCol[i * 4 + j].b = FTOCHAR(col[0]); finalCol[i * 4 + j].g = FTOCHAR(col[1]); finalCol[i * 4 + j].r = FTOCHAR(col[2]); } } else for (j = 0; j < 4; j++) { finalCol[i * 4 + j].b = 255; finalCol[i * 4 + j].g = 255; finalCol[i * 4 + j].r = 255; } } } else { for (j = 0; j < 4; j++) { finalCol[i * 4 + j].r = mcol[i * 4 + j].r; finalCol[i * 4 + j].g = mcol[i * 4 + j].g; finalCol[i * 4 + j].b = mcol[i * 4 + j].b; } } } }
bool data_transfer_layersmapping_vgroups( ListBase *r_map, 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, Object *ob_src, Object *ob_dst, CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, const int fromlayers, const int tolayers) { int idx_src, idx_dst; MDeformVert *data_src, *data_dst = NULL; const size_t elem_size = sizeof(*((MDeformVert *)NULL)); /* Note: VGroups are a bit hairy, since their layout is defined on object level (ob->defbase), while their actual * data is a (mesh) CD layer. * This implies we may have to handle data layout itself while having NULL data itself, * and even have to support NULL data_src in transfer data code (we always create a data_dst, though). */ if (BLI_listbase_is_empty(&ob_src->defbase)) { if (use_delete) { BKE_object_defgroup_remove_all(ob_dst); } return true; } data_src = CustomData_get_layer(cd_src, CD_MDEFORMVERT); data_dst = CustomData_get_layer(cd_dst, CD_MDEFORMVERT); if (data_dst && 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, CD_MDEFORMVERT, num_elem_dst); } if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) { /* Note: use_delete has not much meaning in this case, ignored. */ if (fromlayers >= 0) { idx_src = fromlayers; BLI_assert(idx_src < BLI_listbase_count(&ob_src->defbase)); } else if ((idx_src = ob_src->actdef - 1) == -1) { return false; } if (tolayers >= 0) { /* Note: in this case we assume layer exists! */ idx_dst = tolayers; BLI_assert(idx_dst < BLI_listbase_count(&ob_dst->defbase)); } else if (tolayers == DT_LAYERS_ACTIVE_DST) { if ((idx_dst = ob_dst->actdef - 1) == -1) { bDeformGroup *dg_src; if (!use_create) { return true; } dg_src = BLI_findlink(&ob_src->defbase, idx_src); BKE_object_defgroup_add_name(ob_dst, dg_src->name); idx_dst = ob_dst->actdef - 1; } } else if (tolayers == DT_LAYERS_INDEX_DST) { int num = BLI_listbase_count(&ob_src->defbase); idx_dst = idx_src; if (num <= idx_dst) { if (!use_create) { return true; } /* Create as much vgroups as necessary! */ for (; num <= idx_dst; num++) { BKE_object_defgroup_add(ob_dst); } } } else if (tolayers == DT_LAYERS_NAME_DST) { bDeformGroup *dg_src = BLI_findlink(&ob_src->defbase, idx_src); if ((idx_dst = defgroup_name_index(ob_dst, dg_src->name)) == -1) { if (!use_create) { return true; } BKE_object_defgroup_add_name(ob_dst, dg_src->name); idx_dst = ob_dst->actdef - 1; } } else { return false; } if (r_map) { /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest! * use_create is not relevant in this case */ if (!data_dst) { data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst); } data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights, data_src, data_dst, idx_src, idx_dst, elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL); } } else { int num_src, num_sel_unused; bool *use_layers_src = NULL; bool ret = false; switch (fromlayers) { case DT_LAYERS_ALL_SRC: use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_ALL, &num_src, &num_sel_unused); break; case DT_LAYERS_VGROUP_SRC_BONE_SELECT: use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_BONE_SELECT, &num_src, &num_sel_unused); break; case DT_LAYERS_VGROUP_SRC_BONE_DEFORM: use_layers_src = BKE_object_defgroup_subset_from_select_type(ob_src, WT_VGROUP_BONE_DEFORM, &num_src, &num_sel_unused); break; } if (use_layers_src) { ret = data_transfer_layersmapping_vgroups_multisrc_to_dst( r_map, mix_mode, mix_factor, mix_weights, num_elem_dst, use_create, use_delete, ob_src, ob_dst, data_src, data_dst, cd_src, cd_dst, use_dupref_dst, tolayers, use_layers_src, num_src); } MEM_SAFE_FREE(use_layers_src); return ret; } return true; }
static bool data_transfer_layersmapping_vgroups_multisrc_to_dst( ListBase *r_map, 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, Object *ob_src, Object *ob_dst, MDeformVert *data_src, MDeformVert *data_dst, CustomData *UNUSED(cd_src), CustomData *cd_dst, const bool UNUSED(use_dupref_dst), const int tolayers, bool *use_layers_src, const int num_layers_src) { int idx_src; int idx_dst; int tot_dst = BLI_listbase_count(&ob_dst->defbase); const size_t elem_size = sizeof(*((MDeformVert *)NULL)); switch (tolayers) { case DT_LAYERS_INDEX_DST: idx_dst = tot_dst; /* Find last source actually used! */ idx_src = num_layers_src; while (idx_src-- && !use_layers_src[idx_src]); idx_src++; if (idx_dst < idx_src) { if (!use_create) { return false; } /* Create as much vgroups as necessary! */ for (; idx_dst < idx_src; idx_dst++) { BKE_object_defgroup_add(ob_dst); } } else if (use_delete && idx_dst > idx_src) { while (idx_dst-- > idx_src) { BKE_object_defgroup_remove(ob_dst, ob_dst->defbase.last); } } if (r_map) { /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest! * Again, use_create is not relevant in this case */ if (!data_dst) { data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst); } while (idx_src--) { if (!use_layers_src[idx_src]) { continue; } data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights, data_src, data_dst, idx_src, idx_src, elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL); } } break; case DT_LAYERS_NAME_DST: { bDeformGroup *dg_src, *dg_dst; if (use_delete) { /* Remove all unused dst vgroups first, simpler in this case. */ for (dg_dst = ob_dst->defbase.first; dg_dst;) { bDeformGroup *dg_dst_next = dg_dst->next; if (defgroup_name_index(ob_src, dg_dst->name) == -1) { BKE_object_defgroup_remove(ob_dst, dg_dst); } dg_dst = dg_dst_next; } } for (idx_src = 0, dg_src = ob_src->defbase.first; idx_src < num_layers_src; idx_src++, dg_src = dg_src->next) { if (!use_layers_src[idx_src]) { continue; } if ((idx_dst = defgroup_name_index(ob_dst, dg_src->name)) == -1) { if (!use_create) { if (r_map) { BLI_freelistN(r_map); } return false; } BKE_object_defgroup_add_name(ob_dst, dg_src->name); idx_dst = ob_dst->actdef - 1; } if (r_map) { /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest! * use_create is not relevant in this case */ if (!data_dst) { data_dst = CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_CALLOC, NULL, num_elem_dst); } data_transfer_layersmapping_add_item( r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights, data_src, data_dst, idx_src, idx_dst, elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL); } } break; } default: return false; } return true; }
static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd) { DerivedMesh *result; MVert *mverts; MPoly *mpolys; MLoop *mloops; int *origindex; int cdlayer; const int rx = omd->resolution * omd->resolution; const int ry = omd->resolution * omd->resolution; const int res_x = rx * omd->repeat_x; const int res_y = ry * omd->repeat_y; const int num_verts = (res_x + 1) * (res_y + 1); /* const int num_edges = (res_x * res_y * 2) + res_x + res_y; */ /* UNUSED BMESH */ const int num_faces = res_x * res_y; float sx = omd->size * omd->spatial_size; float sy = omd->size * omd->spatial_size; const float ox = -sx / 2.0f; const float oy = -sy / 2.0f; float ix, iy; int x, y; sx /= rx; sy /= ry; result = CDDM_new(num_verts, 0, 0, num_faces * 4, num_faces); mverts = CDDM_get_verts(result); mpolys = CDDM_get_polys(result); mloops = CDDM_get_loops(result); origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX); /* create vertices */ #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) for (y = 0; y <= res_y; y++) { for (x = 0; x <= res_x; x++) { const int i = y * (res_x + 1) + x; float *co = mverts[i].co; co[0] = ox + (x * sx); co[1] = oy + (y * sy); co[2] = 0; } } /* create faces */ #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) for (y = 0; y < res_y; y++) { for (x = 0; x < res_x; x++) { const int fi = y * res_x + x; const int vi = y * (res_x + 1) + x; MPoly *mp = &mpolys[fi]; MLoop *ml = &mloops[fi * 4]; ml->v = vi; ml++; ml->v = vi + 1; ml++; ml->v = vi + 1 + res_x + 1; ml++; ml->v = vi + res_x + 1; ml++; mp->loopstart = fi * 4; mp->totloop = 4; mp->flag |= ME_SMOOTH; /* generated geometry does not map to original faces */ origindex[fi] = ORIGINDEX_NONE; } } CDDM_calc_edges(result); /* add uvs */ cdlayer = CustomData_number_of_layers(&result->loopData, CD_MLOOPUV); if (cdlayer < MAX_MTFACE) { MLoopUV *mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_faces * 4); CustomData_add_layer(&result->polyData, CD_MTEXPOLY, CD_CALLOC, NULL, num_faces); if (mloopuvs) { /* unlikely to fail */ ix = 1.0 / rx; iy = 1.0 / ry; #pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES) for (y = 0; y < res_y; y++) { for (x = 0; x < res_x; x++) { const int i = y * res_x + x; MLoopUV *luv = &mloopuvs[i * 4]; luv->uv[0] = x * ix; luv->uv[1] = y * iy; luv++; luv->uv[0] = (x + 1) * ix; luv->uv[1] = y * iy; luv++; luv->uv[0] = (x + 1) * ix; luv->uv[1] = (y + 1) * iy; luv++; luv->uv[0] = x * ix; luv->uv[1] = (y + 1) * iy; luv++; } } } } result->dirty |= DM_DIRTY_NORMALS; return result; }
/** * \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); } }
/** * 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); }
// ================================================================= // 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); } } }
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; }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag flag) { MultiresModifierData *mmd = (MultiresModifierData *)md; DerivedMesh *result; Mesh *me = (Mesh *)ob->data; const bool useRenderParams = (flag & MOD_APPLY_RENDER) != 0; const bool ignore_simplify = (flag & MOD_APPLY_IGNORE_SIMPLIFY) != 0; MultiresFlags flags = 0; const bool has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); if (mmd->totlvl) { if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) { /* multires always needs a displacement layer */ CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); } } if (has_mask) flags |= MULTIRES_ALLOC_PAINT_MASK; if (useRenderParams) flags |= MULTIRES_USE_RENDER_PARAMS; if (ignore_simplify) flags |= MULTIRES_IGNORE_SIMPLIFY; result = multires_make_derived_from_derived(dm, mmd, ob, flags); if (result == dm) return dm; if (useRenderParams || !(flag & MOD_APPLY_USECACHE)) { DerivedMesh *cddm; cddm = CDDM_copy(result); /* copy hidden/masks to vertices */ if (!useRenderParams) { struct MDisps *mdisps; struct GridPaintMask *grid_paint_mask; mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); grid_paint_mask = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK); if (mdisps) { subsurf_copy_grid_hidden(result, me->mpoly, cddm->getVertArray(cddm), mdisps); BKE_mesh_flush_hidden_from_verts_ex(cddm->getVertArray(cddm), cddm->getLoopArray(cddm), cddm->getEdgeArray(cddm), cddm->getNumEdges(cddm), cddm->getPolyArray(cddm), cddm->getNumPolys(cddm)); } if (grid_paint_mask) { float *paint_mask = CustomData_add_layer(&cddm->vertData, CD_PAINT_MASK, CD_CALLOC, NULL, cddm->getNumVerts(cddm)); subsurf_copy_grid_paint_mask(result, me->mpoly, paint_mask, grid_paint_mask); } } result->release(result); result = cddm; } return result; }
int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md) { Object *obn; ParticleSystem *psys; ParticleCacheKey *key, **cache; ParticleSettings *part; Mesh *me; MVert *mvert; MEdge *medge; int a, k, kmax; int totvert=0, totedge=0, cvert=0; int totpart=0, totchild=0; if(md->type != eModifierType_ParticleSystem) return 0; if(ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0; psys=((ParticleSystemModifierData *)md)->psys; part= psys->part; if(part->ren_as != PART_DRAW_PATH || psys->pathcache == NULL) return 0; totpart= psys->totcached; totchild= psys->totchildcache; if(totchild && (part->draw&PART_DRAW_PARENT)==0) totpart= 0; /* count */ cache= psys->pathcache; for(a=0; a<totpart; a++) { key= cache[a]; if(key->steps > 0) { totvert+= key->steps+1; totedge+= key->steps; } } cache= psys->childcache; for(a=0; a<totchild; a++) { key= cache[a]; if(key->steps > 0) { totvert+= key->steps+1; totedge+= key->steps; } } if(totvert==0) return 0; /* add new mesh */ obn= add_object(scene, OB_MESH); me= obn->data; me->totvert= totvert; me->totedge= totedge; me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert); me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge); me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0); mvert= me->mvert; medge= me->medge; /* copy coordinates */ cache= psys->pathcache; for(a=0; a<totpart; a++) { key= cache[a]; kmax= key->steps; for(k=0; k<=kmax; k++,key++,cvert++,mvert++) { copy_v3_v3(mvert->co,key->co); if(k) { medge->v1= cvert-1; medge->v2= cvert; medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE; medge++; } else { /* cheap trick to select the roots */ mvert->flag |= SELECT; } } } cache=psys->childcache; for(a=0; a<totchild; a++) { key=cache[a]; kmax=key->steps; for(k=0; k<=kmax; k++,key++,cvert++,mvert++) { copy_v3_v3(mvert->co,key->co); if(k) { medge->v1=cvert-1; medge->v2=cvert; medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE; medge++; } else { /* cheap trick to select the roots */ mvert->flag |= SELECT; } } } DAG_scene_sort(bmain, scene); return 1; }
static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BLI_assert(mesh != NULL); WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; MDeformVert *dvert = NULL; MDeformWeight **dw1, **tdw1, **dw2, **tdw2; float *org_w; float *new_w; int *tidx, *indices = NULL; int numIdx = 0; int i; /* Flags. */ #if 0 const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; #endif /* Get number of verts. */ const int numVerts = mesh->totvert; /* 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) || BLI_listbase_is_empty(&ctx->object->defbase)) { return mesh; } /* Get vgroup idx from its name. */ const int defgrp_index = defgroup_name_index(ctx->object, wmd->defgrp_name_a); if (defgrp_index == -1) { return mesh; } /* Get second vgroup idx from its name, if given. */ int defgrp_index_other = -1; if (wmd->defgrp_name_b[0] != '\0') { defgrp_index_other = defgroup_name_index(ctx->object, wmd->defgrp_name_b); if (defgrp_index_other == -1) { return mesh; } } const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT); /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ if (!has_mdef) { /* If not affecting all vertices, just return. */ if (wmd->mix_set != MOD_WVG_SET_ALL) { return mesh; } } if (has_mdef) { dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts); } else { /* Add a valid data layer! */ dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts); } /* Ultimate security check. */ if (!dvert) { return mesh; } mesh->dvert = dvert; /* Find out which vertices to work on. */ tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGMix Modifier, tidx"); tdw1 = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw1"); tdw2 = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "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_index); if (dw) { tdw1[numIdx] = dw; tdw2[numIdx] = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_B: /* All vertices in second vgroup. */ for (i = 0; i < numVerts; i++) { MDeformWeight *dw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; if (dw) { tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_index); 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_index); MDeformWeight *bdw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; 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_index); MDeformWeight *bdw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; 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_index); tdw2[i] = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; } numIdx = -1; break; } if (numIdx == 0) { /* Use no vertices! Hence, return org data. */ MEM_freeN(tdw1); MEM_freeN(tdw2); MEM_freeN(tidx); return mesh; } if (numIdx != -1) { indices = MEM_malloc_arrayN(numIdx, sizeof(int), "WeightVGMix Modifier, indices"); memcpy(indices, tidx, sizeof(int) * numIdx); dw1 = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw1"); memcpy(dw1, tdw1, sizeof(MDeformWeight *) * numIdx); MEM_freeN(tdw1); dw2 = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "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_malloc_arrayN(numIdx, sizeof(float), "WeightVGMix Modifier, org_w"); new_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGMix Modifier, new_w"); /* Mix weights. */ for (i = 0; i < numIdx; i++) { float weight2; 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. */ struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); weightvg_do_mask(ctx, numIdx, indices, org_w, new_w, ctx->object, mesh, wmd->mask_constant, wmd->mask_defgrp_name, 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_index, 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); MEM_SAFE_FREE(indices); /* Return the vgroup-modified mesh. */ return mesh; }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag flag) { DerivedMesh *dm = derivedData; DerivedMesh *result; ScrewModifierData *ltmd = (ScrewModifierData *) md; const int useRenderParams = flag & MOD_APPLY_RENDER; int *origindex; int mpoly_index = 0; unsigned int step; unsigned int i, j; unsigned int i1, i2; unsigned int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps; const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0; const int quad_ord[4] = { do_flip ? 3 : 0, do_flip ? 2 : 1, do_flip ? 1 : 2, do_flip ? 0 : 3, }; const int quad_ord_ofs[4] = { do_flip ? 2 : 0, do_flip ? 1 : 1, do_flip ? 0 : 2, do_flip ? 3 : 3, }; unsigned int maxVerts = 0, maxEdges = 0, maxPolys = 0; const unsigned int totvert = (unsigned int)dm->getNumVerts(dm); const unsigned int totedge = (unsigned int)dm->getNumEdges(dm); const unsigned int totpoly = (unsigned int)dm->getNumPolys(dm); unsigned int *edge_poly_map = NULL; /* orig edge to orig poly */ unsigned int *vert_loop_map = NULL; /* orig vert to orig loop */ /* UV Coords */ const unsigned int mloopuv_layers_tot = (unsigned int)CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV); MLoopUV **mloopuv_layers = BLI_array_alloca(mloopuv_layers, mloopuv_layers_tot); float uv_u_scale; float uv_v_minmax[2] = {FLT_MAX, -FLT_MAX}; float uv_v_range_inv; float uv_axis_plane[4]; char axis_char = 'X'; bool close; float angle = ltmd->angle; float screw_ofs = ltmd->screw_ofs; float axis_vec[3] = {0.0f, 0.0f, 0.0f}; float tmp_vec1[3], tmp_vec2[3]; float mat3[3][3]; float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */ float mtx_tx_inv[4][4]; /* inverted */ float mtx_tmp_a[4][4]; unsigned int vc_tot_linked = 0; short other_axis_1, other_axis_2; const float *tmpf1, *tmpf2; unsigned int edge_offset; MPoly *mpoly_orig, *mpoly_new, *mp_new; MLoop *mloop_orig, *mloop_new, *ml_new; MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new; MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base; ScrewVertConnect *vc, *vc_tmp, *vert_connect = NULL; const char mpoly_flag = (ltmd->flag & MOD_SCREW_SMOOTH_SHADING) ? ME_SMOOTH : 0; /* don't do anything? */ if (!totvert) return CDDM_from_template(dm, 0, 0, 0, 0, 0); switch (ltmd->axis) { case 0: other_axis_1 = 1; other_axis_2 = 2; break; case 1: other_axis_1 = 0; other_axis_2 = 2; break; default: /* 2, use default to quiet warnings */ other_axis_1 = 0; other_axis_2 = 1; break; } axis_vec[ltmd->axis] = 1.0f; if (ltmd->ob_axis) { /* calc the matrix relative to the axis object */ invert_m4_m4(mtx_tmp_a, ob->obmat); copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat); mul_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv); /* calc the axis vec */ mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */ normalize_v3(axis_vec); /* screw */ if (ltmd->flag & MOD_SCREW_OBJECT_OFFSET) { /* find the offset along this axis relative to this objects matrix */ float totlen = len_v3(mtx_tx[3]); if (totlen != 0.0f) { float zero[3] = {0.0f, 0.0f, 0.0f}; float cp[3]; screw_ofs = closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec); } else { screw_ofs = 0.0f; } } /* angle */ #if 0 /* cant incluide this, not predictable enough, though quite fun. */ if (ltmd->flag & MOD_SCREW_OBJECT_ANGLE) { float mtx3_tx[3][3]; copy_m3_m4(mtx3_tx, mtx_tx); float vec[3] = {0, 1, 0}; float cross1[3]; float cross2[3]; cross_v3_v3v3(cross1, vec, axis_vec); mul_v3_m3v3(cross2, mtx3_tx, cross1); { float c1[3]; float c2[3]; float axis_tmp[3]; cross_v3_v3v3(c1, cross2, axis_vec); cross_v3_v3v3(c2, axis_vec, c1); angle = angle_v3v3(cross1, c2); cross_v3_v3v3(axis_tmp, cross1, c2); normalize_v3(axis_tmp); if (len_v3v3(axis_tmp, axis_vec) > 1.0f) angle = -angle; } } #endif } else { /* exis char is used by i_rotate*/ axis_char = (char)(axis_char + ltmd->axis); /* 'X' + axis */ /* useful to be able to use the axis vec in some cases still */ zero_v3(axis_vec); axis_vec[ltmd->axis] = 1.0f; } /* apply the multiplier */ angle *= (float)ltmd->iter; screw_ofs *= (float)ltmd->iter; uv_u_scale = 1.0f / (float)(step_tot); /* multiplying the steps is a bit tricky, this works best */ step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1); /* will the screw be closed? * Note! smaller then FLT_EPSILON * 100 gives problems with float precision so its never closed. */ if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f)) { close = 1; step_tot--; if (step_tot < 3) step_tot = 3; maxVerts = totvert * step_tot; /* -1 because we're joining back up */ maxEdges = (totvert * step_tot) + /* these are the edges between new verts */ (totedge * step_tot); /* -1 because vert edges join */ maxPolys = totedge * step_tot; screw_ofs = 0.0f; } else { close = 0; if (step_tot < 3) step_tot = 3; maxVerts = totvert * step_tot; /* -1 because we're joining back up */ maxEdges = (totvert * (step_tot - 1)) + /* these are the edges between new verts */ (totedge * step_tot); /* -1 because vert edges join */ maxPolys = totedge * (step_tot - 1); } if ((ltmd->flag & MOD_SCREW_UV_STRETCH_U) == 0) { uv_u_scale = (uv_u_scale / (float)ltmd->iter) * (angle / ((float)M_PI * 2.0f)); } result = CDDM_from_template(dm, (int)maxVerts, (int)maxEdges, 0, (int)maxPolys * 4, (int)maxPolys); /* copy verts from mesh */ mvert_orig = dm->getVertArray(dm); medge_orig = dm->getEdgeArray(dm); mvert_new = result->getVertArray(result); mpoly_new = result->getPolyArray(result); mloop_new = result->getLoopArray(result); medge_new = result->getEdgeArray(result); if (!CustomData_has_layer(&result->polyData, CD_ORIGINDEX)) { CustomData_add_layer(&result->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, (int)maxPolys); } origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX); DM_copy_vert_data(dm, result, 0, 0, (int)totvert); /* copy first otherwise this overwrites our own vertex normals */ if (mloopuv_layers_tot) { float zero_co[3] = {0}; plane_from_point_normal_v3(uv_axis_plane, zero_co, axis_vec); } if (mloopuv_layers_tot) { unsigned int uv_lay; for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) { mloopuv_layers[uv_lay] = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, (int)uv_lay); } if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) { for (i = 0, mv_orig = mvert_orig; i < totvert; i++, mv_orig++) { const float v = dist_squared_to_plane_v3(mv_orig->co, uv_axis_plane); uv_v_minmax[0] = min_ff(v, uv_v_minmax[0]); uv_v_minmax[1] = max_ff(v, uv_v_minmax[1]); } uv_v_minmax[0] = sqrtf_signed(uv_v_minmax[0]); uv_v_minmax[1] = sqrtf_signed(uv_v_minmax[1]); } uv_v_range_inv = uv_v_minmax[1] - uv_v_minmax[0]; uv_v_range_inv = uv_v_range_inv ? 1.0f / uv_v_range_inv : 0.0f; } /* Set the locations of the first set of verts */ mv_new = mvert_new; mv_orig = mvert_orig; /* Copy the first set of edges */ med_orig = medge_orig; med_new = medge_new; for (i = 0; i < totedge; i++, med_orig++, med_new++) { med_new->v1 = med_orig->v1; med_new->v2 = med_orig->v2; med_new->crease = med_orig->crease; med_new->flag = med_orig->flag & ~ME_LOOSEEDGE; } /* build polygon -> edge map */ if (totpoly) { MPoly *mp_orig; mpoly_orig = dm->getPolyArray(dm); mloop_orig = dm->getLoopArray(dm); edge_poly_map = MEM_mallocN(sizeof(*edge_poly_map) * totedge, __func__); memset(edge_poly_map, 0xff, sizeof(*edge_poly_map) * totedge); vert_loop_map = MEM_mallocN(sizeof(*vert_loop_map) * totvert, __func__); memset(vert_loop_map, 0xff, sizeof(*vert_loop_map) * totvert); for (i = 0, mp_orig = mpoly_orig; i < totpoly; i++, mp_orig++) { unsigned int loopstart = (unsigned int)mp_orig->loopstart; unsigned int loopend = loopstart + (unsigned int)mp_orig->totloop; MLoop *ml_orig = &mloop_orig[loopstart]; unsigned int k; for (k = loopstart; k < loopend; k++, ml_orig++) { edge_poly_map[ml_orig->e] = i; vert_loop_map[ml_orig->v] = k; /* also order edges based on faces */ if (medge_new[ml_orig->e].v1 != ml_orig->v) { SWAP(unsigned int, medge_new[ml_orig->e].v1, medge_new[ml_orig->e].v2); } } } }