/** * BME_mesh.c jan 2007 * * BMesh mesh level functions. * * $Id: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2007 Blender Foundation. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): Geoffrey Bantle, Levi Schooley. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include "MEM_guardedalloc.h" #include "DNA_listBase.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "BKE_utildefines.h" #include "BKE_mesh.h" #include "BKE_bmesh.h" #include "BKE_global.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" #include "BLI_blenlib.h" #include "BLI_editVert.h" #include "BLI_edgehash.h" #include "BIF_editmesh.h" #include "editmesh.h" #include "bmesh_private.h" #include "BSE_edit.h" BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em, BME_Mesh *bm) { BME_Vert *v1, *v2; BME_Edge *e, *edar[4]; BME_Poly *f; EditVert *eve; EditEdge *eed; EditFace *efa; int len; BME_model_begin(bm); /*add verts*/ eve= em->verts.first; while(eve) { v1 = BME_MV(bm,eve->co); VECCOPY(v1->no,eve->no); v1->flag = eve->f; v1->h = eve->h; v1->bweight = eve->bweight; /* link the verts for edge and face construction; * kind of a dangerous thing - remember to cast back to BME_Vert before using! */ eve->tmp.v = (EditVert*)v1; eve = eve->next; } /*add edges*/ eed= em->edges.first; while(eed) { v1 = (BME_Vert*)eed->v1->tmp.v; v2 = (BME_Vert*)eed->v2->tmp.v; e = BME_ME(bm, v1, v2); e->crease = eed->crease; e->bweight = eed->bweight; e->flag = eed->f & SELECT; if(eed->sharp) e->flag |= ME_SHARP; if(eed->seam) e->flag |= ME_SEAM; if(eed->h & EM_FGON) e->flag |= ME_FGON; if(eed->h & 1) e->flag |= ME_HIDE; /* link the edges for face construction; * kind of a dangerous thing - remember to cast back to BME_Edge before using! */ eed->tmp.e = (EditEdge*)e; eed = eed->next; } /*add faces.*/ efa= em->faces.first; while(efa) { if(efa->v4) len = 4; else len = 3; edar[0] = (BME_Edge*)efa->e1->tmp.e; edar[1] = (BME_Edge*)efa->e2->tmp.e; edar[2] = (BME_Edge*)efa->e3->tmp.e; if(len == 4){ edar[3] = (BME_Edge*)efa->e4->tmp.e; } /*find v1 and v2*/ v1 = (BME_Vert*)efa->v1->tmp.v; v2 = (BME_Vert*)efa->v2->tmp.v; f = BME_MF(bm,v1,v2,edar,len); f->mat_nr = efa->mat_nr; f->flag = efa->flag; if(efa->h) { f->flag |= ME_HIDE; f->flag &= ~ME_FACE_SEL; } else { if(efa->f & 1) f->flag |= ME_FACE_SEL; else f->flag &= ~ME_FACE_SEL; } efa = efa->next; } BME_model_end(bm); return bm; } /* adds the geometry in the bmesh to G.editMesh (does not free G.editMesh) * if td != NULL, the transdata will be mapped to the EditVert's co */ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { BME_Vert *v1; BME_Edge *e; BME_Poly *f; BME_TransData *vtd; EditMesh *em; EditVert *eve1, *eve2, *eve3, *eve4, **evlist; EditEdge *eed; EditFace *efa; int totvert, len, i; em = G.editMesh; if (em == NULL) return NULL; /* convert to EditMesh */ /* make editverts */ totvert = BLI_countlist(&(bm->verts)); evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist"); for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) { v1->tflag1 = i; eve1 = addvertlist(v1->co,NULL); if (td && (vtd = BME_get_transdata(td,v1))) { vtd->loc = eve1->co; } eve1->keyindex = i; evlist[i]= eve1; eve1->f = (unsigned char)v1->flag; eve1->h = (unsigned char)v1->h; eve1->bweight = v1->bweight; } /* make edges */ for (e=bm->edges.first;e;e=e->next) { if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){ eed= addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL); eed->crease = e->crease; eed->bweight = e->bweight; if(e->flag & ME_SEAM) eed->seam = 1; if(e->flag & ME_SHARP) eed->sharp = 1; if(e->flag & SELECT) eed->f |= SELECT; if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! if(e->flag & ME_HIDE) eed->h |= 1; if(G.scene->selectmode==SCE_SELECT_EDGE) EM_select_edge(eed, eed->f & SELECT); } } /* make faces */ for (f=bm->polys.first;f;f=f->next) { len = BME_cycle_length(f->loopbase); if (len==3 || len==4) { eve1= evlist[f->loopbase->v->tflag1]; eve2= evlist[f->loopbase->next->v->tflag1]; eve3= evlist[f->loopbase->next->next->v->tflag1]; if (len == 4) { eve4= evlist[f->loopbase->prev->v->tflag1]; } else { eve4= NULL; } efa = addfacelist(eve1, eve2, eve3, eve4, NULL, NULL); efa->mat_nr = (unsigned char)f->mat_nr; efa->flag= f->flag & ~ME_HIDE; if(f->flag & ME_FACE_SEL) { efa->f |= SELECT; } if(f->flag & ME_HIDE) efa->h= 1; if((G.f & G_FACESELECT) && (efa->f & SELECT)) EM_select_face(efa, 1); /* flush down */ } } MEM_freeN(evlist); countall(); return em; } /* Adds the geometry found in dm to bm * NOTE: it does not allocate a new BME_Mesh! */ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm, BME_Mesh *bm) { MVert *mvert, *mv; MEdge *medge, *me; MFace *mface, *mf; int totface,totedge,totvert,i,len; BME_Vert *v1=NULL,*v2=NULL, **vert_array; BME_Edge *e=NULL; BME_Poly *f=NULL; EdgeHash *edge_hash = BLI_edgehash_new(); totvert = dm->getNumVerts(dm); totedge = dm->getNumEdges(dm); totface = dm->getNumFaces(dm); mvert = dm->getVertArray(dm); medge = dm->getEdgeArray(dm); mface = dm->getFaceArray(dm); vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array"); BME_model_begin(bm); /*add verts*/ for(i=0,mv = mvert; i < totvert;i++,mv++){ v1 = BME_MV(bm,mv->co); vert_array[i] = v1; v1->flag = mv->flag; v1->bweight = mv->bweight/255.0f; } /*add edges*/ for(i=0,me = medge; i < totedge;i++,me++){ v1 = vert_array[me->v1]; v2 = vert_array[me->v2]; e = BME_ME(bm, v1, v2); e->crease = me->crease/255.0f; e->bweight = me->bweight/255.0f; e->flag = (unsigned char)me->flag; BLI_edgehash_insert(edge_hash,me->v1,me->v2,e); } /*add faces.*/ for(i=0,mf = mface; i < totface;i++,mf++){ BME_Edge *edar[4]; if(mf->v4) len = 4; else len = 3; edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2); edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3); if(len == 4){ edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4); edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1); } else edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1); /*find v1 and v2*/ v1 = vert_array[mf->v1]; v2 = vert_array[mf->v2]; f = BME_MF(bm,v1,v2,edar,len); f->mat_nr = mf->mat_nr; f->flag = mf->flag; } BME_model_end(bm); BLI_edgehash_free(edge_hash, NULL); MEM_freeN(vert_array); return bm; } DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm) { MFace *mface, *mf; MEdge *medge, *me; MVert *mvert, *mv; int totface,totedge,totvert,i,bmeshok,len; 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); /*Make Verts*/ mvert = CDDM_get_verts(result); 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); } medge = CDDM_get_edges(result); 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; me++; i++; } } if(totface){ mface = CDDM_get_faces(result); /*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); } i++; mf->mat_nr = (unsigned char)f->mat_nr; mf->flag = (unsigned char)f->flag; } } } BLI_edgehash_free(edge_hash, NULL); return result; }