/* Get the vertex's unique ID from the log */ static unsigned int bm_log_vert_id_get(BMLog *log, BMVert *v) { BLI_assert(BLI_ghash_haskey(log->elem_to_id, v)); return GET_INT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, v)); }
/* Get a vertex from its unique ID */ static BMVert *bm_log_vert_from_id(BMLog *log, unsigned int id) { void *key = SET_INT_IN_POINTER(id); BLI_assert(BLI_ghash_haskey(log->id_to_elem, key)); return BLI_ghash_lookup(log->id_to_elem, key); }
/* Iterate over the CSG Output Descriptors and create a new DerivedMesh from them */ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( CSG_FaceIteratorDescriptor *face_it, CSG_VertexIteratorDescriptor *vertex_it, float parinv[][4], float mapmat[][4], Material **mat, int *totmat, DerivedMesh *dm1, Object *ob1, DerivedMesh *dm2, Object *ob2) { DerivedMesh *result, *orig_dm; GHash *material_hash = NULL; Mesh *me1= (Mesh*)ob1->data; Mesh *me2= (Mesh*)ob2->data; int i; // create a new DerivedMesh result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements); CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH, CD_DEFAULT, face_it->num_elements); CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH, CD_DEFAULT, face_it->num_elements); // step through the vertex iterators: for (i = 0; !vertex_it->Done(vertex_it->it); i++) { CSG_IVertex csgvert; MVert *mvert = CDDM_get_vert(result, i); // retrieve a csg vertex from the boolean module vertex_it->Fill(vertex_it->it, &csgvert); vertex_it->Step(vertex_it->it); // we have to map the vertex coordinates back in the coordinate frame // of the resulting object, since it was computed in world space mul_v3_m4v3(mvert->co, parinv, csgvert.position); } // a hash table to remap materials to indices if (mat) { material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "CSG_mat gh"); *totmat = 0; } // step through the face iterators for(i = 0; !face_it->Done(face_it->it); i++) { Mesh *orig_me; Object *orig_ob; Material *orig_mat; CSG_IFace csgface; MFace *mface; int orig_index, mat_nr; // retrieve a csg face from the boolean module face_it->Fill(face_it->it, &csgface); face_it->Step(face_it->it); // find the original mesh and data orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2; orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2; orig_me = (orig_ob == ob1)? me1: me2; orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1); // copy all face layers, including mface CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1); // set mface mface = CDDM_get_face(result, i); mface->v1 = csgface.vertex_index[0]; mface->v2 = csgface.vertex_index[1]; mface->v3 = csgface.vertex_index[2]; mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0; // set material, based on lookup in hash table orig_mat= give_current_material(orig_ob, mface->mat_nr+1); if (mat && orig_mat) { if (!BLI_ghash_haskey(material_hash, orig_mat)) { mat[*totmat] = orig_mat; mat_nr = mface->mat_nr = (*totmat)++; BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr)); } else mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat)); } else mface->mat_nr = 0; InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number, (orig_me == me2)? mapmat: NULL); test_index_face(mface, &result->faceData, i, csgface.vertex_number); } if (material_hash) BLI_ghash_free(material_hash, NULL, NULL); CDDM_calc_edges(result); CDDM_calc_normals(result); return result; }
static void codegen_set_unique_ids(ListBase *nodes) { GHash *bindhash, *definehash; GPUNode *node; GPUInput *input; GPUOutput *output; int id = 1, texid = 0; bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh"); definehash = BLI_ghash_ptr_new("codegen_set_unique_ids2 gh"); for (node = nodes->first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { /* set id for unique names of uniform variables */ input->id = id++; input->bindtex = false; input->definetex = false; /* set texid used for settings texture slot with multitexture */ if (codegen_input_has_texture(input) && ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) { /* assign only one texid per buffer to avoid sampling * the same texture twice */ if (input->link) { /* input is texture from buffer */ codegen_set_texid(bindhash, input, &texid, input->link); } else if (input->ima) { /* input is texture from image */ codegen_set_texid(bindhash, input, &texid, input->ima); } else if (input->prv) { /* input is texture from preview render */ codegen_set_texid(bindhash, input, &texid, input->prv); } else if (input->tex) { /* input is user created texture, check tex pointer */ codegen_set_texid(bindhash, input, &texid, input->tex); } /* make sure this pixel is defined exactly once */ if (input->source == GPU_SOURCE_TEX_PIXEL) { if (input->ima) { if (!BLI_ghash_haskey(definehash, input->ima)) { input->definetex = true; BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid)); } } else { if (!BLI_ghash_haskey(definehash, input->link)) { input->definetex = true; BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid)); } } } } } for (output = node->outputs.first; output; output = output->next) /* set id for unique names of tmp variables storing output */ output->id = id++; } BLI_ghash_free(bindhash, NULL, NULL); BLI_ghash_free(definehash, NULL, NULL); }
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { DerivedMesh *dm = derivedData; DerivedMesh *result; BuildModifierData *bmd = (BuildModifierData *) md; int i, j, k; int numFaces_dst, numEdges_dst, numLoops_dst = 0; int *vertMap, *edgeMap, *faceMap; float frac; MPoly *mpoly_dst; MLoop *ml_dst, *ml_src /*, *mloop_dst */; GHashIterator *hashIter; /* maps vert indices in old mesh to indices in new mesh */ GHash *vertHash = BLI_ghash_int_new("build ve apply gh"); /* maps edge indices in new mesh to indices in old mesh */ GHash *edgeHash = BLI_ghash_int_new("build ed apply gh"); GHash *edgeHash2 = BLI_ghash_int_new("build ed apply gh"); const int numVert_src = dm->getNumVerts(dm); const int numEdge_src = dm->getNumEdges(dm); const int numPoly_src = dm->getNumPolys(dm); MPoly *mpoly_src = dm->getPolyArray(dm); MLoop *mloop_src = dm->getLoopArray(dm); MEdge *medge_src = dm->getEdgeArray(dm); MVert *mvert_src = dm->getVertArray(dm); vertMap = MEM_mallocN(sizeof(*vertMap) * numVert_src, "build modifier vertMap"); edgeMap = MEM_mallocN(sizeof(*edgeMap) * numEdge_src, "build modifier edgeMap"); faceMap = MEM_mallocN(sizeof(*faceMap) * numPoly_src, "build modifier faceMap"); #pragma omp parallel sections if (numVert_src + numEdge_src + numPoly_src >= DM_OMP_LIMIT) { #pragma omp section { range_vn_i(vertMap, numVert_src, 0); } #pragma omp section { range_vn_i(edgeMap, numEdge_src, 0); } #pragma omp section { range_vn_i(faceMap, numPoly_src, 0); } } frac = (BKE_scene_frame_get(md->scene) - bmd->start) / bmd->length; CLAMP(frac, 0.0f, 1.0f); numFaces_dst = numPoly_src * frac; numEdges_dst = numEdge_src * frac; /* if there's at least one face, build based on faces */ if (numFaces_dst) { MPoly *mpoly, *mp; MLoop *ml, *mloop; MEdge *medge; if (bmd->randomize) { BLI_array_randomize(faceMap, sizeof(*faceMap), numPoly_src, bmd->seed); } /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ mpoly = mpoly_src; mloop = mloop_src; for (i = 0; i < numFaces_dst; i++) { mp = mpoly + faceMap[i]; ml = mloop + mp->loopstart; for (j = 0; j < mp->totloop; j++, ml++) { if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v))) BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(ml->v), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); } numLoops_dst += mp->totloop; } /* get the set of edges that will be in the new mesh (i.e. all edges * that have both verts in the new mesh) */ medge = medge_src; for (i = 0; i < numEdge_src; i++) { MEdge *me = medge + i; if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) { j = BLI_ghash_size(edgeHash); BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j), SET_INT_IN_POINTER(i)); BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(j)); } } } else if (numEdges_dst) { MEdge *medge, *me; if (bmd->randomize) BLI_array_randomize(edgeMap, sizeof(*edgeMap), numEdge_src, bmd->seed); /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ medge = medge_src; for (i = 0; i < numEdges_dst; i++) { me = medge + edgeMap[i]; if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1))) { BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v1), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); } if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) { BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v2), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); } } /* get the set of edges that will be in the new mesh */ for (i = 0; i < numEdges_dst; i++) { j = BLI_ghash_size(edgeHash); BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j), SET_INT_IN_POINTER(edgeMap[i])); BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(edgeMap[i]), SET_INT_IN_POINTER(j)); } } else { int numVerts = numVert_src * frac; if (bmd->randomize) { BLI_array_randomize(vertMap, sizeof(*vertMap), numVert_src, bmd->seed); } /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ for (i = 0; i < numVerts; i++) { BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i)); } } /* now we know the number of verts, edges and faces, we can create * the mesh */ result = CDDM_from_template(dm, BLI_ghash_size(vertHash), BLI_ghash_size(edgeHash), 0, numLoops_dst, numFaces_dst); /* copy the vertices across */ for (hashIter = BLI_ghashIterator_new(vertHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { MVert source; MVert *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); source = mvert_src[oldIndex]; dest = CDDM_get_vert(result, newIndex); DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); /* copy the edges across, remapping indices */ for (i = 0; i < BLI_ghash_size(edgeHash); i++) { MEdge source; MEdge *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i))); source = medge_src[oldIndex]; dest = CDDM_get_edge(result, i); source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); DM_copy_edge_data(dm, result, oldIndex, i, 1); *dest = source; } mpoly_dst = CDDM_get_polys(result); /* mloop_dst = */ ml_dst = CDDM_get_loops(result); /* copy the faces across, remapping indices */ k = 0; for (i = 0; i < numFaces_dst; i++) { MPoly *source; MPoly *dest; source = mpoly_src + faceMap[i]; dest = mpoly_dst + i; DM_copy_poly_data(dm, result, faceMap[i], i, 1); *dest = *source; dest->loopstart = k; DM_copy_loop_data(dm, result, source->loopstart, dest->loopstart, dest->totloop); ml_src = mloop_src + source->loopstart; for (j = 0; j < source->totloop; j++, k++, ml_src++, ml_dst++) { ml_dst->v = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(ml_src->v))); ml_dst->e = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash2, SET_INT_IN_POINTER(ml_src->e))); } } BLI_ghash_free(vertHash, NULL, NULL); BLI_ghash_free(edgeHash, NULL, NULL); BLI_ghash_free(edgeHash2, NULL, NULL); MEM_freeN(vertMap); MEM_freeN(edgeMap); MEM_freeN(faceMap); return result; }
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { DerivedMesh *dm = derivedData; DerivedMesh *result; BuildModifierData *bmd = (BuildModifierData *) md; int i, j, k; int numFaces_dst, numEdges_dst, numLoops_dst = 0; int *vertMap, *edgeMap, *faceMap; float frac; MPoly *mpoly_dst; MLoop *ml_dst, *ml_src /*, *mloop_dst */; GHashIterator gh_iter; /* maps vert indices in old mesh to indices in new mesh */ GHash *vertHash = BLI_ghash_int_new("build ve apply gh"); /* maps edge indices in new mesh to indices in old mesh */ GHash *edgeHash = BLI_ghash_int_new("build ed apply gh"); GHash *edgeHash2 = BLI_ghash_int_new("build ed apply gh"); const int numVert_src = dm->getNumVerts(dm); const int numEdge_src = dm->getNumEdges(dm); const int numPoly_src = dm->getNumPolys(dm); MPoly *mpoly_src = dm->getPolyArray(dm); MLoop *mloop_src = dm->getLoopArray(dm); MEdge *medge_src = dm->getEdgeArray(dm); MVert *mvert_src = dm->getVertArray(dm); vertMap = MEM_malloc_arrayN(numVert_src, sizeof(*vertMap), "build modifier vertMap"); edgeMap = MEM_malloc_arrayN(numEdge_src, sizeof(*edgeMap), "build modifier edgeMap"); faceMap = MEM_malloc_arrayN(numPoly_src, sizeof(*faceMap), "build modifier faceMap"); range_vn_i(vertMap, numVert_src, 0); range_vn_i(edgeMap, numEdge_src, 0); range_vn_i(faceMap, numPoly_src, 0); frac = (BKE_scene_frame_get(md->scene) - bmd->start) / bmd->length; CLAMP(frac, 0.0f, 1.0f); if (bmd->flag & MOD_BUILD_FLAG_REVERSE) { frac = 1.0f - frac; } numFaces_dst = numPoly_src * frac; numEdges_dst = numEdge_src * frac; /* if there's at least one face, build based on faces */ if (numFaces_dst) { MPoly *mpoly, *mp; MLoop *ml, *mloop; MEdge *medge; uintptr_t hash_num, hash_num_alt; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { BLI_array_randomize(faceMap, sizeof(*faceMap), numPoly_src, bmd->seed); } /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ mpoly = mpoly_src; mloop = mloop_src; hash_num = 0; for (i = 0; i < numFaces_dst; i++) { mp = mpoly + faceMap[i]; ml = mloop + mp->loopstart; for (j = 0; j < mp->totloop; j++, ml++) { void **val_p; if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(ml->v), &val_p)) { *val_p = (void *)hash_num; hash_num++; } } numLoops_dst += mp->totloop; } BLI_assert(hash_num == BLI_ghash_len(vertHash)); /* get the set of edges that will be in the new mesh (i.e. all edges * that have both verts in the new mesh) */ medge = medge_src; hash_num = 0; hash_num_alt = 0; for (i = 0; i < numEdge_src; i++, hash_num_alt++) { MEdge *me = medge + i; if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) { BLI_ghash_insert(edgeHash, (void *)hash_num, (void *)hash_num_alt); BLI_ghash_insert(edgeHash2, (void *)hash_num_alt, (void *)hash_num); hash_num++; } } } else if (numEdges_dst) { MEdge *medge, *me; uintptr_t hash_num; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) BLI_array_randomize(edgeMap, sizeof(*edgeMap), numEdge_src, bmd->seed); /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ medge = medge_src; hash_num = 0; BLI_assert(hash_num == BLI_ghash_len(vertHash)); for (i = 0; i < numEdges_dst; i++) { void **val_p; me = medge + edgeMap[i]; if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(me->v1), &val_p)) { *val_p = (void *)hash_num; hash_num++; } if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(me->v2), &val_p)) { *val_p = (void *)hash_num; hash_num++; } } BLI_assert(hash_num == BLI_ghash_len(vertHash)); /* get the set of edges that will be in the new mesh */ for (i = 0; i < numEdges_dst; i++) { j = BLI_ghash_len(edgeHash); BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j), SET_INT_IN_POINTER(edgeMap[i])); BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(edgeMap[i]), SET_INT_IN_POINTER(j)); } } else { int numVerts = numVert_src * frac; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { BLI_array_randomize(vertMap, sizeof(*vertMap), numVert_src, bmd->seed); } /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ for (i = 0; i < numVerts; i++) { BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i)); } } /* now we know the number of verts, edges and faces, we can create * the mesh */ result = CDDM_from_template(dm, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), 0, numLoops_dst, numFaces_dst); /* copy the vertices across */ GHASH_ITER (gh_iter, vertHash) { MVert source; MVert *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)); source = mvert_src[oldIndex]; dest = CDDM_get_vert(result, newIndex); DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); *dest = source; }
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), DerivedMesh *derivedData, int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) { DerivedMesh *dm = derivedData; DerivedMesh *result; BuildModifierData *bmd = (BuildModifierData*) md; int i; int numFaces, numEdges; int *vertMap, *edgeMap, *faceMap; float frac; GHashIterator *hashIter; /* maps vert indices in old mesh to indices in new mesh */ GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "build ve apply gh"); /* maps edge indices in new mesh to indices in old mesh */ GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "build ed apply gh"); const int maxVerts= dm->getNumVerts(dm); const int maxEdges= dm->getNumEdges(dm); const int maxFaces= dm->getNumFaces(dm); vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts, "build modifier vertMap"); for(i = 0; i < maxVerts; ++i) vertMap[i] = i; edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges, "build modifier edgeMap"); for(i = 0; i < maxEdges; ++i) edgeMap[i] = i; faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces, "build modifier faceMap"); for(i = 0; i < maxFaces; ++i) faceMap[i] = i; frac = (BKE_curframe(md->scene) - bmd->start) / bmd->length; CLAMP(frac, 0.0f, 1.0f); numFaces = dm->getNumFaces(dm) * frac; numEdges = dm->getNumEdges(dm) * frac; /* if there's at least one face, build based on faces */ if(numFaces) { if(bmd->randomize) BLI_array_randomize(faceMap, sizeof(*faceMap), maxFaces, bmd->seed); /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ for(i = 0; i < numFaces; ++i) { MFace mf; dm->getFace(dm, faceMap[i], &mf); if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1))) BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2))) BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3))) BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); } /* get the set of edges that will be in the new mesh (i.e. all edges * that have both verts in the new mesh) */ for(i = 0; i < maxEdges; ++i) { MEdge me; dm->getEdge(dm, i, &me); if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2))) BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i)); } } else if(numEdges) { if(bmd->randomize) BLI_array_randomize(edgeMap, sizeof(*edgeMap), maxEdges, bmd->seed); /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ for(i = 0; i < numEdges; ++i) { MEdge me; dm->getEdge(dm, edgeMap[i], &me); if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))) BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2))) BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2), SET_INT_IN_POINTER(BLI_ghash_size(vertHash))); } /* get the set of edges that will be in the new mesh */ for(i = 0; i < numEdges; ++i) { MEdge me; dm->getEdge(dm, edgeMap[i], &me); BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(edgeMap[i])); } } else { int numVerts = dm->getNumVerts(dm) * frac; if(bmd->randomize) BLI_array_randomize(vertMap, sizeof(*vertMap), maxVerts, bmd->seed); /* get the set of all vert indices that will be in the final mesh, * mapped to the new indices */ for(i = 0; i < numVerts; ++i) BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i)); } /* now we know the number of verts, edges and faces, we can create * the mesh */ result = CDDM_from_template(dm, BLI_ghash_size(vertHash), BLI_ghash_size(edgeHash), numFaces); /* copy the vertices across */ for( hashIter = BLI_ghashIterator_new(vertHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { MVert source; MVert *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); dm->getVert(dm, oldIndex, &source); dest = CDDM_get_vert(result, newIndex); DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); /* copy the edges across, remapping indices */ for(i = 0; i < BLI_ghash_size(edgeHash); ++i) { MEdge source; MEdge *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i))); dm->getEdge(dm, oldIndex, &source); dest = CDDM_get_edge(result, i); source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); DM_copy_edge_data(dm, result, oldIndex, i, 1); *dest = source; } /* copy the faces across, remapping indices */ for(i = 0; i < numFaces; ++i) { MFace source; MFace *dest; int orig_v4; dm->getFace(dm, faceMap[i], &source); dest = CDDM_get_face(result, i); orig_v4 = source.v4; source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3))); if(source.v4) source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4))); DM_copy_face_data(dm, result, faceMap[i], i, 1); *dest = source; test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3)); } CDDM_calc_normals(result); BLI_ghash_free(vertHash, NULL, NULL); BLI_ghash_free(edgeHash, NULL, NULL); MEM_freeN(vertMap); MEM_freeN(edgeMap); MEM_freeN(faceMap); return result; }
/* seems messy, but thats what you get with not using pointers but channel names :) */ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *newnamep) { Object *ob; char newname[MAXBONENAME]; char oldname[MAXBONENAME]; /* names better differ! */ if (!STREQLEN(oldnamep, newnamep, MAXBONENAME)) { /* we alter newname string... so make copy */ BLI_strncpy(newname, newnamep, MAXBONENAME); /* we use oldname for search... so make copy */ BLI_strncpy(oldname, oldnamep, MAXBONENAME); /* now check if we're in editmode, we need to find the unique name */ if (arm->edbo) { EditBone *eBone = ED_armature_bone_find_name(arm->edbo, oldname); if (eBone) { unique_editbone_name(arm->edbo, newname, NULL); BLI_strncpy(eBone->name, newname, MAXBONENAME); } else { return; } } else { Bone *bone = BKE_armature_find_bone_name(arm, oldname); if (bone) { unique_bone_name(arm, newname); BLI_strncpy(bone->name, newname, MAXBONENAME); } else { return; } } /* do entire dbase - objects */ for (ob = G.main->object.first; ob; ob = ob->id.next) { ModifierData *md; /* we have the object using the armature */ if (arm == ob->data) { Object *cob; /* Rename the pose channel, if it exists */ if (ob->pose) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname); if (pchan) { GHash *gh = ob->pose->chanhash; /* remove the old hash entry, and replace with the new name */ if (gh) { BLI_assert(BLI_ghash_haskey(gh, pchan->name)); BLI_ghash_remove(gh, pchan->name, NULL, NULL); } BLI_strncpy(pchan->name, newname, MAXBONENAME); if (gh) { BLI_ghash_insert(gh, pchan->name, pchan); } } BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true); } /* Update any object constraints to use the new bone name */ for (cob = G.main->object.first; cob; cob = cob->id.next) { if (cob->constraints.first) constraint_bone_name_fix(ob, &cob->constraints, oldname, newname); if (cob->pose) { bPoseChannel *pchan; for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) { constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname); } } } } /* See if an object is parented to this armature */ if (ob->parent && (ob->parent->data == arm)) { if (ob->partype == PARBONE) { /* bone name in object */ if (STREQ(ob->parsubstr, oldname)) BLI_strncpy(ob->parsubstr, newname, MAXBONENAME); } } if (modifiers_usesArmature(ob, arm)) { bDeformGroup *dg = defgroup_find_name(ob, oldname); if (dg) { BLI_strncpy(dg->name, newname, MAXBONENAME); } } /* fix modifiers that might be using this name */ for (md = ob->modifiers.first; md; md = md->next) { switch (md->type) { case eModifierType_Hook: { HookModifierData *hmd = (HookModifierData *)md; if (hmd->object && (hmd->object->data == arm)) { if (STREQ(hmd->subtarget, oldname)) BLI_strncpy(hmd->subtarget, newname, MAXBONENAME); } break; } case eModifierType_UVWarp: { UVWarpModifierData *umd = (UVWarpModifierData *)md; if (umd->object_src && (umd->object_src->data == arm)) { if (STREQ(umd->bone_src, oldname)) BLI_strncpy(umd->bone_src, newname, MAXBONENAME); } if (umd->object_dst && (umd->object_dst->data == arm)) { if (STREQ(umd->bone_dst, oldname)) BLI_strncpy(umd->bone_dst, newname, MAXBONENAME); } break; } default: break; } } } /* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since * other ID-blocks may have drivers referring to this bone [#29822] */ // XXX: the ID here is for armatures, but most bone drivers are actually on the object instead... { BKE_animdata_fix_paths_rename_all(&arm->id, "pose.bones", oldname, newname); } /* correct view locking */ { bScreen *screen; for (screen = G.main->screen.first; screen; screen = screen->id.next) { ScrArea *sa; /* add regions */ for (sa = screen->areabase.first; sa; sa = sa->next) { SpaceLink *sl; for (sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_VIEW3D) { View3D *v3d = (View3D *)sl; if (v3d->ob_centre && v3d->ob_centre->data == arm) { if (STREQ(v3d->ob_centre_bone, oldname)) { BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME); } } } } } } } } }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) { MaskModifierData *mmd= (MaskModifierData *)md; DerivedMesh *dm= derivedData, *result= NULL; GHash *vertHash=NULL, *edgeHash, *faceHash; GHashIterator *hashIter; MDeformVert *dvert= NULL, *dv; int numFaces=0, numEdges=0, numVerts=0; int maxVerts, maxEdges, maxFaces; int i; /* Overview of Method: * 1. Get the vertices that are in the vertexgroup of interest * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices * 3. Make a new mesh containing only the mapping data */ /* get original number of verts, edges, and faces */ maxVerts= dm->getNumVerts(dm); maxEdges= dm->getNumEdges(dm); maxFaces= dm->getNumFaces(dm); /* check if we can just return the original mesh * - must have verts and therefore verts assigned to vgroups to do anything useful */ if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || (maxVerts == 0) || (ob->defbase.first == NULL) ) { return derivedData; } /* if mode is to use selected armature bones, aggregate the bone groups */ if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */ { GHash *vgroupHash; Object *oba= mmd->ob_arm; bPoseChannel *pchan; bDeformGroup *def; char *bone_select_array; int bone_select_tot= 0; /* check that there is armature object with bones to use, otherwise return original mesh */ if (ELEM3(NULL, mmd->ob_arm, mmd->ob_arm->pose, ob->defbase.first)) return derivedData; bone_select_array= MEM_mallocN(BLI_countlist(&ob->defbase) * sizeof(char), "mask array"); for (i = 0, def = ob->defbase.first; def; def = def->next, i++) { if (((pchan= get_pose_channel(oba->pose, def->name)) && pchan->bone && (pchan->bone->flag & BONE_SELECTED))) { bone_select_array[i]= TRUE; bone_select_tot++; } else { bone_select_array[i]= FALSE; } } /* hashes for finding mapping of: * - vgroups to indices -> vgroupHash (string, int) * - bones to vgroup indices -> boneHash (index of vgroup, dummy) */ vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "mask vgroup gh"); /* build mapping of names of vertex groups to indices */ for (i = 0, def = ob->defbase.first; def; def = def->next, i++) BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i)); /* if no bones selected, free hashes and return original mesh */ if (bone_select_tot == 0) { BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); return derivedData; } /* repeat the previous check, but for dverts */ dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); if (dvert == NULL) { BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); return derivedData; } /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert gh"); /* add vertices which exist in vertexgroups into vertHash for filtering */ for (i= 0, dv= dvert; i < maxVerts; i++, dv++) { MDeformWeight *dw= dv->dw; int j; for (j= dv->totweight; j > 0; j--, dw++) { if (bone_select_array[dw->def_nr]) { if(dw->weight != 0.0f) { break; } } } /* check if include vert in vertHash */ if (mmd->flag & MOD_MASK_INV) { /* if this vert is in the vgroup, don't include it in vertHash */ if (dw) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ if (!dw) continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); numVerts++; } /* free temp hashes */ BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); } else /* --- Using Nominated VertexGroup only --- */ { int defgrp_index = defgroup_name_index(ob, mmd->vgroup); /* get dverts */ if (defgrp_index >= 0) dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); /* if no vgroup (i.e. dverts) found, return the initial mesh */ if ((defgrp_index < 0) || (dvert == NULL)) return dm; /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert2 bh"); /* add vertices which exist in vertexgroup into ghash for filtering */ for (i= 0, dv= dvert; i < maxVerts; i++, dv++) { const int weight_set= defvert_find_weight(dv, defgrp_index) != 0.0f; /* check if include vert in vertHash */ if (mmd->flag & MOD_MASK_INV) { /* if this vert is in the vgroup, don't include it in vertHash */ if (weight_set) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ if (!weight_set) continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); numVerts++; } } /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask ed2 gh"); faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask fa2 gh"); /* loop over edges and faces, and do the same thing to * ensure that they only reference existing verts */ for (i = 0; i < maxEdges; i++) { MEdge me; dm->getEdge(dm, i, &me); /* only add if both verts will be in new mesh */ if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) ) { BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges)); numEdges++; } } for (i = 0; i < maxFaces; i++) { MFace mf; dm->getFace(dm, i, &mf); /* all verts must be available */ if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) && (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) ) { BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces)); numFaces++; } } /* now we know the number of verts, edges and faces, * we can create the new (reduced) mesh */ result = CDDM_from_template(dm, numVerts, numEdges, numFaces); /* using ghash-iterators, map data into new mesh */ /* vertices */ for ( hashIter = BLI_ghashIterator_new(vertHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { MVert source; MVert *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); dm->getVert(dm, oldIndex, &source); dest = CDDM_get_vert(result, newIndex); DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); /* edges */ for ( hashIter = BLI_ghashIterator_new(edgeHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { MEdge source; MEdge *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); dm->getEdge(dm, oldIndex, &source); dest = CDDM_get_edge(result, newIndex); source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); DM_copy_edge_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); /* faces */ for ( hashIter = BLI_ghashIterator_new(faceHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { MFace source; MFace *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); int orig_v4; dm->getFace(dm, oldIndex, &source); dest = CDDM_get_face(result, newIndex); orig_v4 = source.v4; source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3))); if (source.v4) source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4))); DM_copy_face_data(dm, result, oldIndex, newIndex, 1); *dest = source; test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3)); } BLI_ghashIterator_free(hashIter); /* recalculate normals */ CDDM_calc_normals(result); /* free hashes */ BLI_ghash_free(vertHash, NULL, NULL); BLI_ghash_free(edgeHash, NULL, NULL); BLI_ghash_free(faceHash, NULL, NULL); /* return the new mesh */ return result; }
/* Get the face's unique ID from the log */ static unsigned int bm_log_face_id_get(BMLog *log, BMFace *f) { BLI_assert(BLI_ghash_haskey(log->elem_to_id, f)); return GET_UINT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, f)); }
static DerivedMesh *applyModifier( ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag UNUSED(flag)) { MaskModifierData *mmd = (MaskModifierData *)md; const bool found_test = (mmd->flag & MOD_MASK_INV) == 0; DerivedMesh *result = NULL; GHash *vertHash = NULL, *edgeHash, *polyHash; GHashIterator gh_iter; MDeformVert *dvert, *dv; int numPolys = 0, numLoops = 0, numEdges = 0, numVerts = 0; int maxVerts, maxEdges, maxPolys; int i; const MVert *mvert_src; const MEdge *medge_src; const MPoly *mpoly_src; const MLoop *mloop_src; MPoly *mpoly_dst; MLoop *mloop_dst; MEdge *medge_dst; MVert *mvert_dst; int *loop_mapping; dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); if (dvert == NULL) { return found_test ? CDDM_from_template(dm, 0, 0, 0, 0, 0) : dm; } /* Overview of Method: * 1. Get the vertices that are in the vertexgroup of interest * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices * 3. Make a new mesh containing only the mapping data */ /* get original number of verts, edges, and faces */ maxVerts = dm->getNumVerts(dm); maxEdges = dm->getNumEdges(dm); maxPolys = dm->getNumPolys(dm); /* check if we can just return the original mesh * - must have verts and therefore verts assigned to vgroups to do anything useful */ if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || (maxVerts == 0) || BLI_listbase_is_empty(&ob->defbase)) { return dm; } /* if mode is to use selected armature bones, aggregate the bone groups */ if (mmd->mode == MOD_MASK_MODE_ARM) { /* --- using selected bones --- */ Object *oba = mmd->ob_arm; bPoseChannel *pchan; bDeformGroup *def; bool *bone_select_array; int bone_select_tot = 0; const int defbase_tot = BLI_listbase_count(&ob->defbase); /* check that there is armature object with bones to use, otherwise return original mesh */ if (ELEM(NULL, oba, oba->pose, ob->defbase.first)) return dm; /* determine whether each vertexgroup is associated with a selected bone or not * - each cell is a boolean saying whether bone corresponding to the ith group is selected * - groups that don't match a bone are treated as not existing (along with the corresponding ungrouped verts) */ bone_select_array = MEM_malloc_arrayN((size_t)defbase_tot, sizeof(char), "mask array"); for (i = 0, def = ob->defbase.first; def; def = def->next, i++) { pchan = BKE_pose_channel_find_name(oba->pose, def->name); if (pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED)) { bone_select_array[i] = true; bone_select_tot++; } else { bone_select_array[i] = false; } } /* verthash gives mapping from original vertex indices to the new indices (including selected matches only) * key = oldindex, value = newindex */ vertHash = BLI_ghash_int_new_ex("mask vert gh", (unsigned int)maxVerts); /* add vertices which exist in vertexgroups into vertHash for filtering * - dv = for each vertex, what vertexgroups does it belong to * - dw = weight that vertex was assigned to a vertexgroup it belongs to */ for (i = 0, dv = dvert; i < maxVerts; i++, dv++) { MDeformWeight *dw = dv->dw; bool found = false; int j; /* check the groups that vertex is assigned to, and see if it was any use */ for (j = 0; j < dv->totweight; j++, dw++) { if (dw->def_nr < defbase_tot) { if (bone_select_array[dw->def_nr]) { if (dw->weight != 0.0f) { found = true; break; } } } } if (found_test != found) { continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); numVerts++; } /* free temp hashes */ MEM_freeN(bone_select_array); } else { /* --- Using Nominated VertexGroup only --- */ int defgrp_index = defgroup_name_index(ob, mmd->vgroup); /* if no vgroup (i.e. dverts) found, return the initial mesh */ if (defgrp_index == -1) return dm; /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ vertHash = BLI_ghash_int_new_ex("mask vert2 bh", (unsigned int)maxVerts); /* add vertices which exist in vertexgroup into ghash for filtering */ for (i = 0, dv = dvert; i < maxVerts; i++, dv++) { const bool found = defvert_find_weight(dv, defgrp_index) != 0.0f; if (found_test != found) { continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); numVerts++; } } /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ edgeHash = BLI_ghash_int_new_ex("mask ed2 gh", (unsigned int)maxEdges); polyHash = BLI_ghash_int_new_ex("mask fa2 gh", (unsigned int)maxPolys); mvert_src = dm->getVertArray(dm); medge_src = dm->getEdgeArray(dm); mpoly_src = dm->getPolyArray(dm); mloop_src = dm->getLoopArray(dm); /* overalloc, assume all polys are seen */ loop_mapping = MEM_malloc_arrayN((size_t)maxPolys, sizeof(int), "mask loopmap"); /* loop over edges and faces, and do the same thing to * ensure that they only reference existing verts */ for (i = 0; i < maxEdges; i++) { const MEdge *me = &medge_src[i]; /* only add if both verts will be in new mesh */ if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) { BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges)); numEdges++; } } for (i = 0; i < maxPolys; i++) { const MPoly *mp_src = &mpoly_src[i]; const MLoop *ml_src = &mloop_src[mp_src->loopstart]; bool ok = true; int j; for (j = 0; j < mp_src->totloop; j++, ml_src++) { if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml_src->v))) { ok = false; break; } } /* all verts must be available */ if (ok) { BLI_ghash_insert(polyHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numPolys)); loop_mapping[numPolys] = numLoops; numPolys++; numLoops += mp_src->totloop; } } /* now we know the number of verts, edges and faces, * we can create the new (reduced) mesh */ result = CDDM_from_template(dm, numVerts, numEdges, 0, numLoops, numPolys); mpoly_dst = CDDM_get_polys(result); mloop_dst = CDDM_get_loops(result); medge_dst = CDDM_get_edges(result); mvert_dst = CDDM_get_verts(result); /* using ghash-iterators, map data into new mesh */ /* vertices */ GHASH_ITER (gh_iter, vertHash) { const MVert *v_src; MVert *v_dst; const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter)); const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)); v_src = &mvert_src[i_src]; v_dst = &mvert_dst[i_dst]; *v_dst = *v_src; DM_copy_vert_data(dm, result, i_src, i_dst, 1); } /* edges */ GHASH_ITER (gh_iter, edgeHash) { const MEdge *e_src; MEdge *e_dst; const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter)); const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)); e_src = &medge_src[i_src]; e_dst = &medge_dst[i_dst]; DM_copy_edge_data(dm, result, i_src, i_dst, 1); *e_dst = *e_src; e_dst->v1 = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(e_src->v1))); e_dst->v2 = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(e_src->v2))); } /* faces */ GHASH_ITER (gh_iter, polyHash) { const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter)); const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)); const MPoly *mp_src = &mpoly_src[i_src]; MPoly *mp_dst = &mpoly_dst[i_dst]; const int i_ml_src = mp_src->loopstart; const int i_ml_dst = loop_mapping[i_dst]; const MLoop *ml_src = &mloop_src[i_ml_src]; MLoop *ml_dst = &mloop_dst[i_ml_dst]; DM_copy_poly_data(dm, result, i_src, i_dst, 1); DM_copy_loop_data(dm, result, i_ml_src, i_ml_dst, mp_src->totloop); *mp_dst = *mp_src; mp_dst->loopstart = i_ml_dst; for (i = 0; i < mp_src->totloop; i++) { ml_dst[i].v = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(ml_src[i].v))); ml_dst[i].e = GET_UINT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_UINT_IN_POINTER(ml_src[i].e))); } } MEM_freeN(loop_mapping); /* why is this needed? - campbell */ /* recalculate normals */ result->dirty |= DM_DIRTY_NORMALS; /* free hashes */ BLI_ghash_free(vertHash, NULL, NULL); BLI_ghash_free(edgeHash, NULL, NULL); BLI_ghash_free(polyHash, NULL, NULL); /* return the new mesh */ return result; }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { MaskModifierData *mmd = (MaskModifierData *)md; DerivedMesh *dm = derivedData, *result = NULL; GHash *vertHash = NULL, *edgeHash, *polyHash; GHashIterator *hashIter; MDeformVert *dvert = NULL, *dv; int numPolys = 0, numLoops = 0, numEdges = 0, numVerts = 0; int maxVerts, maxEdges, maxPolys; int i; MPoly *mpoly; MLoop *mloop; MPoly *mpoly_new; MLoop *mloop_new; MEdge *medge_new; MVert *mvert_new; int *loop_mapping; /* Overview of Method: * 1. Get the vertices that are in the vertexgroup of interest * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices * 3. Make a new mesh containing only the mapping data */ /* get original number of verts, edges, and faces */ maxVerts = dm->getNumVerts(dm); maxEdges = dm->getNumEdges(dm); maxPolys = dm->getNumPolys(dm); /* check if we can just return the original mesh * - must have verts and therefore verts assigned to vgroups to do anything useful */ if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || (maxVerts == 0) || (ob->defbase.first == NULL) ) { return derivedData; } /* if mode is to use selected armature bones, aggregate the bone groups */ if (mmd->mode == MOD_MASK_MODE_ARM) { /* --- using selected bones --- */ GHash *vgroupHash; Object *oba = mmd->ob_arm; bPoseChannel *pchan; bDeformGroup *def; char *bone_select_array; int bone_select_tot = 0; const int defbase_tot = BLI_countlist(&ob->defbase); /* check that there is armature object with bones to use, otherwise return original mesh */ if (ELEM3(NULL, mmd->ob_arm, mmd->ob_arm->pose, ob->defbase.first)) return derivedData; bone_select_array = MEM_mallocN(defbase_tot * sizeof(char), "mask array"); for (i = 0, def = ob->defbase.first; def; def = def->next, i++) { pchan = BKE_pose_channel_find_name(oba->pose, def->name); if (pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED)) { bone_select_array[i] = TRUE; bone_select_tot++; } else { bone_select_array[i] = FALSE; } } /* hashes for finding mapping of: * - vgroups to indices -> vgroupHash (string, int) * - bones to vgroup indices -> boneHash (index of vgroup, dummy) */ vgroupHash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "mask vgroup gh"); /* build mapping of names of vertex groups to indices */ for (i = 0, def = ob->defbase.first; def; def = def->next, i++) BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i)); /* if no bones selected, free hashes and return original mesh */ if (bone_select_tot == 0) { BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); return derivedData; } /* repeat the previous check, but for dverts */ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); if (dvert == NULL) { BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); return derivedData; } /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ vertHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert gh"); /* add vertices which exist in vertexgroups into vertHash for filtering */ for (i = 0, dv = dvert; i < maxVerts; i++, dv++) { MDeformWeight *dw = dv->dw; int j; for (j = dv->totweight; j > 0; j--, dw++) { if (dw->def_nr < defbase_tot) { if (bone_select_array[dw->def_nr]) { if (dw->weight != 0.0f) { break; } } } } /* check if include vert in vertHash */ if (mmd->flag & MOD_MASK_INV) { /* if this vert is in the vgroup, don't include it in vertHash */ if (dw) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ if (!dw) continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); numVerts++; } /* free temp hashes */ BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); } else { /* --- Using Nominated VertexGroup only --- */ int defgrp_index = defgroup_name_index(ob, mmd->vgroup); /* get dverts */ if (defgrp_index >= 0) dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); /* if no vgroup (i.e. dverts) found, return the initial mesh */ if ((defgrp_index < 0) || (dvert == NULL)) return dm; /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ vertHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert2 bh"); /* add vertices which exist in vertexgroup into ghash for filtering */ for (i = 0, dv = dvert; i < maxVerts; i++, dv++) { const int weight_set = defvert_find_weight(dv, defgrp_index) != 0.0f; /* check if include vert in vertHash */ if (mmd->flag & MOD_MASK_INV) { /* if this vert is in the vgroup, don't include it in vertHash */ if (weight_set) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ if (!weight_set) continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); numVerts++; } } /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ edgeHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask ed2 gh"); polyHash = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask fa2 gh"); mpoly = dm->getPolyArray(dm); mloop = dm->getLoopArray(dm); loop_mapping = MEM_callocN(sizeof(int) * maxPolys, "mask loopmap"); /* overalloc, assume all polys are seen */ /* loop over edges and faces, and do the same thing to * ensure that they only reference existing verts */ for (i = 0; i < maxEdges; i++) { MEdge me; dm->getEdge(dm, i, &me); /* only add if both verts will be in new mesh */ if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2))) { BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges)); numEdges++; } } for (i = 0; i < maxPolys; i++) { MPoly *mp = &mpoly[i]; MLoop *ml = mloop + mp->loopstart; int ok = TRUE; int j; for (j = 0; j < mp->totloop; j++, ml++) { if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v))) { ok = FALSE; break; } } /* all verts must be available */ if (ok) { BLI_ghash_insert(polyHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numPolys)); loop_mapping[numPolys] = numLoops; numPolys++; numLoops += mp->totloop; } } /* now we know the number of verts, edges and faces, * we can create the new (reduced) mesh */ result = CDDM_from_template(dm, numVerts, numEdges, 0, numLoops, numPolys); mpoly_new = CDDM_get_polys(result); mloop_new = CDDM_get_loops(result); medge_new = CDDM_get_edges(result); mvert_new = CDDM_get_verts(result); /* using ghash-iterators, map data into new mesh */ /* vertices */ for (hashIter = BLI_ghashIterator_new(vertHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { MVert source; MVert *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); dm->getVert(dm, oldIndex, &source); dest = &mvert_new[newIndex]; DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); /* edges */ for (hashIter = BLI_ghashIterator_new(edgeHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter)) { MEdge source; MEdge *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); dm->getEdge(dm, oldIndex, &source); dest = &medge_new[newIndex]; source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); DM_copy_edge_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); /* faces */ for (hashIter = BLI_ghashIterator_new(polyHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); MPoly *source = &mpoly[oldIndex]; MPoly *dest = &mpoly_new[newIndex]; int oldLoopIndex = source->loopstart; int newLoopIndex = loop_mapping[newIndex]; MLoop *source_loop = &mloop[oldLoopIndex]; MLoop *dest_loop = &mloop_new[newLoopIndex]; DM_copy_poly_data(dm, result, oldIndex, newIndex, 1); DM_copy_loop_data(dm, result, oldLoopIndex, newLoopIndex, source->totloop); *dest = *source; dest->loopstart = newLoopIndex; for (i = 0; i < source->totloop; i++) { dest_loop[i].v = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source_loop[i].v))); dest_loop[i].e = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(source_loop[i].e))); } } BLI_ghashIterator_free(hashIter); MEM_freeN(loop_mapping); /* why is this needed? - campbell */ /* recalculate normals */ CDDM_calc_normals(result); /* free hashes */ BLI_ghash_free(vertHash, NULL, NULL); BLI_ghash_free(edgeHash, NULL, NULL); BLI_ghash_free(polyHash, NULL, NULL); /* return the new mesh */ return result; }
/* Get a face from its unique ID */ static BMFace *bm_log_face_from_id(BMLog *log, uint id) { void *key = SET_UINT_IN_POINTER(id); BLI_assert(BLI_ghash_haskey(log->id_to_elem, key)); return BLI_ghash_lookup(log->id_to_elem, key); }