forked from bartvdbraak/blender
remove files no longer used since bmesh merge.
This commit is contained in:
parent
b2956ecd00
commit
b1a3d3cea1
@ -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
|
Loading…
Reference in New Issue
Block a user