bmeshafied righthandfaces (ctrl-n, compute normals)
This commit is contained in:
@@ -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*));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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", "");
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user