static DerivedMesh * explodeMesh(ExplodeModifierData *emd, ParticleSystemModifierData *psmd, Scene *scene, Object *ob, DerivedMesh *to_explode) { DerivedMesh *explode, *dm=to_explode; MFace *mf= NULL, *mface; /* ParticleSettings *part=psmd->psys->part; */ /* UNUSED */ ParticleSimulationData sim= {NULL}; ParticleData *pa=NULL, *pars=psmd->psys->particles; ParticleKey state, birth; EdgeHash *vertpahash; EdgeHashIterator *ehi; float *vertco= NULL, imat[4][4]; float rot[4]; float cfra; /* float timestep; */ int *facepa=emd->facepa; int totdup=0,totvert=0,totface=0,totpart=0; int i, j, v, mindex=0; MTFace *mtface = NULL, *mtf; totface= dm->getNumFaces(dm); totvert= dm->getNumVerts(dm); mface= dm->getFaceArray(dm); totpart= psmd->psys->totpart; sim.scene= scene; sim.ob= ob; sim.psys= psmd->psys; sim.psmd= psmd; /* timestep= psys_get_timestep(&sim); */ //if(part->flag & PART_GLOB_TIME) cfra= BKE_curframe(scene); //else // cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0); /* hash table for vertice <-> particle relations */ vertpahash= BLI_edgehash_new(); for (i=0; i<totface; i++) { /* do mindex + totvert to ensure the vertex index to be the first * with BLI_edgehashIterator_getKey */ if(facepa[i]==totpart || cfra < (pars+facepa[i])->time) mindex = totvert+totpart; else mindex = totvert+facepa[i]; mf= &mface[i]; /* set face vertices to exist in particle group */ BLI_edgehash_insert(vertpahash, mf->v1, mindex, NULL); BLI_edgehash_insert(vertpahash, mf->v2, mindex, NULL); BLI_edgehash_insert(vertpahash, mf->v3, mindex, NULL); if(mf->v4) BLI_edgehash_insert(vertpahash, mf->v4, mindex, NULL); } /* make new vertice indexes & count total vertices after duplication */ ehi= BLI_edgehashIterator_new(vertpahash); for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup)); totdup++; } BLI_edgehashIterator_free(ehi); /* the final duplicated vertices */ explode= CDDM_from_template(dm, totdup, 0,totface); mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname); /*dupvert= CDDM_get_verts(explode);*/ /* getting back to object space */ invert_m4_m4(imat,ob->obmat); psmd->psys->lattice = psys_get_lattice(&sim); /* duplicate & displace vertices */ ehi= BLI_edgehashIterator_new(vertpahash); for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { MVert source; MVert *dest; /* get particle + vertex from hash */ BLI_edgehashIterator_getKey(ehi, &j, &i); i -= totvert; v= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); dm->getVert(dm, j, &source); dest = CDDM_get_vert(explode,v); DM_copy_vert_data(dm,explode,j,v,1); *dest = source; if(i!=totpart) { /* get particle */ pa= pars+i; psys_get_birth_coordinates(&sim, pa, &birth, 0, 0); state.time=cfra; psys_get_particle_state(&sim, i, &state, 1); vertco=CDDM_get_vert(explode,v)->co; mul_m4_v3(ob->obmat,vertco); sub_v3_v3(vertco, birth.co); /* apply rotation, size & location */ sub_qt_qtqt(rot, state.rot, birth.rot); mul_qt_v3(rot, vertco); if(emd->flag & eExplodeFlag_PaSize) mul_v3_fl(vertco,pa->size); add_v3_v3(vertco, state.co); mul_m4_v3(imat, vertco); } } BLI_edgehashIterator_free(ehi); /*map new vertices to faces*/ for (i=0; i<totface; i++) { MFace source; int orig_v4; if(facepa[i]!=totpart) { pa=pars+facepa[i]; if(pa->alive==PARS_UNBORN && (emd->flag&eExplodeFlag_Unborn)==0) continue; if(pa->alive==PARS_ALIVE && (emd->flag&eExplodeFlag_Alive)==0) continue; if(pa->alive==PARS_DEAD && (emd->flag&eExplodeFlag_Dead)==0) continue; } dm->getFace(dm,i,&source); mf=CDDM_get_face(explode,i); orig_v4 = source.v4; if(facepa[i]!=totpart && cfra < pa->time) mindex = totvert+totpart; else mindex = totvert+facepa[i]; source.v1 = edgecut_get(vertpahash, source.v1, mindex); source.v2 = edgecut_get(vertpahash, source.v2, mindex); source.v3 = edgecut_get(vertpahash, source.v3, mindex); if(source.v4) source.v4 = edgecut_get(vertpahash, source.v4, mindex); DM_copy_face_data(dm,explode,i,i,1); *mf = source; /* override uv channel for particle age */ if(mtface) { float age = (cfra - pa->time)/pa->lifetime; /* Clamp to this range to avoid flipping to the other side of the coordinates. */ CLAMP(age, 0.001f, 0.999f); mtf = mtface + i; mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age; mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f; } test_index_face(mf, &explode->faceData, i, (orig_v4 ? 4 : 3)); } /* cleanup */ BLI_edgehash_free(vertpahash, NULL); /* finalization */ CDDM_calc_edges(explode); CDDM_calc_normals(explode); if(psmd->psys->lattice){ end_latt_deform(psmd->psys->lattice); psmd->psys->lattice= NULL; } return explode; }
static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, Object *ob, DerivedMesh *dm, int axis) { int i; float tolerance = mmd->tolerance; DerivedMesh *result; int numVerts, numEdges, numFaces; int maxVerts = dm->getNumVerts(dm); int maxEdges = dm->getNumEdges(dm); int maxFaces = dm->getNumFaces(dm); int *flip_map= NULL, flip_map_len= 0; int do_vgroup_mirr= (mmd->flag & MOD_MIR_VGROUP); unsigned int (*indexMap)[2]; float mtx[4][4], imtx[4][4]; numVerts = numEdges = numFaces = 0; indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap"); result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2); if (do_vgroup_mirr) { flip_map= defgroup_flip_map(ob, &flip_map_len, FALSE); if(flip_map == NULL) do_vgroup_mirr= 0; } if (mmd->mirror_ob) { float obinv[4][4]; invert_m4_m4(obinv, mmd->mirror_ob->obmat); mult_m4_m4m4(mtx, obinv, ob->obmat); invert_m4_m4(imtx, mtx); } for(i = 0; i < maxVerts; i++) { MVert inMV; MVert *mv = CDDM_get_vert(result, numVerts); int isShared; float co[3]; dm->getVert(dm, i, &inMV); copy_v3_v3(co, inMV.co); if (mmd->mirror_ob) { mul_m4_v3(mtx, co); } if(mmd->flag & MOD_MIR_NO_MERGE) isShared = 0; else isShared = ABS(co[axis])<=tolerance; /* Because the topology result (# of vertices) must be the same if * the mesh data is overridden by vertex cos, have to calc sharedness * based on original coordinates. This is why we test before copy. */ DM_copy_vert_data(dm, result, i, numVerts, 1); *mv = inMV; indexMap[i][0] = numVerts; indexMap[i][1] = !isShared; numVerts++; if(isShared ) { co[axis] = 0.0f; if (mmd->mirror_ob) { mul_m4_v3(imtx, co); } copy_v3_v3(mv->co, co); mv->flag |= ME_VERT_MERGED; } else { MVert *mv2 = CDDM_get_vert(result, numVerts); DM_copy_vert_data(dm, result, i, numVerts, 1); *mv2 = *mv; co[axis] = -co[axis]; if (mmd->mirror_ob) { mul_m4_v3(imtx, co); } copy_v3_v3(mv2->co, co); if (do_vgroup_mirr) { MDeformVert *dvert= DM_get_vert_data(result, numVerts, CD_MDEFORMVERT); if(dvert) { defvert_flip(dvert, flip_map, flip_map_len); } } numVerts++; } } for(i = 0; i < maxEdges; i++) { MEdge inMED; MEdge *med = CDDM_get_edge(result, numEdges); dm->getEdge(dm, i, &inMED); DM_copy_edge_data(dm, result, i, numEdges, 1); *med = inMED; numEdges++; med->v1 = indexMap[inMED.v1][0]; med->v2 = indexMap[inMED.v2][0]; if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) { MEdge *med2 = CDDM_get_edge(result, numEdges); DM_copy_edge_data(dm, result, i, numEdges, 1); *med2 = *med; numEdges++; med2->v1 += indexMap[inMED.v1][1]; med2->v2 += indexMap[inMED.v2][1]; } } for(i = 0; i < maxFaces; i++) { MFace inMF; MFace *mf = CDDM_get_face(result, numFaces); dm->getFace(dm, i, &inMF); DM_copy_face_data(dm, result, i, numFaces, 1); *mf = inMF; numFaces++; mf->v1 = indexMap[inMF.v1][0]; mf->v2 = indexMap[inMF.v2][0]; mf->v3 = indexMap[inMF.v3][0]; mf->v4 = indexMap[inMF.v4][0]; if ( indexMap[inMF.v1][1] || indexMap[inMF.v2][1] || indexMap[inMF.v3][1] || (mf->v4 && indexMap[inMF.v4][1])) { MFace *mf2 = CDDM_get_face(result, numFaces); static int corner_indices[4] = {2, 1, 0, 3}; DM_copy_face_data(dm, result, i, numFaces, 1); *mf2 = *mf; mf2->v1 += indexMap[inMF.v1][1]; mf2->v2 += indexMap[inMF.v2][1]; mf2->v3 += indexMap[inMF.v3][1]; if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1]; /* mirror UVs if enabled */ if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) { MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE); if(tf) { int j; for(j = 0; j < 4; ++j) { if(mmd->flag & MOD_MIR_MIRROR_U) tf->uv[j][0] = 1.0f - tf->uv[j][0]; if(mmd->flag & MOD_MIR_MIRROR_V) tf->uv[j][1] = 1.0f - tf->uv[j][1]; } } } /* Flip face normal */ SWAP(unsigned int, mf2->v1, mf2->v3); DM_swap_face_data(result, numFaces, corner_indices); test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3); numFaces++; } }
static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm){ DerivedMesh *splitdm; MFace *mf=NULL,*df1=NULL; MFace *mface=dm->getFaceArray(dm); MVert *dupve, *mv; EdgeHash *edgehash; EdgeHashIterator *ehi; int totvert=dm->getNumVerts(dm); int totface=dm->getNumFaces(dm); int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_facesplit"); int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2"); int *facepa = emd->facepa; int *fs, totesplit=0,totfsplit=0,curdupface=0; int i,j,v1,v2,v3,v4,esplit, v[4], uv[4]; int numlayer; edgehash= BLI_edgehash_new(); /* recreate vertpa from facepa calculation */ for (i=0,mf=mface; i<totface; i++,mf++) { vertpa[mf->v1]=facepa[i]; vertpa[mf->v2]=facepa[i]; vertpa[mf->v3]=facepa[i]; if(mf->v4) vertpa[mf->v4]=facepa[i]; } /* mark edges for splitting and how to split faces */ for (i=0,mf=mface,fs=facesplit; i<totface; i++,mf++,fs++) { v1=vertpa[mf->v1]; v2=vertpa[mf->v2]; v3=vertpa[mf->v3]; if(v1!=v2){ BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL); (*fs) |= 1; } if(v2!=v3){ BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL); (*fs) |= 2; } if(mf->v4){ v4=vertpa[mf->v4]; if(v3!=v4){ BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL); (*fs) |= 4; } if(v1!=v4){ BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL); (*fs) |= 8; } /* mark center vertex as a fake edge split */ if(*fs == 15) BLI_edgehash_insert(edgehash, mf->v1, mf->v3, NULL); } else { (*fs) |= 16; /* mark face as tri */ if(v1!=v3){ BLI_edgehash_insert(edgehash, mf->v1, mf->v3, NULL); (*fs) |= 4; } } } /* count splits & create indexes for new verts */ ehi= BLI_edgehashIterator_new(edgehash); totesplit=totvert; for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totesplit)); totesplit++; } BLI_edgehashIterator_free(ehi); /* count new faces due to splitting */ for(i=0,fs=facesplit; i<totface; i++,fs++) totfsplit += add_faces[*fs]; splitdm= CDDM_from_template(dm, totesplit, 0, totface+totfsplit); numlayer = CustomData_number_of_layers(&splitdm->faceData, CD_MTFACE); /* copy new faces & verts (is it really this painful with custom data??) */ for(i=0; i<totvert; i++){ MVert source; MVert *dest; dm->getVert(dm, i, &source); dest = CDDM_get_vert(splitdm, i); DM_copy_vert_data(dm, splitdm, i, i, 1); *dest = source; } /* override original facepa (original pointer is saved in caller function) */ facepa= MEM_callocN(sizeof(int)*(totface+totfsplit),"explode_facepa"); //memcpy(facepa,emd->facepa,totface*sizeof(int)); emd->facepa=facepa; /* create new verts */ ehi= BLI_edgehashIterator_new(edgehash); for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { BLI_edgehashIterator_getKey(ehi, &i, &j); esplit= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); mv=CDDM_get_vert(splitdm,j); dupve=CDDM_get_vert(splitdm,esplit); DM_copy_vert_data(splitdm,splitdm,j,esplit,1); *dupve=*mv; mv=CDDM_get_vert(splitdm,i); add_v3_v3(dupve->co, mv->co); mul_v3_fl(dupve->co, 0.5f); } BLI_edgehashIterator_free(ehi); /* create new faces */ curdupface=0;//=totface; //curdupin=totesplit; for(i=0,fs=facesplit; i<totface; i++,fs++){ mf = dm->getFaceData(dm, i, CD_MFACE); switch(*fs) { case 3: case 10: case 11: case 15: SET_VERTS(1, 2, 3, 4) break; case 5: case 6: case 7: SET_VERTS(2, 3, 4, 1) break; case 9: case 13: SET_VERTS(4, 1, 2, 3) break; case 12: case 14: SET_VERTS(3, 4, 1, 2) break; case 21: case 23: SET_VERTS(1, 2, 3, 4) break; case 19: SET_VERTS(2, 3, 1, 4) break; case 22: SET_VERTS(3, 1, 2, 4) break; } switch(*fs) { case 3: case 6: case 9: case 12: remap_faces_3_6_9_12(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); if(numlayer) remap_uvs_3_6_9_12(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); break; case 5: case 10: remap_faces_5_10(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); if(numlayer) remap_uvs_5_10(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); break; case 15: remap_faces_15(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); if(numlayer) remap_uvs_15(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); break; case 7: case 11: case 13: case 14: remap_faces_7_11_13_14(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); if(numlayer) remap_uvs_7_11_13_14(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); break; case 19: case 21: case 22: remap_faces_19_21_22(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]); if(numlayer) remap_uvs_19_21_22(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]); break; case 23: remap_faces_23(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]); if(numlayer) remap_uvs_23(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]); break; case 0: case 16: df1 = get_dface(dm, splitdm, curdupface, i, mf); facepa[curdupface] = vertpa[mf->v1]; if(df1->v4) df1->flag |= ME_FACE_SEL; else df1->flag &= ~ME_FACE_SEL; break; } curdupface += add_faces[*fs]+1; } for(i=0; i<curdupface; i++) { mf = CDDM_get_face(splitdm, i); test_index_face(mf, &splitdm->faceData, i, (mf->flag & ME_FACE_SEL ? 4 : 3)); } BLI_edgehash_free(edgehash, NULL); MEM_freeN(facesplit); MEM_freeN(vertpa); return splitdm; }
/* 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; }
DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) { MFace *mface, *mf; MEdge *medge, *me; MVert *mvert, *mv; int *origindex; int totface,totedge,totvert,i,bmeshok,len, numTex, numCol; BME_Vert *v1=NULL; BME_Edge *e=NULL, *oe=NULL; BME_Poly *f=NULL; DerivedMesh *result; EdgeHash *edge_hash = BLI_edgehash_new(); totvert = BLI_countlist(&(bm->verts)); totedge = 0; /*we cannot have double edges in a derived mesh!*/ for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i; for(e=bm->edges.first; e; e=e->next){ oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1); if(!oe){ totedge++; BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e); e->tflag2 = 1; } else{ e->tflag2 = 0; } } /*count quads and tris*/ totface = 0; bmeshok = 1; for(f=bm->polys.first;f;f=f->next){ len = BME_cycle_length(f->loopbase); if(len == 3 || len == 4) totface++; } /*convert back to mesh*/ result = CDDM_from_template(dm,totvert,totedge,totface); CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert); CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge); CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface); CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface); numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); /*Make Verts*/ mvert = CDDM_get_verts(result); origindex = result->getVertDataArray(result, CD_ORIGINDEX); for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){ VECCOPY(mv->co,v1->co); mv->flag = (unsigned char)v1->flag; mv->bweight = (char)(255.0*v1->bweight); CustomData_from_bmesh_block(&bm->vdata, &result->vertData, &v1->data, i); origindex[i] = ORIGINDEX_NONE; } medge = CDDM_get_edges(result); origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); i=0; for(e=bm->edges.first,me=medge;e;e=e->next){ if(e->tflag2){ if(e->v1->tflag1 < e->v2->tflag1){ me->v1 = e->v1->tflag1; me->v2 = e->v2->tflag1; } else{ me->v1 = e->v2->tflag1; me->v2 = e->v1->tflag1; } me->crease = (char)(255.0*e->crease); me->bweight = (char)(255.0*e->bweight); me->flag = e->flag; CustomData_from_bmesh_block(&bm->edata, &result->edgeData, &e->data, i); origindex[i] = ORIGINDEX_NONE; me++; i++; } } if(totface){ mface = CDDM_get_faces(result); origindex = result->getFaceDataArray(result, CD_ORIGINDEX); /*make faces*/ for(i=0,f=bm->polys.first;f;f=f->next){ mf = &mface[i]; len = BME_cycle_length(f->loopbase); if(len==3 || len==4){ mf->v1 = f->loopbase->v->tflag1; mf->v2 = f->loopbase->next->v->tflag1; mf->v3 = f->loopbase->next->next->v->tflag1; if(len == 4){ mf->v4 = f->loopbase->prev->v->tflag1; } /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */ if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){ test_index_face(mf, NULL, i, len); } mf->mat_nr = (unsigned char)f->mat_nr; mf->flag = (unsigned char)f->flag; CustomData_from_bmesh_block(&bm->pdata, &result->faceData, &f->data, i); BME_DMloops_to_corners(bm, &result->faceData, i, f,numCol,numTex); origindex[i] = ORIGINDEX_NONE; i++; } } } BLI_edgehash_free(edge_hash, NULL); return result; }
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; }
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; }
/* read .bobj.gz file into a fluidsimDerivedMesh struct */ static DerivedMesh *fluidsim_read_obj(const char *filename) { int wri = 0,i; int gotBytes; gzFile gzf; int numverts = 0, numfaces = 0; DerivedMesh *dm = NULL; MFace *mf; MVert *mv; short *normals, *no_s; float no[3]; // ------------------------------------------------ // get numverts + numfaces first // ------------------------------------------------ gzf = gzopen(filename, "rb"); if (!gzf) { return NULL; } // read numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); numverts = wri; // skip verts gotBytes = gzseek(gzf, numverts * 3 * sizeof(float), SEEK_CUR) != -1; // read number of normals if(gotBytes) gotBytes = gzread(gzf, &wri, sizeof(wri)); // skip normals gotBytes = gzseek(gzf, numverts * 3 * sizeof(float), SEEK_CUR) != -1; /* get no. of triangles */ if(gotBytes) gotBytes = gzread(gzf, &wri, sizeof(wri)); numfaces = wri; gzclose( gzf ); // ------------------------------------------------ if(!numfaces || !numverts || !gotBytes) return NULL; gzf = gzopen(filename, "rb"); if (!gzf) { return NULL; } dm = CDDM_new(numverts, 0, numfaces); if(!dm) { gzclose( gzf ); return NULL; } // read numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); // read vertex position from file mv = CDDM_get_verts(dm); for(i=0; i<numverts; i++, mv++) gotBytes = gzread(gzf, mv->co, sizeof(float) * 3); // should be the same as numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); if(wri != numverts) { if(dm) dm->release(dm); gzclose( gzf ); return NULL; } normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" ); if(!normals) { if(dm) dm->release(dm); gzclose( gzf ); return NULL; } // read normals from file (but don't save them yet) for(i=numverts, no_s= normals; i>0; i--, no_s += 3) { gotBytes = gzread(gzf, no, sizeof(float) * 3); normal_float_to_short_v3(no_s, no); } /* read no. of triangles */ gotBytes = gzread(gzf, &wri, sizeof(wri)); if(wri!=numfaces) { printf("Fluidsim: error in reading data from file.\n"); if(dm) dm->release(dm); gzclose( gzf ); MEM_freeN(normals); return NULL; } // read triangles from file mf = CDDM_get_faces(dm); for(i=numfaces; i>0; i--, mf++) { int face[3]; gotBytes = gzread(gzf, face, sizeof(int) * 3); // check if 3rd vertex has index 0 (not allowed in blender) if(face[2]) { mf->v1 = face[0]; mf->v2 = face[1]; mf->v3 = face[2]; } else { mf->v1 = face[1]; mf->v2 = face[2]; mf->v3 = face[0]; } mf->v4 = 0; test_index_face(mf, NULL, 0, 3); } gzclose( gzf ); CDDM_calc_edges(dm); CDDM_apply_vert_normals(dm, (short (*)[3])normals); MEM_freeN(normals); // CDDM_calc_normals(result); return dm; }
/* makes Mesh out of editmesh */ void load_editMesh(Scene *scene, Object *obedit) { Mesh *me= obedit->data; MVert *mvert, *oldverts; MEdge *medge; MFace *mface; MSelect *mselect; EditMesh *em= me->edit_mesh; EditVert *eve; EditFace *efa, *efa_act; EditEdge *eed; EditSelection *ese; float *fp, *newkey, *oldkey; int i, a, ototvert; /* this one also tests of edges are not in faces: */ /* eed->f2==0: not in face, f2==1: draw it */ /* eed->f1 : flag for dynaface (cylindertest, old engine) */ /* eve->f1 : flag for dynaface (sphere test, old engine) */ /* eve->f2 : being used in vertexnormals */ edge_drawflags(me, em); EM_stats_update(em); /* new Vertex block */ if(em->totvert==0) mvert= NULL; else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert"); /* new Edge block */ if(em->totedge==0) medge= NULL; else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge"); /* new Face block */ if(em->totface==0) mface= NULL; else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face"); /* lets save the old verts just in case we are actually working on * a key ... we now do processing of the keys at the end */ oldverts= me->mvert; ototvert= me->totvert; /* don't free this yet */ CustomData_set_layer(&me->vdata, CD_MVERT, NULL); /* free custom data */ CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); /* add new custom data */ me->totvert= em->totvert; me->totedge= em->totedge; me->totface= em->totface; CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert); CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge); CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface); CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface); mesh_update_customdata_pointers(me); /* the vertices, use ->tmp.l as counter */ eve= em->verts.first; a= 0; while(eve) { VECCOPY(mvert->co, eve->co); /* vertex normal */ normal_float_to_short_v3(mvert->no, eve->no); /* note: it used to remove me->dvert when it was not in use, cancelled that... annoying when you have a fresh vgroup */ CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a); eve->tmp.l = a++; /* counter */ mvert->flag= 0; mvert->flag |= (eve->f & SELECT); if (eve->h) mvert->flag |= ME_HIDE; mvert->bweight= (char)(255.0f*eve->bweight); eve= eve->next; mvert++; } /* the edges */ a= 0; eed= em->edges.first; while(eed) { medge->v1= (unsigned int) eed->v1->tmp.l; medge->v2= (unsigned int) eed->v2->tmp.l; medge->flag= (eed->f & SELECT) | ME_EDGERENDER; if(eed->f2<2) medge->flag |= ME_EDGEDRAW; if(eed->f2==0) medge->flag |= ME_LOOSEEDGE; if(eed->sharp) medge->flag |= ME_SHARP; if(eed->seam) medge->flag |= ME_SEAM; if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes if(eed->h & 1) medge->flag |= ME_HIDE; medge->crease= (char)(255.0f*eed->crease); medge->bweight= (char)(255.0f*eed->bweight); CustomData_from_em_block(&em->edata, &me->edata, eed->data, a); eed->tmp.l = a++; medge++; eed= eed->next; } /* the faces */ a = 0; efa= em->faces.first; efa_act= EM_get_actFace(em, 0); i = 0; me->act_face = -1; while(efa) { mface= &((MFace *) me->mface)[i]; mface->v1= (unsigned int) efa->v1->tmp.l; mface->v2= (unsigned int) efa->v2->tmp.l; mface->v3= (unsigned int) efa->v3->tmp.l; if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l; mface->mat_nr= efa->mat_nr; mface->flag= efa->flag; /* bit 0 of flag is already taken for smooth... */ if(efa->h) { mface->flag |= ME_HIDE; mface->flag &= ~ME_FACE_SEL; } else { if(efa->f & 1) mface->flag |= ME_FACE_SEL; else mface->flag &= ~ME_FACE_SEL; } /* watch: efa->e1->f2==0 means loose edge */ if(efa->e1->f2==1) { efa->e1->f2= 2; } if(efa->e2->f2==1) { efa->e2->f2= 2; } if(efa->e3->f2==1) { efa->e3->f2= 2; } if(efa->e4 && efa->e4->f2==1) { efa->e4->f2= 2; } CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i); /* no index '0' at location 3 or 4 */ test_index_face(mface, &me->fdata, i, efa->v4?4:3); if (efa_act == efa) me->act_face = a; efa->tmp.l = a++; i++; efa= efa->next; } /* patch hook indices and vertex parents */ { Object *ob; ModifierData *md; EditVert **vertMap = NULL; int j; for (ob=G.main->object.first; ob; ob=ob->id.next) { if (ob->parent==obedit && ELEM(ob->partype, PARVERT1,PARVERT3)) { /* duplicate code from below, make it function later...? */ if (!vertMap) { vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); for (eve=em->verts.first; eve; eve=eve->next) { if (eve->keyindex!=-1) vertMap[eve->keyindex] = eve; } } if(ob->par1 < ototvert) { eve = vertMap[ob->par1]; if(eve) ob->par1= eve->tmp.l; } if(ob->par2 < ototvert) { eve = vertMap[ob->par2]; if(eve) ob->par2= eve->tmp.l; } if(ob->par3 < ototvert) { eve = vertMap[ob->par3]; if(eve) ob->par3= eve->tmp.l; } } if (ob->data==me) { for (md=ob->modifiers.first; md; md=md->next) { if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; if (!vertMap) { vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); for (eve=em->verts.first; eve; eve=eve->next) { if (eve->keyindex!=-1) vertMap[eve->keyindex] = eve; } } for (i=j=0; i<hmd->totindex; i++) { if(hmd->indexar[i] < ototvert) { eve = vertMap[hmd->indexar[i]]; if (eve) { hmd->indexar[j++] = eve->tmp.l; } } else j++; } hmd->totindex = j; } } } } if (vertMap) MEM_freeN(vertMap); } /* are there keys? */ if(me->key) { KeyBlock *currkey; KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1); float (*ofs)[3] = NULL; /* editing the base key should update others */ if(me->key->type==KEY_RELATIVE && oldverts) { int act_is_basis = 0; /* find if this key is a basis for any others */ for(currkey = me->key->block.first; currkey; currkey= currkey->next) { if(em->shapenr-1 == currkey->relative) { act_is_basis = 1; break; } } if(act_is_basis) { /* active key is a base */ float (*fp)[3]= actkey->data; i=0; ofs= MEM_callocN(sizeof(float) * 3 * em->totvert, "currkey->data"); eve= em->verts.first; mvert = me->mvert; while(eve) { if(eve->keyindex>=0) { sub_v3_v3v3(ofs[i], mvert->co, fp[eve->keyindex]); } eve= eve->next; i++; mvert++; } } } /* Lets reorder the key data so that things line up roughly * with the way things were before editmode */ currkey = me->key->block.first; while(currkey) { int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative)); fp= newkey= MEM_callocN(me->key->elemsize*em->totvert, "currkey->data"); oldkey = currkey->data; eve= em->verts.first; i = 0; mvert = me->mvert; while(eve) { if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex if(currkey == actkey) { if(actkey == me->key->refkey) { VECCOPY(fp, mvert->co); } else { VECCOPY(fp, mvert->co); if(oldverts) { VECCOPY(mvert->co, oldverts[eve->keyindex].co); } } } else { if(oldkey) { VECCOPY(fp, oldkey + 3 * eve->keyindex); } } } else { VECCOPY(fp, mvert->co); } /* propagate edited basis offsets to other shapes */ if(apply_offset) { VECADD(fp, fp, ofs[i]); } fp+= 3; ++i; ++mvert; eve= eve->next; } currkey->totelem= em->totvert; if(currkey->data) MEM_freeN(currkey->data); currkey->data = newkey; currkey= currkey->next; } if(ofs) MEM_freeN(ofs); } if(oldverts) MEM_freeN(oldverts); i = 0; for(ese=em->selected.first; ese; ese=ese->next) i++; me->totselect = i; if(i==0) mselect= NULL; else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections"); if(me->mselect) MEM_freeN(me->mselect); me->mselect= mselect; for(ese=em->selected.first; ese; ese=ese->next){ mselect->type = ese->type; if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l; else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l; else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l; mselect++; } /* to be sure: clear ->tmp.l pointers */ eve= em->verts.first; while(eve) { eve->tmp.l = 0; eve= eve->next; } eed= em->edges.first; while(eed) { eed->tmp.l = 0; eed= eed->next; } efa= em->faces.first; while(efa) { efa->tmp.l = 0; efa= efa->next; } /* remake softbody of all users */ if(me->id.us>1) { Base *base; for(base= scene->base.first; base; base= base->next) if(base->object->data==me) base->object->recalc |= OB_RECALC_DATA; } mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); /* topology could be changed, ensure mdisps are ok */ multires_topology_changed(scene, obedit); }
/* read .bobj.gz file into a fluidsimDerivedMesh struct */ static DerivedMesh *fluidsim_read_obj(char *filename) { int wri,i,j; float wrf; int gotBytes; gzFile gzf; int numverts = 0, numfaces = 0; DerivedMesh *dm = NULL; MFace *mface; MVert *mvert; short *normals; // ------------------------------------------------ // get numverts + numfaces first // ------------------------------------------------ gzf = gzopen(filename, "rb"); if (!gzf) { return NULL; } // read numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); numverts = wri; // skip verts for(i=0; i<numverts*3; i++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); } // read number of normals gotBytes = gzread(gzf, &wri, sizeof(wri)); // skip normals for(i=0; i<numverts*3; i++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); } /* get no. of triangles */ gotBytes = gzread(gzf, &wri, sizeof(wri)); numfaces = wri; gzclose( gzf ); // ------------------------------------------------ if(!numfaces || !numverts) return NULL; gzf = gzopen(filename, "rb"); if (!gzf) { return NULL; } dm = CDDM_new(numverts, 0, numfaces); if(!dm) { gzclose( gzf ); return NULL; } // read numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); // read vertex position from file mvert = CDDM_get_verts(dm); for(i=0; i<numverts; i++) { MVert *mv = &mvert[i]; for(j=0; j<3; j++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); mv->co[j] = wrf; } } // should be the same as numverts gotBytes = gzread(gzf, &wri, sizeof(wri)); if(wri != numverts) { if(dm) dm->release(dm); gzclose( gzf ); return NULL; } normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" ); if(!normals) { if(dm) dm->release(dm); gzclose( gzf ); return NULL; } // read normals from file (but don't save them yet) for(i=0; i<numverts*3; i++) { gotBytes = gzread(gzf, &wrf, sizeof( wrf )); normals[i] = (short)(wrf*32767.0f); } /* read no. of triangles */ gotBytes = gzread(gzf, &wri, sizeof(wri)); if(wri!=numfaces) printf("Fluidsim: error in reading data from file.\n"); // read triangles from file mface = CDDM_get_faces(dm); for(i=0; i<numfaces; i++) { int face[4]; MFace *mf = &mface[i]; gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); face[3] = 0; // check if 3rd vertex has index 0 (not allowed in blender) if(face[2]) { mf->v1 = face[0]; mf->v2 = face[1]; mf->v3 = face[2]; } else { mf->v1 = face[1]; mf->v2 = face[2]; mf->v3 = face[0]; } mf->v4 = face[3]; test_index_face(mf, NULL, 0, 3); } gzclose( gzf ); CDDM_calc_edges(dm); CDDM_apply_vert_normals(dm, (short (*)[3])normals); MEM_freeN(normals); // CDDM_calc_normals(result); return dm; }
static Mesh *explodeMesh(ExplodeModifierData *emd, ParticleSystemModifierData *psmd, const ModifierEvalContext *ctx, Scene *scene, Mesh *to_explode) { Mesh *explode, *mesh = to_explode; MFace *mf = NULL, *mface; /* ParticleSettings *part=psmd->psys->part; */ /* UNUSED */ ParticleSimulationData sim = {NULL}; ParticleData *pa = NULL, *pars = psmd->psys->particles; ParticleKey state, birth; EdgeHash *vertpahash; EdgeHashIterator *ehi; float *vertco = NULL, imat[4][4]; float rot[4]; float cfra; /* float timestep; */ const int *facepa = emd->facepa; int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0; int i, v, u; unsigned int ed_v1, ed_v2, mindex = 0; MTFace *mtface = NULL, *mtf; totface = mesh->totface; totvert = mesh->totvert; mface = mesh->mface; totpart = psmd->psys->totpart; sim.depsgraph = ctx->depsgraph; sim.scene = scene; sim.ob = ctx->object; sim.psys = psmd->psys; sim.psmd = psmd; /* timestep = psys_get_timestep(&sim); */ cfra = BKE_scene_frame_get(scene); /* hash table for vertice <-> particle relations */ vertpahash = BLI_edgehash_new(__func__); for (i = 0; i < totface; i++) { if (facepa[i] != totpart) { pa = pars + facepa[i]; if ((pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) || (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) || (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0)) { delface++; continue; } } /* do mindex + totvert to ensure the vertex index to be the first * with BLI_edgehashIterator_getKey */ if (facepa[i] == totpart || cfra < (pars + facepa[i])->time) { mindex = totvert + totpart; } else { mindex = totvert + facepa[i]; } mf = &mface[i]; /* set face vertices to exist in particle group */ BLI_edgehash_reinsert(vertpahash, mf->v1, mindex, NULL); BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, NULL); BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, NULL); if (mf->v4) { BLI_edgehash_reinsert(vertpahash, mf->v4, mindex, NULL); } } /* make new vertice indexes & count total vertices after duplication */ ehi = BLI_edgehashIterator_new(vertpahash); for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { BLI_edgehashIterator_setValue(ehi, POINTER_FROM_INT(totdup)); totdup++; } BLI_edgehashIterator_free(ehi); /* the final duplicated vertices */ explode = BKE_mesh_new_nomain_from_template(mesh, totdup, 0, totface - delface, 0, 0); mtface = CustomData_get_layer_named(&explode->fdata, CD_MTFACE, emd->uvname); /*dupvert = CDDM_get_verts(explode);*/ /* getting back to object space */ invert_m4_m4(imat, ctx->object->obmat); psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); /* duplicate & displace vertices */ ehi = BLI_edgehashIterator_new(vertpahash); for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { MVert source; MVert *dest; /* get particle + vertex from hash */ BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2); ed_v2 -= totvert; v = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); source = mesh->mvert[ed_v1]; dest = &explode->mvert[v]; CustomData_copy_data(&mesh->vdata, &explode->vdata, ed_v1, v, 1); *dest = source; if (ed_v2 != totpart) { /* get particle */ pa = pars + ed_v2; psys_get_birth_coords(&sim, pa, &birth, 0, 0); state.time = cfra; psys_get_particle_state(&sim, ed_v2, &state, 1); vertco = explode->mvert[v].co; mul_m4_v3(ctx->object->obmat, vertco); sub_v3_v3(vertco, birth.co); /* apply rotation, size & location */ sub_qt_qtqt(rot, state.rot, birth.rot); mul_qt_v3(rot, vertco); if (emd->flag & eExplodeFlag_PaSize) { mul_v3_fl(vertco, pa->size); } add_v3_v3(vertco, state.co); mul_m4_v3(imat, vertco); } } BLI_edgehashIterator_free(ehi); /*map new vertices to faces*/ for (i = 0, u = 0; i < totface; i++) { MFace source; int orig_v4; if (facepa[i] != totpart) { pa = pars + facepa[i]; if (pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) { continue; } if (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) { continue; } if (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0) { continue; } } source = mesh->mface[i]; mf = &explode->mface[u]; orig_v4 = source.v4; if (facepa[i] != totpart && cfra < pa->time) { mindex = totvert + totpart; } else { mindex = totvert + facepa[i]; } source.v1 = edgecut_get(vertpahash, source.v1, mindex); source.v2 = edgecut_get(vertpahash, source.v2, mindex); source.v3 = edgecut_get(vertpahash, source.v3, mindex); if (source.v4) { source.v4 = edgecut_get(vertpahash, source.v4, mindex); } CustomData_copy_data(&mesh->fdata, &explode->fdata, i, u, 1); *mf = source; /* override uv channel for particle age */ if (mtface) { float age = (cfra - pa->time) / pa->lifetime; /* Clamp to this range to avoid flipping to the other side of the coordinates. */ CLAMP(age, 0.001f, 0.999f); mtf = mtface + u; mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age; mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f; } test_index_face(mf, &explode->fdata, u, (orig_v4 ? 4 : 3)); u++; } /* cleanup */ BLI_edgehash_free(vertpahash, NULL); /* finalization */ BKE_mesh_calc_edges_tessface(explode); BKE_mesh_convert_mfaces_to_mpolys(explode); explode->runtime.cd_dirty_vert |= CD_MASK_NORMAL; if (psmd->psys->lattice_deform_data) { end_latt_deform(psmd->psys->lattice_deform_data); psmd->psys->lattice_deform_data = NULL; } return explode; }
static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) { Mesh *split_m; MFace *mf = NULL, *df1 = NULL; MFace *mface = mesh->mface; MVert *dupve, *mv; EdgeHash *edgehash; EdgeHashIterator *ehi; int totvert = mesh->totvert; int totface = mesh->totface; int *facesplit = MEM_calloc_arrayN(totface, sizeof(int), "explode_facesplit"); int *vertpa = MEM_calloc_arrayN(totvert, sizeof(int), "explode_vertpa2"); int *facepa = emd->facepa; int *fs, totesplit = 0, totfsplit = 0, curdupface = 0; int i, v1, v2, v3, v4, esplit, v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */ uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */ int numlayer; unsigned int ed_v1, ed_v2; edgehash = BLI_edgehash_new(__func__); /* recreate vertpa from facepa calculation */ for (i = 0, mf = mface; i < totface; i++, mf++) { vertpa[mf->v1] = facepa[i]; vertpa[mf->v2] = facepa[i]; vertpa[mf->v3] = facepa[i]; if (mf->v4) { vertpa[mf->v4] = facepa[i]; } } /* mark edges for splitting and how to split faces */ for (i = 0, mf = mface, fs = facesplit; i < totface; i++, mf++, fs++) { v1 = vertpa[mf->v1]; v2 = vertpa[mf->v2]; v3 = vertpa[mf->v3]; if (v1 != v2) { BLI_edgehash_reinsert(edgehash, mf->v1, mf->v2, NULL); (*fs) |= 1; } if (v2 != v3) { BLI_edgehash_reinsert(edgehash, mf->v2, mf->v3, NULL); (*fs) |= 2; } if (mf->v4) { v4 = vertpa[mf->v4]; if (v3 != v4) { BLI_edgehash_reinsert(edgehash, mf->v3, mf->v4, NULL); (*fs) |= 4; } if (v1 != v4) { BLI_edgehash_reinsert(edgehash, mf->v1, mf->v4, NULL); (*fs) |= 8; } /* mark center vertex as a fake edge split */ if (*fs == 15) { BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL); } } else { (*fs) |= 16; /* mark face as tri */ if (v1 != v3) { BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL); (*fs) |= 4; } } } /* count splits & create indexes for new verts */ ehi = BLI_edgehashIterator_new(edgehash); totesplit = totvert; for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { BLI_edgehashIterator_setValue(ehi, POINTER_FROM_INT(totesplit)); totesplit++; } BLI_edgehashIterator_free(ehi); /* count new faces due to splitting */ for (i = 0, fs = facesplit; i < totface; i++, fs++) { totfsplit += add_faces[*fs]; } split_m = BKE_mesh_new_nomain_from_template(mesh, totesplit, 0, totface + totfsplit, 0, 0); numlayer = CustomData_number_of_layers(&split_m->fdata, CD_MTFACE); /* copy new faces & verts (is it really this painful with custom data??) */ for (i = 0; i < totvert; i++) { MVert source; MVert *dest; source = mesh->mvert[i]; dest = &split_m->mvert[i]; CustomData_copy_data(&mesh->vdata, &split_m->vdata, i, i, 1); *dest = source; } /* override original facepa (original pointer is saved in caller function) */ /* BMESH_TODO, (totfsplit * 2) over allocation is used since the quads are * later interpreted as tri's, for this to work right I think we probably * have to stop using tessface - campbell */ facepa = MEM_calloc_arrayN((totface + (totfsplit * 2)), sizeof(int), "explode_facepa"); // memcpy(facepa, emd->facepa, totface*sizeof(int)); emd->facepa = facepa; /* create new verts */ ehi = BLI_edgehashIterator_new(edgehash); for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2); esplit = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); mv = &split_m->mvert[ed_v2]; dupve = &split_m->mvert[esplit]; CustomData_copy_data(&split_m->vdata, &split_m->vdata, ed_v2, esplit, 1); *dupve = *mv; mv = &split_m->mvert[ed_v1]; mid_v3_v3v3(dupve->co, dupve->co, mv->co); } BLI_edgehashIterator_free(ehi); /* create new faces */ curdupface = 0; //=totface; // curdupin=totesplit; for (i = 0, fs = facesplit; i < totface; i++, fs++) { mf = &mesh->mface[i]; switch (*fs) { case 3: case 10: case 11: case 15: SET_VERTS(1, 2, 3, 4); break; case 5: case 6: case 7: SET_VERTS(2, 3, 4, 1); break; case 9: case 13: SET_VERTS(4, 1, 2, 3); break; case 12: case 14: SET_VERTS(3, 4, 1, 2); break; case 21: case 23: SET_VERTS(1, 2, 3, 4); break; case 19: SET_VERTS(2, 3, 1, 4); break; case 22: SET_VERTS(3, 1, 2, 4); break; } switch (*fs) { case 3: case 6: case 9: case 12: remap_faces_3_6_9_12( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); if (numlayer) { remap_uvs_3_6_9_12(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); } break; case 5: case 10: remap_faces_5_10( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); if (numlayer) { remap_uvs_5_10(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); } break; case 15: remap_faces_15( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); if (numlayer) { remap_uvs_15(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); } break; case 7: case 11: case 13: case 14: remap_faces_7_11_13_14( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]); if (numlayer) { remap_uvs_7_11_13_14(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]); } break; case 19: case 21: case 22: remap_faces_19_21_22( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]); if (numlayer) { remap_uvs_19_21_22(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2]); } break; case 23: remap_faces_23( mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]); if (numlayer) { remap_uvs_23(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2]); } break; case 0: case 16: df1 = get_dface(mesh, split_m, curdupface, i, mf); facepa[curdupface] = vertpa[mf->v1]; if (df1->v4) { df1->flag |= ME_FACE_SEL; } else { df1->flag &= ~ME_FACE_SEL; } break; } curdupface += add_faces[*fs] + 1; } for (i = 0; i < curdupface; i++) { mf = &split_m->mface[i]; test_index_face(mf, &split_m->fdata, i, ((mf->flag & ME_FACE_SEL) ? 4 : 3)); } BLI_edgehash_free(edgehash, NULL); MEM_freeN(facesplit); MEM_freeN(vertpa); BKE_mesh_calc_edges_tessface(split_m); BKE_mesh_convert_mfaces_to_mpolys(split_m); return split_m; }