back in selection history for bmesh->mesh and mesh->bmesh conversions: ---------------------------------------------- Select Vertex Path had wrong invoke callback (shouldn't have any?). Also selection history was not converted when doing bmesh->mesh or mesh->bmesh conversions. This meant that tabbing in and out of editmode would make your selection history dissapear. Undo pop would also not preserve selection history so any operators that relied on it would not work when you adjusted their settings.
833 lines
22 KiB
C
833 lines
22 KiB
C
#include <string.h>
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "DNA_listBase.h"
|
|
#include "DNA_customdata_types.h"
|
|
#include "DNA_mesh_types.h"
|
|
#include "DNA_meshdata_types.h"
|
|
#include "DNA_modifier_types.h"
|
|
#include "DNA_key_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "BKE_customdata.h"
|
|
#include "BKE_mesh.h"
|
|
#include "BKE_global.h"
|
|
#include "BKE_DerivedMesh.h"
|
|
#include "BKE_cdderivedmesh.h"
|
|
#include "BKE_key.h"
|
|
#include "BKE_main.h"
|
|
|
|
#include "BLI_utildefines.h"
|
|
#include "BLI_math.h"
|
|
#include "BLI_blenlib.h"
|
|
#include "BLI_edgehash.h"
|
|
#include "BLI_editVert.h"
|
|
#include "BLI_scanfill.h"
|
|
#include "BLI_array.h"
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "ED_mesh.h"
|
|
|
|
#include "mesh_intern.h"
|
|
#include "bmesh.h"
|
|
#include "bmesh_private.h"
|
|
|
|
/*
|
|
* MESH CONV.C
|
|
*
|
|
* This file contains functions
|
|
* for converting a Mesh
|
|
* into a Bmesh, and back again.
|
|
*
|
|
*/
|
|
|
|
void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
|
|
Object *ob = BMO_Get_Pnt(op, "object");
|
|
Mesh *me = BMO_Get_Pnt(op, "mesh");
|
|
MVert *mvert;
|
|
BLI_array_declare(verts);
|
|
MEdge *medge;
|
|
MLoop *ml;
|
|
MPoly *mpoly;
|
|
KeyBlock *actkey, *block;
|
|
BMVert *v, **vt=NULL, **verts = NULL;
|
|
BMEdge *e, **fedges=NULL, **et = NULL;
|
|
BMFace *f;
|
|
BLI_array_declare(fedges);
|
|
float (*keyco)[3]= NULL;
|
|
int *keyi;
|
|
int set_key = BMO_Get_Int(op, "set_shapekey");
|
|
int totuv, i, j, li, allocsize[4] = {512, 512, 2048, 512};
|
|
|
|
if (!me || !me->totvert) return; /*sanity check*/
|
|
|
|
mvert = me->mvert;
|
|
vt = MEM_mallocN(sizeof(void**)*me->totvert, "mesh to bmesh vtable");
|
|
|
|
CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
|
|
CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
|
|
CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
|
|
CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
|
|
|
|
/*make sure uv layer names are consistent*/
|
|
totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
|
|
for (i=0; i<totuv; i++) {
|
|
int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i);
|
|
CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
|
|
}
|
|
|
|
if (!CustomData_has_layer(&bm->edata, CD_CREASE))
|
|
CustomData_add_layer(&bm->edata, CD_CREASE, CD_ASSIGN, NULL, 0);
|
|
|
|
if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT))
|
|
CustomData_add_layer(&bm->edata, CD_BWEIGHT, CD_ASSIGN, NULL, 0);
|
|
|
|
if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT))
|
|
CustomData_add_layer(&bm->vdata, CD_BWEIGHT, CD_ASSIGN, NULL, 0);
|
|
|
|
|
|
if (me->key && ob->shapenr > me->key->totkey) {
|
|
ob->shapenr = me->key->totkey-1;
|
|
}
|
|
|
|
actkey = ob_get_keyblock(ob);
|
|
if(actkey && actkey->totelem == me->totvert) {
|
|
CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
|
|
|
|
/*check if we need to generate unique ids for the shapekeys.
|
|
this also exists in the file reading code, but is here for
|
|
a sanity check*/
|
|
if (!me->key->uidgen) {
|
|
printf("yeek! had to generate shape key uid's in a situation we shouldn't need to!\n");
|
|
me->key->uidgen = 1;
|
|
for (block=me->key->block.first; block; block=block->next) {
|
|
block->uid = me->key->uidgen++;
|
|
}
|
|
}
|
|
|
|
keyco= actkey->data;
|
|
bm->shapenr= ob->shapenr;
|
|
for (i=0, block=me->key->block.first; block; block=block->next, i++) {
|
|
CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY,
|
|
CD_ASSIGN, NULL, 0, block->name);
|
|
|
|
j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
|
|
bm->vdata.layers[j].uid = block->uid;
|
|
}
|
|
} else if (actkey) {
|
|
printf("shapekey<->mesh mismatch!\n");
|
|
}
|
|
|
|
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]);
|
|
|
|
for (i=0; i<me->totvert; i++, mvert++) {
|
|
v = BM_Make_Vert(bm, keyco&&set_key ? keyco[i] : mvert->co, NULL);
|
|
normal_short_to_float_v3(v->no, mvert->no);
|
|
|
|
vt[i] = v;
|
|
BM_SetIndex(v, i);
|
|
|
|
/*this is necassary for selection counts to work properly*/
|
|
if(v->head.flag & BM_SELECT) BM_Select_Vert(bm, v, 1);
|
|
|
|
/*transfer flags*/
|
|
v->head.flag = MEFlags_To_BMFlags(mvert->flag, BM_VERT);
|
|
BM_SetCDf(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f);
|
|
|
|
/*Copy Custom Data*/
|
|
CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
|
|
|
|
/*set shapekey data*/
|
|
if (me->key) {
|
|
/*set shape key original index*/
|
|
keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
|
|
*keyi = i;
|
|
|
|
for (block=me->key->block.first, j=0; block; block=block->next, j++) {
|
|
float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data,
|
|
CD_SHAPEKEY, j);
|
|
if (co)
|
|
VECCOPY(co, ((float*)block->data)+3*i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!me->totedge) {
|
|
MEM_freeN(vt);
|
|
return;
|
|
}
|
|
|
|
et = MEM_mallocN(sizeof(void**)*me->totedge, "mesh to bmesh etable");
|
|
|
|
medge = me->medge;
|
|
for (i=0; i<me->totedge; i++, medge++) {
|
|
e = BM_Make_Edge(bm, vt[medge->v1], vt[medge->v2], NULL, 0);
|
|
et[i] = e;
|
|
|
|
/*Copy Custom Data*/
|
|
CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data);
|
|
|
|
BM_SetCDf(&bm->edata, e, CD_CREASE, (float)medge->crease / 255.0f);
|
|
BM_SetCDf(&bm->edata, e, CD_BWEIGHT, (float)medge->bweight / 255.0f);
|
|
|
|
/*this is necassary for selection counts to work properly*/
|
|
if (e->head.flag & BM_SELECT) BM_Select(bm, e, 1);
|
|
|
|
/*transfer flags*/
|
|
e->head.flag = MEFlags_To_BMFlags(medge->flag, BM_EDGE);
|
|
}
|
|
|
|
if (!me->totpoly) {
|
|
MEM_freeN(vt);
|
|
MEM_freeN(et);
|
|
return;
|
|
}
|
|
|
|
mpoly = me->mpoly;
|
|
li = 0;
|
|
for (i=0; i<me->totpoly; i++, mpoly++) {
|
|
BMVert *v1, *v2;
|
|
BMIter iter;
|
|
BMLoop *l;
|
|
|
|
BLI_array_empty(fedges);
|
|
BLI_array_empty(verts);
|
|
for (j=0; j<mpoly->totloop; j++) {
|
|
ml = &me->mloop[mpoly->loopstart+j];
|
|
v = vt[ml->v];
|
|
e = et[ml->e];
|
|
|
|
BLI_array_growone(fedges);
|
|
BLI_array_growone(verts);
|
|
|
|
fedges[j] = e;
|
|
verts[j] = v;
|
|
}
|
|
|
|
v1 = vt[me->mloop[mpoly->loopstart].v];
|
|
v2 = vt[me->mloop[mpoly->loopstart+1].v];
|
|
|
|
if (v1 == fedges[0]->v1) v2 = fedges[0]->v2;
|
|
else {
|
|
v1 = fedges[0]->v2;
|
|
v2 = fedges[0]->v1;
|
|
}
|
|
|
|
f = BM_Make_Face(bm, verts, fedges, mpoly->totloop);
|
|
|
|
if (!f) {
|
|
printf("Warning! Bad face in mesh"
|
|
" \"%s\" at index %d!\n", me->id.name+2, i);
|
|
continue;
|
|
}
|
|
|
|
/*this is necassary for selection counts to work properly*/
|
|
if (f->head.flag & BM_SELECT) BM_Select(bm, f, 1);
|
|
|
|
/*transfer flags*/
|
|
f->head.flag = MEFlags_To_BMFlags(mpoly->flag, BM_FACE);
|
|
|
|
f->mat_nr = mpoly->mat_nr;
|
|
if (i == me->act_face) bm->act_face = f;
|
|
|
|
/*Copy over loop customdata*/
|
|
j = 0;
|
|
BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
|
|
CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart+j, &l->head.data);
|
|
li++;
|
|
j++;
|
|
}
|
|
|
|
/*Copy Custom Data*/
|
|
CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data);
|
|
}
|
|
|
|
{
|
|
BMIter iter;
|
|
BMVert *vertex;
|
|
BMEdge *edge;
|
|
BMFace *face;
|
|
BMVert **vertex_array = MEM_callocN(sizeof(BMVert *) * bm->totvert,
|
|
"Selection Conversion Vertex Pointer Array");
|
|
BMEdge **edge_array = MEM_callocN(sizeof(BMEdge *) * bm->totedge,
|
|
"Selection Conversion Edge Pointer Array");
|
|
BMFace **face_array = MEM_callocN(sizeof(BMFace *) * bm->totface,
|
|
"Selection Conversion Face Pointer Array");
|
|
|
|
for(i = 0, vertex = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
|
|
vertex; i++, vertex = BMIter_Step(&iter)){
|
|
vertex_array[i] = vertex;
|
|
}
|
|
|
|
for(i = 0, edge = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
|
|
edge; i++, edge = BMIter_Step(&iter)){
|
|
edge_array[i] = edge;
|
|
}
|
|
|
|
for(i = 0, face = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
|
|
face; i++, face = BMIter_Step(&iter)){
|
|
face_array[i] = face;
|
|
}
|
|
|
|
for(i = 0; i < me->totselect; i++){
|
|
if(me->mselect[i].type == ME_VSEL){
|
|
BM_store_selection(bm, vertex_array[me->mselect[i].index]);
|
|
}else if(me->mselect[i].type == ME_ESEL){
|
|
BM_store_selection(bm, edge_array[me->mselect[i].index]);
|
|
}else if(me->mselect[i].type == ME_FSEL){
|
|
BM_store_selection(bm, face_array[me->mselect[i].index]);
|
|
}
|
|
}
|
|
|
|
MEM_freeN(vertex_array);
|
|
MEM_freeN(edge_array);
|
|
MEM_freeN(face_array);
|
|
}
|
|
|
|
BLI_array_free(fedges);
|
|
BLI_array_free(verts);
|
|
|
|
MEM_freeN(vt);
|
|
MEM_freeN(et);
|
|
}
|
|
|
|
|
|
static void loops_to_corners(BMesh *bm, Mesh *me, int findex,
|
|
BMFace *f, BMLoop *ls[3], int numTex, int numCol)
|
|
{
|
|
BMLoop *l;
|
|
MTFace *texface;
|
|
MTexPoly *texpoly;
|
|
MCol *mcol;
|
|
MLoopCol *mloopcol;
|
|
MLoopUV *mloopuv;
|
|
int i, j;
|
|
|
|
for(i=0; i < numTex; i++){
|
|
texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
|
|
texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.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;
|
|
|
|
for (j=0; j<3; j++) {
|
|
l = ls[j];
|
|
mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
|
|
texface->uv[j][0] = mloopuv->uv[0];
|
|
texface->uv[j][1] = mloopuv->uv[1];
|
|
}
|
|
}
|
|
|
|
for(i=0; i < numCol; i++){
|
|
mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
|
|
|
|
for (j=0; j<3; j++) {
|
|
l = ls[j];
|
|
mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
|
|
mcol[j].r = mloopcol->r;
|
|
mcol[j].g = mloopcol->g;
|
|
mcol[j].b = mloopcol->b;
|
|
mcol[j].a = mloopcol->a;
|
|
}
|
|
}
|
|
}
|
|
|
|
void object_load_bmesh_exec(BMesh *bm, BMOperator *op) {
|
|
Object *ob = BMO_Get_Pnt(op, "object");
|
|
/* Scene *scene = BMO_Get_Pnt(op, "scene"); */
|
|
Mesh *me = ob->data;
|
|
|
|
BMO_CallOpf(bm, "bmesh_to_mesh mesh=%p object=%p", me, ob);
|
|
}
|
|
|
|
void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
|
|
Mesh *me = BMO_Get_Pnt(op, "mesh");
|
|
/* Object *ob = BMO_Get_Pnt(op, "object"); */
|
|
MLoop *mloop;
|
|
KeyBlock *block;
|
|
MPoly *mpoly;
|
|
MVert *mvert, *oldverts;
|
|
MEdge *medge;
|
|
MFace *mface;
|
|
BMVert *v, *eve;
|
|
BMEdge *e;
|
|
BMLoop *l;
|
|
BMFace *f;
|
|
BMIter iter, liter;
|
|
float *facenors = NULL;
|
|
int i, j, *keyi, ototvert, totloop, totface, numTex, numCol;
|
|
int dotess = !BMO_Get_Int(op, "notesselation");
|
|
|
|
numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
|
|
numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
|
|
|
|
ototvert = me->totvert;
|
|
|
|
/* new Vertex block */
|
|
if(bm->totvert==0) mvert= NULL;
|
|
else mvert= MEM_callocN(bm->totvert*sizeof(MVert), "loadeditbMesh vert");
|
|
|
|
/* new Edge block */
|
|
if(bm->totedge==0) medge= NULL;
|
|
else medge= MEM_callocN(bm->totedge*sizeof(MEdge), "loadeditbMesh edge");
|
|
|
|
/*build ngon data*/
|
|
/* new Ngon Face block */
|
|
if(bm->totface==0) mpoly = NULL;
|
|
else mpoly= MEM_callocN(bm->totface*sizeof(MPoly), "loadeditbMesh poly");
|
|
|
|
/*find number of loops to allocate*/
|
|
totloop = 0;
|
|
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
|
totloop += f->len;
|
|
}
|
|
|
|
if (totloop==0) mloop = NULL;
|
|
else mloop = MEM_callocN(totloop*sizeof(MLoop), "loadeditbMesh loop");
|
|
|
|
/* lets save the old verts just in case we are actually working on
|
|
* a key ... we now do processing of the keys at the end */
|
|
oldverts= me->mvert;
|
|
|
|
/* don't free this yet */
|
|
CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
|
|
|
|
/* free custom data */
|
|
CustomData_free(&me->vdata, me->totvert);
|
|
CustomData_free(&me->edata, me->totedge);
|
|
CustomData_free(&me->fdata, me->totface);
|
|
CustomData_free(&me->ldata, me->totloop);
|
|
CustomData_free(&me->pdata, me->totpoly);
|
|
|
|
/* add new custom data */
|
|
me->totvert= bm->totvert;
|
|
me->totedge= bm->totedge;
|
|
me->totloop= totloop;
|
|
me->totpoly= bm->totface;
|
|
|
|
CustomData_copy(&bm->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
|
|
CustomData_copy(&bm->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
|
|
CustomData_copy(&bm->ldata, &me->ldata, CD_MASK_MESH, CD_CALLOC, me->totloop);
|
|
CustomData_copy(&bm->pdata, &me->pdata, CD_MASK_MESH, CD_CALLOC, me->totpoly);
|
|
|
|
CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
|
|
CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
|
|
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
|
|
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
|
|
|
|
i = 0;
|
|
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
float *bweight = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BWEIGHT);
|
|
|
|
mvert->bweight = bweight ? (char)((*bweight)*255) : 0;
|
|
|
|
VECCOPY(mvert->co, v->co);
|
|
|
|
mvert->no[0] = (short) (v->no[0]*32767.0f);
|
|
mvert->no[1] = (short) (v->no[1]*32767.0f);
|
|
mvert->no[2] = (short) (v->no[2]*32767.0f);
|
|
|
|
mvert->flag = BMFlags_To_MEFlags(v);
|
|
|
|
BM_SetIndex(v, i);
|
|
|
|
/*copy over customdata*/
|
|
CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i);
|
|
|
|
i++;
|
|
mvert++;
|
|
|
|
CHECK_ELEMENT(bm, v);
|
|
}
|
|
|
|
i = 0;
|
|
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
|
float *crease = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE);
|
|
float *bweight = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT);
|
|
|
|
medge->v1 = BM_GetIndex(e->v1);
|
|
medge->v2 = BM_GetIndex(e->v2);
|
|
medge->crease = crease ? (char)((*crease)*255) : 0;
|
|
medge->bweight = bweight ? (char)((*bweight)*255) : 0;
|
|
|
|
medge->flag = BMFlags_To_MEFlags(e);
|
|
|
|
BM_SetIndex(e, i);
|
|
|
|
/*copy over customdata*/
|
|
CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i);
|
|
|
|
i++;
|
|
medge++;
|
|
CHECK_ELEMENT(bm, e);
|
|
}
|
|
|
|
/*new scanfill tesselation code*/
|
|
if (dotess) {
|
|
/*first counter number of faces we'll need*/
|
|
totface = 0;
|
|
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
|
EditVert *eve, *lasteve = NULL, *firsteve = NULL;
|
|
|
|
BLI_begin_edgefill();
|
|
i = 0;
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
|
|
eve = BLI_addfillvert(l->v->co);
|
|
eve->tmp.p = l;
|
|
|
|
BM_SetIndex(l, i);
|
|
|
|
if (lasteve) {
|
|
BLI_addfilledge(lasteve, eve);
|
|
}
|
|
|
|
lasteve = eve;
|
|
if (!firsteve) firsteve = eve;
|
|
|
|
i++;
|
|
}
|
|
|
|
BLI_addfilledge(lasteve, firsteve);
|
|
totface += BLI_edgefill(0);
|
|
|
|
BLI_end_edgefill();
|
|
}
|
|
|
|
me->totface = totface;
|
|
|
|
/* new tess face block */
|
|
if(totface==0) mface= NULL;
|
|
else {
|
|
mface= MEM_callocN(totface*sizeof(MFace), "loadeditbMesh face");
|
|
facenors = MEM_callocN(totface*sizeof(float)*3, "facenors");
|
|
}
|
|
|
|
CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
|
|
CustomData_add_layer(&me->fdata, CD_NORMAL, CD_ASSIGN, facenors, me->totface);
|
|
CustomData_from_bmeshpoly(&me->fdata, &bm->pdata, &bm->ldata, totface);
|
|
|
|
mesh_update_customdata_pointers(me);
|
|
|
|
i = 0;
|
|
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
|
EditVert *eve, *lasteve = NULL, *firsteve = NULL;
|
|
EditFace *efa;
|
|
BMLoop *ls[3];
|
|
|
|
BLI_begin_edgefill();
|
|
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
|
|
eve = BLI_addfillvert(l->v->co);
|
|
eve->tmp.p = l;
|
|
|
|
if (lasteve) {
|
|
BLI_addfilledge(lasteve, eve);
|
|
}
|
|
|
|
lasteve = eve;
|
|
if (!firsteve) firsteve = eve;
|
|
}
|
|
|
|
BLI_addfilledge(lasteve, firsteve);
|
|
BLI_edgefill(0);
|
|
|
|
for (efa=fillfacebase.first; efa; efa=efa->next) {
|
|
ls[0] = efa->v1->tmp.p;
|
|
ls[1] = efa->v2->tmp.p;
|
|
ls[2] = efa->v3->tmp.p;
|
|
|
|
/*ensure correct winding. I believe this is
|
|
analogous to bubble sort on three elements.*/
|
|
if (BM_GetIndex(ls[0]) > BM_GetIndex(ls[1])) {
|
|
SWAP(BMLoop*, ls[0], ls[1]);
|
|
}
|
|
if (BM_GetIndex(ls[1]) > BM_GetIndex(ls[2])) {
|
|
SWAP(BMLoop*, ls[1], ls[2]);
|
|
}
|
|
if (BM_GetIndex(ls[0]) > BM_GetIndex(ls[1])) {
|
|
SWAP(BMLoop*, ls[0], ls[1]);
|
|
}
|
|
|
|
mface->mat_nr = f->mat_nr;
|
|
mface->flag = BMFlags_To_MEFlags(f);
|
|
|
|
mface->v1 = BM_GetIndex(ls[0]->v);
|
|
mface->v2 = BM_GetIndex(ls[1]->v);
|
|
mface->v3 = BM_GetIndex(ls[2]->v);
|
|
|
|
test_index_face(mface, &me->fdata, i, 1);
|
|
|
|
loops_to_corners(bm, me, i, f, ls, numTex, numCol);
|
|
VECCOPY(facenors, ls[0]->f->no);
|
|
|
|
mface++;
|
|
facenors += 3;
|
|
i++;
|
|
}
|
|
BLI_end_edgefill();
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
j = 0;
|
|
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
|
mpoly->loopstart = j;
|
|
mpoly->totloop = f->len;
|
|
mpoly->mat_nr = f->mat_nr;
|
|
mpoly->flag = BMFlags_To_MEFlags(f);
|
|
|
|
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
|
|
for ( ; l; l=BMIter_Step(&liter), j++, mloop++) {
|
|
mloop->e = BM_GetIndex(l->e);
|
|
mloop->v = BM_GetIndex(l->v);
|
|
|
|
/*copy over customdata*/
|
|
CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l->head.data, j);
|
|
CHECK_ELEMENT(bm, l);
|
|
CHECK_ELEMENT(bm, l->e);
|
|
CHECK_ELEMENT(bm, l->v);
|
|
}
|
|
|
|
if (f == bm->act_face) me->act_face = i;
|
|
|
|
/*copy over customdata*/
|
|
CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i);
|
|
|
|
i++;
|
|
mpoly++;
|
|
CHECK_ELEMENT(bm, f);
|
|
}
|
|
|
|
/* patch hook indices and vertex parents */
|
|
{
|
|
Object *ob;
|
|
ModifierData *md;
|
|
BMVert **vertMap = NULL;
|
|
int i,j;
|
|
|
|
for (ob=G.main->object.first; ob; ob=ob->id.next) {
|
|
if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) {
|
|
|
|
/* duplicate code from below, make it function later...? */
|
|
if (!vertMap) {
|
|
vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
|
|
|
|
BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
|
|
if (*keyi != ORIGINDEX_NONE)
|
|
vertMap[*keyi] = eve;
|
|
}
|
|
}
|
|
if(ob->par1 < ototvert) {
|
|
eve = vertMap[ob->par1];
|
|
if(eve) ob->par1= BM_GetIndex(eve);
|
|
}
|
|
if(ob->par2 < ototvert) {
|
|
eve = vertMap[ob->par2];
|
|
if(eve) ob->par2= BM_GetIndex(eve);
|
|
}
|
|
if(ob->par3 < ototvert) {
|
|
eve = vertMap[ob->par3];
|
|
if(eve) ob->par3= BM_GetIndex(eve);
|
|
}
|
|
|
|
}
|
|
if (ob->data==me) {
|
|
for (md=ob->modifiers.first; md; md=md->next) {
|
|
if (md->type==eModifierType_Hook) {
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
if (!vertMap) {
|
|
vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
|
|
|
|
BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
|
|
if (*keyi != ORIGINDEX_NONE)
|
|
vertMap[*keyi] = eve;
|
|
}
|
|
}
|
|
|
|
for (i=j=0; i<hmd->totindex; i++) {
|
|
if(hmd->indexar[i] < ototvert) {
|
|
eve = vertMap[hmd->indexar[i]];
|
|
|
|
if (eve) {
|
|
hmd->indexar[j++] = BM_GetIndex(eve);
|
|
}
|
|
}
|
|
else j++;
|
|
}
|
|
|
|
hmd->totindex = j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (vertMap) MEM_freeN(vertMap);
|
|
}
|
|
|
|
mesh_update_customdata_pointers(me);
|
|
|
|
{
|
|
BMEditSelection *selected;
|
|
me->totselect = BLI_countlist(&(bm->selected));
|
|
|
|
me->mselect = MEM_callocN(sizeof(MSelect) * me->totselect, "Mesh selection history");
|
|
|
|
|
|
for(i = 0, selected = bm->selected.first; selected; i++, selected = selected->next){
|
|
if(selected->type == BM_VERT){
|
|
me->mselect[i].type = ME_VSEL;
|
|
|
|
}else if(selected->type == BM_EDGE){
|
|
me->mselect[i].type = ME_ESEL;
|
|
|
|
}else if(selected->type == BM_FACE){
|
|
me->mselect[i].type = ME_FSEL;
|
|
}
|
|
|
|
me->mselect[i].index = BM_GetIndex(selected->data);
|
|
}
|
|
}
|
|
|
|
if (me->key) {
|
|
KeyBlock *actkey= BLI_findlink(&me->key->block, bm->shapenr-1);
|
|
|
|
/*go through and find any shapekey customdata layers
|
|
that might not have corrusponding KeyBlocks, and add them if
|
|
necassary.*/
|
|
j = 0;
|
|
for (i=0; i<bm->vdata.totlayer; i++) {
|
|
if (bm->vdata.layers[i].type != CD_SHAPEKEY)
|
|
continue;
|
|
|
|
for (block=me->key->block.first; block; block=block->next) {
|
|
if (block->uid == bm->vdata.layers[i].uid)
|
|
break;
|
|
}
|
|
|
|
if (!block) {
|
|
block = MEM_callocN(sizeof(KeyBlock), "KeyBlock mesh_conv.c");
|
|
block->type = KEY_LINEAR;
|
|
block->slidermin = 0.0f;
|
|
block->slidermax = 1.0f;
|
|
|
|
BLI_addtail(&me->key->block, block);
|
|
me->key->totkey++;
|
|
}
|
|
|
|
j++;
|
|
}
|
|
|
|
for (block=me->key->block.first; block; block=block->next) {
|
|
j = 0;
|
|
|
|
for (i=0; i<bm->vdata.totlayer; i++) {
|
|
if (bm->vdata.layers[i].type != CD_SHAPEKEY)
|
|
continue;
|
|
|
|
if (block->uid == bm->vdata.layers[i].uid) {
|
|
float *fp, *co;
|
|
|
|
if (block->data)
|
|
MEM_freeN(block->data);
|
|
block->data = fp = MEM_mallocN(sizeof(float)*3*bm->totvert, "shape key data");
|
|
block->totelem = bm->totvert;
|
|
|
|
BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
co = block==actkey ? eve->co : CustomData_bmesh_get_n(&bm->vdata, eve->head.data, CD_SHAPEKEY, j);
|
|
|
|
VECCOPY(fp, co);
|
|
fp += 3;
|
|
}
|
|
break;
|
|
}
|
|
|
|
j++;
|
|
}
|
|
|
|
/*if we didn't find a shapekey, tag the block to be reconstructed
|
|
via the old method below*/
|
|
if (j == CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY)) {
|
|
block->flag |= KEYBLOCK_MISSING;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* old method of reconstructing keys via vertice's original key indices,
|
|
currently used if the new method above fails (which is theoretically
|
|
possible in certain cases of undo).*/
|
|
if(me->key) {
|
|
float *fp, *newkey, *oldkey;
|
|
KeyBlock *currkey;
|
|
KeyBlock *actkey= BLI_findlink(&me->key->block, bm->shapenr-1);
|
|
|
|
/* Lets reorder the key data so that things line up roughly
|
|
* with the way things were before editmode */
|
|
currkey = me->key->block.first;
|
|
while(currkey) {
|
|
if (!(currkey->flag & KEYBLOCK_MISSING)) {
|
|
currkey = currkey->next;
|
|
continue;
|
|
}
|
|
|
|
printf("warning: had to hackishly reconstruct shape key \"%s\","
|
|
" it may not be correct anymore.\n", currkey->name);
|
|
|
|
currkey->flag &= ~KEYBLOCK_MISSING;
|
|
|
|
fp= newkey= MEM_callocN(me->key->elemsize*bm->totvert, "currkey->data");
|
|
oldkey = currkey->data;
|
|
|
|
eve= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
|
|
|
|
i = 0;
|
|
mvert = me->mvert;
|
|
while(eve) {
|
|
keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
|
|
if (*keyi >= 0 && *keyi < currkey->totelem) { // valid old vertex
|
|
if(currkey == actkey) {
|
|
if(actkey == me->key->refkey) {
|
|
VECCOPY(fp, mvert->co);
|
|
}
|
|
else {
|
|
VECCOPY(fp, mvert->co);
|
|
if(oldverts) {
|
|
VECCOPY(mvert->co, oldverts[*keyi].co);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if(oldkey) {
|
|
VECCOPY(fp, oldkey + 3 * *keyi);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
VECCOPY(fp, mvert->co);
|
|
}
|
|
fp+= 3;
|
|
++i;
|
|
++mvert;
|
|
eve= BMIter_Step(&iter);
|
|
}
|
|
currkey->totelem= bm->totvert;
|
|
if(currkey->data) MEM_freeN(currkey->data);
|
|
currkey->data = newkey;
|
|
|
|
currkey= currkey->next;
|
|
}
|
|
}
|
|
|
|
if(oldverts) MEM_freeN(oldverts);
|
|
}
|