This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/bmesh/intern/in-progress/BME_conversions.c

485 lines
13 KiB
C

#if 0
/**
* BME_conversions.c August 2008
*
* BM to Derived Mesh conversion 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2007 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Geoffrey Bantle, Levi Schooley.
*
* ***** END GPL 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