bmeshafied righthandfaces (ctrl-n, compute normals)

This commit is contained in:
2009-08-06 08:23:10 +00:00
parent 88b43b52b1
commit 416a3bf4a1
6 changed files with 250 additions and 72 deletions

View File

@@ -61,9 +61,20 @@ next to them, e.g.
the doc generator would automatically detect the presence of "output slot"
and flag the slot as an output. the same happens for "input slot". also
note that "edges", "faces", "verts", "loops", and "geometry" are valid
substitutions for "slot".
substitutions for "slot".
note that slots default to being input slots.
*/
BMOpDefine def_righthandfaces = {
"righthandfaces",
{{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
{0} /*null-terminating sentinel*/,
},
bmesh_righthandfaces_exec,
0
};
/*
Region Extend
@@ -156,60 +167,89 @@ BMOpDefine def_mirror = {
0,
};
/*
Find Doubles
Takes input verts and find vertices they should weld to. Outputs a
mapping slot suitable for use with the weld verts bmop.
*/
BMOpDefine def_finddoubles = {
"finddoubles",
/*maps welded vertices to verts they should weld to.*/
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
//list of verts to keep
{BMOP_OPSLOT_ELEMENT_BUF, "keepverts"},
{BMOP_OPSLOT_FLT, "dist"},
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
{BMOP_OPSLOT_ELEMENT_BUF, "keepverts"}, //list of verts to keep
{BMOP_OPSLOT_FLT, "dist"}, //minimum distance
{BMOP_OPSLOT_MAPPING, "targetmapout"},
{0, /*null-terminating sentinel*/}},
bmesh_finddoubles_exec,
0,
};
/*
Remove Doubles
Finds groups of vertices closer then dist and merges them together,
using the weld verts bmop.
*/
BMOpDefine def_removedoubles = {
"removedoubles",
/*maps welded vertices to verts they should weld to.*/
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
{BMOP_OPSLOT_FLT, "dist"},
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input verts
{BMOP_OPSLOT_FLT, "dist"}, //minimum distance
{0, /*null-terminating sentinel*/}},
bmesh_removedoubles_exec,
0,
};
/*
Weld Verts
Welds verts together (kindof like remove doubles, merge, etc, all of which
use or will use this bmop). You pass in mappings from vertices to the vertices
they weld with.
*/
BMOpDefine def_weldverts = {
"weldverts",
/*maps welded vertices to verts they should weld to.*/
{{BMOP_OPSLOT_MAPPING, "targetmap"},
{{BMOP_OPSLOT_MAPPING, "targetmap"}, /*maps welded vertices to verts they should weld to.*/
{0, /*null-terminating sentinel*/}},
bmesh_weldverts_exec,
0,
};
/*
Make Vertex
Creates a single vertex; this bmop was necassary
for click-create-vertex.
*/
BMOpDefine def_makevert = {
"makevert",
{{BMOP_OPSLOT_VEC, "co"},
{BMOP_OPSLOT_ELEMENT_BUF, "newvertout"},
{{BMOP_OPSLOT_VEC, "co"}, //the coordinate of the new vert
{BMOP_OPSLOT_ELEMENT_BUF, "newvertout"}, //the new vert
{0, /*null-terminating sentinel*/}},
bmesh_makevert_exec,
0,
};
/*contextual_create is fkey, it creates
new faces, makes stuff from edge nets,
makes wire edges, etc. it also dissolves
faces.*/
/*
Contextual Create
This is basically fkey, it creates
new faces from vertices, makes stuff from edge nets,
makes wire edges, etc. It also dissolves
faces.
Three verts become a triangle, four become a quad. Two
become a wire edge.
*/
BMOpDefine def_contextual_create= {
"contextual_create",
{{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
{BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
{{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, //input geometry.
{BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, //newly-made face(s)
{0, /*null-terminating sentinel*/}},
bmesh_contextual_create_exec,
0,
};
/*this may be unimplemented*/
BMOpDefine def_edgenet_fill= {
"edgenet_fill",
{{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
@@ -219,37 +259,59 @@ BMOpDefine def_edgenet_fill= {
0,
};
/*
Rotate
Rotate vertices around a center, using a 3x3 rotation
matrix. Equivilent of the old rotateflag function.
*/
BMOpDefine def_rotate = {
"rotate",
{{BMOP_OPSLOT_VEC, "cent"},
{BMOP_OPSLOT_MAT, "mat"},
{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
{{BMOP_OPSLOT_VEC, "cent"}, //center of rotation
{BMOP_OPSLOT_MAT, "mat"}, //matrix defining rotation
{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
{0, /*null-terminating sentinel*/}},
bmesh_rotate_exec,
0,
};
/*
Translate
Translate vertices by an offset. Equivelent of the
old translateflag function.
*/
BMOpDefine def_translate= {
"translate",
{{BMOP_OPSLOT_VEC, "vec"},
{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
{{BMOP_OPSLOT_VEC, "vec"}, //translation offset
{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
{0, /*null-terminating sentinel*/}},
bmesh_translate_exec,
0,
};
/*applies a transform to vertices*/
/*
Transform
Transforms a set of vertices by a matrix. Multiplies
the vertex coordinates with the matrix.
*/
BMOpDefine def_transform = {
"transform",
{{BMOP_OPSLOT_MAT, "mat"},
{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
{{BMOP_OPSLOT_MAT, "mat"}, //transform matrix
{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
{0, /*null-terminating sentinel*/}},
bmesh_transform_exec,
0,
};
/*loads a bmesh into an object*/
/*
Object Load BMesh
Loads a bmesh into an object/mesh. This is a "private"
bmop.
*/
BMOpDefine def_object_load_bmesh = {
"object_load_bmesh",
{{BMOP_OPSLOT_PNT, "scene"},
@@ -260,19 +322,29 @@ BMOpDefine def_object_load_bmesh = {
};
/*
Mesh to BMesh
Load the contents of a mesh into the bmesh.
*/
BMOpDefine def_mesh_to_bmesh = {
"mesh_to_bmesh",
{{BMOP_OPSLOT_PNT, "mesh"},
{{BMOP_OPSLOT_PNT, "mesh"}, //pointer to a Mesh structure
{0, /*null-terminating sentinel*/}},
mesh_to_bmesh_exec,
0
};
/*
Individual Vertex Extrude
Extrudes wire edges from vertices.
*/
BMOpDefine def_extrudeverts_indiv = {
"extrude_vert_indiv",
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
{BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
{BMOP_OPSLOT_ELEMENT_BUF, "vertout"},
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
{BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, //output wire edges
{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output vertices
{0} /*null-terminating sentinel*/},
extrude_vert_indiv_exec,
0
@@ -474,6 +546,7 @@ BMOpDefine *opdefines[] = {
&def_reversefaces,
&def_edgerotate,
&def_regionextend,
&def_righthandfaces,
};
int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));

View File

@@ -39,5 +39,6 @@ void esplit_exec(BMesh *bm, BMOperator *op);
void bmesh_reversefaces_exec(BMesh *bm, BMOperator *op);
void bmesh_edgerotate_exec(BMesh *bm, BMOperator *op);
void bmesh_regionextend_exec(BMesh *bm, BMOperator *op);
void bmesh_righthandfaces_exec(BMesh *bm, BMOperator *op);
#endif

View File

@@ -483,6 +483,7 @@ void bmesh_update_face_normal(BMesh *bm, BMFace *f, float (*projectverts)[3])
void BM_flip_normal(BMesh *bm, BMFace *f)
{
bmesh_loop_reverse(bm, f);
BM_Face_UpdateNormal(bm, f);
}
/* detects if two line segments cross each other (intersects).

View File

@@ -209,4 +209,111 @@ void bmesh_regionextend_exec(BMesh *bm, BMOperator *op)
bmesh_regionextend_extend(bm, op, usefaces);
BMO_Flag_To_Slot(bm, op, "geomout", SEL_FLAG, BM_ALL);
}
}
/********* righthand faces implementation ********/
#define FACE_VIS 1
#define FACE_FLAG 2
#define FACE_MARK 4
/* NOTE: these are the original righthandfaces comment in editmesh_mods.c,
copied here for reference.
*/
/* based at a select-connected to witness loose objects */
/* count per edge the amount of faces */
/* find the ultimate left, front, upper face (not manhattan dist!!) */
/* also evaluate both triangle cases in quad, since these can be non-flat */
/* put normal to the outside, and set the first direction flags in edges */
/* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
/* this is in fact the 'select connected' */
/* in case (selected) faces were not done: start over with 'find the ultimate ...' */
/*note: this function uses recursion, which is a little unusual for a bmop
function, but acceptable I think.*/
void bmesh_righthandfaces_exec(BMesh *bm, BMOperator *op)
{
BMIter liter, liter2;
BMOIter siter;
BMFace *f, *startf, **fstack = NULL;
V_DECLARE(fstack);
BMLoop *l, *l2;
float maxx, cent[3];
int i, maxi;
startf= NULL;
maxx= -1.0e10;
BMO_Flag_Buffer(bm, op, "faces", FACE_FLAG);
/*find a starting face*/
BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
if (BMO_TestFlag(bm, f, FACE_VIS))
continue;
if (!startf) startf = f;
BM_Compute_Face_Center(bm, f, cent);
cent[0] = cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
if (cent[0] > maxx) {
maxx = cent[0];
startf = f;
}
}
if (!startf) return;
BM_Compute_Face_Center(bm, startf, cent);
if (cent[0]*startf->no[0] + cent[1]*startf->no[1] + cent[2]*startf->no[2] < 0.0)
BM_flip_normal(bm, startf);
V_GROW(fstack);
fstack[0] = startf;
BMO_SetFlag(bm, startf, FACE_VIS);
i = 0;
maxi = 1;
while (i >= 0) {
f = fstack[i];
i--;
BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_LOOP, l) {
if (!BMO_TestFlag(bm, l2->f, FACE_FLAG) || l2 == l)
continue;
if (!BMO_TestFlag(bm, l2->f, FACE_VIS)) {
BMO_SetFlag(bm, l2->f, FACE_VIS);
i++;
if (l2->v == l->v)
BM_flip_normal(bm, l2->f);
if (i == maxi) {
V_GROW(fstack);
maxi++;
}
fstack[i] = l2->f;
}
}
}
}
V_FREE(fstack);
/*check if we have faces yet to do. if so, recurse.*/
BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
if (!BMO_TestFlag(bm, f, FACE_VIS)) {
bmesh_righthandfaces_exec(bm, op);
break;
}
}
}

View File

@@ -1655,3 +1655,38 @@ void MESH_OT_reveal(wmOperatorType *ot)
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int normals_make_consistent_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
if (!EDBM_CallOpf(em, op, "righthandfaces faces=%hf", BM_SELECT))
return OPERATOR_CANCELLED;
if (RNA_boolean_get(op->ptr, "inside"))
EDBM_CallOpf(em, op, "reversefaces faces=%hf", BM_SELECT);
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); //TODO is this needed ?
return OPERATOR_FINISHED;
}
void MESH_OT_normals_make_consistent(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Make Normals Consistent";
ot->idname= "MESH_OT_normals_make_consistent";
/* api callbacks */
ot->exec= normals_make_consistent_exec;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
}

View File

@@ -2700,46 +2700,7 @@ void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning *
waitcursor(0);
}
static int righthandfaces_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
/* 'standard' behaviour - check if selected, then apply relevant selection */
// XXX need other args
righthandfaces(em, RNA_boolean_get(op->ptr, "inside"));
BKE_mesh_end_editmesh(obedit->data, em);
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); //TODO is this needed ?
return OPERATOR_FINISHED;
}
void MESH_OT_normals_make_consistent(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Make Normals Consistent";
ot->idname= "MESH_OT_normals_make_consistent";
/* api callbacks */
ot->exec= righthandfaces_exec;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
}
/* ********** ALIGN WITH VIEW **************** */
static void editmesh_calc_selvert_center(EditMesh *em, float cent_r[3])
{
EditVert *eve;