brought back x-mirror editing, though it's currently buggy. also made tesselation face normals writable to disk.

This commit is contained in:
Joseph Eagar 2010-03-11 05:30:01 +00:00
parent b8b6fad640
commit d6158a4019
11 changed files with 205 additions and 45 deletions

View File

@ -57,6 +57,10 @@ typedef struct BMEditMesh {
/*Mesh structure this editmesh came from, if it came from one*/ /*Mesh structure this editmesh came from, if it came from one*/
struct Mesh *me; struct Mesh *me;
struct Object *ob; struct Object *ob;
/*temp variables for x-mirror editing*/
int mirror_cdlayer;
int mirr_free_arrays;
} BMEditMesh; } BMEditMesh;
void BMEdit_RecalcTesselation(BMEditMesh *tm); void BMEdit_RecalcTesselation(BMEditMesh *tm);

View File

@ -936,7 +936,7 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerSwap_mcol, layerDefault_mcol}, layerSwap_mcol, layerDefault_mcol},
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 3 floats per normal vector */ /* 3 floats per normal vector */
{sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(float)*3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL}, {sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL},
{sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL}, {sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL},

View File

@ -316,6 +316,7 @@ void BM_Data_Interp_From_Verts(struct BMesh *bm, struct BMVert *v1, struct BMVer
void BM_Data_Facevert_Edgeinterp(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, struct BMEdge *e1, float fac); void BM_Data_Facevert_Edgeinterp(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, struct BMEdge *e1, float fac);
//void bmesh_data_interp_from_face(struct BMesh *bm, struct BMFace *source, struct BMFace *target); //void bmesh_data_interp_from_face(struct BMesh *bm, struct BMFace *source, struct BMFace *target);
void BM_add_data_layer(BMesh *em, CustomData *data, int type); void BM_add_data_layer(BMesh *em, CustomData *data, int type);
void BM_add_data_layer_named(BMesh *bm, CustomData *data, int type, char *name);
void BM_free_data_layer(BMesh *em, CustomData *data, int type); void BM_free_data_layer(BMesh *em, CustomData *data, int type);

View File

@ -254,6 +254,18 @@ void BM_add_data_layer(BMesh *bm, CustomData *data, int type)
if (olddata.layers) MEM_freeN(olddata.layers); if (olddata.layers) MEM_freeN(olddata.layers);
} }
void BM_add_data_layer_named(BMesh *bm, CustomData *data, int type, char *name)
{
CustomData olddata;
olddata= *data;
olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name);
update_data_blocks(bm, &olddata, data);
if (olddata.layers) MEM_freeN(olddata.layers);
}
void BM_free_data_layer(BMesh *bm, CustomData *data, int type) void BM_free_data_layer(BMesh *bm, CustomData *data, int type)
{ {
CustomData olddata; CustomData olddata;

View File

@ -128,35 +128,14 @@ void BM_Select_Vert(BMesh *bm, BMVert *v, int select)
if (BM_TestHFlag(v, BM_SELECT)) bm->totvertsel -= 1; if (BM_TestHFlag(v, BM_SELECT)) bm->totvertsel -= 1;
BM_ClearHFlag(v, BM_SELECT); BM_ClearHFlag(v, BM_SELECT);
} }
/*BMESH_TODO hrm, not sure if flushing here is such a good idea. . .
but probably easier then calling a EDBM_Normalize_Selection after
each tool?*/
#if 0
BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
if (!BM_TestHFlag(e, BM_SELECT) && BM_TestHFlag(e->v1, BM_SELECT)
&& BM_TestHFlag(e->v2, BM_SELECT)) {
BM_SetHFlag(e, BM_SELECT);
bm->totedgesel += 1;
} else if (BM_TestHFlag(e, BM_SELECT) && (!BM_TestHFlag(e->v1, BM_SELECT)
|| !BM_TestHFlag(e->v2, BM_SELECT))) {
BM_ClearHFlag(e, BM_SELECT);
bm->totedgesel -= 1;
}
}
#endif
} }
/* /*
* BMESH SELECT EDGE * BMESH SELECT EDGE
* *
* Changes selection state of a single edge * Changes selection state of a single edge
* in a mesh. Note that this is actually not * in a mesh. Note that this may not be
* 100 percent reliable. Deselecting an edge * 100 percent reliable.
* will also deselect both its vertices
* regardless of the selection state of
* other edges incident upon it. Fixing this
* issue breaks multi-select mode though...
* *
*/ */
@ -165,7 +144,7 @@ void BM_Select_Edge(BMesh *bm, BMEdge *e, int select)
int candesel; int candesel;
int testiso = 1; int testiso = 1;
/*I might move this logic to bmeshutils_mods.c, where it'd be invoked /*I might move this logic to editors/mesh/bmesh_select.c, where it'd be invoked
by the selection tools. in that case, we'd still retain the checks by the selection tools. in that case, we'd still retain the checks
for if an edge's verts can be deselected.*/ for if an edge's verts can be deselected.*/

View File

@ -85,6 +85,28 @@ struct rcti;
/* bmeshutils.c */ /* bmeshutils.c */
/*x-mirror editing api. usage:
EDBM_CacheMirrorVerts(em);
...
...
BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
mirrorv = EDBM_GetMirrorVert(em, v);
}
...
...
EDBM_EndMirrorCache(em);
note: why do we only allow x axis mirror editing?
*/
void EDBM_CacheMirrorVerts(struct BMEditMesh *em);
/*retrieves mirrored cache vert, or NULL if there isn't one.
note: calling this without ensuring the mirror cache state
is bad.*/
struct BMVert *EDBM_GetMirrorVert(struct BMEditMesh *em, struct BMVert *v);
void EDBM_EndMirrorCache(struct BMEditMesh *em);
void EDBM_RecalcNormals(struct BMEditMesh *em); void EDBM_RecalcNormals(struct BMEditMesh *em);
void EDBM_MakeEditBMesh(struct ToolSettings *ts, struct Scene *scene, struct Object *ob); void EDBM_MakeEditBMesh(struct ToolSettings *ts, struct Scene *scene, struct Object *ob);

View File

@ -73,6 +73,8 @@
#include "BKE_report.h" #include "BKE_report.h"
#include "BKE_tessmesh.h" #include "BKE_tessmesh.h"
#include "bmesh.h"
#include "BIF_gl.h" #include "BIF_gl.h"
#include "BIF_glutil.h" #include "BIF_glutil.h"
@ -86,8 +88,8 @@
#include "UI_interface.h" #include "UI_interface.h"
#include "editbmesh_bvh.h"
#include "mesh_intern.h" #include "mesh_intern.h"
#include "bmesh.h"
void EDBM_RecalcNormals(BMEditMesh *em) void EDBM_RecalcNormals(BMEditMesh *em)
{ {
@ -805,3 +807,91 @@ int EDBM_vertColorCheck(BMEditMesh *em)
return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL); return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
} }
void EDBM_CacheMirrorVerts(BMEditMesh *em)
{
BMBVHTree *tree = BMBVH_NewBVH(em);
BMIter iter;
BMVert *v;
float invmat[4][4];
int li, i;
if (!em->vert_index) {
EDBM_init_index_arrays(em, 1, 0, 0);
em->mirr_free_arrays = 1;
}
if (!CustomData_get_layer_named(&em->bm->vdata, CD_PROP_INT, "__mirror_index")) {
BM_add_data_layer_named(em->bm, &em->bm->vdata, CD_PROP_INT, "__mirror_index");
}
li = CustomData_get_named_layer_index(&em->bm->vdata, CD_PROP_INT, "__mirror_index");
em->bm->vdata.layers[li].flag |= CD_FLAG_TEMPORARY;
/*multiply verts by object matrix, temporarily*/
i = 0;
BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
BMINDEX_SET(v, i);
i++;
if (em->ob)
mul_m4_v3(em->ob->obmat, v->co);
}
BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
BMVert *mirr;
int *idx = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, li);
float co[3] = {-v->co[0], v->co[1], v->co[2]};
//temporary for testing, check for selection
if (!BM_TestHFlag(v, BM_SELECT))
continue;
mirr = BMBVH_FindClosestVertTopo(tree, co, BM_SEARCH_MAXDIST, v);
if (mirr && mirr != v) {
*idx = BMINDEX_GET(mirr);
idx = CustomData_bmesh_get_layer_n(&em->bm->vdata,mirr->head.data, li);
*idx = BMINDEX_GET(v);
} else *idx = -1;
}
/*unmultiply by object matrix*/
if (em->ob) {
i = 0;
invert_m4_m4(invmat, em->ob->obmat);
BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
BMINDEX_SET(v, i);
i++;
mul_m4_v3(invmat, v->co);
}
BMBVH_FreeBVH(tree);
}
}
BMVert *EDBM_GetMirrorVert(BMEditMesh *em, BMVert *v)
{
int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
if (mirr && *mirr >=0 && *mirr < em->bm->totvert) {
if (!em->vert_index) {
printf("err: should only be called between "
"EDBM_CacheMirrorVerts and EDBM_EndMirrorCache");
return NULL;
}
return em->vert_index[*mirr];
}
return NULL;
}
void EDBM_EndMirrorCache(BMEditMesh *em)
{
if (em->mirr_free_arrays) {
MEM_freeN(em->vert_index);
em->vert_index = NULL;
}
}

View File

@ -325,7 +325,7 @@ static float topo_compare(BMesh *bm, BMVert *v1, BMVert *v2, int tag)
BLI_array_declare(stack2); BLI_array_declare(stack2);
float vec1[3], vec2[3], minangle=FLT_MAX, w; float vec1[3], vec2[3], minangle=FLT_MAX, w;
int lvl=1; int lvl=1;
static int maxlevel = 8; static int maxlevel = 3;
/*ok. see how similar v is to v2, based on topological similaritys in the local /*ok. see how similar v is to v2, based on topological similaritys in the local
topological neighborhood*/ topological neighborhood*/
@ -409,17 +409,65 @@ static float topo_compare(BMesh *bm, BMVert *v1, BMVert *v2, int tag)
if (!s1->curl) if (!s1->curl)
s1->curl = s1->cure->loop; s1->curl = s1->cure->loop;
if (!s2->curl) { if (!s2->curl) {
float no1[3], no2[3], angle;
int wind1, wind2; int wind1, wind2;
s2->curl = s2->cure->loop; s2->curl = s2->cure->loop;
/*find which of two possible faces to use*/ /*find which of two possible faces to use*/
wind1 = winding(s1->v->co, s1->lastv->co, l1 = BM_OtherFaceLoop(s1->curl->e, s1->curl->f, s1->lastv);
s1->v == s1->curl->v ? ((BMLoop*)s1->curl->head.prev->prev)->v->co : ((BMLoop*)s1->curl->head.next->next)->v->co); l2 = BM_OtherFaceLoop(s2->curl->e, s2->curl->f, s2->lastv);
wind2 = winding(s2->v->co, s2->lastv->co, if (l1->v == s2->lastv) {
s2->v == s2->curl->v ? ((BMLoop*)s2->curl->head.prev->prev)->v->co : ((BMLoop*)s2->curl->head.next->next)->v->co); l1 = (BMLoop*) l1->head.next;
if (l1->v == s2->v)
l1 = (BMLoop*) l1->head.prev->prev;
} else if (l1->v == s2->v) {
l1 = (BMLoop*) l1->head.next;
if (l1->v == s2->lastv)
l1 = (BMLoop*) l1->head.prev->prev;
}
if (l2->v == s2->lastv) {
l2 = (BMLoop*) l2->head.next;
if (l2->v == s2->v)
l2 = (BMLoop*) l2->head.prev->prev;
} else if (l2->v == s2->v) {
l2 = (BMLoop*) l2->head.next;
if (l2->v == s2->lastv)
l2 = (BMLoop*) l2->head.prev->prev;
}
wind1 = winding(s1->v->co, s1->lastv->co, l1->v->co);
wind2 = winding(s2->v->co, s2->lastv->co, l2->v->co);
/*if angle between the two adjacent faces is greater then 90 degrees,
we need to flip wind2*/
l1 = l2;
l2 = s2->curl->radial.next->data;
l2 = BM_OtherFaceLoop(l2->e, l2->f, s2->lastv);
if (l2->v == s2->lastv) {
l2 = (BMLoop*) l2->head.next;
if (l2->v == s2->v)
l2 = (BMLoop*) l2->head.prev->prev;
} else if (l2->v == s2->v) {
l2 = (BMLoop*) l2->head.next;
if (l2->v == s2->lastv)
l2 = (BMLoop*) l2->head.prev->prev;
}
normal_tri_v3(no1, s2->v->co, s2->lastv->co, l1->v->co);
normal_tri_v3(no2, s2->v->co, s2->lastv->co, l2->v->co);
/*enforce identical winding as no1*/
mul_v3_fl(no2, -1.0);
angle = angle_v3v3(no1, no2);
if (angle > M_PI/2 - FLT_EPSILON*2)
wind2 = !wind2;
if (wind1 == wind2) if (wind1 == wind2)
s2->curl = s2->curl->radial.next->data; s2->curl = s2->curl->radial.next->data;
} }
@ -444,10 +492,10 @@ static float topo_compare(BMesh *bm, BMVert *v1, BMVert *v2, int tag)
/*repush the current stack item*/ /*repush the current stack item*/
lvl++; lvl++;
if (maxlevel % 2 == 0) { //if (maxlevel % 2 == 0) {
BLI_ghash_insert(gh, v1, NULL); BLI_ghash_insert(gh, v1, NULL);
BLI_ghash_insert(gh, v2, NULL); BLI_ghash_insert(gh, v2, NULL);
} //}
/*now push the child node*/ /*now push the child node*/
SPUSH(stack1, lvl, v1, lastv1, e1); SPUSH(stack1, lvl, v1, lastv1, e1);
@ -565,17 +613,13 @@ BMVert *BMBVH_FindClosestVertTopo(BMBVHTree *tree, float *co, float maxdist, BMV
VECCOPY(hit.co, co); VECCOPY(hit.co, co);
VECCOPY(tree->co, co); VECCOPY(tree->co, co);
hit.index = -1; hit.index = -1;
hit.dist = 10.0f; hit.dist = maxdist;
tree->curw = FLT_MAX; tree->curw = FLT_MAX;
tree->curd = FLT_MAX; tree->curd = FLT_MAX;
tree->curv = NULL; tree->curv = NULL;
tree->curtag = 1; tree->curtag = 1;
BM_ITER(v, &iter, tree->bm, BM_VERTS_OF_MESH, NULL) {
BMINDEX_SET(v, 0);
}
tree->gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); tree->gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
tree->maxdist = maxdist; tree->maxdist = maxdist;

View File

@ -17,6 +17,8 @@ struct BMFace *BMBVH_RayCast(struct BMBVHTree *tree, float *co, float *dir, floa
int BMBVH_EdgeVisible(struct BMBVHTree *tree, struct BMEdge *e, int BMBVH_EdgeVisible(struct BMBVHTree *tree, struct BMEdge *e,
struct RegionView3D *r3d, struct Object *obedit); struct RegionView3D *r3d, struct Object *obedit);
#define BM_SEARCH_MAXDIST 0.4f
/*find a vert closest to co in a sphere of radius maxdist*/ /*find a vert closest to co in a sphere of radius maxdist*/
struct BMVert *BMBVH_FindClosestVert(struct BMBVHTree *tree, float *co, float maxdist); struct BMVert *BMBVH_FindClosestVert(struct BMBVHTree *tree, float *co, float maxdist);
struct BMVert *BMBVH_FindClosestVertTopo(struct BMBVHTree *tree, float *co, struct BMVert *BMBVH_FindClosestVertTopo(struct BMBVHTree *tree, float *co,

View File

@ -2167,6 +2167,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
if (t->flag & T_MIRROR) if (t->flag & T_MIRROR)
{ {
EDBM_CacheMirrorVerts(em);
mirror = 1; mirror = 1;
} }
@ -2359,12 +2360,12 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
/* Mirror? */ /* Mirror? */
//BMESH_TODO //BMESH_TODO
//if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) { if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
// BMVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, eve, tob->iloc, a); /* initializes octree on first call */ BMVert *vmir= EDBM_GetMirrorVert(em, eve); //t->obedit, em, eve, tob->iloc, a);
// if(vmir != eve) { if(vmir && vmir != eve) {
// tob->extra = vmir; tob->extra = vmir;
// } }
//} }
tob++; tob++;
} }
} }
@ -2390,6 +2391,12 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
MEM_freeN(defmats); MEM_freeN(defmats);
BLI_array_free(selstate); BLI_array_free(selstate);
if (t->flag & T_MIRROR)
{
EDBM_EndMirrorCache(em);
mirror = 1;
}
} }
/* *** NODE EDITOR *** */ /* *** NODE EDITOR *** */

View File

@ -250,7 +250,6 @@ static void editbmesh_apply_to_mirror(TransInfo *t)
{ {
TransData *td = t->data; TransData *td = t->data;
BMVert *eve; BMVert *eve;
BMIter iter;
int i; int i;
for(i = 0 ; i < t->total; i++, td++) { for(i = 0 ; i < t->total; i++, td++) {