remove files no longer used since bmesh merge.

This commit is contained in:
Campbell Barton 2012-02-19 19:27:06 +00:00
parent b2956ecd00
commit b1a3d3cea1
10 changed files with 0 additions and 5790 deletions

@ -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

@ -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 <string.h>
#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

@ -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

@ -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;i<len;i++) elist[i]->eflag1=elist[i]->eflag2 = 0;
for(i=0;i<len;i++){
elist[i]->eflag1 |= 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; i<len; i++){
edok = BME_disk_count_edgeflag(elist[i]->v1, 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; i<len; i++){
if((elist[i]->eflag1 & 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;i<len;i++){
curvert = vlist[i];
l = BME_create_loop(bm,curvert,NULL,f,NULL);
if(!(f->loopbase)) f->lbase = l;
BME_cycle_append(f->lbase, l);
}
/*take care of edge pointers and radial cycle*/
for(i=0, l = f->loopbase; i<len; i++, l=l->next){
e = NULL;
if(l == f->loopbase) e = elist[0]; /*first edge*/
else{/*search elist for others*/
for(j=1; j<len; j++){
edok = BME_verts_in_edge(l->v, 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; i<len; i++, l=l->next){
/*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; i<radlen; i++, killoop = BME_radial_nextloop(killoop)){
/*relink loops and fix vertex pointer*/
killoop->next->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(i<radlen){
bm->lpar[i] = killoop;
killoop = killoop->radial_next;
i++;
}
i=0;
while(i<radlen){
BME_free_loop(bm,bm->lpar[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; i<radlen; i++, nextl = BME_radial_nextloop(nextl)){
edok = BME_cycle_validate(nextl->f->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

@ -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

@ -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 <limits.h>
#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; i<len; i++){
if(tflag){
if(curedge->tflag1 == 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; i<len; i++){
if(curedge == e) return 1;
else curedge=BME_disk_nextedge(curedge, v);
}
}
return 0;
}
/*end disk cycle routines*/
BME_Loop *BME_radial_nextloop(BME_Loop *l){
return (BME_Loop*)(l->radial_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

File diff suppressed because it is too large Load Diff

@ -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

File diff suppressed because it is too large Load Diff

@ -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