From b1a3d3cea158de51074fb4929d147826c17eb079 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 19 Feb 2012 19:27:06 +0000 Subject: [PATCH] remove files no longer used since bmesh merge. --- source/blender/blenkernel/CMakeLists.txt | 6 - .../blenkernel/intern/BME_Customdata.c | 200 --- .../blenkernel/intern/BME_conversions.c | 651 -------- source/blender/blenkernel/intern/BME_eulers.c | 975 ------------ source/blender/blenkernel/intern/BME_mesh.c | 287 ---- .../blender/blenkernel/intern/BME_structure.c | 631 -------- source/blender/blenkernel/intern/BME_tools.c | 1345 ----------------- source/blender/bmesh/CMakeLists.txt | 1 - source/blender/bmesh/intern/bmesh_eulers.c | 1215 --------------- .../intern/in-progress/BME_conversions.c | 479 ------ 10 files changed, 5790 deletions(-) delete mode 100644 source/blender/blenkernel/intern/BME_Customdata.c delete mode 100644 source/blender/blenkernel/intern/BME_conversions.c delete mode 100644 source/blender/blenkernel/intern/BME_eulers.c delete mode 100644 source/blender/blenkernel/intern/BME_mesh.c delete mode 100644 source/blender/blenkernel/intern/BME_structure.c delete mode 100644 source/blender/blenkernel/intern/BME_tools.c delete mode 100644 source/blender/bmesh/intern/bmesh_eulers.c delete mode 100644 source/blender/bmesh/intern/in-progress/BME_conversions.c diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index dc93885c05c..7519aef4c3e 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -58,12 +58,6 @@ set(INC_SYS ) set(SRC - intern/BME_Customdata.c - intern/BME_conversions.c - intern/BME_eulers.c - intern/BME_mesh.c - intern/BME_structure.c - intern/BME_tools.c intern/CCGSubSurf.c intern/DerivedMesh.c intern/action.c diff --git a/source/blender/blenkernel/intern/BME_Customdata.c b/source/blender/blenkernel/intern/BME_Customdata.c deleted file mode 100644 index af0e5c93aba..00000000000 --- a/source/blender/blenkernel/intern/BME_Customdata.c +++ /dev/null @@ -1,200 +0,0 @@ -#if 0 -/** - * BME_customdata.c jan 2007 - * - * Custom Data functions for Bmesh - * - * - * ***** BEGIN GPL 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. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2004 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Geoffrey Bantle, Brecht Van Lommel, Ben Batt - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/BME_Customdata.c - * \ingroup bke - */ - - -#include - -#include "MEM_guardedalloc.h" -#include "BKE_bmeshCustomData.h" -#include "bmesh_private.h" - -/********************* Layer type information **********************/ -typedef struct BME_LayerTypeInfo { - int size; - const char *defaultname; - void (*copy)(const void *source, void *dest, int count); - void (*free)(void *data, int count, int size); - void (*interp)(void **sources, float *weights, float *sub_weights, int count, void *dest); - void (*set_default)(void *data, int count); -} BME_LayerTypeInfo; -const BME_LayerTypeInfo BMELAYERTYPEINFO[BME_CD_NUMTYPES] = { - {sizeof(BME_facetex), "TexFace", NULL, NULL, NULL, NULL}, - {sizeof(BME_looptex), "UV", NULL, NULL, NULL, NULL}, - {sizeof(BME_loopcol), "VCol", NULL, NULL, NULL, NULL}, - {sizeof(BME_DeformVert), "Group", NULL, NULL, NULL, NULL} -}; -static const BME_LayerTypeInfo *BME_layerType_getInfo(int type) -{ - if(type < 0 || type >= CD_NUMTYPES) return NULL; - - return &BMELAYERTYPEINFO[type]; -} -void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc) -{ - int i, j, offset=0; - const BME_LayerTypeInfo *info; - - /*initialize data members*/ - data->layers = NULL; - data->pool = NULL; - data->totlayer = 0; - data->totsize = 0; - - /*first count how many layers to alloc*/ - for(i=0; i < BME_CD_NUMTYPES; i++){ - info = BME_layerType_getInfo(i); - data->totlayer += init->layout[i]; - data->totsize += (init->layout[i] * info->size); - } - /*alloc our layers*/ - if(data->totlayer){ - /*alloc memory*/ - data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers"); - data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, TRUE); - /*initialize layer data*/ - for(i=0; i < BME_CD_NUMTYPES; i++){ - if(init->layout[i]){ - info = BME_layerType_getInfo(i); - for(j=0; j < init->layout[i]; j++){ - if(j==0) data->layers[j+i].active = init->active[i]; - data->layers[j+i].type = i; - data->layers[j+i].offset = offset; - strcpy(data->layers[j+i].name, &(init->nametemplate[j+i])); - offset += info->size; - } - } - } - } -} - -void BME_CD_Free(BME_CustomData *data) -{ - if(data->pool) BLI_mempool_destroy(data->pool); -} - -/*Block level ops*/ -void BME_CD_free_block(BME_CustomData *data, void **block) -{ - const BME_LayerTypeInfo *typeInfo; - int i; - - if(!*block) return; - for(i = 0; i < data->totlayer; ++i) { - typeInfo = BME_layerType_getInfo(data->layers[i].type); - if(typeInfo->free) { - int offset = data->layers[i].offset; - typeInfo->free((char*)*block + offset, 1, typeInfo->size); - } - } - BLI_mempool_free(data->pool, *block); - *block = NULL; -} - - -static void BME_CD_alloc_block(BME_CustomData *data, void **block) -{ - - if (*block) BME_CD_free_block(data, block); //if we copy layers that have their own free functions like deformverts - - if (data->totsize > 0) - *block = BLI_mempool_alloc(data->pool); - else - *block = NULL; -} - -void BME_CD_copy_data(const BME_CustomData *source, BME_CustomData *dest, - void *src_block, void **dest_block) -{ - const BME_LayerTypeInfo *typeInfo; - int dest_i, src_i; - - if (!*dest_block) /*for addXXXlist functions!*/ - BME_CD_alloc_block(dest, dest_block); - - /* copies a layer at a time */ - dest_i = 0; - for(src_i = 0; src_i < source->totlayer; ++src_i) { - - /* find the first dest layer with type >= the source type - * (this should work because layers are ordered by type) - */ - while(dest_i < dest->totlayer - && dest->layers[dest_i].type < source->layers[src_i].type) - ++dest_i; - - /* if there are no more dest layers, we're done */ - if(dest_i >= dest->totlayer) return; - - /* if we found a matching layer, copy the data */ - if(dest->layers[dest_i].type == source->layers[src_i].type && - strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) { - char *src_data = (char*)src_block + source->layers[src_i].offset; - char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset; - - typeInfo = BME_layerType_getInfo(source->layers[src_i].type); - - if(typeInfo->copy) - typeInfo->copy(src_data, dest_data, 1); - else - memcpy(dest_data, src_data, typeInfo->size); - - /* if there are multiple source & dest layers of the same type, - * we don't want to copy all source layers to the same dest, so - * increment dest_i - */ - ++dest_i; - } - } -} -void BME_CD_set_default(BME_CustomData *data, void **block) -{ - const BME_LayerTypeInfo *typeInfo; - int i; - - if (!*block) - BME_CD_alloc_block(data, block); //for addXXXlist functions... - - for(i = 0; i < data->totlayer; ++i) { - int offset = data->layers[i].offset; - - typeInfo = BME_layerType_getInfo(data->layers[i].type); - - if(typeInfo->set_default) - typeInfo->set_default((char*)*block + offset, 1); - } -} -#endif diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c deleted file mode 100644 index 65a8ee8e0bb..00000000000 --- a/source/blender/blenkernel/intern/BME_conversions.c +++ /dev/null @@ -1,651 +0,0 @@ -#if 0 -/** - * BME_mesh.c jan 2007 - * - * BMesh mesh level functions. - * - * - * ***** BEGIN GPL 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. - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/BME_conversions.c - * \ingroup bke - */ - - -#include "MEM_guardedalloc.h" - -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "BLI_edgehash.h" -#include "BLI_listbase.h" -#include "BLI_utildefines.h" - -#include "BKE_mesh.h" -#include "BKE_cdderivedmesh.h" - -//XXX #include "BIF_editmesh.h" -//XXX #include "editmesh.h" -#include "bmesh_private.h" - -//XXX #include "BSE_edit.h" - -/* XXX IMPORTANT: editmesh stuff doesn't belong in kernel! (ton) */ - -/*merge these functions*/ -static void BME_DMcorners_to_loops(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f, int numCol, int numTex){ - int i, j; - BME_Loop *l; - MTFace *texface; - MTexPoly *texpoly; - MCol *mcol; - MLoopCol *mloopcol; - MLoopUV *mloopuv; - - for(i=0; i< numTex; i++){ - texface = CustomData_get_layer_n(facedata, CD_MTFACE, i); - texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); - - texpoly->tpage = texface[index].tpage; - texpoly->flag = texface[index].flag; - texpoly->transp = texface[index].transp; - texpoly->mode = texface[index].mode; - texpoly->tile = texface[index].tile; - texpoly->unwrap = texface[index].unwrap; - - j = 0; - l = f->loopbase; - do{ - mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); - mloopuv->uv[0] = texface[index].uv[j][0]; - mloopuv->uv[1] = texface[index].uv[j][1]; - j++; - l = l->next; - }while(l!=f->loopbase); - } - - for(i=0; i < numCol; i++){ - mcol = CustomData_get_layer_n(facedata, CD_MCOL, i); - j = 0; - l = f->loopbase; - do{ - mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); - mloopcol->r = mcol[(index*4)+j].r; - mloopcol->g = mcol[(index*4)+j].g; - mloopcol->b = mcol[(index*4)+j].b; - mloopcol->a = mcol[(index*4)+j].a; - j++; - l = l->next; - }while(l!=f->loopbase); - } -} - -static void BME_DMloops_to_corners(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f,int numCol, int numTex){ - int i, j; - BME_Loop *l; - MTFace *texface; - MTexPoly *texpoly; - MCol *mcol; - MLoopCol *mloopcol; - MLoopUV *mloopuv; - - for(i=0; i < numTex; i++){ - texface = CustomData_get_layer_n(facedata, CD_MTFACE, i); - texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); - - texface[index].tpage = texpoly->tpage; - texface[index].flag = texpoly->flag; - texface[index].transp = texpoly->transp; - texface[index].mode = texpoly->mode; - texface[index].tile = texpoly->tile; - texface[index].unwrap = texpoly->unwrap; - - j = 0; - l = f->loopbase; - do{ - mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); - texface[index].uv[j][0] = mloopuv->uv[0]; - texface[index].uv[j][1] = mloopuv->uv[1]; - j++; - l = l->next; - }while(l!=f->loopbase); - - } - for(i=0; i < numCol; i++){ - mcol = CustomData_get_layer_n(facedata,CD_MCOL, i); - j = 0; - l = f->loopbase; - do{ - mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); - mcol[(index*4) + j].r = mloopcol->r; - mcol[(index*4) + j].g = mloopcol->g; - mcol[(index*4) + j].b = mloopcol->b; - mcol[(index*4) + j].a = mloopcol->a; - j++; - l = l->next; - }while(l!=f->loopbase); - } -} - - -static void BME_corners_to_loops(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){ - int i, j; - BME_Loop *l; - MTFace *texface; - MTexPoly *texpoly; - MCol *mcol; - MLoopCol *mloopcol; - MLoopUV *mloopuv; - - for(i=0; i < numTex; i++){ - texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i); - texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); - - texpoly->tpage = texface->tpage; - texpoly->flag = texface->flag; - texpoly->transp = texface->transp; - texpoly->mode = texface->mode; - texpoly->tile = texface->tile; - texpoly->unwrap = texface->unwrap; - - j = 0; - l = f->loopbase; - do{ - mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); - mloopuv->uv[0] = texface->uv[j][0]; - mloopuv->uv[1] = texface->uv[j][1]; - j++; - l = l->next; - }while(l!=f->loopbase); - - } - for(i=0; i < numCol; i++){ - mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i); - j = 0; - l = f->loopbase; - do{ - mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); - mloopcol->r = mcol[j].r; - mloopcol->g = mcol[j].g; - mloopcol->b = mcol[j].b; - mloopcol->a = mcol[j].a; - j++; - l = l->next; - }while(l!=f->loopbase); - } -} - -static void BME_loops_to_corners(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){ - int i, j; - BME_Loop *l; - MTFace *texface; - MTexPoly *texpoly; - MCol *mcol; - MLoopCol *mloopcol; - MLoopUV *mloopuv; - - for(i=0; i < numTex; i++){ - texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i); - texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); - - texface->tpage = texpoly->tpage; - texface->flag = texpoly->flag; - texface->transp = texpoly->transp; - texface->mode = texpoly->mode; - texface->tile = texpoly->tile; - texface->unwrap = texpoly->unwrap; - - j = 0; - l = f->loopbase; - do{ - mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); - texface->uv[j][0] = mloopuv->uv[0]; - texface->uv[j][1] = mloopuv->uv[1]; - j++; - l = l->next; - }while(l!=f->loopbase); - - } - for(i=0; i < numCol; i++){ - mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i); - j = 0; - l = f->loopbase; - do{ - mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); - mcol[j].r = mloopcol->r; - mcol[j].g = mloopcol->g; - mcol[j].b = mloopcol->b; - mcol[j].a = mloopcol->a; - j++; - l = l->next; - }while(l!=f->loopbase); - } -} -/*move the EditMesh conversion functions to editmesh_tools.c*/ -BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { - BME_Mesh *bm; - int allocsize[4] = {512,512,2048,512}, numTex, numCol; - BME_Vert *v1, *v2; - BME_Edge *e, *edar[4]; - BME_Poly *f; - - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - int len; - bm = BME_make_mesh(allocsize); - - /*copy custom data layout*/ - CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); - - /*copy face corner data*/ - CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata, 0, 0); - /*initialize memory pools*/ - CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]); - CustomData_bmesh_init_pool(&bm->edata, allocsize[1]); - CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]); - CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]); - /*needed later*/ - numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); - numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); - - 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; - /*Copy Custom Data*/ - CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v1->data); - 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; - //XXX if(eed->h & EM_FGON) e->flag |= ME_FGON; - if(eed->h & 1) e->flag |= ME_HIDE; - eed->tmp.e = (EditEdge*)e; - CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data); - 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; - } - CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->data); - BME_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex); - efa = efa->next; - } - BME_model_end(bm); - return bm; -} -/* adds the geometry in the bmesh to editMesh (does not free editMesh) - * if td != NULL, the transdata will be mapped to the EditVert's co */ -void BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td, EditMesh *em) { - BME_Vert *v1; - BME_Edge *e; - BME_Poly *f; - - BME_TransData *vtd; - - EditVert *eve1, /* *eve2, *eve3, *eve4, */ /* UNUSED */ **evlist; - EditEdge *eed; - EditFace *efa; - - int totvert, len, i, numTex, numCol; - - if (em == NULL) return; - - CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0); - numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); - numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); - - - /* 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 = NULL; //XXX 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; - CustomData_em_copy_data(&bm->vdata, &em->vdata, v1->data, &eve1->data); - } - - /* make edges */ - for (e=bm->edges.first;e;e=e->next) { - if(0) { //XXX if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){ - eed= NULL; //XXX 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; - //XXX if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! - if(e->flag & ME_HIDE) eed->h |= 1; - if(em->selectmode==SCE_SELECT_EDGE) { - ; //XXX EM_select_edge(eed, eed->f & SELECT); - } - CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data); - } - } - - /* 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]; */ /* UNUSED */ - /* eve3= evlist[f->loopbase->next->next->v->tflag1]; */ /* UNUSED */ - /* if (len == 4) { - eve4= evlist[f->loopbase->prev->v->tflag1]; - } - else { - eve4= NULL; - } */ /* UNUSED */ - - efa = NULL; //XXX 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; - // XXX flag depricated - // if((G.f & G_FACESELECT) && (efa->f & SELECT)) - //XXX EM_select_face(efa, 1); /* flush down */ - CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data); - BME_loops_to_corners(bm, &em->fdata, efa->data, f,numCol,numTex); - } - } - - MEM_freeN(evlist); - -} - -/* Adds the geometry found in dm to bm - */ -BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm) -{ - - BME_Mesh *bm; - int allocsize[4] = {512,512,2048,512}; - MVert *mvert, *mv; - MEdge *medge, *me; - MFace *mface, *mf; - int totface,totedge,totvert,i,len, numTex, numCol; - BME_Vert *v1=NULL,*v2=NULL, **vert_array; - BME_Edge *e=NULL; - BME_Poly *f=NULL; - - EdgeHash *edge_hash = BLI_edgehash_new(); - - bm = BME_make_mesh(allocsize); - /*copy custom data layout*/ - CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); - - /*copy face corner data*/ - CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata, 0, 0); - /*initialize memory pools*/ - CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]); - CustomData_bmesh_init_pool(&bm->edata, allocsize[1]); - CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]); - CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]); - /*needed later*/ - numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); - numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); - - totvert = dm->getNumVerts(dm); - totedge = dm->getNumEdges(dm); - totface = dm->getNumTessFaces(dm); - mvert = dm->getVertArray(dm); - medge = dm->getEdgeArray(dm); - mface = dm->getTessFaceArray(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; - CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v1->data); - } - /*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); - CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->data); - } - /*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; - CustomData_to_bmesh_block(&dm->faceData,&bm->pdata,i,&f->data); - BME_DMcorners_to_loops(bm, &dm->faceData,i,f, numCol,numTex); - } - - 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 *origindex; - int totface, totedge, totvert, i, /* bmeshok, */ /* UNUSED */ 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; */ /* UNUSED */ - 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*/ - /*BMESH_TODO this should add in mloops and mpolys as well*/ - result = CDDM_from_template(dm,totvert,totedge,totface, 0, 0); - 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_tessfaces(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; -} -#endif diff --git a/source/blender/blenkernel/intern/BME_eulers.c b/source/blender/blenkernel/intern/BME_eulers.c deleted file mode 100644 index 215493fb6cf..00000000000 --- a/source/blender/blenkernel/intern/BME_eulers.c +++ /dev/null @@ -1,975 +0,0 @@ -#if 0 -/** - * BME_eulers.c jan 2007 - * - * BMesh Euler construction API. - * - * - * ***** BEGIN GPL 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. - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2004 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Geoffrey Bantle. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/BME_eulers.c - * \ingroup bke - */ - - -#include "MEM_guardedalloc.h" -#include "BLI_listbase.h" -#include "BLI_utildefines.h" - -#include "bmesh_private.h" - -/********************************************************* - * "Euler API" * - * * - * * - * Primitive construction operators for mesh tools. * - * * - **********************************************************/ - - -/* - The functions in this file represent the 'primitive' or 'atomic' operators that - mesh tools use to manipulate the topology of the structure.* The purpose of these - functions is to provide a trusted set of operators to manipulate the mesh topology - and which can also be combined together like building blocks to create more - sophisticated tools. It needs to be stressed that NO manipulation of an existing - mesh structure should be done outside of these functions. - - In the BMesh system, each euler is named by an ancronym which describes what it actually does. - Furthermore each Euler has a logical inverse. An important design criteria of all Eulers is that - through a Euler's logical inverse you can 'undo' an operation. (Special note should - be taken of BME_loop_reverse, which is its own inverse). - - BME_MF/KF: Make Face and Kill Face - BME_ME/KE: Make Edge and Kill Edge - BME_MV/KV: Make Vert and Kill Vert - BME_SEMV/JEKV: Split Edge, Make Vert and Join Edge, Kill Vert - BME_SFME/JFKE: Split Face, Make Edge and Join Face, Kill Edge - BME_loop_reverse: Reverse a Polygon's loop cycle. (used for flip normals for one) - - Using a combination of these eleven eulers any non-manifold modelling operation can be achieved. - Each Euler operator has a detailed explanation of what is does in the comments preceding its - code. - - *The term "Euler Operator" is actually a misnomer when referring to a non-manifold - data structure. Its use is in keeping with the convention established by others. - - TODO: - -Finish inserting 'strict' validation in all Eulers -*/ - -void *BME_exit(char *s) { - if (s) printf("%s\n",s); - return NULL; -} - -#define RETCLEAR(bm) {bm->rval->v = bm->rval->e = bm->rval->f = bm->rva->l = NULL;} -/*MAKE Eulers*/ - -/** - * BME_MV - * - * MAKE VERT EULER: - * - * Makes a single loose vertex. - * - * Returns - - * A BME_Vert pointer. - */ - -BME_Vert *BME_MV(BME_Mesh *bm, float *vec){ - BME_Vert *v = BME_addvertlist(bm, NULL); - VECCOPY(v->co,vec); - return v; -} - -/** - * BME_ME - * - * MAKE EDGE EULER: - * - * Makes a single wire edge between two vertices. - * If the caller does not want there to be duplicate - * edges between the vertices, it is up to them to check - * for this condition beforehand. - * - * Returns - - * A BME_Edge pointer. - */ - -BME_Edge *BME_ME(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2){ - BME_Edge *e=NULL; - BME_CycleNode *d1=NULL, *d2=NULL; - int valance1=0, valance2=0, edok; - - /*edge must be between two distinct vertices...*/ - if(v1 == v2) return NULL; - - #ifndef BME_FASTEULER - /*count valance of v1*/ - if(v1->e){ - d1 = BME_disk_getpointer(v1->e,v1); - if(d1) valance1 = BME_cycle_length(d1); - else BME_error(); - } - if(v2->e){ - d2 = BME_disk_getpointer(v2->e,v2); - if(d2) valance2 = BME_cycle_length(d2); - else BME_error(); - } - #endif - - /*go ahead and add*/ - e = BME_addedgelist(bm, v1, v2, NULL); - BME_disk_append_edge(e, e->v1); - BME_disk_append_edge(e, e->v2); - - #ifndef BME_FASTEULER - /*verify disk cycle lengths*/ - d1 = BME_disk_getpointer(e, e->v1); - edok = BME_cycle_validate(valance1+1, d1); - if(!edok) BME_error(); - d2 = BME_disk_getpointer(e, e->v2); - edok = BME_cycle_validate(valance2+1, d2); - if(!edok) BME_error(); - - /*verify that edge actually made it into the cycle*/ - edok = BME_disk_hasedge(v1, e); - if(!edok) BME_error(); - edok = BME_disk_hasedge(v2, e); - if(!edok) BME_error(); - #endif - return e; -} - - - -/** - * BME_MF - * - * MAKE FACE EULER: - * Takes a list of edge pointers which form a closed loop and makes a face - * from them. The first edge in elist is considered to be the start of the - * polygon, and v1 and v2 are its vertices and determine the winding of the face - * Other than the first edge, no other assumptions are made about the order of edges - * in the elist array. To verify that it is a single closed loop and derive the correct - * order a simple series of verifications is done and all elements are visited. - * - * Returns - - * A BME_Poly pointer - */ - -#define MF_CANDIDATE 1 -#define MF_VISITED 2 -#define MF_TAKEN 4 - -BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int len) -{ - BME_Poly *f = NULL; - BME_Edge *curedge; - BME_Vert *curvert, *tv, **vlist; - int i, j, done, cont, edok; - - if(len < 2) return NULL; - - /*make sure that v1 and v2 are in elist[0]*/ - if(BME_verts_in_edge(v1,v2,elist[0]) == 0) return NULL; - - /*clear euler flags*/ - for(i=0;ieflag1=elist[i]->eflag2 = 0; - for(i=0;ieflag1 |= MF_CANDIDATE; - - /*if elist[i] has a loop, count its radial length*/ - if(elist[i]->loop) elist[i]->eflag2 = BME_cycle_length(&(elist[i]->l->radial)); - else elist[i]->eflag2 = 0; - } - - /* For each vertex in each edge, it must have exactly two MF_CANDIDATE edges attached to it - Note that this does not gauruntee that face is a single closed loop. At best it gauruntees - that elist contains a finite number of seperate closed loops. - */ - for(i=0; iv1, MF_CANDIDATE, 0); - if(edok != 2) return NULL; - edok = BME_disk_count_edgeflag(elist[i]->v2, MF_CANDIDATE, 0); - if(edok != 2) return NULL; - } - - /*set start edge, start vert and target vert for our loop traversal*/ - curedge = elist[0]; - tv = v1; - curvert = v2; - - if(bm->vtarlen < len){ - MEM_freeN(bm->vtar); - bm->vtar = MEM_callocN(sizeof(BME_Vert *)* len, "BMesh Vert pointer array"); - bm->vtarlen = len; - } - /*insert tv into vlist since its the first vertex in face*/ - i=0; - vlist=bm->vtar; - vlist[i] = tv; - - /* Basic procedure: Starting with curv we find the edge in it's disk cycle which hasn't - been visited yet. When we do, we put curv in a linked list and find the next MF_CANDIDATE - edge, loop until we find TV. We know TV is reachable because of test we did earlier. - */ - done=0; - while(!done){ - /*add curvert to vlist*/ - /*insert some error cheking here for overflows*/ - i++; - vlist[i] = curvert; - - /*mark curedge as visited*/ - curedge->eflag1 |= MF_VISITED; - - /*find next edge and vert*/ - curedge = BME_disk_next_edgeflag(curedge, curvert, MF_CANDIDATE, 0); - curvert = BME_edge_getothervert(curedge, curvert); - if(curvert == tv){ - curedge->eflag1 |= MF_VISITED; - done=1; - } - } - - /* Verify that all edges have been visited It's possible that we did reach tv - from sv, but that several unconnected loops were passed in via elist. - */ - cont=1; - for(i=0; ieflag1 & MF_VISITED) == 0) cont = 0; - } - - /*if we get this far, its ok to allocate the face and add the loops*/ - if(cont){ - BME_Loop *l; - BME_Edge *e; - f = BME_addpolylist(bm, NULL); - f->len = len; - for(i=0;iloopbase)) f->lbase = l; - BME_cycle_append(f->lbase, l); - } - - /*take care of edge pointers and radial cycle*/ - for(i=0, l = f->loopbase; inext){ - e = NULL; - if(l == f->loopbase) e = elist[0]; /*first edge*/ - - else{/*search elist for others*/ - for(j=1; jv, l->next->v, elist[j]); - if(edok){ - e = elist[j]; - break; - } - } - } - l->e = e; /*set pointer*/ - BME_radial_append(e, l); /*append into radial*/ - } - - f->len = len; - - /*Validation Loop cycle*/ - edok = BME_cycle_validate(len, f->lbase); - if(!edok) BME_error(); - for(i=0, l = f->loopbase; inext){ - /*validate loop vert pointers*/ - edok = BME_verts_in_edge(l->v, l->next->v, l->e); - if(!edok) BME_error(); - /*validate the radial cycle of each edge*/ - edok = BME_cycle_length(&(l->radial)); - if(edok != (l->e->eflag2 + 1)) BME_error(); - } - } - return f; -} - -/* KILL Eulers */ - -/** - * BME_KV - * - * KILL VERT EULER: - * - * Kills a single loose vertex. - * - * Returns - - * 1 for success, 0 for failure. - */ - -int BME_KV(BME_Mesh *bm, BME_Vert *v){ - if(v->e == NULL){ - BLI_remlink(&(bm->verts), v); - BME_free_vert(bm,v); - return 1; - } - return 0; -} - -/** - * BME_KE - * - * KILL EDGE EULER: - * - * Kills a wire edge. - * - * Returns - - * 1 for success, 0 for failure. - */ - -int BME_KE(BME_Mesh *bm, BME_Edge *e){ - int edok; - - /*Make sure that no faces!*/ - if(e->l == NULL){ - BME_disk_remove_edge(e, e->v1); - BME_disk_remove_edge(e, e->v2); - - /*verify that edge out of disk*/ - edok = BME_disk_hasedge(e->v1, e); - if(edok) BME_error(); - edok = BME_disk_hasedge(e->v2, e); - if(edok) BME_error(); - - /*remove and deallocate*/ - BLI_remlink(&(bm->edges), e); - BME_free_edge(bm, e); - return 1; - } - return 0; -} - -/** - * BME_KF - * - * KILL FACE EULER: - * - * The logical inverse of BME_MF. - * Kills a face and removes each of its loops from the radial that it belongs to. - * - * Returns - - * 1 for success, 0 for failure. -*/ - -int BME_KF(BME_Mesh *bm, BME_Poly *bply){ - BME_Loop *newbase,*oldbase, *curloop; - int i,len=0; - - /*add validation to make sure that radial cycle is cleaned up ok*/ - /*deal with radial cycle first*/ - len = BME_cycle_length(bply->lbase); - for(i=0, curloop=bply->loopbase; i < len; i++, curloop = curloop->next) - BME_radial_remove_loop(curloop, curloop->e); - - /*now deallocate the editloops*/ - for(i=0; i < len; i++){ - newbase = bply->lbase->next; - oldbase = bply->lbase; - BME_cycle_remove(oldbase, oldbase); - BME_free_loop(bm, oldbase); - bply->loopbase = newbase; - } - - BLI_remlink(&(bm->polys), bply); - BME_free_poly(bm, bply); - return 1; -} - -/*SPLIT Eulers*/ - -/** - * BME_SEMV - * - * SPLIT EDGE MAKE VERT: - * Takes a given edge and splits it into two, creating a new vert. - * - * - * Before: OV---------TV - * After: OV----NV---TV - * - * Returns - - * BME_Vert pointer. - * -*/ - -BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){ - BME_Vert *nv, *ov; - BME_CycleNode *diskbase; - BME_Edge *ne; - int i, edok, valance1=0, valance2=0; - - if(BME_vert_in_edge(e,tv) == 0) return NULL; - ov = BME_edge_getothervert(e,tv); - //v2 = tv; - - /*count valance of v1*/ - diskbase = BME_disk_getpointer(e, ov); - valance1 = BME_cycle_length(diskbase); - /*count valance of v2*/ - diskbase = BME_disk_getpointer(e, tv); - valance2 = BME_cycle_length(diskbase); - - nv = BME_addvertlist(bm, tv); - ne = BME_addedgelist(bm, nv, tv, e); - - //e->v2 = nv; - /*remove e from v2's disk cycle*/ - BME_disk_remove_edge(e, tv); - /*swap out tv for nv in e*/ - BME_edge_swapverts(e, tv, nv); - /*add e to nv's disk cycle*/ - BME_disk_append_edge(e, nv); - /*add ne to nv's disk cycle*/ - BME_disk_append_edge(ne, nv); - /*add ne to tv's disk cycle*/ - BME_disk_append_edge(ne, tv); - /*verify disk cycles*/ - diskbase = BME_disk_getpointer(ov->e,ov); - edok = BME_cycle_validate(valance1, diskbase); - if(!edok) BME_error(); - diskbase = BME_disk_getpointer(tv->e,tv); - edok = BME_cycle_validate(valance2, diskbase); - if(!edok) BME_error(); - diskbase = BME_disk_getpointer(nv->e,nv); - edok = BME_cycle_validate(2, diskbase); - if(!edok) BME_error(); - - /*Split the radial cycle if present*/ - if(e->l){ - BME_Loop *nl,*l; - BME_CycleNode *radEBase=NULL, *radNEBase=NULL; - int radlen = BME_cycle_length(&(e->l->radial)); - /*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/ - while(e->l){ - l=e->l; - l->f->len++; - BME_radial_remove_loop(l,e); - - nl = BME_create_loop(bm,NULL,NULL,l->f,l); - nl->prev = l; - nl->next = l->next; - nl->prev->next = nl; - nl->next->prev = nl; - nl->v = nv; - - /*assign the correct edge to the correct loop*/ - if(BME_verts_in_edge(nl->v, nl->next->v, e)){ - nl->e = e; - l->e = ne; - - /*append l into ne's rad cycle*/ - if(!radNEBase){ - radNEBase = &(l->radial); - radNEBase->next = NULL; - radNEBase->prev = NULL; - } - - if(!radEBase){ - radEBase = &(nl->radial); - radEBase->next = NULL; - radEBase->prev = NULL; - } - - BME_cycle_append(radEBase,&(nl->radial)); - BME_cycle_append(radNEBase,&(l->radial)); - - } - else if(BME_verts_in_edge(nl->v,nl->next->v,ne)){ - nl->e = ne; - l->e = e; - - if(!radNEBase){ - radNEBase = &(nl->radial); - radNEBase->next = NULL; - radNEBase->prev = NULL; - } - if(!radEBase){ - radEBase = &(l->radial); - radEBase->next = NULL; - radEBase->prev = NULL; - } - BME_cycle_append(radEBase,&(l->radial)); - BME_cycle_append(radNEBase,&(nl->radial)); - } - - } - - e->l = radEBase->data; - ne->l = radNEBase->data; - - /*verify length of radial cycle*/ - edok = BME_cycle_validate(radlen,&(e->l->radial)); - if(!edok) BME_error(); - edok = BME_cycle_validate(radlen,&(ne->l->radial)); - if(!edok) BME_error(); - - /*verify loop->v and loop->next->v pointers for e*/ - for(i=0,l=e->l; i < radlen; i++, l = l->radial_next){ - if(!(l->e == e)) BME_error(); - if(!(l->radial.data == l)) BME_error(); - if(l->prev->e != ne && l->next->e != ne) BME_error(); - edok = BME_verts_in_edge(l->v, l->next->v, e); - if(!edok) BME_error(); - if(l->v == l->next->v) BME_error(); - if(l->e == l->next->e) BME_error(); - /*verify loop cycle for kloop->f*/ - edok = BME_cycle_validate(l->f->len, l->f->lbase); - if(!edok) BME_error(); - } - /*verify loop->v and loop->next->v pointers for ne*/ - for(i=0,l=ne->l; i < radlen; i++, l = l->radial_next){ - if(!(l->e == ne)) BME_error(); - if(!(l->radial.data == l)) BME_error(); - if(l->prev->e != e && l->next->e != e) BME_error(); - edok = BME_verts_in_edge(l->v, l->next->v, ne); - if(!edok) BME_error(); - if(l->v == l->next->v) BME_error(); - if(l->e == l->next->e) BME_error(); - /*verify loop cycle for kloop->f. Redundant*/ - edok = BME_cycle_validate(l->f->len, l->f->lbase); - if(!edok) BME_error(); - } - } - - if(re) *re = ne; - return nv; -} - -/** - * BME_SFME - * - * SPLIT FACE MAKE EDGE: - * - * Takes as input two vertices in a single face. An edge is created which divides the original face - * into two distinct regions. One of the regions is assigned to the original face and it is closed off. - * The second region has a new face assigned to it. - * - * Examples: - * - * Before: After: - * ---------- ---------- - * | | | | - * | | | f1 | - * v1 f1 v2 v1======v2 - * | | | f2 | - * | | | | - * ---------- ---------- - * - * Note that the input vertices can be part of the same edge. This will result in a two edged face. - * This is desirable for advanced construction tools and particularly essential for edge bevel. Because - * of this it is up to the caller to decide what to do with the extra edge. - * - * Returns - - * A BME_Poly pointer - */ -BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Loop **rl){ - - BME_Poly *f2; - BME_Loop *v1loop = NULL, *v2loop = NULL, *curloop, *f1loop=NULL, *f2loop=NULL; - BME_Edge *e; - int i, len, f1len, f2len; - - - /*verify that v1 and v2 are in face.*/ - len = BME_cycle_length(f->lbase); - for(i = 0, curloop = f->loopbase; i < len; i++, curloop = curloop->next){ - if(curloop->v == v1) v1loop = curloop; - else if(curloop->v == v2) v2loop = curloop; - } - - if(!v1loop || !v2loop) return NULL; - - /*allocate new edge between v1 and v2*/ - e = BME_addedgelist(bm, v1, v2,NULL); - BME_disk_append_edge(e, v1); - BME_disk_append_edge(e, v2); - - f2 = BME_addpolylist(bm,f); - f1loop = BME_create_loop(bm,v2,e,f,v2loop); - f2loop = BME_create_loop(bm,v1,e,f2,v1loop); - - f1loop->prev = v2loop->prev; - f2loop->prev = v1loop->prev; - v2loop->prev->next = f1loop; - v1loop->prev->next = f2loop; - - f1loop->next = v1loop; - f2loop->next = v2loop; - v1loop->prev = f1loop; - v2loop->prev = f2loop; - - f2->loopbase = f2loop; - f->loopbase = f1loop; - - /*validate both loops*/ - /*I dont know how many loops are supposed to be in each face at this point! FIXME!*/ - - /*go through all of f2's loops and make sure they point to it properly.*/ - f2len = BME_cycle_length(f2->lbase); - for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = curloop->next) curloop->f = f2; - - /*link up the new loops into the new edges radial*/ - BME_radial_append(e, f1loop); - BME_radial_append(e, f2loop); - - - f2->len = f2len; - - f1len = BME_cycle_length(f->lbase); - f->len = f1len; - - if(rl) *rl = f2loop; - return f2; -} - - -/** - * BME_JEKV - * - * JOIN EDGE KILL VERT: - * Takes a an edge and pointer to one of its vertices and collapses - * the edge on that vertex. - * - * Before: OE KE - * ------- ------- - * | || | - * OV KV TV - * - * - * After: OE - * --------------- - * | | - * OV TV - * - * - * Restrictions: - * KV is a vertex that must have a valance of exactly two. Furthermore - * both edges in KV's disk cycle (OE and KE) must be unique (no double - * edges). - * - * It should also be noted that this euler has the possibility of creating - * faces with just 2 edges. It is up to the caller to decide what to do with - * these faces. - * - * Returns - - * 1 for success, 0 for failure. - */ -int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) -{ - BME_Edge *oe; - BME_Vert *ov, *tv; - BME_CycleNode *diskbase; - BME_Loop *killoop,*nextl; - int len,radlen=0, halt = 0, i, valance1, valance2,edok; - - if(BME_vert_in_edge(ke,kv) == 0) return 0; - diskbase = BME_disk_getpointer(kv->e, kv); - len = BME_cycle_length(diskbase); - - if(len == 2){ - oe = BME_disk_nextedge(ke, kv); - tv = BME_edge_getothervert(ke, kv); - ov = BME_edge_getothervert(oe, kv); - halt = BME_verts_in_edge(kv, tv, oe); //check for double edges - - if(halt) return 0; - else{ - - /*For verification later, count valance of ov and tv*/ - diskbase = BME_disk_getpointer(ov->e, ov); - valance1 = BME_cycle_length(diskbase); - diskbase = BME_disk_getpointer(tv->e, tv); - valance2 = BME_cycle_length(diskbase); - - /*remove oe from kv's disk cycle*/ - BME_disk_remove_edge(oe,kv); - /*relink oe->kv to be oe->tv*/ - BME_edge_swapverts(oe, kv, tv); - /*append oe to tv's disk cycle*/ - BME_disk_append_edge(oe, tv); - /*remove ke from tv's disk cycle*/ - BME_disk_remove_edge(ke, tv); - - - - /*deal with radial cycle of ke*/ - if(ke->l){ - /*first step, fix the neighboring loops of all loops in ke's radial cycle*/ - radlen = BME_cycle_length(&(ke->l->radial)); - for(i=0,killoop = ke->l; inext->prev = killoop->prev; - killoop->prev->next = killoop->next; - if(killoop->next->v == kv) killoop->next->v = tv; - - /*fix len attribute of face*/ - killoop->f->len--; - if(killoop->f->loopbase == killoop) killoop->f->lbase = killoop->next; - } - /*second step, remove all the hanging loops attached to ke*/ - killoop = ke->l; - radlen = BME_cycle_length(&(ke->l->radial)); - /*make sure we have enough room in bm->lpar*/ - if(bm->lparlen < radlen){ - MEM_freeN(bm->lpar); - bm->lpar = MEM_callocN(sizeof(BME_Loop *)* radlen, "BMesh Loop pointer array"); - bm->lparlen = bm->lparlen * radlen; - } - /*this should be wrapped into a bme_free_radial function to be used by BME_KF as well...*/ - i=0; - while(ilpar[i] = killoop; - killoop = killoop->radial_next; - i++; - } - i=0; - while(ilpar[i]); - i++; - } - /*Validate radial cycle of oe*/ - edok = BME_cycle_validate(radlen,&(oe->l->radial)); - - } - - - /*Validate disk cycles*/ - diskbase = BME_disk_getpointer(ov->e,ov); - edok = BME_cycle_validate(valance1, diskbase); - if(!edok) BME_error(); - diskbase = BME_disk_getpointer(tv->e,tv); - edok = BME_cycle_validate(valance2, diskbase); - if(!edok) BME_error(); - - /*Validate loop cycle of all faces attached to oe*/ - for(i=0,nextl = oe->l; if->len,nextl->f->lbase); - if(!edok) BME_error(); - } - /*deallocate edge*/ - BLI_remlink(&(bm->edges), ke); - BME_free_edge(bm, ke); - /*deallocate vertex*/ - BLI_remlink(&(bm->verts), kv); - BME_free_vert(bm, kv); - return 1; - } - } - return 0; -} - - -/** - * BME_loop_reverse - * - * FLIP FACE EULER - * - * Changes the winding order of a face from CW to CCW or vice versa. - * This euler is a bit peculiar in compairson to others as it is its - * own inverse. - * - * TODO: reinsert validation code. - * - * Returns - - * 1 for success, 0 for failure. - */ - -int BME_loop_reverse(BME_Mesh *bm, BME_Poly *f){ - BME_Loop *l = f->loopbase, *curloop, *oldprev, *oldnext; - int i, j, edok, len = 0; - - len = BME_cycle_length(l); - if(bm->edarlen < len){ - MEM_freeN(bm->edar); - bm->edar = MEM_callocN(sizeof(BME_Edge *)* len, "BMesh Edge pointer array"); - bm->edarlen = len; - } - - for(i=0, curloop = l; i< len; i++, curloop=curloop->next){ - curloop->e->eflag1 = 0; - curloop->e->eflag2 = BME_cycle_length(&curloop->radial); - BME_radial_remove_loop(curloop, curloop->e); - /*in case of border edges we HAVE to zero out curloop->radial Next/Prev*/ - curloop->radial.next = curloop->radial.prev = NULL; - bm->edar[i] = curloop->e; - } - - /*actually reverse the loop. This belongs in BME_cycle_reverse!*/ - for(i=0, curloop = l; i < len; i++){ - oldnext = curloop->next; - oldprev = curloop->prev; - curloop->next = oldprev; - curloop->prev = oldnext; - curloop = oldnext; - } - - if(len == 2){ //two edged face - //do some verification here! - l->e = bm->edar[1]; - l->next->e = bm->edar[0]; - } - else{ - for(i=0, curloop = l; i < len; i++, curloop = curloop->next){ - edok = 0; - for(j=0; j < len; j++){ - edok = BME_verts_in_edge(curloop->v, curloop->next->v, bm->edar[j]); - if(edok){ - curloop->e = bm->edar[j]; - break; - } - } - } - } - /*rebuild radial*/ - for(i=0, curloop = l; i < len; i++, curloop = curloop->next) BME_radial_append(curloop->e, curloop); - - /*validate radial*/ - for(i=0, curloop = l; i < len; i++, curloop = curloop->next){ - edok = BME_cycle_validate(curloop->e->eflag2, &(curloop->radial)); - if(!edok){ - BME_error(); - } - } - return 1; -} - -/** - * BME_JFKE - * - * JOIN FACE KILL EDGE: - * - * Takes two faces joined by a single 2-manifold edge and fuses them togather. - * The edge shared by the faces must not be connected to any other edges which have - * Both faces in its radial cycle - * - * Examples: - * - * A B - * ---------- ---------- - * | | | | - * | f1 | | f1 | - * v1========v2 = Ok! v1==V2==v3 == Wrong! - * | f2 | | f2 | - * | | | | - * ---------- ---------- - * - * In the example A, faces f1 and f2 are joined by a single edge, and the euler can safely be used. - * In example B however, f1 and f2 are joined by multiple edges and will produce an error. The caller - * in this case should call BME_JEKV on the extra edges before attempting to fuse f1 and f2. - * - * Also note that the order of arguments decides whether or not certain per-face attributes are present - * in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited - * from f1, not f2. - * - * Returns - - * A BME_Poly pointer -*/ - -BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) -{ - - BME_Loop *curloop, *f1loop=NULL, *f2loop=NULL; - int loopok = 0, newlen = 0,i, f1len=0, f2len=0, radlen=0, edok; - - if(f1 == f2) return NULL; //can't join a face to itself - /*verify that e is in both f1 and f2*/ - f1len = BME_cycle_length(f1->lbase); - f2len = BME_cycle_length(f2->lbase); - for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = curloop->next){ - if(curloop->e == e){ - f1loop = curloop; - break; - } - } - for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = curloop->next){ - if(curloop->e==e){ - f2loop = curloop; - break; - } - } - if(!(f1loop && f2loop)) return NULL; - - /*validate that edge is 2-manifold edge*/ - radlen = BME_cycle_length(&(f1loop->radial)); - if(radlen != 2) return NULL; - - /*validate direction of f2's loop cycle is compatible.*/ - if(f1loop->v == f2loop->v) return NULL; - - /* - Finally validate that for each face, each vertex has another edge in its disk cycle that is - not e, and not shared. - */ - if(BME_radial_find_face(f1loop->next->e,f2)) return NULL; - if(BME_radial_find_face(f1loop->prev->e,f2)) return NULL; - if(BME_radial_find_face(f2loop->next->e,f1)) return NULL; - if(BME_radial_find_face(f2loop->prev->e,f1)) return NULL; - - /*join the two loops*/ - f1loop->prev->next = f2loop->next; - f2loop->next->prev = f1loop->prev; - - f1loop->next->prev = f2loop->prev; - f2loop->prev->next = f1loop->next; - - /*if f1loop was baseloop, give f1loop->next the base.*/ - if(f1->loopbase == f1loop) f1->lbase = f1loop->next; - - /*validate the new loop*/ - loopok = BME_cycle_validate((f1len+f2len)-2, f1->lbase); - if(!loopok) BME_error(); - - /*make sure each loop points to the proper face*/ - newlen = BME_cycle_length(f1->lbase); - for(i = 0, curloop = f1->loopbase; i < newlen; i++, curloop = curloop->next) curloop->f = f1; - - f1->len = newlen; - - edok = BME_cycle_validate(f1->len, f1->lbase); - if(!edok) BME_error(); - - /*remove edge from the disk cycle of its two vertices.*/ - BME_disk_remove_edge(f1loop->e, f1loop->e->v1); - BME_disk_remove_edge(f1loop->e, f1loop->e->v2); - - /*deallocate edge and its two loops as well as f2*/ - BLI_remlink(&(bm->edges), f1loop->e); - BLI_remlink(&(bm->polys), f2); - BME_free_edge(bm, f1loop->e); - BME_free_loop(bm, f1loop); - BME_free_loop(bm, f2loop); - BME_free_poly(bm, f2); - return f1; -} -#endif diff --git a/source/blender/blenkernel/intern/BME_mesh.c b/source/blender/blenkernel/intern/BME_mesh.c deleted file mode 100644 index dcca2da5414..00000000000 --- a/source/blender/blenkernel/intern/BME_mesh.c +++ /dev/null @@ -1,287 +0,0 @@ -#if 0 -/** - * BME_mesh.c jan 2007 - * - * BMesh mesh level functions. - * - * - * ***** BEGIN GPL 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. - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/BME_mesh.c - * \ingroup bke - */ - - -#include "BLI_listbase.h" -#include "MEM_guardedalloc.h" -#include "BKE_bmesh.h" -#include "bmesh_private.h" - -/* - * BME MAKE MESH - * - * Allocates a new BME_Mesh structure. - * Returns - - * Pointer to a Bmesh - * -*/ - -BME_Mesh *BME_make_mesh(int allocsize[4]) -{ - /*allocate the structure*/ - BME_Mesh *bm = MEM_callocN(sizeof(BME_Mesh),"BMesh"); - /*allocate the memory pools for the mesh elements*/ - bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], TRUE, FALSE); - bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], TRUE, FALSE); - bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], TRUE, FALSE); - bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], TRUE, FALSE); - return bm; -} -/* - * BME FREE MESH - * - * Frees a BME_Mesh structure. -*/ - -void BME_free_mesh(BME_Mesh *bm) -{ - BME_Vert *v; - BME_Edge *e; - BME_Loop *l; - BME_Poly *f; - - for(v=bm->verts.first; v; v=v->next) CustomData_bmesh_free_block(&bm->vdata, &v->data); - for(e=bm->edges.first; e; e=e->next) CustomData_bmesh_free_block(&bm->edata, &e->data); - for(f=bm->polys.first; f; f=f->next){ - CustomData_bmesh_free_block(&bm->pdata, &f->data); - l = f->loopbase; - do{ - CustomData_bmesh_free_block(&bm->ldata, &l->data); - l = l->next; - }while(l!=f->lbase); - } - - /*Free custom data pools, This should probably go in CustomData_free?*/ - if(bm->vdata.totlayer) BLI_mempool_destroy(bm->vdata.pool); - if(bm->edata.totlayer) BLI_mempool_destroy(bm->edata.pool); - if(bm->ldata.totlayer) BLI_mempool_destroy(bm->ldata.pool); - if(bm->pdata.totlayer) BLI_mempool_destroy(bm->pdata.pool); - - /*free custom data*/ - CustomData_free(&bm->vdata,0); - CustomData_free(&bm->edata,0); - CustomData_free(&bm->ldata,0); - CustomData_free(&bm->pdata,0); - - /*destroy element pools*/ - BLI_mempool_destroy(bm->vpool); - BLI_mempool_destroy(bm->epool); - BLI_mempool_destroy(bm->ppool); - BLI_mempool_destroy(bm->lpool); - - MEM_freeN(bm); -} - -/* - * BME MODEL BEGIN AND END - * - * These two functions represent the 'point of entry' for tools. Every BMesh tool - * must begin with a call to BME_model_end() and finish with a call to BME_model_end(). - * No modification of mesh data is allowed except in between these two calls. - * - * The purpose of these calls is allow for housekeeping tasks to be performed, - * such as allocating/freeing scratch arrays or performing debug validation of - * the mesh structure. - * - * Returns - - * Nothing - * -*/ - -int BME_model_begin(BME_Mesh *bm){ - /*Initialize some scratch pointer arrays used by eulers*/ - bm->vtar = MEM_callocN(sizeof(BME_Vert *) * 1024, "BMesh scratch vert array"); - bm->edar = MEM_callocN(sizeof(BME_Edge *) * 1024, "BMesh scratch edge array"); - bm->lpar = MEM_callocN(sizeof(BME_Loop *) * 1024, "BMesh scratch loop array"); - bm->plar = MEM_callocN(sizeof(BME_Poly *) * 1024, "BMesh scratch poly array"); - - bm->vtarlen = bm->edarlen = bm->lparlen = bm->plarlen = 1024; - - return 1; -} - -void BME_model_end(BME_Mesh *bm){ - int meshok, totvert, totedge, totpoly; - - totvert = BLI_countlist(&(bm->verts)); - totedge = BLI_countlist(&(bm->edges)); - totpoly = BLI_countlist(&(bm->polys)); - - if(bm->vtar) MEM_freeN(bm->vtar); - if(bm->edar) MEM_freeN(bm->edar); - if(bm->lpar) MEM_freeN(bm->lpar); - if(bm->plar) MEM_freeN(bm->plar); - - bm->vtar = NULL; - bm->edar = NULL; - bm->lpar = NULL; - bm->plar = NULL; - bm->vtarlen = bm->edarlen = bm->lparlen = bm->plarlen = 0; - - - if(bm->totvert!=totvert || bm->totedge!=totedge || bm->totpoly!=totpoly) - BME_error(); - - meshok = BME_validate_mesh(bm, 1); - if(!meshok){ - BME_error(); - } -} - -/* - * BME VALIDATE MESH - * - * There are several levels of validation for meshes. At the - * Euler level, some basic validation is done to local topology. - * To catch more subtle problems however, BME_validate_mesh() is - * called by BME_model_end() whenever a tool is done executing. - * The purpose of this function is to insure that during the course - * of tool execution that nothing has been done to invalidate the - * structure, and if it has, provide a way of reporting that so that - * we can restore the proper structure from a backup. Since a full mesh - * validation would be too expensive, this is presented as a compromise. - * - * TODO - * - * -Make this only part of debug builds - */ - -#define VHALT(halt) {BME_error(); if(halt) return 0;} - -int BME_validate_mesh(struct BME_Mesh *bm, int halt) -{ - BME_Vert *v; - BME_Edge *e; - BME_Poly *f; - BME_Loop *l; - BME_CycleNode *diskbase; - int i, ok; - - /*Simple edge verification*/ - for(e=bm->edges.first; e; e=e->next){ - if(e->v1 == e->v2) VHALT(halt); - /*validate e->d1.data and e->d2.data*/ - if(e->d1.data != e || e->d2.data != e) VHALT(halt); - /*validate e->l->e*/ - if(e->l){ - if(e->l->e != e) VHALT(halt); - } - } - - /*calculate disk cycle lengths*/ - for(v=bm->verts.first; v; v=v->next) v->tflag1 = v->tflag2 = 0; - for(e=bm->edges.first; e; e=e->next){ - e->v1->tflag1++; - e->v2->tflag1++; - } - /*Validate vertices and disk cycle*/ - for(v=bm->verts.first; v; v=v->next){ - /*validate v->e pointer*/ - if(v->tflag1){ - if(v->e){ - ok = BME_vert_in_edge(v->e,v); - if(!ok) VHALT(halt); - /*validate length of disk cycle*/ - diskbase = BME_disk_getpointer(v->e, v); - ok = BME_cycle_validate(v->tflag1, diskbase); - if(!ok) VHALT(halt); - /*validate that each edge in disk cycle contains V*/ - for(i=0, e=v->e; i < v->tflag1; i++, e = BME_disk_nextedge(e,v)){ - ok = BME_vert_in_edge(e, v); - if(!ok) VHALT(halt); - } - } - else VHALT(halt); - } - } - /*validate edges*/ - for(e=bm->edges.first; e; e=e->next){ - /*seperate these into BME_disk_hasedge (takes pointer to edge)*/ - /*search v1 disk cycle for edge*/ - ok = BME_disk_hasedge(e->v1,e); - if(!ok) VHALT(halt); - /*search v2 disk cycle for edge*/ - ok = BME_disk_hasedge(e->v2,e); - if(!ok) VHALT(halt); - } - - for(e=bm->edges.first; e; e=e->next) e->tflag2 = 0; //store incident faces - /*Validate the loop cycle integrity.*/ - for(f=bm->polys.first; f; f=f->next){ - ok = BME_cycle_length(f->lbase); - if(ok > 1){ - f->tflag1 = ok; - } - else VHALT(halt); - for(i=0, l=f->loopbase; i < f->tflag1; i++, l=l->next){ - /*verify loop->v pointers*/ - ok = BME_verts_in_edge(l->v, l->next->v, l->e); - if(!ok) VHALT(halt); - /*verify radial node data pointer*/ - if(l->radial.data != l) VHALT(halt); - /*validate l->e->l poitner*/ - if(l->e->l == NULL) VHALT(halt); - /*validate l->f pointer*/ - if(l->f != f) VHALT(halt); - /*see if l->e->l is actually in radial cycle*/ - - l->e->tflag2++; - } - } - - /*validate length of radial cycle*/ - for(e=bm->edges.first; e; e=e->next){ - if(e->l){ - ok = BME_cycle_validate(e->tflag2,&(e->l->radial)); - if(!ok) VHALT(halt); - } - } - - /*validate that EIDs are within range... if not indicates corrupted mem*/ - - /*if we get this far, pretty safe to return 1*/ - return 1; -} - -/* Currently just a convient place for a breakpoint. - Probably should take an error string -*/ -void BME_error(void){ - printf("BME modelling error!"); -} -#endif diff --git a/source/blender/blenkernel/intern/BME_structure.c b/source/blender/blenkernel/intern/BME_structure.c deleted file mode 100644 index 789812a99c8..00000000000 --- a/source/blender/blenkernel/intern/BME_structure.c +++ /dev/null @@ -1,631 +0,0 @@ -#if 0 -/** - * BME_structure.c jan 2007 - * - * Low level routines for manipulating the BMesh structure. - * - * - * ***** BEGIN GPL 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. - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#if 0 -/** \file blender/blenkernel/intern/BME_structure.c - * \ingroup bke - */ - - -#include - -#include "MEM_guardedalloc.h" -#include "BLI_listbase.h" -#include "BLI_utildefines.h" -#include "BKE_bmesh.h" -/** - * MISC utility functions. - * - */ - -int BME_vert_in_edge(BME_Edge *e, BME_Vert *v){ - if(e->v1 == v || e->v2 == v) return 1; - return 0; -} -int BME_verts_in_edge(BME_Vert *v1, BME_Vert *v2, BME_Edge *e){ - if(e->v1 == v1 && e->v2 == v2) return 1; - else if(e->v1 == v2 && e->v2 == v1) return 1; - return 0; -} - -BME_Vert *BME_edge_getothervert(BME_Edge *e, BME_Vert *v){ - if(e->v1 == v) return e->v2; - else if(e->v2 == v) return e->v1; - return NULL; -} - -int BME_edge_swapverts(BME_Edge *e, BME_Vert *orig, BME_Vert *new){ - if(e->v1 == orig){ - e->v1 = new; - e->d1.next = NULL; - e->d1.prev = NULL; - return 1; - } - else if(e->v2 == orig){ - e->v2 = new; - e->d2.next = NULL; - e->d2.prev = NULL; - return 1; - } - return 0; -} - -/** - * ALLOCATION/DEALLOCATION FUNCTIONS - */ - -BME_Vert *BME_addvertlist(BME_Mesh *bm, BME_Vert *example){ - BME_Vert *v=NULL; - v = BLI_mempool_alloc(bm->vpool); - v->next = v->prev = NULL; - v->EID = bm->nextv; - v->co[0] = v->co[1] = v->co[2] = 0.0f; - v->no[0] = v->no[1] = v->no[2] = 0.0f; - v->e = NULL; - v->data = NULL; - v->eflag1 = v->eflag2 = v->tflag1 = v->tflag2 = 0; - v->flag = v->h = 0; - v->bweight = 0.0f; - BLI_addtail(&(bm->verts), v); - bm->nextv++; - bm->totvert++; - - if(example){ - VECCOPY(v->co,example->co); - CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->data, &v->data); - } - else - CustomData_bmesh_set_default(&bm->vdata, &v->data); - - return v; -} -BME_Edge *BME_addedgelist(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge *example){ - BME_Edge *e=NULL; - e = BLI_mempool_alloc(bm->epool); - e->next = e->prev = NULL; - e->EID = bm->nexte; - e->v1 = v1; - e->v2 = v2; - e->d1.next = e->d1.prev = e->d2.next = e->d2.prev = NULL; - e->d1.data = e; - e->d2.data = e; - e->l = NULL; - e->data = NULL; - e->eflag1 = e->eflag2 = e->tflag1 = e->tflag2 = 0; - e->flag = e->h = 0; - e->crease = e->bweight = 0.0f; - bm->nexte++; - bm->totedge++; - BLI_addtail(&(bm->edges), e); - - if(example) - CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->data, &e->data); - else - CustomData_bmesh_set_default(&bm->edata, &e->data); - - - return e; -} -BME_Loop *BME_create_loop(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Poly *f, BME_Loop *example){ - BME_Loop *l=NULL; - l = BLI_mempool_alloc(bm->lpool); - l->next = l->prev = NULL; - l->EID = bm->nextl; - l->radial.next = l->radial.prev = NULL; - l->radial.data = l; - l->v = v; - l->e = e; - l->f = f; - l->data = NULL; - l->eflag1 = l->eflag2 = l->tflag1 = l->tflag2 = 0; - l->flag = l->h = 0; //stupid waste! - bm->nextl++; - bm->totloop++; - - if(example) - CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->data, &l->data); - else - CustomData_bmesh_set_default(&bm->ldata, &l->data); - - return l; -} - -BME_Poly *BME_addpolylist(BME_Mesh *bm, BME_Poly *example){ - BME_Poly *f = NULL; - f = BLI_mempool_alloc(bm->ppool); - f->next = f->prev = NULL; - f->EID = bm->nextp; - f->loopbase = NULL; - f->len = 0; - f->data = NULL; - f->eflag1 = f->eflag2 = f->tflag1 = f->tflag2 = 0; - f->flag = f->h = f->mat_nr; - BLI_addtail(&(bm->polys),f); - bm->nextp++; - bm->totpoly++; - - if(example) - CustomData_bmesh_copy_data(&bm->pdata, &bm->pdata, example->data, &f->data); - else - CustomData_bmesh_set_default(&bm->pdata, &f->data); - - - return f; -} - -/* free functions dont do much *yet*. When per-vertex, per-edge and per-face/faceloop - data is added though these will be needed. -*/ -void BME_free_vert(BME_Mesh *bm, BME_Vert *v){ - bm->totvert--; - CustomData_bmesh_free_block(&bm->vdata, &v->data); - BLI_mempool_free(bm->vpool, v); -} -void BME_free_edge(BME_Mesh *bm, BME_Edge *e){ - bm->totedge--; - CustomData_bmesh_free_block(&bm->edata, &e->data); - BLI_mempool_free(bm->epool, e); -} -void BME_free_poly(BME_Mesh *bm, BME_Poly *f){ - bm->totpoly--; - CustomData_bmesh_free_block(&bm->pdata, &f->data); - BLI_mempool_free(bm->ppool, f); -} -void BME_free_loop(BME_Mesh *bm, BME_Loop *l){ - bm->totloop--; - CustomData_bmesh_free_block(&bm->ldata, &l->data); - BLI_mempool_free(bm->lpool, l); -} -/** - * BMESH CYCLES - * - * Cycles are circular doubly linked lists that form the basis of adjacency - * information in the BME modeller. Full adjacency relations can be derived - * from examining these cycles very quickly. Although each cycle is a double - * circular linked list, each one is considered to have a 'base' or 'head', - * and care must be taken by Euler code when modifying the contents of a cycle. - * - * The contents of this file are split into two parts. First there are the - * BME_cycle family of functions which are generic circular double linked list - * procedures. The second part contains higher level procedures for supporting - * modification of specific cycle types. - * - * The three cycles explicitly stored in the BMesh data structure are as follows: - * - * 1: The Disk Cycle - A circle of edges around a vertex - * Base: vertex->edge pointer. - * - * This cycle is the most complicated in terms of its structure. Each BME_Edge contains - * two BME_CycleNode structures to keep track of that edge's membership in the disk cycle - * of each of its vertices. However for any given vertex it may be the first in some edges - * in its disk cycle and the second for others. The BME_disk_XXX family of functions contain - * some nice utilities for navigating disk cycles in a way that hides this detail from the - * tool writer. - * - * Note that the disk cycle is completley independant from face data. One advantage of this - * is that wire edges are fully integrated into the topology database. Another is that the - * the disk cycle has no problems dealing with non-manifold conditions involving faces. - * - * Functions relating to this cycle: - * - * BME_disk_append_edge - * BME_disk_remove_edge - * BME_disk_nextedge - * BME_disk_getpointer - * - * 2: The Radial Cycle - A circle of face edges (BME_Loop) around an edge - * Base: edge->l->radial structure. - * - * The radial cycle is similar to the radial cycle in the radial edge data structure.* - * Unlike the radial edge however, the radial cycle does not require a large amount of memory - * to store non-manifold conditions since BMesh does not keep track of region/shell - * information. - * - * Functions relating to this cycle: - * - * BME_radial_append - * BME_radial_remove_loop - * BME_radial_nextloop - * BME_radial_find_face - * - * - * 3: The Loop Cycle - A circle of face edges around a polygon. - * Base: polygon->lbase. - * - * The loop cycle keeps track of a faces vertices and edges. It should be noted that the - * direction of a loop cycle is either CW or CCW depending on the face normal, and is - * not oriented to the faces editedges. - * - * Functions relating to this cycle: - * - * BME_cycle_XXX family of functions. - * - * - * Note that the order of elements in all cycles except the loop cycle is undefined. This - * leads to slightly increased seek time for deriving some adjacency relations, however the - * advantage is that no intrinsic properties of the data structures are dependant upon the - * cycle order and all non-manifold conditions are represented trivially. - * -*/ - - -void BME_cycle_append(void *h, void *nt) -{ - BME_CycleNode *oldtail, *head, *newtail; - - head = (BME_CycleNode*)h; - newtail = (BME_CycleNode*)nt; - - if(head->next == NULL){ - head->next = newtail; - head->prev = newtail; - newtail->next = head; - newtail->prev = head; - } - else{ - oldtail = head->prev; - oldtail->next = newtail; - newtail->next = head; - newtail->prev = oldtail; - head->prev = newtail; - - } -} - -/** - * BME_cycle_length - * - * Count the nodes in a cycle. - * - * Returns - - * Integer - */ - -int BME_cycle_length(void *h){ - - int len = 0; - BME_CycleNode *head, *curnode; - head = (BME_CycleNode*)h; - - if(head){ - len = 1; - for(curnode = head->next; curnode != head; curnode=curnode->next){ - if(len == INT_MAX){ //check for infinite loop/corrupted cycle - return -1; - } - len++; - } - } - return len; -} - - -/** - * BME_cycle_remove - * - * Removes a node from a cycle. - * - * Returns - - * 1 for success, 0 for failure. - */ - -int BME_cycle_remove(void *h, void *remn) -{ - int i, len; - BME_CycleNode *head, *remnode, *curnode; - - head = (BME_CycleNode*)h; - remnode = (BME_CycleNode*)remn; - len = BME_cycle_length(h); - - if(len == 1 && head == remnode){ - head->next = NULL; - head->prev = NULL; - return 1; - } - else{ - for(i=0, curnode = head; i < len; curnode = curnode->next){ - if(curnode == remnode){ - remnode->prev->next = remnode->next; - remnode->next->prev = remnode->prev; - /*zero out remnode pointers, important!*/ - //remnode->next = NULL; - //remnode->prev = NULL; - return 1; - - } - } - } - return 0; -} - -/** - * BME_cycle_validate - * - * Validates a cycle. Takes as an argument the expected length of the cycle and - * a pointer to the cycle head or base. - * - * - * Returns - - * 1 for success, 0 for failure. - */ - -int BME_cycle_validate(int len, void *h){ - int i; - BME_CycleNode *curnode, *head; - head = (BME_CycleNode*)h; - - /*forward validation*/ - for(i = 0, curnode = head; i < len; i++, curnode = curnode->next); - if(curnode != head) return 0; - - /*reverse validation*/ - for(i = 0, curnode = head; i < len; i++, curnode = curnode->prev); - if(curnode != head) return 0; - - return 1; -} - -/*Begin Disk Cycle routines*/ - -/** - * BME_disk_nextedge - * - * Find the next edge in a disk cycle - * - * Returns - - * Pointer to the next edge in the disk cycle for the vertex v. - */ - -BME_Edge *BME_disk_nextedge(BME_Edge *e, BME_Vert *v) -{ - if(BME_vert_in_edge(e, v)){ - if(e->v1 == v) return e->d1.next->data; - else if(e->v2 == v) return e->d2.next->data; - } - return NULL; -} - -/** - * BME_disk_getpointer - * - * Given an edge and one of its vertices, find the apporpriate CycleNode - * - * Returns - - * Pointer to BME_CycleNode. - */ -BME_CycleNode *BME_disk_getpointer(BME_Edge *e, BME_Vert *v){ - /*returns pointer to the cycle node for the appropriate vertex in this disk*/ - if(e->v1 == v) return &(e->d1); - else if (e->v2 == v) return &(e->d2); - return NULL; -} - -/** - * BME_disk_append_edge - * - * Appends edge to the end of a vertex disk cycle. - * - * Returns - - * 1 for success, 0 for failure - */ - -int BME_disk_append_edge(BME_Edge *e, BME_Vert *v) -{ - - BME_CycleNode *base, *tail; - - if(BME_vert_in_edge(e, v) == 0) return 0; /*check to make sure v is in e*/ - - /*check for loose vert first*/ - if(v->e == NULL){ - v->e = e; - base = tail = BME_disk_getpointer(e, v); - BME_cycle_append(base, tail); /*circular reference is ok!*/ - return 1; - } - - /*insert e at the end of disk cycle and make it the new v->e*/ - base = BME_disk_getpointer(v->e, v); - tail = BME_disk_getpointer(e, v); - BME_cycle_append(base, tail); - return 1; -} - -/** - * BME_disk_remove_edge - * - * Removes an edge from a disk cycle. If the edge to be removed is - * at the base of the cycle, the next edge becomes the new base. - * - * - * Returns - - * Nothing - */ - -void BME_disk_remove_edge(BME_Edge *e, BME_Vert *v) -{ - BME_CycleNode *base, *remnode; - BME_Edge *newbase; - int len; - - base = BME_disk_getpointer(v->e, v); - remnode = BME_disk_getpointer(e, v); - - /*first deal with v->e pointer...*/ - len = BME_cycle_length(base); - if(len == 1) newbase = NULL; - else if(v->e == e) newbase = base->next-> data; - else newbase = v->e; - - /*remove and rebase*/ - BME_cycle_remove(base, remnode); - v->e = newbase; -} - -/** - * BME_disk_next_edgeflag - * - * Searches the disk cycle of v, starting with e, for the - * next edge that has either eflag or tflag. - * - * BME_Edge pointer. - */ - -BME_Edge *BME_disk_next_edgeflag(BME_Edge *e, BME_Vert *v, int eflag, int tflag){ - - /* BME_CycleNode *diskbase; */ /* UNUSED */ - BME_Edge *curedge; - int /* len, */ /* UNUSED */ ok; - - if(eflag && tflag) return NULL; - - ok = BME_vert_in_edge(e,v); - if(ok){ - /* diskbase = BME_disk_getpointer(e, v); */ /* UNUSED */ - /* len = BME_cycle_length(diskbase); */ /* UNUSED */ - curedge = BME_disk_nextedge(e,v); - while(curedge != e){ - if(tflag){ - if(curedge->tflag1 == tflag) return curedge; - } - else if(eflag){ - if(curedge->eflag1 == eflag) return curedge; - } - curedge = BME_disk_nextedge(curedge, v); - } - } - return NULL; -} - -/** - * BME_disk_count_edgeflag - * - * Counts number of edges in this verts disk cycle which have - * either eflag or tflag (but not both!) - * - * Returns - - * Integer. - */ - -int BME_disk_count_edgeflag(BME_Vert *v, int eflag, int tflag){ - BME_CycleNode *diskbase; - BME_Edge *curedge; - int i, len=0, count=0; - - if(v->e){ - if(eflag && tflag) return 0; /*tflag and eflag are reserved for different functions!*/ - diskbase = BME_disk_getpointer(v->e, v); - len = BME_cycle_length(diskbase); - - for(i = 0, curedge=v->e; itflag1 == tflag) count++; - } - else if(eflag){ - if(curedge->eflag1 == eflag) count++; - } - curedge = BME_disk_nextedge(curedge, v); - } - } - return count; -} - -int BME_disk_hasedge(BME_Vert *v, BME_Edge *e){ - BME_CycleNode *diskbase; - BME_Edge *curedge; - int i, len=0; - - if(v->e){ - diskbase = BME_disk_getpointer(v->e,v); - len = BME_cycle_length(diskbase); - - for(i = 0, curedge=v->e; iradial_next); -} - -void BME_radial_append(BME_Edge *e, BME_Loop *l){ - if(e->l == NULL) e->l = l; - BME_cycle_append(&(e->l->radial), &(l->radial)); -} - -void BME_radial_remove_loop(BME_Loop *l, BME_Edge *e) -{ - BME_Loop *newbase; - int len; - - /*deal with edge->l pointer*/ - len = BME_cycle_length(&(e->l->radial)); - if(len == 1) newbase = NULL; - else if(e->l == l) newbase = e->l->radial_next; - else newbase = e->l; - - /*remove and rebase*/ - BME_cycle_remove(&(e->l->radial), &(l->radial)); - e->l = newbase; -} - -int BME_radial_find_face(BME_Edge *e,BME_Poly *f) -{ - - BME_Loop *curloop; - int i, len; - - len = BME_cycle_length(&(e->l->radial)); - for(i = 0, curloop = e->l; i < len; i++, curloop = curloop->radial_next){ - if(curloop->f == f) return 1; - } - return 0; -} - -struct BME_Loop *BME_loop_find_loop(struct BME_Poly *f, struct BME_Vert *v) { - BME_Loop *l; - int i, len; - - len = BME_cycle_length(f->lbase); - for (i = 0, l=f->loopbase; i < len; i++, l=l->next) { - if (l->v == v) return l; - } - return NULL; -} -#endif -#endif diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c deleted file mode 100644 index 32e608623d5..00000000000 --- a/source/blender/blenkernel/intern/BME_tools.c +++ /dev/null @@ -1,1345 +0,0 @@ -#if 0 -/** - * BME_tools.c jan 2007 - * - * Functions for changing the topology of a mesh. - * - * - * ***** BEGIN GPL 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. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2004 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Geoffrey Bantle and Levi Schooley. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/BME_tools.c - * \ingroup bke - */ - - -#include - -#include "MEM_guardedalloc.h" - -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "BKE_bmesh.h" - -/*split this all into a seperate bevel.c file in src*/ - -/* ------- Bevel code starts here -------- */ - -BME_TransData_Head *BME_init_transdata(int bufsize) { - BME_TransData_Head *td; - - td = MEM_callocN(sizeof(BME_TransData_Head), "BMesh transdata header"); - td->gh = BLI_ghash_new(BLI_ghashutil_ptrhash,BLI_ghashutil_ptrcmp, "BME_init_transdata gh"); - td->ma = BLI_memarena_new(bufsize, "BME_TransData arena"); - BLI_memarena_use_calloc(td->ma); - - return td; -} - -void BME_free_transdata(BME_TransData_Head *td) { - BLI_ghash_free(td->gh,NULL,NULL); - BLI_memarena_free(td->ma); - MEM_freeN(td); -} - -BME_TransData *BME_assign_transdata( - BME_TransData_Head *td, BME_Mesh *bm, BME_Vert *v, - float *co, float *org, float *vec, float *loc, - float factor, float weight, float maxfactor, float *max) -{ - BME_TransData *vtd; - int is_new = 0; - - if (v == NULL) return NULL; - - if ((vtd = BLI_ghash_lookup(td->gh, v)) == NULL && bm != NULL) { - vtd = BLI_memarena_alloc(td->ma, sizeof(*vtd)); - BLI_ghash_insert(td->gh, v, vtd); - td->len++; - is_new = 1; - } - - vtd->bm = bm; - vtd->v = v; - - if (co != NULL) { - copy_v3_v3(vtd->co, co); - } - - if (org == NULL && is_new) { - copy_v3_v3(vtd->org, v->co); /* default */ - } - else if (org != NULL) { - copy_v3_v3(vtd->org,org); - } - - if (vec != NULL) { - copy_v3_v3(vtd->vec,vec); - normalize_v3(vtd->vec); - } - - vtd->loc = loc; - - vtd->factor = factor; - vtd->weight = weight; - vtd->maxfactor = maxfactor; - vtd->max = max; - - return vtd; -} - -BME_TransData *BME_get_transdata(BME_TransData_Head *td, BME_Vert *v) { - BME_TransData *vtd; - vtd = BLI_ghash_lookup(td->gh, v); - return vtd; -} - -/* a hack (?) to use the transdata memarena to allocate floats for use with the max limits */ -float *BME_new_transdata_float(BME_TransData_Head *td) { - return BLI_memarena_alloc(td->ma, sizeof(float)); -} - -static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) { - BME_Edge *e, *oe; - BME_Loop *l; - int len, count, flag; - - if (v->e == NULL) { - /* loose vert */ - return 1; - } - - /* count edges while looking for non-manifold edges */ - oe = v->e; - for (len=0,e=v->e; e != oe || (e == oe && len == 0); len++,e=BME_disk_nextedge(e,v)) { - if (e->l == NULL) { - /* loose edge */ - return 1; - } - - if (BME_cycle_length(&(e->l->radial)) > 2) { - /* edge shared by more than two faces */ - return 1; - } - } - - count = 1; - flag = 1; - e = NULL; - oe = v->e; - l = oe->l; - while(e != oe) { - if (l->v == v) l = l->prev; - else l = l->next; - e = l->e; - count++; /* count the edges */ - - if (flag && l->radial_next == l) { - /* we've hit the edge of an open mesh, reset once */ - flag = 0; - count = 1; - oe = e; - e = NULL; - l = oe->l; - } - else if (l->radial_next == l) { - /* break the loop */ - e = oe; - } - else { - l = l->radial_next; - } - } - - if (count < len) { - /* vert shared by multiple regions */ - return 1; - } - - return 0; -} - -/* a wrapper for BME_JFKE that [for now just] checks to - * make sure loop directions are compatible */ -static BME_Poly *BME_JFKE_safe(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) { - BME_Loop *l1, *l2; - - l1 = e->l; - l2 = l1->radial_next; - if (l1->v == l2->v) { - BME_loop_reverse(bm, f2); - } - - return BME_JFKE(bm, f1, f2, e); -} - -/* a wrapper for BME_SFME that transfers element flags */ -static BME_Poly *BME_split_face(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Loop **nl, BME_Edge *example) { - BME_Poly *nf; - nf = BME_SFME(bm,f,v1,v2,nl); - nf->flag = f->flag; - /* if the edge was selected, select this face, too */ - if (example && (example->flag & SELECT)) f->flag |= ME_FACE_SEL; - nf->h = f->h; - nf->mat_nr = f->mat_nr; - if (nl && example) { - (*nl)->e->flag = example->flag; - (*nl)->e->h = example->h; - (*nl)->e->crease = example->crease; - (*nl)->e->bweight = example->bweight; - } - - return nf; -} - - -#if 0 -static void BME_data_interp_from_verts(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, float fac) -{ - void *src[2]; - float w[2]; - if (v1->data && v2->data) { - src[0]= v1->data; - src[1]= v2->data; - w[0] = 1.0f-fac; - w[1] = fac; - CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->data); - } -} -#endif - - -static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *UNUSED(v2), BME_Vert *v, BME_Edge *e1, float fac){ - void *src[2]; - float w[2]; - BME_Loop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL; - - w[0] = 1.0f - fac; - w[1] = fac; - - if(!e1->l) return; - l = e1->l; - do{ - if(l->v == v1){ - v1loop = l; - vloop = v1loop->next; - v2loop = vloop->next; - }else if(l->v == v){ - v1loop = l->next; - vloop = l; - v2loop = l->prev; - - } - - src[0] = v1loop->data; - src[1] = v2loop->data; - - CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->data); - l = l->radial_next; - }while(l!=e1->l); -} - - -/* a wrapper for BME_SEMV that transfers element flags */ /*add custom data interpolation in here!*/ -static BME_Vert *BME_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Edge **ne, float percent) { - BME_Vert *nv, *v2; - float len; - - v2 = BME_edge_getothervert(e,v); - nv = BME_SEMV(bm,v,e,ne); - if (nv == NULL) return NULL; - VECSUB(nv->co,v2->co,v->co); - len = len_v3(nv->co); - VECADDFAC(nv->co,v->co,nv->co,len*percent); - nv->flag = v->flag; - nv->bweight = v->bweight; - if (ne) { - (*ne)->flag = e->flag; - (*ne)->h = e->h; - (*ne)->crease = e->crease; - (*ne)->bweight = e->bweight; - } - /*v->nv->v2*/ - BME_data_facevert_edgesplit(bm,v2, v, nv, e, 0.75); - return nv; -} - -static void BME_collapse_vert(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv, float fac){ - void *src[2]; - float w[2]; - BME_Loop *l=NULL, *kvloop=NULL, *tvloop=NULL; - BME_Vert *tv = BME_edge_getothervert(ke,kv); - - w[0] = 1.0f - fac; - w[1] = fac; - - if(ke->l){ - l = ke->l; - do{ - if(l->v == tv && l->next->v == kv){ - tvloop = l; - kvloop = l->next; - - src[0] = kvloop->data; - src[1] = tvloop->data; - CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->data); - } - l=l->radial_next; - }while(l!=ke->l); - } - BME_JEKV(bm,ke,kv); -} - - - -static int BME_bevel_is_split_vert(BME_Loop *l) { - /* look for verts that have already been added to the edge when - * beveling other polys; this can be determined by testing the - * vert and the edges around it for originality - */ - if ((l->v->tflag1 & BME_BEVEL_ORIG)==0 - && (l->e->tflag1 & BME_BEVEL_ORIG) - && (l->prev->e->tflag1 & BME_BEVEL_ORIG)) - { - return 1; - } - return 0; -} - -/* get a vector, vec, that points from v1->co to wherever makes sense to - * the bevel operation as a whole based on the relationship between v1 and v2 - * (won't necessarily be a vec from v1->co to v2->co, though it probably will be); - * the return value is -1 for failure, 0 if we used vert co's, and 1 if we used transform origins */ -static int BME_bevel_get_vec(float *vec, BME_Vert *v1, BME_Vert *v2, BME_TransData_Head *td) -{ - BME_TransData *vtd1, *vtd2; - - vtd1 = BME_get_transdata(td,v1); - vtd2 = BME_get_transdata(td,v2); - if (!vtd1 || !vtd2) { - //printf("BME_bevel_get_vec() got called without proper BME_TransData\n"); - return -1; - } - - /* compare the transform origins to see if we can use the vert co's; - * if they belong to different origins, then we will use the origins to determine - * the vector */ - if (compare_v3v3(vtd1->org,vtd2->org,0.000001f)) { - sub_v3_v3v3(vec, v2->co, v1->co); - if (len_v3(vec) < 0.000001f) { - zero_v3(vec); - } - return 0; - } - else { - sub_v3_v3v3(vec,vtd2->org,vtd1->org); - if (len_v3(vec) < 0.000001f) { - zero_v3(vec); - } - return 1; - } -} - -/* "Projects" a vector perpendicular to vec2 against vec1, such that - * the projected vec1 + vec2 has a min distance of 1 from the "edge" defined by vec2. - * note: the direction, is_forward, is used in conjunction with up_vec to determine - * whether this is a convex or concave corner. If it is a concave corner, it will - * be projected "backwards." If vec1 is before vec2, is_forward should be 0 (we are projecting backwards). - * vec1 is the vector to project onto (expected to be normalized) - * vec2 is the direction of projection (pointing away from vec1) - * up_vec is used for orientation (expected to be normalized) - * returns the length of the projected vector that lies along vec1 */ -static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *UNUSED(td)) -{ - float factor, vec3[3], tmp[3],c1,c2; - - cross_v3_v3v3(tmp,vec1,vec2); - normalize_v3(tmp); - factor = dot_v3v3(up_vec,tmp); - if ((factor > 0 && is_forward) || (factor < 0 && !is_forward)) { - cross_v3_v3v3(vec3,vec2,tmp); /* hmm, maybe up_vec should be used instead of tmp */ - } - else { - cross_v3_v3v3(vec3,tmp,vec2); /* hmm, maybe up_vec should be used instead of tmp */ - } - normalize_v3(vec3); - c1 = dot_v3v3(vec3,vec1); - c2 = dot_v3v3(vec1,vec1); - if (fabsf(c1) < 0.000001f || fabsf(c2) < 0.000001f) { - factor = 0.0f; - } - else { - factor = c2/c1; - } - - return factor; -} - -/* BME_bevel_split_edge() is the main math work-house; its responsibilities are: - * using the vert and the loop passed, get or make the split vert, set its coordinates - * and transform properties, and set the max limits. - * Finally, return the split vert. */ -static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, BME_Loop *l, float *up_vec, float value, BME_TransData_Head *td) { - BME_TransData *vtd, *vtd1 /* , *vtd2 */ /* UNUSED */; - BME_Vert *sv, *v2, *v3 /* , *ov */ /* UNUSED */; - BME_Loop *lv1, *lv2; - BME_Edge *ne, *e1, *e2; - float maxfactor, scale, len, dis, vec1[3], vec2[3], t_up_vec[3]; - int is_edge, forward /* , is_split_vert */ /* UNUSED */; - - if (l == NULL) { - /* what you call operator overloading in C :) - * I wanted to use the same function for both wire edges and poly loops - * so... here we walk around edges to find the needed verts */ - forward = 1; - /* is_split_vert = 0; */ /* UNUSED */ - if (v->e == NULL) { - //printf("We can't split a loose vert's edge!\n"); - return NULL; - } - e1 = v->e; /* we just use the first two edges */ - e2 = BME_disk_nextedge(v->e, v); - if (e1 == e2) { - //printf("You need at least two edges to use BME_bevel_split_edge()\n"); - return NULL; - } - v2 = BME_edge_getothervert(e1, v); - v3 = BME_edge_getothervert(e2, v); - if (v1 != v2 && v1 != v3) { - //printf("Error: more than 2 edges in v's disk cycle, or v1 does not share an edge with v\n"); - return NULL; - } - if (v1 == v2) { - v2 = v3; - } - else { - e1 = e2; - } - /* ov = BME_edge_getothervert(e1,v); */ /* UNUSED */ - sv = BME_split_edge(bm,v,e1,&ne,0); - //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/ - //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25); - //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25); - BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */ - sv->tflag1 |= BME_BEVEL_BEVEL; - ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */ - BME_bevel_get_vec(vec1,v1,v,td); - BME_bevel_get_vec(vec2,v2,v,td); - cross_v3_v3v3(t_up_vec,vec1,vec2); - normalize_v3(t_up_vec); - up_vec = t_up_vec; - } - else { - /* establish loop direction */ - if (l->v == v) { - forward = 1; - lv1 = l->next; - lv2 = l->prev; - v1 = l->next->v; - v2 = l->prev->v; - } - else if (l->next->v == v) { - forward = 0; - lv1 = l; - lv2 = l->next->next; - v1 = l->v; - v2 = l->next->next->v; - } - else { - //printf("ERROR: BME_bevel_split_edge() - v must be adjacent to l\n"); - return NULL; - } - - if (BME_bevel_is_split_vert(lv1)) { - /* is_split_vert = 1; */ /* UNUSED */ - sv = v1; - if (forward) v1 = l->next->next->v; - else v1 = l->prev->v; - } - else { - /* is_split_vert = 0; */ /* UNUSED */ - /* ov = BME_edge_getothervert(l->e,v); */ /* UNUSED */ - sv = BME_split_edge(bm,v,l->e,&ne,0); - //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/ - //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25); - //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25); - BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */ - sv->tflag1 |= BME_BEVEL_BEVEL; - ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */ - } - - if (BME_bevel_is_split_vert(lv2)) { - if (forward) v2 = lv2->prev->v; - else v2 = lv2->next->v; - } - } - - is_edge = BME_bevel_get_vec(vec1,v,v1,td); /* get the vector we will be projecting onto */ - BME_bevel_get_vec(vec2,v,v2,td); /* get the vector we will be projecting parallel to */ - len = len_v3(vec1); - normalize_v3(vec1); - - vtd = BME_get_transdata(td, sv); - vtd1 = BME_get_transdata(td, v); - /* vtd2 = BME_get_transdata(td,v1); */ /* UNUSED */ - - if (vtd1->loc == NULL) { - /* this is a vert with data only for calculating initial weights */ - if (vtd1->weight < 0) { - vtd1->weight = 0; - } - scale = vtd1->weight/vtd1->factor; - if (!vtd1->max) { - vtd1->max = BME_new_transdata_float(td); - *vtd1->max = -1; - } - } - else { - scale = vtd1->weight; - } - vtd->max = vtd1->max; - - if (is_edge && vtd1->loc != NULL) { - maxfactor = vtd1->maxfactor; - } - else { - maxfactor = scale*BME_bevel_project_vec(vec1,vec2,up_vec,forward,td); - if (vtd->maxfactor > 0 && vtd->maxfactor < maxfactor) { - maxfactor = vtd->maxfactor; - } - } - - dis = (v1->tflag1 & BME_BEVEL_ORIG)? len/3 : len/2; - if (is_edge || dis > maxfactor*value) { - dis = maxfactor*value; - } - madd_v3_v3v3fl(sv->co, v->co, vec1, dis); - sub_v3_v3v3(vec1, sv->co, vtd1->org); - dis = len_v3(vec1); - normalize_v3(vec1); - BME_assign_transdata(td, bm, sv, vtd1->org, vtd1->org, vec1, sv->co, dis, scale, maxfactor, vtd->max); - - return sv; -} - -static float BME_bevel_set_max(BME_Vert *v1, BME_Vert *v2, float value, BME_TransData_Head *td) { - BME_TransData *vtd1, *vtd2; - float max, fac1, fac2, vec1[3], vec2[3], vec3[3]; - - BME_bevel_get_vec(vec1,v1,v2,td); - vtd1 = BME_get_transdata(td,v1); - vtd2 = BME_get_transdata(td,v2); - - if (vtd1->loc == NULL) { - fac1 = 0; - } - else { - copy_v3_v3(vec2, vtd1->vec); - mul_v3_fl(vec2, vtd1->factor); - if (dot_v3v3(vec1, vec1)) { - project_v3_v3v3(vec2, vec2,vec1); - fac1 = len_v3(vec2) / value; - } - else { - fac1 = 0; - } - } - - if (vtd2->loc == NULL) { - fac2 = 0; - } - else { - copy_v3_v3(vec3, vtd2->vec); - mul_v3_fl(vec3, vtd2->factor); - if (dot_v3v3(vec1, vec1)) { - project_v3_v3v3(vec2, vec3, vec1); - fac2 = len_v3(vec2) / value; - } - else { - fac2 = 0; - } - } - - if (fac1 || fac2) { - max = len_v3(vec1) / (fac1 + fac2); - if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) { - *vtd1->max = max; - } - if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) { - *vtd2->max = max; - } - } - else { - max = -1; - } - - return max; -} - -static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int UNUSED(options), BME_TransData_Head *td) { - BME_Vert *ov1, *ov2, *v1, *v2; - - ov1 = BME_edge_getothervert(v->e, v); - ov2 = BME_edge_getothervert(BME_disk_nextedge(v->e, v), v); - - /* split the edges */ - v1 = BME_bevel_split_edge(bm,v,ov1,NULL,NULL,value,td); - v1->tflag1 |= BME_BEVEL_NONMAN; - v2 = BME_bevel_split_edge(bm,v,ov2,NULL,NULL,value,td); - v2->tflag1 |= BME_BEVEL_NONMAN; - - if (value > 0.5) { - BME_bevel_set_max(v1,ov1,value,td); - BME_bevel_set_max(v2,ov2,value,td); - } - - /* remove the original vert */ - if (res) { - BME_JEKV(bm,v->e,v); - } - - return v1; -} - -static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUSED(options), float *up_vec, BME_TransData_Head *td) { - BME_Vert *v1, *v2, *kv; - BME_Loop *kl=NULL, *nl; - BME_Edge *e; - BME_Poly *f; - - f = l->f; - e = l->e; - - if ((l->e->tflag1 & BME_BEVEL_BEVEL) == 0 - && ((l->v->tflag1 & BME_BEVEL_BEVEL) || (l->next->v->tflag1 & BME_BEVEL_BEVEL))) - { /* sanity check */ - return l; - } - - /* checks and operations for prev edge */ - /* first, check to see if this edge was inset previously */ - if ((l->prev->e->tflag1 & BME_BEVEL_ORIG) == 0 - && (l->v->tflag1 & BME_BEVEL_NONMAN) == 0) { - kl = l->prev->radial_next; - if (kl->v == l->v) kl = kl->prev; - else kl = kl->next; - kv = l->v; - } - else { - kv = NULL; - } - /* get/make the first vert to be used in SFME */ - if (l->v->tflag1 & BME_BEVEL_NONMAN){ - v1 = l->v; - } - else { /* we'll need to split the previous edge */ - v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td); - } - /* if we need to clean up geometry... */ - if (kv) { - l = l->next; - if (kl->v == kv) { - BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e); - BME_JFKE(bm,((BME_Loop*)kl->prev->radial_next)->f,kl->f,kl->prev->e); - BME_collapse_vert(bm, kl->e, kv, 1.0); - //BME_JEKV(bm,kl->e,kv); - - } - else { - BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e); - BME_JFKE(bm,((BME_Loop*)kl->next->radial_next)->f,kl->f,kl->next->e); - BME_collapse_vert(bm, kl->e, kv, 1.0); - //BME_JEKV(bm,kl->e,kv); - } - l = l->prev; - } - - /* checks and operations for the next edge */ - /* first, check to see if this edge was inset previously */ - if ((l->next->e->tflag1 & BME_BEVEL_ORIG) == 0 - && (l->next->v->tflag1 & BME_BEVEL_NONMAN) == 0) { - kl = l->next->radial_next; - if (kl->v == l->next->v) kl = kl->prev; - else kl = kl->next; - kv = l->next->v; - } - else { - kv = NULL; - } - /* get/make the second vert to be used in SFME */ - if (l->next->v->tflag1 & BME_BEVEL_NONMAN) { - v2 = l->next->v; - } - else { /* we'll need to split the next edge */ - v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td); - } - /* if we need to clean up geometry... */ - if (kv) { - if (kl->v == kv) { - BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e); - BME_JFKE(bm,((BME_Loop*)kl->prev->radial_next)->f,kl->f,kl->prev->e); - BME_collapse_vert(bm, kl->e, kv, 1.0); - //BME_JEKV(bm,kl->e,kv); - } - else { - BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e); - BME_JFKE(bm,((BME_Loop*)kl->next->radial_next)->f,kl->f,kl->next->e); - BME_collapse_vert(bm, kl->e, kv, 1.0); - //BME_JEKV(bm,kl->e,kv); - } - } - - if ((v1->tflag1 & BME_BEVEL_NONMAN)==0 || (v2->tflag1 & BME_BEVEL_NONMAN)==0) { - BME_split_face(bm,f,v2,v1,&l,e); - l->e->tflag1 = BME_BEVEL_BEVEL; - l = l->radial_next; - } - - if (l->f != f){ - //printf("Whoops! You got something out of order in BME_bevel_edge()!\n"); - } - - return l; -} - -static BME_Loop *BME_bevel_vert(BME_Mesh *bm, BME_Loop *l, float value, int UNUSED(options), float *up_vec, BME_TransData_Head *td) { - BME_Vert *v1, *v2; - /* BME_Poly *f; */ /* UNUSED */ - - /* get/make the first vert to be used in SFME */ - /* may need to split the previous edge */ - v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td); - - /* get/make the second vert to be used in SFME */ - /* may need to split this edge (so move l) */ - l = l->prev; - v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td); - l = l->next->next; - - /* "cut off" this corner */ - /* f = */ /* UNUSED */ BME_split_face(bm,l->f,v2,v1,NULL,l->e); - - return l; -} - -/** - * BME_bevel_poly - * - * Polygon inset tool: - * - * Insets a polygon/face based on the tflag1's of its vertices - * and edges. Used by the bevel tool only, for now. - * The parameter "value" is the distance to inset (should be negative). - * The parameter "options" is not currently used. - * - * Returns - - * A BME_Poly pointer to the resulting inner face. -*/ -static BME_Poly *BME_bevel_poly(BME_Mesh *bm, BME_Poly *f, float value, int options, BME_TransData_Head *td) { - BME_Loop *l, *ol; - BME_TransData *vtd1, *vtd2; - float up_vec[3], vec1[3], vec2[3], vec3[3], fac1, fac2, max = -1; - int len, i; - - up_vec[0] = 0.0f; - up_vec[1] = 0.0f; - up_vec[2] = 0.0f; - /* find a good normal for this face (there's better ways, I'm sure) */ - ol = f->loopbase; - l = ol->next; - for (i=0,ol=f->loopbase,l=ol->next; l->next!=ol; l=l->next) { - BME_bevel_get_vec(vec1,l->next->v,ol->v,td); - BME_bevel_get_vec(vec2,l->v,ol->v,td); - cross_v3_v3v3(vec3, vec2, vec1); - add_v3_v3(up_vec, vec3); - i++; - } - mul_v3_fl(up_vec,1.0f/i); - normalize_v3(up_vec); - - for (i=0,len=f->len; inext) { - if ((l->e->tflag1 & BME_BEVEL_BEVEL) && (l->e->tflag1 & BME_BEVEL_ORIG)) { - max = 1.0f; - l = BME_bevel_edge(bm, l, value, options, up_vec, td); - } - else if ((l->v->tflag1 & BME_BEVEL_BEVEL) && (l->v->tflag1 & BME_BEVEL_ORIG) && (l->prev->e->tflag1 & BME_BEVEL_BEVEL) == 0) { - max = 1.0f; - l = BME_bevel_vert(bm, l, value, options, up_vec, td); - } - } - - /* max pass */ - if (value > 0.5 && max > 0) { - max = -1; - for (i=0,len=f->len; inext) { - if ((l->e->tflag1 & BME_BEVEL_BEVEL) || (l->e->tflag1 & BME_BEVEL_ORIG)) { - BME_bevel_get_vec(vec1,l->v,l->next->v,td); - vtd1 = BME_get_transdata(td,l->v); - vtd2 = BME_get_transdata(td,l->next->v); - if (vtd1->loc == NULL) { - fac1 = 0; - } - else { - copy_v3_v3(vec2,vtd1->vec); - mul_v3_fl(vec2,vtd1->factor); - if (dot_v3v3(vec1, vec1)) { - project_v3_v3v3(vec2,vec2,vec1); - fac1 = len_v3(vec2)/value; - } - else { - fac1 = 0; - } - } - if (vtd2->loc == NULL) { - fac2 = 0; - } - else { - copy_v3_v3(vec3,vtd2->vec); - mul_v3_fl(vec3,vtd2->factor); - if (dot_v3v3(vec1, vec1)) { - project_v3_v3v3(vec2,vec3,vec1); - fac2 = len_v3(vec2)/value; - } - else { - fac2 = 0; - } - } - if (fac1 || fac2) { - max = len_v3(vec1)/(fac1 + fac2); - if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) { - *vtd1->max = max; - } - if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) { - *vtd2->max = max; - } - } - } - } - } - - return l->f; -} - -static void BME_bevel_add_vweight(BME_TransData_Head *td, BME_Mesh *bm, BME_Vert *v, float weight, float factor, int options) -{ - BME_TransData *vtd; - - if (v->tflag1 & BME_BEVEL_NONMAN) return; - v->tflag1 |= BME_BEVEL_BEVEL; - if ( (vtd = BME_get_transdata(td, v)) ) { - if (options & BME_BEVEL_EMIN) { - vtd->factor = 1.0; - if (vtd->weight < 0 || weight < vtd->weight) { - vtd->weight = weight; - } - } - else if (options & BME_BEVEL_EMAX) { - vtd->factor = 1.0; - if (weight > vtd->weight) { - vtd->weight = weight; - } - } - else if (vtd->weight < 0) { - vtd->factor = factor; - vtd->weight = weight; - } - else { - vtd->factor += factor; /* increment number of edges with weights (will be averaged) */ - vtd->weight += weight; /* accumulate all the weights */ - } - } - else { - /* we'll use vtd->loc == NULL to mark that this vert is not moving */ - vtd = BME_assign_transdata(td, bm, v, v->co, NULL, NULL, NULL, factor, weight, -1, NULL); - } -} - -static float BME_bevel_get_angle(BME_Mesh *UNUSED(bm), BME_Edge *e, BME_Vert *v) { - BME_Vert *v1, *v2; - BME_Loop *l1, *l2; - float vec1[3], vec2[3], vec3[3], vec4[3]; - - l1 = e->l; - l2 = e->l->radial_next; - if (l1->v == v) { - v1 = l1->prev->v; - v2 = l1->next->v; - } - else { - v1 = l1->next->next->v; - v2 = l1->v; - } - VECSUB(vec1,v1->co,v->co); - VECSUB(vec2,v2->co,v->co); - cross_v3_v3v3(vec3,vec1,vec2); - - l1 = l2; - if (l1->v == v) { - v1 = l1->prev->v; - v2 = l1->next->v; - } - else { - v1 = l1->next->next->v; - v2 = l1->v; - } - VECSUB(vec1,v1->co,v->co); - VECSUB(vec2,v2->co,v->co); - cross_v3_v3v3(vec4,vec2,vec1); - - normalize_v3(vec3); - normalize_v3(vec4); - - return dot_v3v3(vec3,vec4); -} -static int BME_face_sharededges(BME_Poly *f1, BME_Poly *f2){ - BME_Loop *l; - int count = 0; - - l = f1->loopbase; - do{ - if(BME_radial_find_face(l->e,f2)) count++; - l = l->next; - }while(l != f1->lbase); - - return count; -} -/** - * BME_bevel_initialize - * - * Prepare the mesh for beveling: - * - * Sets the tflag1's of the mesh elements based on the options passed. - * - * Returns - - * A BME_Mesh pointer to the BMesh passed as a parameter. -*/ -static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defgrp_index), float angle, BME_TransData_Head *td) { - BME_Vert *v; - BME_Edge *e; - BME_Poly *f; - /* BME_TransData *vtd; */ /* UNUSED */ - /* MDeformVert *dvert; */ /* UNUSED */ - /* MDeformWeight *dw; */ /* UNUSED */ - int len; - float weight, threshold; - - /* vert pass */ - for (v=bm->verts.first; v; v=v->next) { - /* dvert = NULL; */ /* UNUSED */ - /* dw = NULL; */ /* UNUSED */ - v->tflag1 = BME_BEVEL_ORIG; - /* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if - * the vert is manifold (or is shared by only two edges - wire bevel) - * BME_BEVEL_SELECT is passed and the vert has v->flag&SELECT or - * BME_BEVEL_VWEIGHT is passed, and the vert has a defgrp and weight - * BME_BEVEL_ANGLE is not passed - * BME_BEVEL_EWEIGHT is not passed - */ - /* originally coded, a vertex gets tagged with BME_BEVEL_NONMAN in this pass if - * the vert is loose, shared by multiple regions, or is shared by wire edges - * note: verts belonging to edges of open meshes are not tagged with BME_BEVEL_NONMAN - */ - /* originally coded, a vertex gets a transform weight set in this pass if - * BME_BEVEL_VWEIGHT is passed, and the vert has a defgrp and weight - */ - - /* get disk cycle length */ - if (v->e == NULL) { - len = 0; - } - else { - len = BME_cycle_length(BME_disk_getpointer(v->e,v)); - /* we'll assign a default transform data to every vert (except the loose ones) */ - /* vtd = */ /* UNUSED */ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL); - } - - /* check for non-manifold vert */ - if (BME_is_nonmanifold_vert(bm,v)) { - v->tflag1 |= BME_BEVEL_NONMAN; - } - - /* BME_BEVEL_BEVEL tests */ - if ((v->tflag1 & BME_BEVEL_NONMAN) == 0 || len == 2) { /* either manifold vert, or wire vert */ - if (((options & BME_BEVEL_SELECT) && (v->flag & SELECT)) - || ((options & BME_BEVEL_WEIGHT) && (options & BME_BEVEL_VERT)) /* use weights for verts */ - || ((options & BME_BEVEL_ANGLE) == 0 - && (options & BME_BEVEL_SELECT) == 0 - && (options & BME_BEVEL_WEIGHT) == 0)) - { - if (options & BME_BEVEL_WEIGHT) { - /* do vert weight stuff */ - //~ dvert = CustomData_em_get(&bm->vdata,v->data,CD_MDEFORMVERT); - //~ if (!dvert) continue; - //~ for (i = 0; i < dvert->totweight; ++i) { - //~ if(dvert->dw[i].def_nr == defgrp_index) { - //~ dw = &dvert->dw[i]; - //~ break; - //~ } - //~ } - //~ if (!dw || dw->weight == 0.0) continue; - if (v->bweight == 0.0) continue; - /* vtd = */ /* UNUSED */ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0, v->bweight, -1, NULL); - v->tflag1 |= BME_BEVEL_BEVEL; - } - else { - /* vtd = */ /* UNUSED */ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0, 1.0, -1, NULL); - v->tflag1 |= BME_BEVEL_BEVEL; - } - } - } - } - - /* edge pass */ - threshold = (float)cos((angle + 0.001) * M_PI / 180.0); - for (e=bm->edges.first; e; e=e->next) { - e->tflag1 = BME_BEVEL_ORIG; - weight = 0.0; - /* originally coded, an edge gets tagged with BME_BEVEL_BEVEL in this pass if - * BME_BEVEL_VERT is not set - * the edge is manifold (shared by exactly two faces) - * BME_BEVEL_SELECT is passed and the edge has e->flag&SELECT or - * BME_BEVEL_EWEIGHT is passed, and the edge has the crease set or - * BME_BEVEL_ANGLE is passed, and the edge is sharp enough - * BME_BEVEL_VWEIGHT is passed, and both verts are set for bevel - */ - /* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if - * the vert belongs to the edge - * the vert is not tagged with BME_BEVEL_NONMAN - * the edge is eligible for bevel (even if BME_BEVEL_VERT is set, or the edge is shared by less than 2 faces) - */ - /* originally coded, a vertex gets a transform weight set in this pass if - * the vert belongs to the edge - * the edge has a weight - */ - /* note: edge weights are cumulative at the verts, - * i.e. the vert's weight is the average of the weights of its weighted edges - */ - - if (e->l == NULL) { - len = 0; - e->v1->tflag1 |= BME_BEVEL_NONMAN; - e->v2->tflag1 |= BME_BEVEL_NONMAN; - } - else { - len = BME_cycle_length(&(e->l->radial)); - } - - if (len > 2) { - /* non-manifold edge of the worst kind */ - continue; - } - - if ((options & BME_BEVEL_SELECT) && (e->flag & SELECT)) { - weight = 1.0; - /* stupid editmode doesn't always flush selections, or something */ - e->v1->flag |= SELECT; - e->v2->flag |= SELECT; - } - else if ((options & BME_BEVEL_WEIGHT) && (options & BME_BEVEL_VERT) == 0) { - weight = e->bweight; - } - else if (options & BME_BEVEL_ANGLE) { - if ((e->v1->tflag1 & BME_BEVEL_NONMAN) == 0 && BME_bevel_get_angle(bm,e,e->v1) < threshold) { - e->tflag1 |= BME_BEVEL_BEVEL; - e->v1->tflag1 |= BME_BEVEL_BEVEL; - BME_bevel_add_vweight(td, bm, e->v1, 1.0, 1.0, options); - } - else { - BME_bevel_add_vweight(td, bm, e->v1, 0.0, 1.0, options); - } - if ((e->v2->tflag1 & BME_BEVEL_NONMAN) == 0 && BME_bevel_get_angle(bm,e,e->v2) < threshold) { - e->tflag1 |= BME_BEVEL_BEVEL; - e->v2->tflag1 |= BME_BEVEL_BEVEL; - BME_bevel_add_vweight(td, bm, e->v2, 1.0, 1.0, options); - } - else { - BME_bevel_add_vweight(td, bm, e->v2, 0.0, 1.0, options); - } - } - //~ else if ((options & BME_BEVEL_VWEIGHT) && (options & BME_BEVEL_VERT) == 0) { - //~ if ((e->v1->tflag1 & BME_BEVEL_BEVEL) && (e->v2->tflag1 & BME_BEVEL_BEVEL)) { - //~ e->tflag1 |= BME_BEVEL_BEVEL; - //~ } - //~ } - else if ((options & BME_BEVEL_SELECT) == 0 - && (options & BME_BEVEL_VERT) == 0) - { - weight = 1.0; - } - - if (weight > 0.0) { - e->tflag1 |= BME_BEVEL_BEVEL; - BME_bevel_add_vweight(td, bm, e->v1, weight, 1.0, options); - BME_bevel_add_vweight(td, bm, e->v2, weight, 1.0, options); - } - - if (len != 2 || options & BME_BEVEL_VERT) { - e->tflag1 &= ~BME_BEVEL_BEVEL; - } - } - - /* face pass */ - for (f=bm->polys.first; f; f=f->next) f->tflag1 = BME_BEVEL_ORIG; - - /*clean up edges with 2 faces that share more than one edge*/ - for (e=bm->edges.first; e; e=e->next){ - if(e->tflag1 & BME_BEVEL_BEVEL){ - int count = 0; - count = BME_face_sharededges(e->l->f, ((BME_Loop*)e->l->radial_next)->f); - if(count > 1){ - e->tflag1 &= ~BME_BEVEL_BEVEL; - } - } - } - - return bm; - -} - -/* tags all elements as originals */ -static BME_Mesh *BME_bevel_reinitialize(BME_Mesh *bm) { - BME_Vert *v; - BME_Edge *e; - BME_Poly *f; - - for (v = bm->verts.first; v; v=v->next) { - v->tflag1 |= BME_BEVEL_ORIG; - } - - for (e=bm->edges.first; e; e=e->next) { - e->tflag1 |= BME_BEVEL_ORIG; - } - - for (f=bm->polys.first; f; f=f->next) { - f->tflag1 |= BME_BEVEL_ORIG; - } - return bm; - -} - -/** - * BME_bevel_mesh - * - * Mesh beveling tool: - * - * Bevels an entire mesh. It currently uses the tflag1's of - * its vertices and edges to track topological changes. - * The parameter "value" is the distance to inset (should be negative). - * The parameter "options" is not currently used. - * - * Returns - - * A BME_Mesh pointer to the BMesh passed as a parameter. -*/ - -static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){ - BME_Poly *f; - BME_Edge *e; - int done, len; - - if(v->e){ - done = 0; - while(!done){ - done = 1; - e = v->e; /*loop the edge looking for a edge to dissolve*/ - do{ - f = NULL; - len = BME_cycle_length(&(e->l->radial)); - if(len == 2){ - f = BME_JFKE_safe(bm,e->l->f, ((BME_Loop*)(e->l->radial_next))->f, e); - } - if(f){ - done = 0; - break; - } - e = BME_disk_nextedge(e,v); - }while(e != v->e); - } - BME_collapse_vert(bm, v->e, v, 1.0); - //BME_JEKV(bm,v->e,v); - } -} -static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int UNUSED(defgrp_index), BME_TransData_Head *td) { - BME_Vert *v, *nv; - BME_Edge *e, *oe; - BME_Loop *l, *l2; - BME_Poly *f; - unsigned int i, len; - - for (f=bm->polys.first; f; f=f->next) { - if(f->tflag1 & BME_BEVEL_ORIG) { - BME_bevel_poly(bm,f,value,options,td); - } - } - - /* here we will loop through all the verts to clean up the left over geometry */ - /* crazy idea. when res == 0, don't remove the original geometry */ - for (v = bm->verts.first; v; /* we may kill v, so increment in-loop */) { - nv = v->next; - if ((v->tflag1 & BME_BEVEL_NONMAN) && (v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG)) { - v = BME_bevel_wire(bm, v, value, res, options, td); - } - else if (res && ((v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG))) { - int count = 0; - /* first, make sure we're not sitting on an edge to be removed */ - oe = v->e; - e = BME_disk_nextedge(oe,v); - while ((e->tflag1 & BME_BEVEL_BEVEL) && (e->tflag1 & BME_BEVEL_ORIG)) { - e = BME_disk_nextedge(e,v); - if (e == oe) { - //printf("Something's wrong! We can't remove every edge here!\n"); - break; - } - } - /* look for original edges, and remove them */ - oe = e; - while ( (e = BME_disk_next_edgeflag(oe, v, 0, BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) ) { - count++; - /* join the faces (we'll split them later) */ - f = BME_JFKE_safe(bm,e->l->f,((BME_Loop*)e->l->radial_next)->f,e); - if (!f){ - //printf("Non-manifold geometry not getting tagged right?\n"); - } - } - - /*need to do double check *before* you bevel to make sure that manifold edges are for two faces that share only *one* edge to make sure it doesnt hang here!*/ - - - /* all original edges marked to be beveled have been removed; - * now we need to link up the edges for this "corner" */ - len = BME_cycle_length(BME_disk_getpointer(v->e, v)); - for (i=0,e=v->e; i < len; i++,e=BME_disk_nextedge(e,v)) { - l = e->l; - l2 = l->radial_next; - if (l->v != v) l = l->next; - if (l2->v != v) l2 = l2->next; - /* look for faces that have had the original edges removed via JFKE */ - if (l->f->len > 3) { - BME_split_face(bm,l->f,l->next->v,l->prev->v,&l,l->e); /* clip this corner off */ - if (len > 2) { - l->e->tflag1 |= BME_BEVEL_BEVEL; - } - } - if (l2->f->len > 3) { - BME_split_face(bm,l2->f,l2->next->v,l2->prev->v,&l,l2->e); /* clip this corner off */ - if (len > 2) { - l->e->tflag1 |= BME_BEVEL_BEVEL; - } - } - } - bmesh_dissolve_disk(bm, v); - } - v = nv; - } - - return bm; -} - -static BME_Mesh *BME_tesselate(BME_Mesh *bm) { - BME_Loop *l, *nextloop; - BME_Poly *f; - - for (f=bm->polys.first; f; f=f->next) { - l = f->loopbase; - while (l->f->len > 4) { - nextloop = l->next->next->next; - /* make a quad */ - BME_split_face(bm,l->f,l->v,nextloop->v,NULL,l->e); - l = nextloop; - } - } - return bm; -} - - -/*Main bevel function: - Should be only one exported - -*/ - -/* options that can be passed: - * BME_BEVEL_VWEIGHT <---- v, Look at vertex weights; use defgrp_index if option is present - * BME_BEVEL_SELECT <---- v,e, check selection for verts and edges - * BME_BEVEL_ANGLE <---- v,e, don't bevel-tag verts - tag verts per edge - * BME_BEVEL_VERT <---- e, don't tag edges - * BME_BEVEL_EWEIGHT <---- e, use crease flag for now - * BME_BEVEL_PERCENT <---- Will need to think about this one; will probably need to incorporate into actual bevel routine - * BME_BEVEL_RADIUS <---- Will need to think about this one; will probably need to incorporate into actual bevel routine - * All weights/limits are stored per-vertex - */ -BME_Mesh *BME_bevel(BME_Mesh *bm, float value, int res, int options, int defgrp_index, float angle, BME_TransData_Head **rtd) { - BME_Vert *v; - BME_TransData_Head *td; - BME_TransData *vtd; - int i; - float fac=1, d; - - td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE); - - BME_bevel_initialize(bm, options, defgrp_index, angle, td); - - /* recursion math courtesy of Martin Poirier (theeth) */ - for (i=0; iverts.first; v; v=v->next) { - if ( (vtd = BME_get_transdata(td, v)) ) { - if (vtd->max && (*vtd->max > 0 && value > *vtd->max)) { - d = *vtd->max; - } - else { - d = value; - } - madd_v3_v3v3fl(v->co,vtd->org,vtd->vec,vtd->factor*d); - } - v->tflag1 = 0; - } - - BME_free_transdata(td); - return bm; -} -#endif diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index d8349012a5f..463237c39a8 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -94,7 +94,6 @@ set(SRC intern/bmesh_polygon.c intern/bmesh_queries.c intern/bmesh_opdefines.c - intern/bmesh_eulers.c intern/bmesh_operators.c intern/bmesh_private.h intern/bmesh_walkers.c diff --git a/source/blender/bmesh/intern/bmesh_eulers.c b/source/blender/bmesh/intern/bmesh_eulers.c deleted file mode 100644 index b1ba4ca3176..00000000000 --- a/source/blender/bmesh/intern/bmesh_eulers.c +++ /dev/null @@ -1,1215 +0,0 @@ -/*some of this may come back, such as split face or split edge, if necassary for speed*/ - -#if 0 -/* - * ***** BEGIN GPL 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. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2004 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Geoffrey Bantle. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/bmesh/intern/bmesh_eulers.c - * \ingroup bmesh - * - * BM Euler construction API. - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_listBase.h" -#include "DNA_meshdata_types.h" -#include "DNA_mesh_types.h" - -#include "BKE_customdata.h" -#include "BKE_utildefines.h" - -#include "bmesh.h" -#include "bmesh_private.h" - -#include "BLI_blenlib.h" -#include "BLI_ghash.h" - -/********************************************************* - * "Euler API" * - * * - * * - * Primitive construction operators for mesh tools. * - * * - **********************************************************/ - - -/* - The functions in this file represent the 'primitive' or 'atomic' operators that - mesh tools use to manipulate the topology of the structure.* The purpose of these - functions is to provide a trusted set of operators to manipulate the mesh topology - and which can also be combined together like building blocks to create more - sophisticated tools. It needs to be stressed that NO manipulation of an existing - mesh structure should be done outside of these functions. - - In the BM system, each euler is named by an ancronym which describes what it actually does. - Furthermore each Euler has a logical inverse. An important design criteria of all Eulers is that - through a Euler's logical inverse you can 'undo' an operation. (Special note should - be taken of bmesh_loop_reverse, which is its own inverse). - - bmesh_MF/KF: Make Face and Kill Face - bmesh_ME/KE: Make Edge and Kill Edge - bmesh_MV/KV: Make Vert and Kill Vert - bmesh_SEMV/JEKV: Split Edge, Make Vert and Join Edge, Kill Vert - bmesh_SFME/JFKE: Split Face, Make Edge and Join Face, Kill Edge - bmesh_loop_reverse: Reverse a Polygon's loop cycle. (used for flip normals for one) - - Using a combination of these eleven eulers any non-manifold modelling operation can be achieved. - Each Euler operator has a detailed explanation of what is does in the comments preceding its - code. - - *The term "Euler Operator" is actually a misnomer when referring to a non-manifold - data structure. Its use is in keeping with the convention established by others. - - BMESH_TODO: - -Make seperate 'debug levels' of validation - -Add in the UnglueFaceRegionMakeVert and GlueFaceRegionKillVert eulers. - - NOTE: - -The functions in this file are notoriously difficult to debug and even understand sometimes. - better code comments would be nice.... - -*/ - - -/*MAKE Eulers*/ - -/** - * bmesh_MV - * - * MAKE VERT EULER: - * - * Makes a single loose vertex. - * - * Returns - - * A BMVert pointer. - */ - -BMVert *bmesh_mv(BMesh *bm, const float vec[3]) -{ - BMVert *v = bmesh_addvertlist(bm, NULL); - copy_v3_v3(v->co,vec); - return v; -} - -/** - * bmesh_ME - * - * MAKE EDGE EULER: - * - * Makes a single wire edge between two vertices. - * If the caller does not want there to be duplicate - * edges between the vertices, it is up to them to check - * for this condition beforehand. - * - * Returns - - * A BMEdge pointer. - */ - -BMEdge *bmesh_me(BMesh *bm, BMVert *v1, BMVert *v2) -{ - BMEdge *e=NULL; - BMNode *d1=NULL, *d2=NULL; - int valance1=0, valance2=0, edok; - - /*edge must be between two distinct vertices...*/ - if(v1 == v2) return NULL; - - #ifndef bmesh_FASTEULER - /*count valance of v1*/ - if(v1->e) { - d1 = bmesh_disk_getpointer(v1->e,v1); - if(d1) valance1 = bmesh_cycle_length(d1); - else bmesh_error(); - } - if(v2->e) { - d2 = bmesh_disk_getpointer(v2->e,v2); - if(d2) valance2 = bmesh_cycle_length(d2); - else bmesh_error(); - } - #endif - - /*go ahead and add*/ - e = bmesh_addedgelist(bm, v1, v2, NULL); - bmesh_disk_append_edge(e, e->v1); - bmesh_disk_append_edge(e, e->v2); - - #ifndef bmesh_FASTEULER - /*verify disk cycle lengths*/ - d1 = bmesh_disk_getpointer(e, e->v1); - edok = bmesh_cycle_validate(valance1+1, d1); - if(!edok) bmesh_error(); - d2 = bmesh_disk_getpointer(e, e->v2); - edok = bmesh_cycle_validate(valance2+1, d2); - if(!edok) bmesh_error(); - - /*verify that edge actually made it into the cycle*/ - edok = bmesh_disk_hasedge(v1, e); - if(!edok) bmesh_error(); - edok = bmesh_disk_hasedge(v2, e); - if(!edok) bmesh_error(); - #endif - return e; -} - - - -/** - * bmesh_MF - * - * MAKE FACE EULER: - * Takes a list of edge pointers which form a closed loop and makes a face - * from them. The first edge in elist is considered to be the start of the - * polygon, and v1 and v2 are its vertices and determine the winding of the face - * Other than the first edge, no other assumptions are made about the order of edges - * in the elist array. To verify that it is a single closed loop and derive the correct - * order a simple series of verifications is done and all elements are visited. - * - * Returns - - * A BMFace pointer - */ - -#define MF_CANDIDATE 1 -#define MF_VISITED 2 -#define MF_TAKEN 4 - -BMFace *bmesh_mf(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **elist, int len) -{ - BMFace *f = NULL; - BMEdge *curedge; - BMVert *curvert, *tv, **vlist; - int i, j, done, cont, edok; - - if(len < 2) return NULL; - - /*make sure that v1 and v2 are in elist[0]*/ - //if(bmesh_verts_in_edge(v1,v2,elist[0]) == 0) - // return NULL; - - /*clear euler flags*/ - for(i=0;iv2 : elist[i]->v1; - diskbase = bmesh_disk_getpointer(v1->e, v1); - len = bmesh_cycle_length(diskbase); - - for(a=0,curedge=v1->e;ahead.eflag1 = curedge->head.eflag2 = 0; - } - } - } - - for(i=0;ihead.eflag1 |= MF_CANDIDATE; - - /*if elist[i] has a loop, count its radial length*/ - if(elist[i]->loop) elist[i]->head.eflag2 = bmesh_cycle_length(&(elist[i]->l->radial)); - else elist[i]->head.eflag2 = 0; - } - - /* For each vertex in each edge, it must have exactly two MF_CANDIDATE edges attached to it - Note that this does not gauruntee that face is a single closed loop. At best it gauruntees - that elist contains a finite number of seperate closed loops. - */ -// for(i=0; iv1, MF_CANDIDATE, 0); -// if(edok != 2) return NULL; -// edok = bmesh_disk_count_edgeflag(elist[i]->v2, MF_CANDIDATE, 0); -// if(edok != 2) return NULL; -// } - - /*set start edge, start vert and target vert for our loop traversal*/ - curedge = elist[0]; - tv = v1; - curvert = v2; - - if(bm->vtarlen < len) { - if (bm->vtar) MEM_freeN(bm->vtar); - bm->vtar = MEM_callocN(sizeof(BMVert *)* len, "BM Vert pointer array"); - bm->vtarlen = len; - } - /*insert tv into vlist since its the first vertex in face*/ - - i=0; - vlist=bm->vtar; - vlist[i] = tv; - - /* Basic procedure: Starting with curv we find the edge in it's disk cycle which hasn't - been visited yet. When we do, we put curv in a linked list and find the next MF_CANDIDATE - edge, loop until we find TV. We know TV is reachable because of test we did earlier. - */ - done=0; - while(!done) { - /*add curvert to vlist*/ - /*insert some error cheking here for overflows*/ - i++; - vlist[i] = curvert; - - /*mark curedge as visited*/ - curedge->head.eflag1 |= MF_VISITED; - - /*find next edge and vert*/ - curedge = bmesh_disk_next_edgeflag(curedge, curvert, MF_CANDIDATE, 0); - curvert = bmesh_edge_getothervert(curedge, curvert); - if(curvert == tv) { - curedge->head.eflag1 |= MF_VISITED; - done=1; - } - } - - /* Verify that all edges have been visited It's possible that we did reach tv - from sv, but that several unconnected loops were passed in via elist. - */ - cont=1; -// for(i=0; ihead.eflag1 & MF_VISITED) == 0) cont = 0; -// } - - /*if we get this far, its ok to allocate the face and add the loops*/ - if(cont) { - BMLoop *l; - BMEdge *e; - f = bmesh_addpolylist(bm, NULL); - f->len = len; - for(i=0;iloopbase)) f->lbase = l; - bmesh_cycle_append(f->lbase, l); - } - - /*take care of edge pointers and radial cycle*/ - for(i=0, l = f->loopbase; inext) { - e = NULL; - if(l == f->loopbase) e = elist[0]; /*first edge*/ - - else {/*search elist for others*/ - for(j=1; jv, ((l->next))->v, elist[j]); - if(edok) { - e = elist[j]; - break; - } - } - } - l->e = e; /*set pointer*/ - bmesh_radial_append(e, l); /*append into radial*/ - } - - f->len = len; - - /*Validation Loop cycle*/ - edok = bmesh_cycle_validate(len, f->lbase); - if(!edok) bmesh_error(); - for(i=0, l = f->loopbase; inext))) { - /*validate loop vert pointers*/ - edok = bmesh_verts_in_edge(l->v, ((l->next))->v, l->e); - if(!edok) bmesh_error(); - /*validate the radial cycle of each edge*/ - edok = bmesh_cycle_length(&(l->radial)); - if(edok != (l->e->head.eflag2 + 1)) bmesh_error(); - } - } - - for(i=0;ihead.eflag1=elist[i]->head.eflag2 = 0; - return f; -} - -/* KILL Eulers */ - -/** - * bmesh_KV - * - * KILL VERT EULER: - * - * Kills a single loose vertex. - * - * Returns - - * 1 for success, 0 for failure. - */ - -int bmesh_kv(BMesh *bm, BMVert *v) -{ - if(v->e == NULL) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) bm->totvertsel--; - - BLI_remlink(&(bm->verts), &(v->head)); - bmesh_free_vert(bm,v); - return 1; - } - return 0; -} - -/** - * bmesh_KE - * - * KILL EDGE EULER: - * - * Kills a wire edge. - * - * Returns - - * 1 for success, 0 for failure. - */ - -int bmesh_ke(BMesh *bm, BMEdge *e) -{ - int edok; - - /*Make sure that no faces!*/ - if(e->l == NULL) { - bmesh_disk_remove_edge(e, e->v1); - bmesh_disk_remove_edge(e, e->v2); - - /*verify that edge out of disk*/ - edok = bmesh_disk_hasedge(e->v1, e); - if(edok) bmesh_error(); - edok = bmesh_disk_hasedge(e->v2, e); - if(edok) bmesh_error(); - - /*remove and deallocate*/ - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) bm->totedgesel--; - BLI_remlink(&(bm->edges), &(e->head)); - bmesh_free_edge(bm, e); - return 1; - } - return 0; -} - -/** - * bmesh_KF - * - * KILL FACE EULER: - * - * The logical inverse of bmesh_MF. - * Kills a face and removes each of its loops from the radial that it belongs to. - * - * Returns - - * 1 for success, 0 for failure. -*/ - -int bmesh_kf(BMesh *bm, BMFace *bply) -{ - BMLoop *newbase,*oldbase, *curloop; - int i,len=0; - - /*add validation to make sure that radial cycle is cleaned up ok*/ - /*deal with radial cycle first*/ - len = bmesh_cycle_length(bply->lbase); - for(i=0, curloop=bply->loopbase; i < len; i++, curloop = ((curloop->next))) - bmesh_radial_remove_loop(curloop, curloop->e); - - /*now deallocate the editloops*/ - for(i=0; i < len; i++) { - newbase = ((bply->lbase->next)); - oldbase = bply->lbase; - bmesh_cycle_remove(oldbase, oldbase); - bmesh_free_loop(bm, oldbase); - bply->loopbase = newbase; - } - - if (BM_elem_flag_test(bply, BM_ELEM_SELECT)) bm->totfacesel--; - BLI_remlink(&(bm->polys), &(bply->head)); - bmesh_free_poly(bm, bply); - return 1; -} - -/*SPLIT Eulers*/ - -/** - * bmesh_SEMV - * - * SPLIT EDGE MAKE VERT: - * Takes a given edge and splits it into two, creating a new vert. - * - * - * Before: OV---------TV - * After: OV----NV---TV - * - * Returns - - * BMVert pointer. - * -*/ - -BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **re) -{ - BMVert *nv, *ov; - BMNode *diskbase; - BMEdge *ne; - int i, edok, valance1=0, valance2=0; - - if(bmesh_vert_in_edge(e,tv) == 0) return NULL; - ov = bmesh_edge_getothervert(e,tv); - //v2 = tv; - - /*count valance of v1*/ - diskbase = bmesh_disk_getpointer(e, ov); - valance1 = bmesh_cycle_length(diskbase); - /*count valance of v2*/ - diskbase = bmesh_disk_getpointer(e, tv); - valance2 = bmesh_cycle_length(diskbase); - - nv = bmesh_addvertlist(bm, tv); - ne = bmesh_addedgelist(bm, nv, tv, e); - - //e->v2 = nv; - /*remove e from v2's disk cycle*/ - bmesh_disk_remove_edge(e, tv); - /*swap out tv for nv in e*/ - bmesh_edge_swapverts(e, tv, nv); - /*add e to nv's disk cycle*/ - bmesh_disk_append_edge(e, nv); - /*add ne to nv's disk cycle*/ - bmesh_disk_append_edge(ne, nv); - /*add ne to tv's disk cycle*/ - bmesh_disk_append_edge(ne, tv); - /*verify disk cycles*/ - diskbase = bmesh_disk_getpointer(ov->e,ov); - edok = bmesh_cycle_validate(valance1, diskbase); - if(!edok) bmesh_error(); - diskbase = bmesh_disk_getpointer(tv->e,tv); - edok = bmesh_cycle_validate(valance2, diskbase); - if(!edok) bmesh_error(); - diskbase = bmesh_disk_getpointer(nv->e,nv); - edok = bmesh_cycle_validate(2, diskbase); - if(!edok) bmesh_error(); - - /*Split the radial cycle if present*/ - if(e->l) { - BMLoop *nl,*l; - BMNode *radEBase=NULL, *radNEBase=NULL; - int radlen = bmesh_cycle_length(&(e->l->radial)); - /*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/ - while(e->l) { - l=e->l; - l->f->len++; - bmesh_radial_remove_loop(l,e); - - nl = bmesh_create_loop(bm,NULL,NULL,l->f,l); - nl->prev = (BMHeader*)l; - nl->next = (BMHeader*)(l->next); - nl->prev->next = (BMHeader*)nl; - nl->next->prev = (BMHeader*)nl; - nl->v = nv; - - /*assign the correct edge to the correct loop*/ - if(bmesh_verts_in_edge(nl->v, ((nl->next))->v, e)) { - nl->e = e; - l->e = ne; - - /*append l into ne's rad cycle*/ - if(!radNEBase) { - radNEBase = &(l->radial); - radNEBase->next = NULL; - radNEBase->prev = NULL; - } - - if(!radEBase) { - radEBase = &(nl->radial); - radEBase->next = NULL; - radEBase->prev = NULL; - } - - bmesh_cycle_append(radEBase,&(nl->radial)); - bmesh_cycle_append(radNEBase,&(l->radial)); - - } - else if(bmesh_verts_in_edge(nl->v,((nl->next))->v,ne)) { - nl->e = ne; - l->e = e; - - if(!radNEBase) { - radNEBase = &(nl->radial); - radNEBase->next = NULL; - radNEBase->prev = NULL; - } - if(!radEBase) { - radEBase = &(l->radial); - radEBase->next = NULL; - radEBase->prev = NULL; - } - bmesh_cycle_append(radEBase,&(l->radial)); - bmesh_cycle_append(radNEBase,&(nl->radial)); - } - - } - - e->l = radEBase->data; - ne->l = radNEBase->data; - - /*verify length of radial cycle*/ - edok = bmesh_cycle_validate(radlen,&(e->l->radial)); - if(!edok) bmesh_error(); - edok = bmesh_cycle_validate(radlen,&(ne->l->radial)); - if(!edok) bmesh_error(); - - /*verify loop->v and loop->next->v pointers for e*/ - for(i=0,l=e->l; i < radlen; i++, l = l->radial_next) { - if(!(l->e == e)) bmesh_error(); - if(!(l->radial.data == l)) bmesh_error(); - if( ((l->prev))->e != ne && ((l->next))->e != ne) bmesh_error(); - edok = bmesh_verts_in_edge(l->v, ((l->next))->v, e); - if(!edok) bmesh_error(); - if(l->v == ((l->next))->v) bmesh_error(); - if(l->e == ((l->next))->e) bmesh_error(); - /*verify loop cycle for kloop->f*/ - edok = bmesh_cycle_validate(l->f->len, l->f->lbase); - if(!edok) bmesh_error(); - } - /*verify loop->v and loop->next->v pointers for ne*/ - for(i=0,l=ne->l; i < radlen; i++, l = l->radial_next) { - if(!(l->e == ne)) bmesh_error(); - if(!(l->radial.data == l)) bmesh_error(); - if( ((l->prev))->e != e && ((l->next))->e != e) bmesh_error(); - edok = bmesh_verts_in_edge(l->v, ((l->next))->v, ne); - if(!edok) bmesh_error(); - if(l->v == ((l->next))->v) bmesh_error(); - if(l->e == ((l->next))->e) bmesh_error(); - /*verify loop cycle for kloop->f. Redundant*/ - edok = bmesh_cycle_validate(l->f->len, l->f->lbase); - if(!edok) bmesh_error(); - } - } - - if(re) *re = ne; - return nv; -} - -/** - * bmesh_SFME - * - * SPLIT FACE MAKE EDGE: - * - * Takes as input two vertices in a single face. An edge is created which divides the original face - * into two distinct regions. One of the regions is assigned to the original face and it is closed off. - * The second region has a new face assigned to it. - * - * Examples: - * - * Before: After: - * ---------- ---------- - * | | | | - * | | | f1 | - * v1 f1 v2 v1======v2 - * | | | f2 | - * | | | | - * ---------- ---------- - * - * Note that the input vertices can be part of the same edge. This will result in a two edged face. - * This is desirable for advanced construction tools and particularly essential for edge bevel. Because - * of this it is up to the caller to decide what to do with the extra edge. - * - * Note that the tesselator abuses eflag2 while using this euler! (don't ever ever do this....) - * - * Returns - - * A BMFace pointer - */ -BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **rl) -{ - - BMFace *f2; - BMLoop *v1loop = NULL, *v2loop = NULL, *curloop, *f1loop=NULL, *f2loop=NULL; - BMEdge *e; - int i, len, f1len, f2len; - - - /*verify that v1 and v2 are in face.*/ - len = bmesh_cycle_length(f->lbase); - for(i = 0, curloop = f->loopbase; i < len; i++, curloop = ((curloop->next)) ) { - if(curloop->v == v1) v1loop = curloop; - else if(curloop->v == v2) v2loop = curloop; - } - - if(!v1loop || !v2loop) return NULL; - - /*allocate new edge between v1 and v2*/ - e = bmesh_addedgelist(bm, v1, v2,NULL); - bmesh_disk_append_edge(e, v1); - bmesh_disk_append_edge(e, v2); - - f2 = bmesh_addpolylist(bm,f); - f1loop = bmesh_create_loop(bm,v2,e,f,v2loop); - f2loop = bmesh_create_loop(bm,v1,e,f2,v1loop); - - f1loop->prev = v2loop->prev; - f2loop->prev = v1loop->prev; - v2loop->prev->next = (BMHeader*)f1loop; - v1loop->prev->next = (BMHeader*)f2loop; - - f1loop->next = (BMHeader*)v1loop; - f2loop->next = (BMHeader*)v2loop; - v1loop->prev = (BMHeader*)f1loop; - v2loop->prev = (BMHeader*)f2loop; - - f2->loopbase = f2loop; - f->loopbase = f1loop; - - /*validate both loops*/ - /*I dont know how many loops are supposed to be in each face at this point! FIXME!*/ - - /*go through all of f2's loops and make sure they point to it properly.*/ - f2len = bmesh_cycle_length(f2->lbase); - for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ) curloop->f = f2; - - /*link up the new loops into the new edges radial*/ - bmesh_radial_append(e, f1loop); - bmesh_radial_append(e, f2loop); - - - f2->len = f2len; - - f1len = bmesh_cycle_length(f->lbase); - f->len = f1len; - - if(rl) *rl = f2loop; - return f2; -} - - -/** - * bmesh_JEKV - * - * JOIN EDGE KILL VERT: - * Takes a an edge and pointer to one of its vertices and collapses - * the edge on that vertex. - * - * Before: OE KE - * ------- ------- - * | || | - * OV KV TV - * - * - * After: OE - * --------------- - * | | - * OV TV - * - * - * Restrictions: - * KV is a vertex that must have a valance of exactly two. Furthermore - * both edges in KV's disk cycle (OE and KE) must be unique (no double - * edges). - * - * It should also be noted that this euler has the possibility of creating - * faces with just 2 edges. It is up to the caller to decide what to do with - * these faces. - * - * Returns - - * 1 for success, 0 for failure. - */ -int bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv) -{ - BMEdge *oe; - BMVert *ov, *tv; - BMNode *diskbase; - BMLoop *killoop,*nextl; - int len,radlen=0, halt = 0, i, valance1, valance2,edok; - - if(bmesh_vert_in_edge(ke,kv) == 0) return 0; - diskbase = bmesh_disk_getpointer(kv->e, kv); - len = bmesh_cycle_length(diskbase); - - if(len == 2) { - oe = bmesh_disk_nextedge(ke, kv); - tv = bmesh_edge_getothervert(ke, kv); - ov = bmesh_edge_getothervert(oe, kv); - halt = bmesh_verts_in_edge(kv, tv, oe); //check for double edges - - if(halt) return 0; - else { - - /*For verification later, count valance of ov and tv*/ - diskbase = bmesh_disk_getpointer(ov->e, ov); - valance1 = bmesh_cycle_length(diskbase); - diskbase = bmesh_disk_getpointer(tv->e, tv); - valance2 = bmesh_cycle_length(diskbase); - - /*remove oe from kv's disk cycle*/ - bmesh_disk_remove_edge(oe,kv); - /*relink oe->kv to be oe->tv*/ - bmesh_edge_swapverts(oe, kv, tv); - /*append oe to tv's disk cycle*/ - bmesh_disk_append_edge(oe, tv); - /*remove ke from tv's disk cycle*/ - bmesh_disk_remove_edge(ke, tv); - - - - /*deal with radial cycle of ke*/ - if(ke->l) { - /*first step, fix the neighboring loops of all loops in ke's radial cycle*/ - radlen = bmesh_cycle_length(&(ke->l->radial)); - for(i=0,killoop = ke->l; inext->prev = killoop->prev; - killoop->prev->next = killoop->next; - if( ((killoop->next))->v == kv) ((killoop->next))->v = tv; - - /*fix len attribute of face*/ - killoop->f->len--; - if(killoop->f->loopbase == killoop) killoop->f->lbase = ((killoop->next)); - } - /*second step, remove all the hanging loops attached to ke*/ - killoop = ke->l; - radlen = bmesh_cycle_length(&(ke->l->radial)); - /*make sure we have enough room in bm->lpar*/ - if(bm->lparlen < radlen) { - MEM_freeN(bm->lpar); - bm->lpar = MEM_callocN(sizeof(BMLoop *)* radlen, "BM Loop pointer array"); - bm->lparlen = bm->lparlen * radlen; - } - /*this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well...*/ - i=0; - while(ilpar[i] = killoop; - killoop = killoop->radial_next; - i++; - } - i=0; - while(ilpar[i]); - i++; - } - /*Validate radial cycle of oe*/ - edok = bmesh_cycle_validate(radlen,&(oe->l->radial)); - - } - - - /*Validate disk cycles*/ - diskbase = bmesh_disk_getpointer(ov->e,ov); - edok = bmesh_cycle_validate(valance1, diskbase); - if(!edok) bmesh_error(); - diskbase = bmesh_disk_getpointer(tv->e,tv); - edok = bmesh_cycle_validate(valance2, diskbase); - if(!edok) bmesh_error(); - - /*Validate loop cycle of all faces attached to oe*/ - for(i=0,nextl = oe->l; if->len,nextl->f->lbase); - if(!edok) bmesh_error(); - } - /*deallocate edge*/ - BLI_remlink(&(bm->edges), &(ke->head)); - bmesh_free_edge(bm, ke); - /*deallocate vertex*/ - BLI_remlink(&(bm->verts), &(kv->head)); - bmesh_free_vert(bm, kv); - return 1; - } - } - return 0; -} - - -/** - * bmesh_loop_reverse - * - * FLIP FACE EULER - * - * Changes the winding order of a face from CW to CCW or vice versa. - * This euler is a bit peculiar in compairson to others as it is its - * own inverse. - * - * BMESH_TODO: reinsert validation code. - * - * Returns - - * 1 for success, 0 for failure. - */ - -int bmesh_loop_reverse(BMesh *bm, BMFace *f) -{ - BMLoop *l = f->loopbase, *curloop, *oldprev, *oldnext; - int i, j, edok, len = 0; - - len = bmesh_cycle_length(l); - if(bm->edarlen < len) { - MEM_freeN(bm->edar); - bm->edar = MEM_callocN(sizeof(BMEdge *)* len, "BM Edge pointer array"); - bm->edarlen = len; - } - - for(i=0, curloop = l; i< len; i++, curloop= ((curloop->next)) ) { - curloop->e->head.eflag1 = 0; - curloop->e->head.eflag2 = bmesh_cycle_length(&curloop->radial); - bmesh_radial_remove_loop(curloop, curloop->e); - /*in case of border edges we HAVE to zero out curloop->radial Next/Prev*/ - curloop->radial.next = curloop->radial.prev = NULL; - bm->edar[i] = curloop->e; - } - - /*actually reverse the loop. This belongs in bmesh_cycle_reverse!*/ - for(i=0, curloop = l; i < len; i++) { - oldnext = ((curloop->next)); - oldprev = ((curloop->prev)); - curloop->next = (BMHeader*)oldprev; - curloop->prev = (BMHeader*)oldnext; - curloop = oldnext; - } - - if(len == 2) { //two edged face - //do some verification here! - l->e = bm->edar[1]; - ((l->next))->e = bm->edar[0]; - } - else { - for(i=0, curloop = l; i < len; i++, curloop = ((curloop->next)) ) { - edok = 0; - for(j=0; j < len; j++) { - edok = bmesh_verts_in_edge(curloop->v, ((curloop->next))->v, bm->edar[j]); - if(edok) { - curloop->e = bm->edar[j]; - break; - } - } - } - } - /*rebuild radial*/ - for(i=0, curloop = l; i < len; i++, curloop = curloop->next ) bmesh_radial_append(curloop->e, curloop); - - /*validate radial*/ - for(i=0, curloop = l; i < len; i++, curloop = ((curloop->next)) ) { - edok = bmesh_cycle_validate(curloop->e->head.eflag2, &(curloop->radial)); - if(!edok) { - bmesh_error(); - } - } - return 1; -} - -/** - * bmesh_JFKE - * - * JOIN FACE KILL EDGE: - * - * Takes two faces joined by a single 2-manifold edge and fuses them togather. - * The edge shared by the faces must not be connected to any other edges which have - * Both faces in its radial cycle - * - * Examples: - * - * A B - * ---------- ---------- - * | | | | - * | f1 | | f1 | - * v1========v2 = Ok! v1==V2==v3 == Wrong! - * | f2 | | f2 | - * | | | | - * ---------- ---------- - * - * In the example A, faces f1 and f2 are joined by a single edge, and the euler can safely be used. - * In example B however, f1 and f2 are joined by multiple edges and will produce an error. The caller - * in this case should call bmesh_JEKV on the extra edges before attempting to fuse f1 and f2. - * - * Also note that the order of arguments decides whether or not certain per-face attributes are present - * in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited - * from f1, not f2. - * - * Returns - - * A BMFace pointer -*/ - -//disregarding f1loop and f2loop, if a vertex appears in a joined face more than once, we cancel - -BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) -{ - - BMLoop *curloop, *f1loop=NULL, *f2loop=NULL; - int loopok = 0, newlen = 0,i, f1len=0, f2len=0, radlen=0, edok, shared; - - if(f1 == f2) return NULL; //can't join a face to itself - /*verify that e is in both f1 and f2*/ - f1len = bmesh_cycle_length(f1->lbase); - f2len = bmesh_cycle_length(f2->lbase); - for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((curloop->next)) ) { - if(curloop->e == e) { - f1loop = curloop; - break; - } - } - for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ) { - if(curloop->e==e) { - f2loop = curloop; - break; - } - } - if(!(f1loop && f2loop)) return NULL; - - /*validate that edge is 2-manifold edge*/ - radlen = bmesh_cycle_length(&(f1loop->radial)); - if(radlen != 2) return NULL; - - /*validate direction of f2's loop cycle is compatible.*/ - if(f1loop->v == f2loop->v) return NULL; - - /* - validate that for each face, each vertex has another edge in its disk cycle that is - not e, and not shared. - */ - if(bmesh_radial_find_face( ((f1loop->next))->e,f2)) return NULL; - if(bmesh_radial_find_face( ((f1loop->prev))->e,f2)) return NULL; - if(bmesh_radial_find_face( ((f2loop->next))->e,f1)) return NULL; - if(bmesh_radial_find_face( ((f2loop->prev))->e,f1)) return NULL; - - /*validate only one shared edge*/ - shared = BM_face_share_edges(f1,f2); - if(shared > 1) return NULL; - - /*validate no internal joins*/ - for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((curloop->next)) ) curloop->v->head.eflag1 = 0; - for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ) curloop->v->head.eflag1 = 0; - - for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((curloop->next)) ) { - if(curloop != f1loop) - curloop->v->head.eflag1++; - } - for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ) { - if(curloop != f2loop) - curloop->v->head.eflag1++; - } - - for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((curloop->next)) ) { - if(curloop->v->head.eflag1 > 1) - return NULL; - } - - for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ) { - if(curloop->v->head.eflag1 > 1) - return NULL; - } - - /*join the two loops*/ - f1loop->prev->next = f2loop->next; - f2loop->next->prev = f1loop->prev; - - f1loop->next->prev = f2loop->prev; - f2loop->prev->next = f1loop->next; - - /*if f1loop was baseloop, give f1loop->next the base.*/ - if(f1->loopbase == f1loop) f1->lbase = ((f1loop->next)); - - /*validate the new loop*/ - loopok = bmesh_cycle_validate((f1len+f2len)-2, f1->lbase); - if(!loopok) bmesh_error(); - - /*make sure each loop points to the proper face*/ - newlen = bmesh_cycle_length(f1->lbase); - for(i = 0, curloop = f1->loopbase; i < newlen; i++, curloop = ((curloop->next)) ) curloop->f = f1; - - f1->len = newlen; - - edok = bmesh_cycle_validate(f1->len, f1->lbase); - if(!edok) bmesh_error(); - - /*remove edge from the disk cycle of its two vertices.*/ - bmesh_disk_remove_edge(f1loop->e, f1loop->e->v1); - bmesh_disk_remove_edge(f1loop->e, f1loop->e->v2); - - /*deallocate edge and its two loops as well as f2*/ - BLI_remlink(&(bm->edges), &(f1loop->e->head)); - BLI_remlink(&(bm->polys), &(f2->head)); - bmesh_free_edge(bm, f1loop->e); - bmesh_free_loop(bm, f1loop); - bmesh_free_loop(bm, f2loop); - bmesh_free_poly(bm, f2); - return f1; -} - -/** -* bmesh_URMV -* -* UNGLUE REGION MAKE VERT: -* -* Takes a locally manifold disk of face corners and 'unglues' it -* creating a new vertex -* -**/ - -#define URMV_VISIT 1 -#define URMV_VISIT2 2 - -BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv) -{ - BMVert *nv = NULL; - BMLoop *l = NULL, *sl = NULL; - BMEdge *curedge = NULL; - int numloops = 0, numedges = 0, i, maxedges, maxloops; - - - /*BMESH_TODO: Validation*/ - /*validate radial cycle of all collected loops*/ - /*validate the disk cycle of sv, and nv*/ - /*validate the face length of all faces? overkill?*/ - /*validate the l->e pointers of all affected faces, ie: l->v and l->next->v should be equivalent to l->e*/ - - /*verify that sv has edges*/ - if(sv->e == NULL) - return NULL; - - /*first verify no wire edges on sv*/ - curedge = sv->e; - do { - if(curedge->l == NULL) - return NULL; - curedge = bmesh_disk_nextedge(curedge, sv); - } while(curedge != sv->e); - - /*next verify that sv is in sf*/ - l = sf->loopbase; - do { - if(l->v == sv) { - sl = l; - break; - } - l = (l->next); - } while(l != sf->lbase); - - if(sl == NULL) - return NULL; - - /*clear euler flags*/ - sv->head.eflag1 = 0; - - curedge = sv->e; - do { - curedge->head.eflag1 = 0; - l = curedge->l; - do { - l->head.eflag1 = 0; - l->f->head.eflag1 = 0; - l = bmesh_radial_nextloop(l); - } while(l != curedge->l); - curedge = bmesh_disk_nextedge(curedge, sv); - } while(curedge != sv->e); - - /*search through face disk and flag elements as we go.*/ - /*Note, test this to make sure that it works correct on - non-manifold faces! - */ - l = sl; - l->e->head.eflag1 |= URMV_VISIT; - l->f->head.eflag1 |= URMV_VISIT; - do { - if(l->v == sv) - l = bmesh_radial_nextloop((l->prev)); - else - l = bmesh_radial_nextloop((l->next)); - l->e->head.eflag1 |= URMV_VISIT; - l->f->head.eflag1 |= URMV_VISIT; - } while(l != sl && (bmesh_cycle_length(&(l->radial)) > 1) ); - - /*Verify that all visited edges are at least 1 or 2 manifold*/ - curedge = sv->e; - do { - if(curedge->head.eflag1 && (bmesh_cycle_length(&(curedge->l->radial)) > 2) ) - return NULL; - curedge = bmesh_disk_nextedge(curedge, sv); - } while(curedge != sv->e); - - /*allocate temp storage - we overallocate here instead of trying to be clever*/ - maxedges = 0; - maxloops = 0; - curedge = sv->e; - do { - if(curedge->l) { - l = curedge->l; - do { - maxloops += l->f->len; - l = bmesh_radial_nextloop(l); - } while(l != curedge->l); - } - maxedges+= 1; - curedge = bmesh_disk_nextedge(curedge,sv); - } while(curedge != sv->e); - - if(bm->edarlen < maxedges) { - MEM_freeN(bm->edar); - bm->edar = MEM_callocN(sizeof(BMEdge *) * maxedges, "BM Edge pointer array"); - bm->edarlen = maxedges; - } - if(bm->lparlen < maxloops) { - MEM_freeN(bm->lpar); - bm->lpar = MEM_callocN(sizeof(BMLoop *) * maxloops, "BM Loop pointer array"); - bm->lparlen = maxloops; - } - - /*first get loops by looping around edges and loops around that edges faces*/ - curedge = sv->e; - do { - if(curedge->l) { - l = curedge->l; - do { - if( (l->head.eflag1 & URMV_VISIT) && (!(l->head.eflag1 & URMV_VISIT2)) ) { - bm->lpar[numloops] = l; - l->head.eflag1 |= URMV_VISIT2; - numloops++; - } - l = bmesh_radial_nextloop(l); - } while(l != curedge->l); - } - curedge = bmesh_disk_nextedge(curedge, sv); - } while(curedge != sv->e); - - /*now collect edges by looping around edges and looking at visited flags*/ - curedge = sv->e; - do { - if(curedge->head.eflag1 & URMV_VISIT) { - bm->edar[numedges] = curedge; - numedges++; - } - curedge = bmesh_disk_nextedge(curedge, sv); - } while(curedge != sv->e); - - /*make new vertex*/ - nv = bmesh_addvertlist(bm, sv); - - /*go through and relink edges*/ - for(i = 0; i < numedges; i++) { - curedge = bm->edar[i]; - /*remove curedge from sv*/ - bmesh_disk_remove_edge(curedge, sv); - /*swap out sv for nv in curedge*/ - bmesh_edge_swapverts(curedge, sv, nv); - /*add curedge to nv's disk cycle*/ - bmesh_disk_append_edge(curedge, nv); - } - - /*go through and relink loops*/ - for(i = 0; i < numloops; i ++) { - l = bm->lpar[i]; - if(l->v == sv) - l->v = nv; - } - return nv; -} -#endif diff --git a/source/blender/bmesh/intern/in-progress/BME_conversions.c b/source/blender/bmesh/intern/in-progress/BME_conversions.c deleted file mode 100644 index 279d8f7fd0e..00000000000 --- a/source/blender/bmesh/intern/in-progress/BME_conversions.c +++ /dev/null @@ -1,479 +0,0 @@ -#if 0 - -/* - * ***** BEGIN GPL 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. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LICENSE BLOCK ***** - */ - -#include "MEM_guardedalloc.h" -#include "BKE_customdata.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 "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 "bmesh_private.h" - - - -/* - * BMESH DERIVED MESH CONVERSION FUNCTIONS - * - * The functions in this file provides - * methods for converting to and from - * a bmesh. - * -*/ - - -/* - * DMCORNERS TO LOOPS - * - * Function to convert derived mesh per-face - * corner data (uvs, vertex colors), to n-gon - * per-loop data. - * -*/ - -static void DMcorners_to_loops(BMMesh *bm, CustomData *facedata, int index, BMFace *f, int numCol, int numTex) -{ - int i, j; - BMLoop *l; - MTFace *texface; - MTexPoly *texpoly; - MCol *mcol; - MLoopCol *mloopcol; - MLoopUV *mloopuv; - - for(i=0; i< numTex; i++){ - texface = CustomData_get_layer_n(facedata, CD_MTFACE, i); - texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); - - texpoly->tpage = texface[index].tpage; - texpoly->flag = texface[index].flag; - texpoly->transp = texface[index].transp; - texpoly->mode = texface[index].mode; - texpoly->tile = texface[index].tile; - texpoly->unwrap = texface[index].unwrap; - - j = 0; - l = f->loopbase; - do{ - mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); - mloopuv->uv[0] = texface[index].uv[j][0]; - mloopuv->uv[1] = texface[index].uv[j][1]; - j++; - l = l->next; - }while(l!=f->loopbase); - } - - for(i=0; i < numCol; i++){ - mcol = CustomData_get_layer_n(facedata, CD_MCOL, i); - j = 0; - l = f->loopbase; - do{ - mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); - mloopcol->r = mcol[(index*4)+j].r; - mloopcol->g = mcol[(index*4)+j].g; - mloopcol->b = mcol[(index*4)+j].b; - mloopcol->a = mcol[(index*4)+j].a; - j++; - l = l->next; - }while(l!=f->loopbase); - } -} - -/* - * LOOPS TO DMCORNERS - * - * Function to convert n-gon per-loop data - * (uvs, vertex colors, ect)to derived mesh - * face corner data. - * -*/ - -static void loops_to_DMcorners(BMMesh *bm, CustomData *facedata, int index, BMFace *f,int numCol, int numTex) -{ - int i, j; - BMLoop *l; - MTFace *texface; - MTexPoly *texpoly; - MCol *mcol; - MLoopCol *mloopcol; - MLoopUV *mloopuv; - - for(i=0; i < numTex; i++){ - texface = CustomData_get_layer_n(facedata, CD_MTFACE, i); - texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i); - - texface[index].tpage = texpoly->tpage; - texface[index].flag = texpoly->flag; - texface[index].transp = texpoly->transp; - texface[index].mode = texpoly->mode; - texface[index].tile = texpoly->tile; - texface[index].unwrap = texpoly->unwrap; - - j = 0; - l = f->loopbase; - do{ - mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i); - texface[index].uv[j][0] = mloopuv->uv[0]; - texface[index].uv[j][1] = mloopuv->uv[1]; - j++; - l = l->next; - }while(l!=f->loopbase); - - } - for(i=0; i < numCol; i++){ - mcol = CustomData_get_layer_n(facedata,CD_MCOL, i); - j = 0; - l = f->loopbase; - do{ - mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i); - mcol[(index*4) + j].r = mloopcol->r; - mcol[(index*4) + j].g = mloopcol->g; - mcol[(index*4) + j].b = mloopcol->b; - mcol[(index*4) + j].a = mloopcol->a; - j++; - l = l->next; - }while(l!=f->loopbase); - } -} - -/* - * MVERT TO BMESHVERT - * - * Converts a MVert to a BMVert - * -*/ -static BMVert *mvert_to_bmeshvert(BMMesh *bm, BMVert **vert_array, int index, MVert *mv, CustomData *data) -{ - BMVert *v = NULL; - - v = bmesh_make_vert(bm, mv->co, NULL); - vert_array[index] = v; - if(mv->flag & SELECT) bmesh_set_flag(v, BMESH_SELECT); - v->bweight = mv->bweight/255.0f; - CustomData_to_bmesh_block(data, &bm->vdata, index, &v->data); - - return v; -} - -/* - * MEDGE TO BMESHEDGE - * - * Converts a MEdge to a BMEdge - * -*/ - -static BMEdge *medge_to_bmeshedge(BMMesh *bm, BMVert **vert_array, int index, MEdge *me, CustomData *data, Edge_Hash *edge_hash) -{ - BMVert *v1, *v2; - BMEdge *e = NULL; - - v1 = vert_array[me->v1]; - v2 = vert_array[me->v2]; - e = bmesh_make_edge(bm, v1, v2, NULL, 0); - e->crease = me->crease/255.0f; - e->bweight = me->bweight/255.0f; - if(me->flag & 1) bmesh_set_flag(e, BMESH_SELECT); - if(me->flag & ME_SEAM) bmesh_set_flag(e, BMESH_SEAM); - BLI_edgehash_insert(edge_hash,me->v1,me->v2,e); - CustomData_to_bmesh_block(data, &bm->edata, index, &e->data); - - return e; -} - -/* - * MFACE TO BMESHFACE - * - * Converts a MFace to a BMFace. - * Note that this will fail on eekadoodle - * faces. - * -*/ - -static BMFace *mface_to_bmeshface(BMMesh *bm, BMVert **vert_array, int index, MFace *mf, CustomData *data, Edge_Hash *edge_hash) -{ - BMVert *v1, *v2; - BMEdge *edar[4]; - BMFace *f = NULL; - int len; - - 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 = bmesh_make_ngon(bm, v1, v2, edar, len, 0); - f->mat_nr = mf->mat_nr; - if(mf->flag & 1) bmesh_set_flag(f, BMESH_SELECT); - if(mf->flag & ME_HIDE) bmesh_set_flag(f, BMESH_HIDDEN); - CustomData_to_bmesh_block(data, &bm->pdata, index, &f->data); - - return f; -} - -/* - * DERIVEDMESH TO BMESH - * - * Converts a derived mesh to a bmesh. - * -*/ - -BMMesh *derivedmesh_to_bmesh(DerivedMesh *dm) -{ - - BMMesh *bm; - BMVert **vert_array; - BMFace *f=NULL; - - MVert *mvert, *mv; - MEdge *medge, *me; - MFace *mface, *mf; - - int totface,totedge,totvert,i,len, numTex, numCol; - int allocsize[4] = {512,512,2048,512}; - - EdgeHash *edge_hash = BLI_edgehash_new(); - - /*allocate a new bmesh*/ - bm = bmesh_make_mesh(allocsize); - - /*copy custom data layout*/ - CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0); - CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0); - - /*copy face corner data*/ - CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata); - /*initialize memory pools*/ - CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]); - CustomData_bmesh_init_pool(&bm->edata, allocsize[1]); - CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]); - CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]); - - /*needed later*/ - numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); - numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); - - totvert = dm->getNumVerts(dm); - totedge = dm->getNumEdges(dm); - totface = dm->getNumTessFaces(dm); - mvert = dm->getVertArray(dm); - medge = dm->getEdgeArray(dm); - mface = dm->getTessFaceArray(dm); - - vert_array = MEM_mallocN(sizeof(BMVert *)* totvert,"derivedmesh to bmesh vertex pointer array"); - - bmesh_begin_edit(bm); - /*add verts*/ - for(i=0, mv = mvert; i < totvert; i++, mv++) - mvert_to_bmeshvert(bm, vert_array, i, mv, &dm->vertData); - - /*add edges*/ - for(i=0, me = medge; i < totedge; i++, me++) - medge_to_bmeshedge(bm, vert_array, i, me, &dm->edgeData, edge_hash); - - /*add faces.*/ - for(i=0, mf = mface; i < totface; i++, mf++){ - f = mface_to_bmeshface(bm, vert_array, mf, &dm->faceData, edge_hash); - if(f) DMcorners_to_loops(bm, &dm->faceData, i, f, numCol, numTex); - } - - bmesh_end__edit(bm); - BLI_edgehash_free(edge_hash, NULL); - MEM_freeN(vert_array); - return bm; -} - -static void bmeshvert_to_mvert(BMMesh *bm, BMVert *v, MVert *mv, int index, CustomData *data) -{ - copy_v3_v3(mv->co, v->co); - if(bmesh_test_flag(v, BMESH_SELECT)) mv->flag |= 1; - if(bmesh_test_flag(v, BMESH_HIDDEN)) mv->flag |= ME_HIDE; - mv->bweight = (char)(255.0*v1->bweight); - CustomData_from_bmesh_block(&bm->vdata, data, &v1->data, index); -} - -static int bmeshedge_to_medge(BMMesh *bm, BMEdge *e, MEdge *me, int index, CustomData *data) -{ - if(e->head.eflag2){ - if(e->v1->head.eflag1 < e->v2->head.eflag1){ - me->v1 = e->v1->head.eflag1; - me->v2 = e->v2->head.eflag1; - } - else{ - me->v1 = e->v2->head.eflag1; - me->v2 = e->v1->eflag1; - } - - me->crease = (char)(255.0*e->crease); - me->bweight = (char)(255.0*e->bweight); - if(bmesh_test_flag(e, BMESH_SELECT)) me->flag |= 1; - if(bmesh_test_flag(e, BMESH_HIDDEN)) me->flag |= ME_HIDE; - CustomData_from_bmesh_block(&bm->edata, data, &e->data, index); - return 1; - } - return 0; -} - -static int bmeshface_to_mface(BMMesh *bm, BMFace *f, MFace *mf, int index, CustomData *data) -{ - if(f->len==3 || f->len==4){ - mf->v1 = f->loopbase->v->head.eflag1; - mf->v2 = f->loopbase->next->v->head.eflag1; - mf->v3 = f->loopbase->next->next->v->head.eflag1; - if(len == 4){ - mf->v4 = f->loopbase->prev->v->head.eflag1; - } - /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */ - if(mf->v3 == 0 || (f->len == 4 && mf->v4 == 0)){ - test_index_face(mf, NULL, index, f->len); - } - mf->mat_nr = (unsigned char)f->mat_nr; - if(bmesh_test_flag(f, BMESH_SELECT)) mf->flag |= 1; - if(bmesh_test_flag(f, BMESH_HIDDEN)) mf->flag |= ME_HIDE; - CustomData_from_bmesh_block(&bm->pdata, data, &f->data, index); - return TRUE; - } - return FALSE; -} - -/* - * BMESH TO DERIVEDMESH - * - * Converts a bmesh to a derived mesh. - * -*/ - -DerivedMesh *bmesh_to_derivedmesh(BMMesh *bm, DerivedMesh *dm) -{ - MFace *mface = NULL, *mf = NULL; - MEdge *medge = NULL, *me = NULL; - MVert *mvert = NULL, *mv = NULL; - DerivedMesh *result = NULL; - - BMVert *v=NULL; - BMEdge *e=NULL, *oe=NULL; - BMFace *f=NULL; - - BMIter verts; - BMIter edges; - BMIter faces; - - int totface = 0,totedge = 0,totvert = 0,i = 0, numTex, numCol; - - EdgeHash *edge_hash = BLI_edgehash_new(); - - /*get element counts*/ - totvert = bmesh_count_element(bm, BMESH_VERT); - - /*store element indices. Note that the abuse of eflag here should NOT be duplicated!*/ - for(i=0, v = bmeshIterator_init(verts, BM_VERTS, bm, 0); v; v = bmeshIterator_step(verts), i++) - v->head.eflag1 = i; - - /*we cannot have double edges in a derived mesh!*/ - for(e = bmeshIterator_init(edges, BM_EDGES, bm, 0); e; e = bmeshIterator_step(edges)){ - oe = BLI_edgehash_lookup(edge_hash,e->v1->head.eflag1, e->v2->head.eflag1); - if(!oe){ - totedge++; - BLI_edgehash_insert(edge_hash,e->v1->head.eflag1,e->v2->head.eflag1,e); - e->head.eflag2 = 1; - } - else{ - e->head.eflag2 = 0; - } - } - - /*count quads and tris*/ - for(f = bmeshIterator_init(faces, BM_FACES, bm, 0); f; f = bmeshIterator_step(faces)){ - if(f->len == 3 || f->len == 4) totface++; - } - - /*Allocate derivedmesh and copy custom data*/ - 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); - for(i = 0, v = bmeshIterator_init(verts, BM_VERTS, bm, 0); v; v = bmeshIterator_step(verts), i++, mv++){ - bmeshvert_to_mvert(bm,v,mv,i,&result->vertData); - } - - /*Make Edges*/ - medge = CDDM_get_edges(result); - i=0; - for(e = bmeshIterator_init(edges, BM_EDGES, bm, 0); e; e = bmeshIterator_step(edges)){ - me = &medge[i]; - if(bmeshedge_to_medge(bm, e, me, i, &result->edgeData){ - me++; - i++; - } - } - /*Make Faces*/ - if(totface){ - mface = CDDM_get_faces(result); - i=0; - for(f = bmeshIterator_init(faces, BM_FACES, bm, 0); f; f = bmeshIterator_step(faces)){ - mf = &mface[i]; - if(bmeshface_to_mface(bm, f, mf, i, &result->faceData)){ - loops_to_DMcorners(bm, &result->faceData, i, f, numCol, numTex); - i++; - } - } - } - BLI_edgehash_free(edge_hash, NULL); - return result; -} - -#endif