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*/
struct Mesh *me;
struct Object *ob;
/*temp variables for x-mirror editing*/
int mirror_cdlayer;
int mirr_free_arrays;
} BMEditMesh;
void BMEdit_RecalcTesselation(BMEditMesh *tm);

View File

@ -936,7 +936,7 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerSwap_mcol, layerDefault_mcol},
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 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(MFloatProperty), "MFloatProperty",1,"Float",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 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_named(BMesh *bm, CustomData *data, int type, char *name);
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);
}
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)
{
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;
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
*
* Changes selection state of a single edge
* in a mesh. Note that this is actually not
* 100 percent reliable. Deselecting an edge
* 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...
* in a mesh. Note that this may not be
* 100 percent reliable.
*
*/
@ -165,7 +144,7 @@ void BM_Select_Edge(BMesh *bm, BMEdge *e, int select)
int candesel;
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
for if an edge's verts can be deselected.*/

View File

@ -85,6 +85,28 @@ struct rcti;
/* 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_MakeEditBMesh(struct ToolSettings *ts, struct Scene *scene, struct Object *ob);

View File

@ -73,6 +73,8 @@
#include "BKE_report.h"
#include "BKE_tessmesh.h"
#include "bmesh.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@ -86,8 +88,8 @@
#include "UI_interface.h"
#include "editbmesh_bvh.h"
#include "mesh_intern.h"
#include "bmesh.h"
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);
}
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);
float vec1[3], vec2[3], minangle=FLT_MAX, w;
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
topological neighborhood*/
@ -409,17 +409,65 @@ static float topo_compare(BMesh *bm, BMVert *v1, BMVert *v2, int tag)
if (!s1->curl)
s1->curl = s1->cure->loop;
if (!s2->curl) {
float no1[3], no2[3], angle;
int wind1, wind2;
s2->curl = s2->cure->loop;
/*find which of two possible faces to use*/
wind1 = winding(s1->v->co, s1->lastv->co,
s1->v == s1->curl->v ? ((BMLoop*)s1->curl->head.prev->prev)->v->co : ((BMLoop*)s1->curl->head.next->next)->v->co);
l1 = BM_OtherFaceLoop(s1->curl->e, s1->curl->f, s1->lastv);
l2 = BM_OtherFaceLoop(s2->curl->e, s2->curl->f, s2->lastv);
wind2 = winding(s2->v->co, s2->lastv->co,
s2->v == s2->curl->v ? ((BMLoop*)s2->curl->head.prev->prev)->v->co : ((BMLoop*)s2->curl->head.next->next)->v->co);
if (l1->v == s2->lastv) {
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)
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*/
lvl++;
if (maxlevel % 2 == 0) {
//if (maxlevel % 2 == 0) {
BLI_ghash_insert(gh, v1, NULL);
BLI_ghash_insert(gh, v2, NULL);
}
//}
/*now push the child node*/
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(tree->co, co);
hit.index = -1;
hit.dist = 10.0f;
hit.dist = maxdist;
tree->curw = FLT_MAX;
tree->curd = FLT_MAX;
tree->curv = NULL;
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->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,
struct RegionView3D *r3d, struct Object *obedit);
#define BM_SEARCH_MAXDIST 0.4f
/*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_FindClosestVertTopo(struct BMBVHTree *tree, float *co,

View File

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

View File

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