diff options
45 files changed, 724 insertions, 51 deletions
diff --git a/release/scripts/freestyle/style_modules/parameter_editor.py b/release/scripts/freestyle/style_modules/parameter_editor.py index 1099618e4d1..68ba077277e 100644 --- a/release/scripts/freestyle/style_modules/parameter_editor.py +++ b/release/scripts/freestyle/style_modules/parameter_editor.py @@ -752,6 +752,32 @@ class LengthThresholdUP1D(UnaryPredicate1D): return False return True +class FaceMarkBothUP1D(UnaryPredicate1D): + def __call__(self, inter): # ViewEdge + fe = inter.fedgeA() + while fe is not None: + if fe.isSmooth(): + if fe.faceMark(): + return True + else: + if fe.aFaceMark() and fe.bFaceMark(): + return True + fe = fe.nextEdge() + return False + +class FaceMarkOneUP1D(UnaryPredicate1D): + def __call__(self, inter): # ViewEdge + fe = inter.fedgeA() + while fe is not None: + if fe.isSmooth(): + if fe.faceMark(): + return True + else: + if fe.aFaceMark() or fe.bFaceMark(): + return True + fe = fe.nextEdge() + return False + # predicates for splitting class MaterialBoundaryUP0D(UnaryPredicate0D): @@ -825,6 +851,8 @@ def process(layer_name, lineset_name): flags |= Nature.SUGGESTIVE_CONTOUR if lineset.select_material_boundary: flags |= Nature.MATERIAL_BOUNDARY + if lineset.select_edge_mark: + flags |= Nature.EDGE_MARK if flags != Nature.NO_FEATURE: edge_type_criteria.append(pyNatureUP1D(flags)) else: @@ -842,6 +870,8 @@ def process(layer_name, lineset_name): edge_type_criteria.append(pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR)) if lineset.select_material_boundary: edge_type_criteria.append(pyNatureUP1D(Nature.MATERIAL_BOUNDARY)) + if lineset.select_edge_mark: + edge_type_criteria.append(pyNatureUP1D(Nature.EDGE_MARK)) if lineset.select_contour: edge_type_criteria.append(ContourUP1D()) if lineset.select_external_contour: @@ -854,6 +884,15 @@ def process(layer_name, lineset_name): if lineset.edge_type_negation == "EXCLUSIVE": upred = NotUP1D(upred) selection_criteria.append(upred) + # prepare selection criteria by face marks + if lineset.select_by_face_marks: + if lineset.face_mark_condition == "BOTH": + upred = FaceMarkBothUP1D() + else: + upred = FaceMarkOneUP1D() + if lineset.face_mark_negation == "EXCLUSIVE": + upred = NotUP1D(upred) + selection_criteria.append(upred) # prepare selection criteria by group of objects if lineset.select_by_group: if lineset.group is not None and len(lineset.group.objects) > 0: diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 57b5c9d848a..f8750a01374 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -253,11 +253,20 @@ class RENDER_PT_freestyle(RenderButtonsPanel, Panel): sub.prop(lineset, "select_valley") sub.prop(lineset, "select_suggestive_contour") sub.prop(lineset, "select_material_boundary") + sub.prop(lineset, "select_edge_mark") sub = row.column() sub.prop(lineset, "select_contour") sub.prop(lineset, "select_external_contour") col.separator() # XXX + col.prop(lineset, "select_by_face_marks") + if lineset.select_by_face_marks: + row = col.row() + row.prop(lineset, "face_mark_negation", expand=True) + row = col.row() + row.prop(lineset, "face_mark_condition", expand=True) + col.separator() # XXX + col.prop(lineset, "select_by_group") if lineset.select_by_group: col.prop(lineset, "group") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index f9e42862b9c..be3be6f594d 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1605,6 +1605,11 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.separator() + layout.operator("mesh.mark_freestyle_edge") + layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True + + layout.separator() + layout.operator("mesh.edge_rotate", text="Rotate Edge CW").direction = 'CW' layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").direction = 'CCW' @@ -1647,6 +1652,11 @@ class VIEW3D_MT_edit_mesh_faces(Menu): layout.separator() + layout.operator("mesh.mark_freestyle_face") + layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True + + layout.separator() + layout.operator("mesh.quads_convert_to_tris") layout.operator("mesh.tris_convert_to_quads") layout.operator("mesh.edge_flip") @@ -2170,6 +2180,8 @@ class VIEW3D_PT_view3d_meshdisplay(Panel): col.prop(mesh, "show_edge_bevel_weight", text="Bevel Weights") col.prop(mesh, "show_edge_seams", text="Seams") col.prop(mesh, "show_edge_sharp", text="Sharp") + col.prop(mesh, "show_freestyle_edge_marks", text="Freestyle Edge Marks") + col.prop(mesh, "show_freestyle_face_marks", text="Freestyle Face Marks") col.separator() col.label(text="Normals:") diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c index 4f83d25409a..2aff2b78b72 100644 --- a/source/blender/blenkernel/intern/BME_conversions.c +++ b/source/blender/blenkernel/intern/BME_conversions.c @@ -303,6 +303,7 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { e->flag = eed->f & SELECT; if(eed->sharp) e->flag |= ME_SHARP; if(eed->seam) e->flag |= ME_SEAM; + if(eed->freestyle) e->flag |= ME_FREESTYLE_EDGE; //XXX if(eed->h & EM_FGON) e->flag |= ME_FGON; if(eed->h & 1) e->flag |= ME_HIDE; eed->tmp.e = (EditEdge*)e; @@ -395,6 +396,7 @@ void BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td, EditMesh *em) { eed->bweight = e->bweight; if(e->flag & ME_SEAM) eed->seam = 1; if(e->flag & ME_SHARP) eed->sharp = 1; + if(e->flag & ME_FREESTYLE_EDGE) eed->freestyle = 1; if(e->flag & SELECT) eed->f |= SELECT; //XXX if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! if(e->flag & ME_HIDE) eed->h |= 1; diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 5e462238f31..e3440e183e3 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1199,6 +1199,7 @@ static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r) edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER; if (ee->seam) edge_r->flag |= ME_SEAM; if (ee->sharp) edge_r->flag |= ME_SHARP; + if (ee->freestyle) edge_r->flag |= ME_FREESTYLE_EDGE; #if 0 /* this needs setup of f2 field */ if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE; @@ -1299,6 +1300,7 @@ static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER; if (ee->seam) edge_r->flag |= ME_SEAM; if (ee->sharp) edge_r->flag |= ME_SHARP; + if (ee->freestyle) edge_r->flag |= ME_FREESTYLE_EDGE; #if 0 /* this needs setup of f2 field */ if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE; diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 707bf95f9c3..bf462868271 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1651,6 +1651,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) if(eed->seam) med->flag |= ME_SEAM; if(eed->sharp) med->flag |= ME_SHARP; + if(eed->freestyle) med->flag |= ME_FREESTYLE_EDGE; if(!eed->f2) med->flag |= ME_LOOSEEDGE; *index = i; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 3d3806f7c02..40ac4dc2944 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -751,7 +751,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med) edgeFlag = (ccgdm->edgeFlags)? &ccgdm->edgeFlags[i]: NULL; if(edgeFlag) - flags |= (*edgeFlag & (ME_SEAM | ME_SHARP)) + flags |= (*edgeFlag & (ME_SEAM | ME_SHARP | ME_FREESTYLE_EDGE)) | ME_EDGEDRAW | ME_EDGERENDER; else flags |= ME_EDGEDRAW | ME_EDGERENDER; @@ -936,7 +936,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) if(edgeFlags) { if(edgeIdx != -1) { - flags |= (edgeFlags[index] & (ME_SEAM | ME_SHARP)) + flags |= (edgeFlags[index] & (ME_SEAM | ME_SHARP | ME_FREESTYLE_EDGE)) | ME_EDGEDRAW | ME_EDGERENDER; } } else { diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h index ba745af5a0b..6e0dcb43889 100644 --- a/source/blender/blenlib/BLI_editVert.h +++ b/source/blender/blenlib/BLI_editVert.h @@ -102,7 +102,7 @@ typedef struct EditEdge float fp; } tmp; short f1, f2; /* short, f1 is (ab)used in subdiv */ - unsigned char f, h, dir, seam, sharp; + unsigned char f, h, dir, seam, sharp, freestyle; float crease; float bweight; short fast; /* only 0 or 1, for editmesh_fastmalloc */ diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index ab5b8e8aff3..3a881997ecf 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -248,7 +248,10 @@ enum { TH_DRAWEXTRA_FACEAREA, TH_DRAWEXTRA_FACEANG, - TH_NODE_CURVING + TH_NODE_CURVING, + + TH_FREESTYLE_EDGE_MARK, + TH_FREESTYLE_FACE_MARK }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 9b9237f70cf..a139463c690 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -344,6 +344,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp= ts->handle_sel_vect; break; case TH_HANDLE_SEL_ALIGN: cp= ts->handle_sel_align; break; + case TH_FREESTYLE_EDGE_MARK: + cp= ts->freestyle_edge_mark; break; + case TH_FREESTYLE_FACE_MARK: + cp= ts->freestyle_face_mark; break; case TH_SYNTAX_B: cp= ts->syntaxb; break; @@ -621,6 +625,8 @@ void ui_theme_init_default(void) SETCOL(btheme->tv3d.button_text_hi, 255, 255, 255, 255); SETCOL(btheme->tv3d.button_title, 0, 0, 0, 255); SETCOL(btheme->tv3d.title, 0, 0, 0, 255); + SETCOL(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255); + SETCOL(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51); btheme->tv3d.facedot_size= 4; @@ -1613,6 +1619,19 @@ void init_userdef_do_versions(void) } } + /* Freestyle color settings */ + { + bTheme *btheme; + + for(btheme= U.themes.first; btheme; btheme= btheme->next) { + /* check for alpha==0 is safe, then color was never set */ + if(btheme->tv3d.freestyle_edge_mark[3]==0) { + SETCOL(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255); + SETCOL(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51); + } + } + } + /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { U.texcollectrate = 60; diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index ab62c88deaa..c2ce1a1aef2 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -502,6 +502,10 @@ void edgetag_context_set(Scene *scene, EditEdge *eed, int val) if (val) {eed->bweight = 1.0f;} else {eed->bweight = 0.0f;} break; + case EDGE_MODE_TAG_FREESTYLE: + if (val) {eed->freestyle = 1;} + else {eed->freestyle = 0;} + break; } } @@ -518,6 +522,8 @@ int edgetag_context_check(Scene *scene, EditEdge *eed) return eed->crease ? 1 : 0; case EDGE_MODE_TAG_BEVEL: return eed->bweight ? 1 : 0; + case EDGE_MODE_TAG_FREESTYLE: + return eed->freestyle ? 1 : 0; } return 0; } diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c index 6a263fca915..7964e305a99 100644 --- a/source/blender/editors/mesh/editmesh.c +++ b/source/blender/editors/mesh/editmesh.c @@ -259,6 +259,7 @@ EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *exampl if(example) { eed->crease= example->crease; eed->bweight= example->bweight; + eed->freestyle = example->freestyle; eed->sharp = example->sharp; eed->seam = example->seam; eed->h |= (example->h & EM_FGON); @@ -828,6 +829,7 @@ void make_editMesh(Scene *scene, Object *ob) if(medge->flag & ME_SEAM) eed->seam= 1; if(medge->flag & ME_SHARP) eed->sharp = 1; + if(medge->flag & ME_FREESTYLE_EDGE) eed->freestyle = 1; if(medge->flag & SELECT) eed->f |= SELECT; if(medge->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! if(medge->flag & ME_HIDE) eed->h |= 1; @@ -1023,6 +1025,7 @@ void load_editMesh(Scene *scene, Object *obedit) if(eed->f2==0) medge->flag |= ME_LOOSEEDGE; if(eed->sharp) medge->flag |= ME_SHARP; if(eed->seam) medge->flag |= ME_SEAM; + if(eed->freestyle) medge->flag |= ME_FREESTYLE_EDGE; if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes if(eed->h & 1) medge->flag |= ME_HIDE; @@ -1578,7 +1581,7 @@ typedef struct EditVertC typedef struct EditEdgeC { int v1, v2; - unsigned char f, h, seam, sharp, pad; + unsigned char f, h, seam, sharp, freestyle; short crease, bweight, fgoni; } EditEdgeC; @@ -1680,6 +1683,7 @@ static void *editMesh_to_undoMesh(void *emv) eedc->h= eed->h; eedc->seam= eed->seam; eedc->sharp= eed->sharp; + eedc->freestyle= eed->freestyle; eedc->crease= (short)(eed->crease*255.0f); eedc->bweight= (short)(eed->bweight*255.0f); eedc->fgoni= eed->fgoni; @@ -1778,6 +1782,7 @@ static void undoMesh_to_editMesh(void *umv, void *emv) eed->h= eedc->h; eed->seam= eedc->seam; eed->sharp= eedc->sharp; + eed->freestyle= eedc->freestyle; eed->fgoni= eedc->fgoni; eed->crease= ((float)eedc->crease)/255.0f; eed->bweight= ((float)eedc->bweight)/255.0f; diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index 8c035ca46fd..0707b651a9f 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -702,6 +702,7 @@ static int unified_findnearest(ViewContext *vc, EditVert **eve, EditEdge **eed, #define SIMEDGE_SEAM 106 #define SIMEDGE_SHARP 107 #define SIMEDGE_TOT 108 +#define SIMEDGE_FREESTYLE 109 /* FACE GROUP */ @@ -724,6 +725,7 @@ static EnumPropertyItem prop_similar_types[] = { {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""}, {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""}, {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""}, + {SIMEDGE_FREESTYLE, "FREESTYLE", 0, "Freestyle Edge Mark", ""}, {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""}, {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""}, {SIMFACE_AREA, "AREA", 0, "Area", ""}, @@ -1076,6 +1078,20 @@ static int similar_edge_select__internal(EditMesh *em, int mode, float thresh) return selcount; } } + } else if (mode==SIMEDGE_FREESTYLE) { /* Freestyle edge mark */ + for(eed= em->edges.first; eed; eed= eed->next) { + if ( + !(eed->f & SELECT) && + !eed->h && + (eed->freestyle == base_eed->freestyle) + ) { + EM_select_edge(eed, 1); + selcount++; + deselcount--; + if (!deselcount) /*have we selected all posible faces?, if so return*/ + return selcount; + } + } } } } @@ -2220,6 +2236,9 @@ static void mouse_mesh_shortest_path(bContext *C, const int mval[2]) case EDGE_MODE_TAG_BEVEL: me->drawflag |= ME_DRAWBWEIGHTS; break; + case EDGE_MODE_TAG_FREESTYLE: + me->drawflag |= ME_DRAW_FREESTYLE_EDGE; + break; } /* live unwrap while tagging */ @@ -3861,6 +3880,58 @@ void MESH_OT_mark_sharp(wmOperatorType *ot) RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); } +static int editmesh_mark_freestyle_edge(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + Mesh *me= ((Mesh *)obedit->data); + int clear = RNA_boolean_get(op->ptr, "clear"); + EditEdge *eed; + + /* auto-enable Freestyle edge mark drawing */ + if(!clear) { + me->drawflag |= ME_DRAW_FREESTYLE_EDGE; + } + + if(!clear) { + eed= em->edges.first; + while(eed) { + if(!eed->h && (eed->f & SELECT)) eed->freestyle = 1; + eed = eed->next; + } + } else { + eed= em->edges.first; + while(eed) { + if(!eed->h && (eed->f & SELECT)) eed->freestyle = 0; + eed = eed->next; + } + } + + BKE_mesh_end_editmesh(obedit->data, em); + + DAG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_mark_freestyle_edge(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Mark Freestyle Edge"; + ot->description= "(un)mark selected edges as Freestyle feature edges"; + ot->idname= "MESH_OT_mark_freestyle_edge"; + + /* api callbacks */ + ot->exec= editmesh_mark_freestyle_edge; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); +} + /* **************** NORMALS ************** */ void EM_recalc_normal_direction(EditMesh *em, int inside, int select) /* makes faces righthand turning */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index c8e3075ac60..6c07bb1bac5 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3775,6 +3775,7 @@ static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir) srchedge->h = eed->h; srchedge->dir = eed->dir; srchedge->seam = eed->seam; + srchedge->freestyle = eed->freestyle; srchedge->crease = eed->crease; srchedge->bweight = eed->bweight; } @@ -7604,3 +7605,54 @@ void MESH_OT_select_axis(wmOperatorType *ot) RNA_def_enum(ot->srna, "axis", axis_items_xyz, 0, "Axis", "Select the axis to compare each vertex on"); } +/********************** Freestyle Face Mark Operator *************************/ + +static int mesh_mark_freestyle_face_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + Mesh *me= ((Mesh *)obedit->data); + int clear = RNA_boolean_get(op->ptr, "clear"); + EditFace *efa; + + /* auto-enable Freestyle face mark drawing */ + if(!clear) { + me->drawflag |= ME_DRAW_FREESTYLE_FACE; + } + + if(!clear) { + for(efa= em->faces.first; efa; efa=efa->next) { + if(efa->f & SELECT) + efa->flag |= ME_FREESTYLE_FACE; + } + } else { + for(efa= em->faces.first; efa; efa=efa->next) { + if(efa->f & SELECT) + efa->flag &= ~ME_FREESTYLE_FACE; + } + } + + BKE_mesh_end_editmesh(obedit->data, em); + + DAG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_mark_freestyle_face(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Mark Freestyle Face"; + ot->description= "(un)mark selected faces for exclusion from Freestyle feature edge detection"; + ot->idname= "MESH_OT_mark_freestyle_face"; + + /* api callbacks */ + ot->exec= mesh_mark_freestyle_face_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "clear", 0, "Clear", ""); +} diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 4d620424b0a..0a4ab3c399f 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -162,6 +162,7 @@ void MESH_OT_select_random(struct wmOperatorType *ot); void MESH_OT_loop_multi_select(struct wmOperatorType *ot); void MESH_OT_mark_seam(struct wmOperatorType *ot); void MESH_OT_mark_sharp(struct wmOperatorType *ot); +void MESH_OT_mark_freestyle_edge(struct wmOperatorType *ot); void MESH_OT_vertices_smooth(struct wmOperatorType *ot); void MESH_OT_noise(struct wmOperatorType *ot); void MESH_OT_flip_normals(struct wmOperatorType *ot); @@ -242,6 +243,7 @@ void MESH_OT_rip(struct wmOperatorType *ot); void MESH_OT_shape_propagate_to_all(struct wmOperatorType *ot); void MESH_OT_blend_from_shape(struct wmOperatorType *ot); void MESH_OT_sort_faces(struct wmOperatorType *ot); +void MESH_OT_mark_freestyle_face(struct wmOperatorType *ot); /* ******************* mesh_data.c */ diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 282eeef906f..4d8194a2979 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -118,6 +118,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_faces_shade_smooth); WM_operatortype_append(MESH_OT_faces_shade_flat); WM_operatortype_append(MESH_OT_sort_faces); + WM_operatortype_append(MESH_OT_mark_freestyle_face); WM_operatortype_append(MESH_OT_delete); @@ -130,6 +131,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_loop_multi_select); WM_operatortype_append(MESH_OT_mark_seam); WM_operatortype_append(MESH_OT_mark_sharp); + WM_operatortype_append(MESH_OT_mark_freestyle_edge); WM_operatortype_append(MESH_OT_vertices_smooth); WM_operatortype_append(MESH_OT_noise); WM_operatortype_append(MESH_OT_flip_normals); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 65267bb481a..5c0c6917b4a 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -2098,21 +2098,32 @@ static void draw_dm_edges_sharp(DerivedMesh *dm) dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL); } + /* Draw only Freestyle feature edges */ +static int draw_dm_edges_freestyle__setDrawOptions(void *UNUSED(userData), int index) +{ + EditEdge *eed = EM_get_edge_for_index(index); + + return (eed->h==0 && eed->freestyle); +} +static void draw_dm_edges_freestyle(DerivedMesh *dm) +{ + dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, NULL); +} /* Draw faces with color set based on selection * return 2 for the active face so it renders with stipple enabled */ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r)) { - struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData; + struct { unsigned char *cols[4]; EditFace *efa_act; } * data = userData; EditFace *efa = EM_get_face_for_index(index); unsigned char *col; if (efa->h==0) { if (efa == data->efa_act) { - glColor4ubv(data->cols[2]); + glColor4ubv(data->cols[3]); return 2; /* stipple */ } else { - col = data->cols[(efa->f&SELECT)?1:0]; + col = data->cols[(efa->f & SELECT) ? 1 : (efa->flag & ME_FREESTYLE_FACE) ? 2 : 0]; if (col[3]==0) return 0; glColor4ubv(col); return 1; @@ -2123,7 +2134,7 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNU static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index) { - struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData; + struct { unsigned char *cols[4]; EditFace *efa_act; } * data = userData; EditFace *efa = EM_get_face_for_index(index); EditFace *next_efa = EM_get_face_for_index(next_index); unsigned char *col, *next_col; @@ -2134,8 +2145,8 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int if(efa == data->efa_act || next_efa == data->efa_act) return 0; - col = data->cols[(efa->f&SELECT)?1:0]; - next_col = data->cols[(next_efa->f&SELECT)?1:0]; + col = data->cols[(efa->f & SELECT) ? 1 : (efa->flag & ME_FREESTYLE_FACE) ? 2 : 0]; + next_col = data->cols[(next_efa->f & SELECT) ? 1 : (next_efa->flag & ME_FREESTYLE_FACE) ? 2 : 0]; if(col[3]==0 || next_col[3]==0) return 0; @@ -2144,12 +2155,13 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int } /* also draws the active face */ -static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) +static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *markCol, unsigned char *actCol, EditFace *efa_act) { - struct { unsigned char *cols[3]; EditFace *efa_act; } data; + struct { unsigned char *cols[4]; EditFace *efa_act; } data; data.cols[0] = baseCol; data.cols[1] = selCol; - data.cols[2] = actCol; + data.cols[2] = markCol; + data.cols[3] = actCol; data.efa_act = efa_act; dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions); @@ -2583,11 +2595,12 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object } if(me->drawflag & ME_DRAWFACES) { /* transp faces */ - unsigned char col1[4], col2[4], col3[4]; + unsigned char col1[4], col2[4], col3[4], col4[4]; UI_GetThemeColor4ubv(TH_FACE, col1); UI_GetThemeColor4ubv(TH_FACE_SELECT, col2); - UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3); + UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col3); + UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4); glEnable(GL_BLEND); glDepthMask(0); // disable write in zbuffer, needed for nice transp @@ -2596,7 +2609,10 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object if CHECK_OB_DRAWTEXTURE(v3d, dt) col1[3] = 0; - draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act); + if (!(me->drawflag & ME_DRAW_FREESTYLE_FACE)) + col3[3] = 0; + + draw_dm_faces_sel(cageDM, col1, col2, col3, col4, efa_act); glDisable(GL_BLEND); glDepthMask(1); // restore write in zbuffer @@ -2604,14 +2620,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object /* even if draw faces is off it would be nice to draw the stipple face * Make all other faces zero alpha except for the active * */ - unsigned char col1[4], col2[4], col3[4]; - col1[3] = col2[3] = 0; /* dont draw */ - UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3); + unsigned char col1[4], col2[4], col3[4], col4[4]; + col1[3] = col2[3] = col3[3] = 0; /* dont draw */ + UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4); glEnable(GL_BLEND); glDepthMask(0); // disable write in zbuffer, needed for nice transp - draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act); + draw_dm_faces_sel(cageDM, col1, col2, col3, col4, efa_act); glDisable(GL_BLEND); glDepthMask(1); // restore write in zbuffer @@ -2646,6 +2662,16 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object glLineWidth(1); } + if(me->drawflag & ME_DRAW_FREESTYLE_EDGE) { + UI_ThemeColor(TH_FREESTYLE_EDGE_MARK); + glLineWidth(2); + + draw_dm_edges_freestyle(cageDM); + + glColor3ub(0,0,0); + glLineWidth(1); + } + if(me->drawflag & ME_DRAWCREASES) { draw_dm_creases(cageDM); } diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 3cff4d2cc33..c0aa127b962 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -125,37 +125,47 @@ void BlenderFileLoader::clipLine(float v1[3], float v2[3], float c[3], float z) // obtain a set of vertices after the clipping. The number of vertices // is at most 5. void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], - float triNormals[][3], float n1[3], float n2[3], float n3[3], int clip[3]) + float triNormals[][3], float n1[3], float n2[3], float n3[3], + bool edgeMarks[], bool em1, bool em2, bool em3, int clip[3]) { float *v[3], *n[3]; + bool em[3]; int i, j, k; v[0] = v1; n[0] = n1; v[1] = v2; n[1] = n2; v[2] = v3; n[2] = n3; + em[0] = em1; /* edge mark of the edge between v1 and v2 */ + em[1] = em2; /* edge mark of the edge between v2 and v3 */ + em[2] = em3; /* edge mark of the edge between v3 and v1 */ k = 0; for (i = 0; i < 3; i++) { j = (i + 1) % 3; if (clip[i] == NOT_CLIPPED) { copy_v3_v3(triCoords[k], v[i]); copy_v3_v3(triNormals[k], n[i]); + edgeMarks[k] = em[i]; k++; if (clip[j] != NOT_CLIPPED) { clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far); copy_v3_v3(triNormals[k], n[j]); + edgeMarks[k] = false; k++; } } else if (clip[i] != clip[j]) { if (clip[j] == NOT_CLIPPED) { clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far); copy_v3_v3(triNormals[k], n[i]); + edgeMarks[k] = em[i]; k++; } else { clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far); copy_v3_v3(triNormals[k], n[i]); + edgeMarks[k] = em[i]; k++; clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far); copy_v3_v3(triNormals[k], n[j]); + edgeMarks[k] = false; k++; } } @@ -164,10 +174,12 @@ void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1 } void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3], - float n1[3], float n2[3], float n3[3]) + float n1[3], float n2[3], float n3[3], + bool fm, bool em1, bool em2, bool em3) { float *fv[3], *fn[3], len; unsigned i, j; + IndexedFaceSet::FaceEdgeMark marks = 0; // initialize the bounding box by the first vertex if (ls->currentIndex == 0) { @@ -209,6 +221,11 @@ void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v ls->pni++; ls->pmi++; } + if (fm) marks |= IndexedFaceSet::FACE_MARK; + if (em1) marks |= IndexedFaceSet::EDGE_MARK_V1V2; + if (em2) marks |= IndexedFaceSet::EDGE_MARK_V2V3; + if (em3) marks |= IndexedFaceSet::EDGE_MARK_V3V1; + *ls->pm++ = marks; } void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id) @@ -272,6 +289,8 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id) faceStyle[i] = IndexedFaceSet::TRIANGLES; numVertexPerFaces[i] = 3; } + + IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = new IndexedFaceSet::FaceEdgeMark[numFaces]; unsigned viSize = 3*numFaces; unsigned *VIndices = new unsigned[viSize]; @@ -282,6 +301,7 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id) struct LoaderState ls; ls.pv = vertices; ls.pn = normals; + ls.pm = faceEdgeMarks; ls.pvi = VIndices; ls.pni = NIndices; ls.pmi = MIndices; @@ -339,6 +359,17 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id) numTris_2 = (vlr->v4) ? countClippedFaces(v1, v3, v4, clip_2) : 0; if (numTris_1 == 0 && numTris_2 == 0) continue; + bool fm, em1, em2, em3, em4; + fm = (vlr->flag & ME_FREESTYLE_FACE) != 0; + em1= (vlr->freestyle_edge_mark & R_EDGE_V1V2) != 0; + em2= (vlr->freestyle_edge_mark & R_EDGE_V2V3) != 0; + if (!vlr->v4) { + em3= (vlr->freestyle_edge_mark & R_EDGE_V3V1) != 0; + em4= false; + } else { + em3= (vlr->freestyle_edge_mark & R_EDGE_V3V4) != 0; + em4= (vlr->freestyle_edge_mark & R_EDGE_V4V1) != 0; + } Material *mat = vlr->mat; @@ -379,21 +410,28 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id) } float triCoords[5][3], triNormals[5][3]; + bool edgeMarks[5]; // edgeMarks[i] is for the edge between i-th and (i+1)-th vertices if (numTris_1 > 0) { - clipTriangle(numTris_1, triCoords, v1, v2, v3, triNormals, n1, n2, n3, clip_1); + clipTriangle(numTris_1, triCoords, v1, v2, v3, triNormals, n1, n2, n3, + edgeMarks, em1, em2, (!vlr->v4) ? em3 : false, clip_1); for (i = 0; i < numTris_1; i++) { addTriangle(&ls, triCoords[0], triCoords[i+1], triCoords[i+2], - triNormals[0], triNormals[i+1], triNormals[i+2]); + triNormals[0], triNormals[i+1], triNormals[i+2], + fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i+1], + (i == numTris_1 - 1) ? edgeMarks[i+2] : false); _numFacesRead++; } } if (numTris_2 > 0) { - clipTriangle(numTris_2, triCoords, v1, v3, v4, triNormals, n1, n3, n4, clip_2); + clipTriangle(numTris_2, triCoords, v1, v3, v4, triNormals, n1, n3, n4, + edgeMarks, false, em3, em4, clip_2); for (i = 0; i < numTris_2; i++) { addTriangle(&ls, triCoords[0], triCoords[i+1], triCoords[i+2], - triNormals[0], triNormals[i+1], triNormals[i+2]); + triNormals[0], triNormals[i+1], triNormals[i+2], + fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i+1], + (i == numTris_2 - 1) ? edgeMarks[i+2] : false); _numFacesRead++; } } @@ -444,6 +482,7 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id) marray, meshFrsMaterials.size(), 0, 0, numFaces, numVertexPerFaces, faceStyle, + faceEdgeMarks, cleanVIndices, viSize, cleanNIndices, niSize, MIndices, viSize, diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h index adf3e4eb7b1..94ea0784a30 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h @@ -18,6 +18,7 @@ extern "C" { #endif #include "DNA_material_types.h" + #include "DNA_meshdata_types.h" #include "DNA_scene_types.h" #include "render_types.h" #include "renderdatabase.h" @@ -36,6 +37,7 @@ class NodeGroup; struct LoaderState { float *pv; float *pn; + IndexedFaceSet::FaceEdgeMark *pm; unsigned *pvi; unsigned *pni; unsigned *pmi; @@ -66,9 +68,10 @@ protected: int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]); void clipLine(float v1[3], float v2[3], float c[3], float z); void clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], - float triNormals[][3], float n1[3], float n2[3], float n3[3], int clip[3]); + float triNormals[][3], float n1[3], float n2[3], float n3[3], + bool edgeMarks[5], bool em1, bool em2, bool em3, int clip[3]); void addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3], - float n1[3], float n2[3], float n3[3]); + float n1[3], float n2[3], float n3[3], bool fm, bool em1, bool em2, bool em3); protected: Render* _re; diff --git a/source/blender/freestyle/intern/python/BPy_Nature.cpp b/source/blender/freestyle/intern/python/BPy_Nature.cpp index 35be367b348..149baa9a7f3 100644 --- a/source/blender/freestyle/intern/python/BPy_Nature.cpp +++ b/source/blender/freestyle/intern/python/BPy_Nature.cpp @@ -78,7 +78,8 @@ static char Nature___doc__[] = "* Nature.RIDGE: True for ridges.\n" "* Nature.VALLEY: True for valleys.\n" "* Nature.SUGGESTIVE_CONTOUR: True for suggestive contours.\n" -"* Nature.MATERIAL_BOUNDARY: True for edges at material boundaries.\n"; +"* Nature.MATERIAL_BOUNDARY: True for edges at material boundaries.\n" +"* Nature.EDGE_MARK: True for edges having user-defined edge marks.\n"; /*-----------------------BPy_Nature type definition ------------------------------*/ @@ -181,6 +182,10 @@ static PyLongObject _Nature_MATERIAL_BOUNDARY = { PyVarObject_HEAD_INIT(&Nature_Type, 1) { Nature::MATERIAL_BOUNDARY } }; +static PyLongObject _Nature_EDGE_MARK = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::EDGE_MARK } +}; #define BPy_Nature_POINT ((PyObject *)&_Nature_POINT) #define BPy_Nature_S_VERTEX ((PyObject *)&_Nature_S_VERTEX) @@ -196,6 +201,7 @@ static PyLongObject _Nature_MATERIAL_BOUNDARY = { #define BPy_Nature_VALLEY ((PyObject *)&_Nature_VALLEY) #define BPy_Nature_SUGGESTIVE_CONTOUR ((PyObject *)&_Nature_SUGGESTIVE_CONTOUR) #define BPy_Nature_MATERIAL_BOUNDARY ((PyObject *)&_Nature_MATERIAL_BOUNDARY) +#define BPy_Nature_EDGE_MARK ((PyObject *)&_Nature_EDGE_MARK) //-------------------MODULE INITIALIZATION-------------------------------- int Nature_Init( PyObject *module ) @@ -225,6 +231,7 @@ int Nature_Init( PyObject *module ) PyDict_SetItemString( Nature_Type.tp_dict, "VALLEY", BPy_Nature_VALLEY ); PyDict_SetItemString( Nature_Type.tp_dict, "SUGGESTIVE_CONTOUR", BPy_Nature_SUGGESTIVE_CONTOUR ); PyDict_SetItemString( Nature_Type.tp_dict, "MATERIAL_BOUNDARY", BPy_Nature_MATERIAL_BOUNDARY ); + PyDict_SetItemString( Nature_Type.tp_dict, "EDGE_MARK", BPy_Nature_EDGE_MARK ); return 0; } diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp index ec49167b0c1..39d644b7714 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp @@ -154,6 +154,32 @@ static PyObject * FEdgeSharp_bMaterial( BPy_FEdgeSharp *self ) { return BPy_FrsMaterial_from_FrsMaterial(m); } +static char FEdgeSharp_aFaceMark___doc__[] = +".. method:: aFaceMark()\n" +"\n" +" Returns the face mark of the face lying on the right of the FEdge.\n" +" If this FEdge is a border, it has no face on the right, and thus\n" +" false is returned.\n" +"\n" +" :return: The face mark of the face lying on the right of the FEdge.\n" +" :rtype: bool\n"; + +static PyObject * FEdgeSharp_aFaceMark( BPy_FEdgeSharp *self ) { + return PyBool_from_bool( self->fes->aFaceMark() ); +} + +static char FEdgeSharp_bFaceMark___doc__[] = +".. method:: bFaceMark()\n" +"\n" +" Returns the face mark of the face lying on the left of the FEdge.\n" +"\n" +" :return: The face mark of the face lying on the left of the FEdge.\n" +" :rtype: bool\n"; + +static PyObject * FEdgeSharp_bFaceMark( BPy_FEdgeSharp *self ) { + return PyBool_from_bool( self->fes->bFaceMark() ); +} + static char FEdgeSharp_setNormalA___doc__[] = ".. method:: setNormalA(iNormal)\n" "\n" @@ -240,6 +266,44 @@ static PyObject * FEdgeSharp_setbMaterialIndex( BPy_FEdgeSharp *self, PyObject * Py_RETURN_NONE; } +static char FEdgeSharp_setaFaceMark___doc__[] = +".. method:: setaFaceMark(i)\n" +"\n" +" Sets the face mark of the face lying on the right of the FEdge.\n" +"\n" +" :arg i: A face mark.\n" +" :type i: bool\n"; + +static PyObject * FEdgeSharp_setaFaceMark( BPy_FEdgeSharp *self, PyObject *args ) { + PyObject *obj; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + + self->fes->setaFaceMark( bool_from_PyBool(obj) ); + + Py_RETURN_NONE; +} + +static char FEdgeSharp_setbFaceMark___doc__[] = +".. method:: setbFaceMark(i)\n" +"\n" +" Sets the face mark of the face lying on the left of the FEdge.\n" +"\n" +" :arg i: A face mark.\n" +" :type i: bool\n"; + +static PyObject * FEdgeSharp_setbFaceMark( BPy_FEdgeSharp *self, PyObject *args ) { + PyObject *obj; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + + self->fes->setbFaceMark( bool_from_PyBool(obj) ); + + Py_RETURN_NONE; +} + /*----------------------FEdgeSharp instance definitions ----------------------------*/ static PyMethodDef BPy_FEdgeSharp_methods[] = { {"normalA", ( PyCFunction ) FEdgeSharp_normalA, METH_NOARGS, FEdgeSharp_normalA___doc__}, @@ -248,10 +312,14 @@ static PyMethodDef BPy_FEdgeSharp_methods[] = { {"bMaterialIndex", ( PyCFunction ) FEdgeSharp_bMaterialIndex, METH_NOARGS, FEdgeSharp_bMaterialIndex___doc__}, {"aMaterial", ( PyCFunction ) FEdgeSharp_aMaterial, METH_NOARGS, FEdgeSharp_aMaterial___doc__}, {"bMaterial", ( PyCFunction ) FEdgeSharp_bMaterial, METH_NOARGS, FEdgeSharp_bMaterial___doc__}, + {"aFaceMark", ( PyCFunction ) FEdgeSharp_aFaceMark, METH_NOARGS, FEdgeSharp_aFaceMark___doc__}, + {"bFaceMark", ( PyCFunction ) FEdgeSharp_bFaceMark, METH_NOARGS, FEdgeSharp_bFaceMark___doc__}, {"setNormalA", ( PyCFunction ) FEdgeSharp_setNormalA, METH_VARARGS, FEdgeSharp_setNormalA___doc__}, {"setNormalB", ( PyCFunction ) FEdgeSharp_setNormalB, METH_VARARGS, FEdgeSharp_setNormalB___doc__}, {"setaMaterialIndex", ( PyCFunction ) FEdgeSharp_setaMaterialIndex, METH_VARARGS, FEdgeSharp_setaMaterialIndex___doc__}, {"setbMaterialIndex", ( PyCFunction ) FEdgeSharp_setbMaterialIndex, METH_VARARGS, FEdgeSharp_setbMaterialIndex___doc__}, + {"setaFaceMark", ( PyCFunction ) FEdgeSharp_setaFaceMark, METH_NOARGS, FEdgeSharp_setaFaceMark___doc__}, + {"setbFaceMark", ( PyCFunction ) FEdgeSharp_setbFaceMark, METH_NOARGS, FEdgeSharp_setbFaceMark___doc__}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp index df945b1e6a8..3ddb4d060de 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp @@ -104,6 +104,18 @@ static PyObject * FEdgeSmooth_material( BPy_FEdgeSmooth *self ) { return BPy_FrsMaterial_from_FrsMaterial(m); } +static char FEdgeSmooth_faceMark___doc__[] = +".. method:: faceMark()\n" +"\n" +" Returns the face mark of the face it is running across.\n" +"\n" +" :return: The face mark of the face it is running across.\n" +" :rtype: bool\n"; + +static PyObject * FEdgeSmooth_faceMark( BPy_FEdgeSmooth *self ) { + return PyBool_from_bool( self->fes->faceMark() ); +} + static char FEdgeSmooth_setNormal___doc__[] = ".. method:: setNormal(iNormal)\n" "\n" @@ -147,13 +159,34 @@ static PyObject * FEdgeSmooth_setMaterialIndex( BPy_FEdgeSmooth *self, PyObject Py_RETURN_NONE; } +static char FEdgeSmooth_setFaceMark___doc__[] = +".. method:: setFaceMark(i)\n" +"\n" +" Sets the face mark of the face it is running across.\n" +"\n" +" :arg i: A face mark.\n" +" :type i: bool\n"; + +static PyObject * FEdgeSmooth_setFaceMark( BPy_FEdgeSmooth *self, PyObject *args ) { + PyObject *obj; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + + self->fes->setFaceMark( bool_from_PyBool(obj) ); + + Py_RETURN_NONE; +} + /*----------------------FEdgeSmooth instance definitions ----------------------------*/ static PyMethodDef BPy_FEdgeSmooth_methods[] = { {"normal", ( PyCFunction ) FEdgeSmooth_normal, METH_NOARGS, FEdgeSmooth_normal___doc__}, {"materialIndex", ( PyCFunction ) FEdgeSmooth_materialIndex, METH_NOARGS, FEdgeSmooth_materialIndex___doc__}, {"material", ( PyCFunction ) FEdgeSmooth_material, METH_NOARGS, FEdgeSmooth_material___doc__}, + {"faceMark", ( PyCFunction ) FEdgeSmooth_faceMark, METH_NOARGS, FEdgeSmooth_faceMark___doc__}, {"setNormal", ( PyCFunction ) FEdgeSmooth_setNormal, METH_VARARGS, FEdgeSmooth_setNormal___doc__}, {"setMaterialIndex", ( PyCFunction ) FEdgeSmooth_setMaterialIndex, METH_VARARGS, FEdgeSmooth_setMaterialIndex___doc__}, + {"setFaceMark", ( PyCFunction ) FEdgeSmooth_setFaceMark, METH_VARARGS, FEdgeSmooth_setFaceMark___doc__}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp index 98872c6c8ea..aaeba943ab6 100755 --- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp +++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp @@ -28,6 +28,7 @@ IndexedFaceSet::IndexedFaceSet() _Normals = NULL; _FrsMaterials = 0; _TexCoords = 0; + _FaceEdgeMarks = 0; _VSize = 0; _NSize = 0; _MSize = 0; @@ -51,6 +52,7 @@ IndexedFaceSet::IndexedFaceSet( real *iVertices, unsigned iVSize, FrsMaterial **iMaterials, unsigned iMSize, real *iTexCoords, unsigned iTSize, unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle, + FaceEdgeMark *iFaceEdgeMarks, unsigned *iVIndices, unsigned iVISize, unsigned *iNIndices, unsigned iNISize, unsigned *iMIndices, unsigned iMISize, @@ -89,6 +91,9 @@ IndexedFaceSet::IndexedFaceSet( real *iVertices, unsigned iVSize, _FaceStyle = new TRIANGLES_STYLE[_NumFaces]; memcpy(_FaceStyle, iFaceStyle, _NumFaces*sizeof(TRIANGLES_STYLE)); + _FaceEdgeMarks = new FaceEdgeMark[_NumFaces]; + memcpy(_FaceEdgeMarks, iFaceEdgeMarks, _NumFaces*sizeof(FaceEdgeMark)); + _VISize = iVISize; _VIndices = new unsigned[_VISize]; memcpy(_VIndices, iVIndices, _VISize*sizeof(unsigned)); @@ -129,6 +134,7 @@ IndexedFaceSet::IndexedFaceSet( real *iVertices, unsigned iVSize, _NumFaces = iNumFaces; _NumVertexPerFace = iNumVertexPerFace; _FaceStyle = iFaceStyle; + _FaceEdgeMarks = iFaceEdgeMarks; _VISize = iVISize; _VIndices = iVIndices; @@ -182,6 +188,9 @@ IndexedFaceSet::IndexedFaceSet( const IndexedFaceSet& iBrother) _FaceStyle = new TRIANGLES_STYLE[_NumFaces]; memcpy(_FaceStyle, iBrother.trianglesStyle(), _NumFaces*sizeof(TRIANGLES_STYLE)); + + _FaceEdgeMarks = new FaceEdgeMark[_NumFaces]; + memcpy(_FaceEdgeMarks, iBrother.faceEdgeMarks(), _NumFaces*sizeof(FaceEdgeMark)); _VISize = iBrother.visize(); _VIndices = new unsigned[_VISize]; @@ -249,6 +258,12 @@ IndexedFaceSet::~IndexedFaceSet() _FaceStyle = NULL; } + if(NULL != _FaceEdgeMarks) + { + delete [] _FaceEdgeMarks; + _FaceEdgeMarks = NULL; + } + if(NULL != _VIndices) { delete [] _VIndices; diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h index 41db4db4c42..b578dc1257e 100755 --- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h +++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h @@ -45,6 +45,13 @@ public: /*! Triangles description style:*/ enum TRIANGLES_STYLE{TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES}; + /*! User-specified face and edge marks for feature edge detection */ + typedef unsigned char FaceEdgeMark; + static const FaceEdgeMark FACE_MARK = 1; + static const FaceEdgeMark EDGE_MARK_V1V2 = 2; + static const FaceEdgeMark EDGE_MARK_V2V3 = 4; + static const FaceEdgeMark EDGE_MARK_V3V1 = 8; + /*! Builds an empty indexed face set */ IndexedFaceSet(); @@ -109,6 +116,7 @@ public: FrsMaterial **iMaterials, unsigned iMSize, real *iTexCoords, unsigned iTSize, unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle, + FaceEdgeMark *iFaceEdgeMarks, unsigned *iVIndices, unsigned iVISize, unsigned *iNIndices, unsigned iNISize, unsigned *iMIndices, unsigned iMISize, @@ -124,6 +132,7 @@ public: std::swap(_Normals, ioOther._Normals); std::swap(_FrsMaterials, ioOther._FrsMaterials); std::swap(_TexCoords, ioOther._TexCoords); + std::swap(_FaceEdgeMarks, ioOther._FaceEdgeMarks); std::swap(_VSize, ioOther._VSize); std::swap(_NSize, ioOther._NSize); @@ -180,6 +189,7 @@ public: virtual const unsigned numFaces() const {return _NumFaces;} virtual const unsigned * numVertexPerFaces() const {return _NumVertexPerFace;} virtual const TRIANGLES_STYLE * trianglesStyle() const {return _FaceStyle;} + virtual const unsigned char * faceEdgeMarks() const {return _FaceEdgeMarks;} virtual const unsigned* vindices() const {return _VIndices;} virtual const unsigned* nindices() const {return _NIndices;} virtual const unsigned* mindices() const {return _MIndices;} @@ -204,6 +214,7 @@ protected: unsigned _NumFaces; unsigned *_NumVertexPerFace; TRIANGLES_STYLE *_FaceStyle; + FaceEdgeMark *_FaceEdgeMarks; unsigned *_VIndices; unsigned *_NIndices; diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp index 93e3354cb6a..1cbed8a87c6 100755 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp @@ -72,6 +72,7 @@ void FEdgeXDetector::processShapes(WingedEdge& we) { if(_computeSuggestiveContours) processSuggestiveContourShape(wxs); processSilhouetteShape(wxs); + processEdgeMarksShape(wxs); if (progressBarDisplay) _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); @@ -708,6 +709,26 @@ void FEdgeXDetector::ProcessMaterialBoundaryEdge(WXEdge *iEdge) } } +// EDGE MARKS +///////////// + +void FEdgeXDetector::processEdgeMarksShape(WXShape* iShape) { + // Make a pass on the edges to detect material boundaries + vector<WEdge*>::iterator we, weend; + vector<WEdge*> &wedges = iShape->getEdgeList(); + for(we=wedges.begin(), weend=wedges.end(); + we!=weend; + ++we){ + ProcessEdgeMarks((WXEdge*)(*we)); + } +} + +void FEdgeXDetector::ProcessEdgeMarks(WXEdge *iEdge) { + if (iEdge->GetMark()) { + iEdge->AddNature(Nature::EDGE_MARK); + } +} + // Build Smooth edges ///////////////////// void FEdgeXDetector::buildSmoothEdges(WXShape* iShape){ diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h index d08d75a84b6..d73a086f81d 100755 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h @@ -127,6 +127,10 @@ public: virtual void processMaterialBoundaryShape(WXShape* iWShape); virtual void ProcessMaterialBoundaryEdge(WXEdge *iEdge); + // EDGE MARKS + virtual void processEdgeMarksShape(WXShape* iShape); + virtual void ProcessEdgeMarks(WXEdge *iEdge); + // EVERYBODY virtual void buildSmoothEdges(WXShape* iShape); @@ -142,6 +146,12 @@ public: _changes=true; } } + inline void enableFaceMarks(bool b) { + if (b != _faceMarks) { + _faceMarks = b; + _changes=true; + } + } /*! Sets the radius of the geodesic sphere around each vertex (for the curvature computation) * \param r * The radius of the sphere expressed as a ratio of the mean edge size @@ -175,6 +185,7 @@ protected: bool _computeSuggestiveContours; bool _computeMaterialBoundaries; bool _faceSmoothness; + bool _faceMarks; real _sphereRadius; // expressed as a ratio of the mean edge size real _creaseAngle; // [-1, 1] compared with the inner product of face normals bool _changes; diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h index e7533f659d6..d0952ec8933 100755 --- a/source/blender/freestyle/intern/view_map/Silhouette.h +++ b/source/blender/freestyle/intern/view_map/Silhouette.h @@ -798,6 +798,8 @@ protected: Vec3r _bNormal; // When following the edge, normal of the left face unsigned _aFrsMaterialIndex; unsigned _bFrsMaterialIndex; + bool _aFaceMark; + bool _bFaceMark; public: /*! Returns the string "FEdgeSharp" . */ @@ -807,10 +809,12 @@ public: /*! Default constructor. */ inline FEdgeSharp() : FEdge(){ _aFrsMaterialIndex = _bFrsMaterialIndex = 0; + _aFaceMark = _bFaceMark = false; } /*! Builds an FEdgeSharp going from vA to vB. */ inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB){ _aFrsMaterialIndex = _bFrsMaterialIndex = 0; + _aFaceMark = _bFaceMark = false; } /*! Copy constructor. */ inline FEdgeSharp(FEdgeSharp& iBrother) : FEdge(iBrother){ @@ -818,6 +822,9 @@ public: _bNormal = iBrother._bNormal; _aFrsMaterialIndex = iBrother._aFrsMaterialIndex; _bFrsMaterialIndex = iBrother._bFrsMaterialIndex; + _aFaceMark = iBrother._aFaceMark; + _bFaceMark = iBrother._bFaceMark; + } /*! Destructor. */ virtual ~FEdgeSharp() {} @@ -853,6 +860,12 @@ public: * left of the FEdge. */ const FrsMaterial& bFrsMaterial() const ; + /*! Returns the face mark of the face lying on the right of the FEdge. + * If this FEdge is a border, it has no Face on its right and thus + * false is returned. */ + inline bool aFaceMark() const {return _aFaceMark;} + /*! Returns the face mark of the face lying on the left of the FEdge. */ + inline bool bFaceMark() const {return _bFaceMark;} /*! Sets the normal to the face lying on the right of the FEdge. */ inline void setNormalA(const Vec3r& iNormal) {_aNormal = iNormal;} @@ -862,6 +875,10 @@ public: inline void setaFrsMaterialIndex(unsigned i) {_aFrsMaterialIndex = i;} /*! Sets the index of the material lying on the left of the FEdge.*/ inline void setbFrsMaterialIndex(unsigned i) {_bFrsMaterialIndex = i;} + /*! Sets the face mark of the face lying on the right of the FEdge. */ + inline void setaFaceMark(bool iFaceMark) {_aFaceMark = iFaceMark;} + /*! Sets the face mark of the face lying on the left of the FEdge. */ + inline void setbFaceMark(bool iFaceMark) {_bFaceMark = iFaceMark;} }; @@ -879,6 +896,7 @@ protected: // Vec3r _VisibilityPointB; // using its 2 extremity points A and B void * _Face; // In case of exact silhouette, Face is the WFace crossed by Fedge // NON GERE PAR LE COPY CONSTRUCTEUR + bool _FaceMark; public: /*! Returns the string "FEdgeSmooth" . */ virtual string getExactTypeName() const { @@ -887,12 +905,14 @@ public: /*! Default constructor. */ inline FEdgeSmooth() : FEdge(){ _Face=0; + _FaceMark = false; _FrsMaterialIndex = 0; _isSmooth = true; } /*! Builds an FEdgeSmooth going from vA to vB. */ inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB){ _Face=0; + _FaceMark = false; _FrsMaterialIndex = 0; _isSmooth = true; @@ -901,6 +921,7 @@ public: inline FEdgeSmooth(FEdgeSmooth& iBrother) : FEdge(iBrother){ _Normal = iBrother._Normal; _Face = iBrother._Face; + _FaceMark = iBrother._FaceMark; _FrsMaterialIndex = iBrother._FrsMaterialIndex; _isSmooth = true; } @@ -913,6 +934,8 @@ public: } inline void * face() const {return _Face;} + /*! Returns the face mark of the face it is running across. */ + inline bool faceMark() const {return _FaceMark;} /*! Returns the normal to the Face it is running accross. */ inline const Vec3r& normal() {return _Normal;} /*! Returns the index of the material of the face it is running accross. */ @@ -921,6 +944,8 @@ public: const FrsMaterial& frs_material() const ; inline void setFace(void * iFace) {_Face = iFace;} + /*! Sets the face mark of the face it is running across. */ + inline void setFaceMark(bool iFaceMark) {_FaceMark = iFaceMark;} /*! Sets the normal to the Face it is running accross. */ inline void setNormal(const Vec3r& iNormal) {_Normal = iNormal;} /*! Sets the index of the material of the face it is running accross. */ diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp index 3e0979f684f..47c4ec05e4f 100755 --- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp @@ -472,6 +472,7 @@ FEdge * ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer fe->setId(_currentFId); fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex()); fe->setFace(ifl.fl->getFace()); + fe->setFaceMark(ifl.fl->getFace()->GetMark()); fe->setNormal(normal); fe->setPreviousEdge(feprevious); if(feprevious) @@ -585,19 +586,24 @@ FEdge * ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe) // get the faces normals and the material indices Vec3r normalA, normalB; unsigned matA(0), matB(0); + bool faceMarkA = false, faceMarkB = false; if(iwe.order){ normalB = (iwe.e->GetbFace()->GetNormal()); matB = (iwe.e->GetbFace()->frs_materialIndex()); + faceMarkB = (iwe.e->GetbFace()->GetMark()); if(!(iwe.e->nature() & Nature::BORDER)) { normalA = (iwe.e->GetaFace()->GetNormal()); matA = (iwe.e->GetaFace()->frs_materialIndex()); + faceMarkA = (iwe.e->GetaFace()->GetMark()); } }else{ normalA = (iwe.e->GetbFace()->GetNormal()); matA = (iwe.e->GetbFace()->frs_materialIndex()); + faceMarkA = (iwe.e->GetbFace()->GetMark()); if(!(iwe.e->nature() & Nature::BORDER)) { normalB = (iwe.e->GetaFace()->GetNormal()); matB = (iwe.e->GetaFace()->frs_materialIndex()); + faceMarkB = (iwe.e->GetaFace()->GetMark()); } } // Creates the corresponding feature edge @@ -607,6 +613,8 @@ FEdge * ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe) fe->setId(_currentFId); fe->setaFrsMaterialIndex(matA); fe->setbFrsMaterialIndex(matB); + fe->setaFaceMark(faceMarkA); + fe->setbFaceMark(faceMarkB); fe->setNormalA(normalA); fe->setNormalB(normalB); fe->setPreviousEdge(feprevious); diff --git a/source/blender/freestyle/intern/winged_edge/Nature.h b/source/blender/freestyle/intern/winged_edge/Nature.h index 52c9c60d8c7..62171fae111 100755 --- a/source/blender/freestyle/intern/winged_edge/Nature.h +++ b/source/blender/freestyle/intern/winged_edge/Nature.h @@ -71,6 +71,8 @@ namespace Nature { static const EdgeNature SUGGESTIVE_CONTOUR = (1 << 5); // 32 /*! true for material boundaries */ static const EdgeNature MATERIAL_BOUNDARY = (1 << 6); // 64 + /*! true for user-defined edge marks */ + static const EdgeNature EDGE_MARK = (1 << 7); // 128 } // end of namespace Nature diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp index a5918fd8400..6ef99186a2c 100755 --- a/source/blender/freestyle/intern/winged_edge/WEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp @@ -258,6 +258,7 @@ WFace::WFace(WFace& iBrother) _VerticesTexCoords = iBrother._VerticesTexCoords; _Id = iBrother.GetId(); _FrsMaterialIndex = iBrother._FrsMaterialIndex; + _Mark = iBrother._Mark; userdata = NULL; iBrother.userdata = new facedata; ((facedata*)(iBrother.userdata))->_copy = this; @@ -624,12 +625,12 @@ WShape::WShape(WShape& iBrother) } } -WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial) +WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterial) { // allocate the new face WFace *face = instanciateFace(); - WFace *result = MakeFace(iVertexList, iMaterial, face); + WFace *result = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial, face); if (0 == result) { delete face; return 0; @@ -637,10 +638,10 @@ WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial) return result; } -WFace * WShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterial) +WFace * WShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterial) { // allocate the new face - WFace *face = MakeFace(iVertexList, iMaterial); + WFace *face = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial); if(0 == face) @@ -654,7 +655,7 @@ WFace * WShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsL return face; } -WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial, WFace *face) +WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterial, WFace *face) { int id = _FaceList.size(); @@ -702,6 +703,10 @@ WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial, WFace normal.normalize(); face->setNormal(normal); + vector<bool>::iterator mit = iFaceEdgeMarksList.begin(); + face->setMark(*mit); + mit++; + // vertex pointers used to build each edge vector<WVertex*>::iterator va, vb; @@ -734,6 +739,9 @@ WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial, WFace // compute the mean edge value: _meanEdgeSize += edge->GetaOEdge()->GetVec().norm(); } + + edge->setMark(*mit); + mit++; } // Add the face to the shape's faces list: diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h index abb6263ae69..dc920448add 100755 --- a/source/blender/freestyle/intern/winged_edge/WEdge.h +++ b/source/blender/freestyle/intern/winged_edge/WEdge.h @@ -372,6 +372,7 @@ protected: WOEdge *_paOEdge; // first oriented edge WOEdge *_pbOEdge; // second oriented edge int _nOEdges; // number of oriented edges associated with this edge. (1 means border edge) + bool _Mark; // user-specified edge mark for feature edge detection int _Id; // Identifier for the edge public: @@ -448,6 +449,7 @@ public: inline WOEdge * GetaOEdge() {return _paOEdge;} inline WOEdge * GetbOEdge() {return _pbOEdge;} inline int GetNumberOfOEdges() {return _nOEdges;} + inline bool GetMark() {return _Mark;} inline int GetId() {return _Id;} inline WVertex * GetaVertex() {return _paOEdge->GetaVertex();} inline WVertex * GetbVertex() {return _paOEdge->GetbVertex();} @@ -480,6 +482,7 @@ public: } } inline void setNumberOfOEdges(int n) {_nOEdges = n;} + inline void setMark(bool mark) {_Mark = mark;} inline void setId(int id) {_Id = id;} virtual void ResetUserData() {userdata = 0;} }; @@ -505,6 +508,7 @@ protected: int _Id; unsigned _FrsMaterialIndex; + bool _Mark; // Freestyle face mark (if true, feature edges on this face are ignored) public: void *userdata; @@ -520,6 +524,7 @@ public: inline Vec3r& GetNormal() {return _Normal;} inline int GetId() {return _Id;} inline unsigned frs_materialIndex() const {return _FrsMaterialIndex;} + inline bool GetMark() const {return _Mark;} const FrsMaterial& frs_material() ; /*! The vertex of index i corresponds to the a vertex @@ -663,6 +668,7 @@ public: inline void setTexCoordsList(const vector<Vec2r>& iTexCoordsList) {_VerticesTexCoords = iTexCoordsList;} inline void setId(int id) {_Id = id;} inline void setFrsMaterialIndex(unsigned iMaterialIndex) {_FrsMaterialIndex = iMaterialIndex;} + inline void setMark(bool iMark) {_Mark = iMark;} /*! designed to build a specialized WEdge * for use in MakeEdge @@ -791,7 +797,7 @@ public: * iMaterialIndex * The material index for this face */ - virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex); + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex); /*! adds a new face to the shape. The difference with * the previous method is that this one is designed @@ -814,7 +820,7 @@ public: * The list of tex coords, iTexCoordsList[i] corresponding to the * normal of the vertex iVertexList[i] for that face. */ - virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex); + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex); inline void AddEdge(WEdge *iEdge) {_EdgeList.push_back(iEdge);} inline void AddFace(WFace* iFace) {_FaceList.push_back(iFace);} @@ -892,7 +898,7 @@ protected: * face * The Face that is filled in */ - virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex, WFace *face); + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex, WFace *face); }; diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp index ff567aee06a..d238749570c 100755 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp @@ -258,9 +258,9 @@ void WXFace::ComputeCenter() /**********************************/ -WFace* WXShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex) +WFace* WXShape::MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex) { - WFace *face = WShape::MakeFace(iVertexList, iMaterialIndex); + WFace *face = WShape::MakeFace(iVertexList, iFaceEdgeMarksList, iMaterialIndex); if(0 == face) return 0; @@ -277,9 +277,9 @@ WFace* WXShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex) return face; } -WFace * WXShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex) +WFace * WXShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex) { - WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iMaterialIndex); + WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iFaceEdgeMarksList, iMaterialIndex); // Vec3r center; // for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end(); diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h index 9ec8fd4bddb..1734ad1b41f 100755 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.h +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h @@ -499,7 +499,7 @@ public: * determines the face's edges orientation and (so) the * face orientation. */ - virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex); + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex); /*! adds a new face to the shape. The difference with * the previous method is that this one is designed @@ -520,7 +520,7 @@ public: * The list of tex coords, iTexCoordsList[i] corresponding to the * normal of the vertex iVertexList[i] for that face. */ - virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex); + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex); /*! Reset all edges and vertices flags (which might * have been set up on a previous pass) diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp index a0a80b7ef64..40c14eafe72 100755 --- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp +++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp @@ -102,6 +102,8 @@ void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) { // else if(_current_frs_material) // shape.setFrsMaterial(*_current_frs_material); + const IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = ifs.faceEdgeMarks(); + // sets the current WShape to shape _current_wshape = &shape; @@ -128,6 +130,7 @@ void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) { new_normals, frs_materials, texCoords, + faceEdgeMarks, vindices, nindices, mindices, @@ -139,6 +142,7 @@ void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) { new_normals, frs_materials, texCoords, + faceEdgeMarks, vindices, nindices, mindices, @@ -150,6 +154,7 @@ void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) { new_normals, frs_materials, texCoords, + faceEdgeMarks, vindices, nindices, mindices, @@ -163,6 +168,7 @@ void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) { mindices += numVertexPerFace[index]; if(tindices) tindices += numVertexPerFace[index]; + faceEdgeMarks++; } delete[] new_vertices; @@ -219,6 +225,7 @@ void WingedEdgeBuilder::buildTriangleStrip( const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials, const real *texCoords, + const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, @@ -232,6 +239,7 @@ void WingedEdgeBuilder::buildTriangleStrip( const real *vertices, vector<WVertex *> triangleVertices; vector<Vec3r> triangleNormals; vector<Vec2r> triangleTexCoords; + vector<bool> triangleFaceEdgeMarks; while(nDoneVertices < nvertices) { @@ -270,10 +278,14 @@ void WingedEdgeBuilder::buildTriangleStrip( const real *vertices, triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]], texCoords[tindices[nTriangle+1]+1])); } } + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::FACE_MARK) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V1V2) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V2V3) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V3V1) != 0); if(mindices) - currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, mindices[nTriangle/3]); + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, mindices[nTriangle/3]); else - currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, 0); + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0); nDoneVertices++; // with a strip, each triangle is one vertex more nTriangle++; } @@ -283,6 +295,7 @@ void WingedEdgeBuilder::buildTriangleFan( const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials, const real *texCoords, + const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, @@ -295,6 +308,7 @@ void WingedEdgeBuilder::buildTriangles(const real *vertices, const real *normals, vector<FrsMaterial>& iMaterials, const real *texCoords, + const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, @@ -304,6 +318,7 @@ void WingedEdgeBuilder::buildTriangles(const real *vertices, vector<WVertex *> triangleVertices; vector<Vec3r> triangleNormals; vector<Vec2r> triangleTexCoords; + vector<bool> triangleFaceEdgeMarks; // Each triplet of vertices is considered as an independent triangle for(unsigned i = 0; i < nvertices / 3; i++) @@ -321,11 +336,16 @@ void WingedEdgeBuilder::buildTriangles(const real *vertices, triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+1]],texCoords[tindices[3*i+1]+1])); triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+2]], texCoords[tindices[3*i+2]+1])); } + + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::FACE_MARK) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V1V2) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V2V3) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V3V1) != 0); } if(mindices) - currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, mindices[0]); + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, mindices[0]); else - currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords,0); + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0); } diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h index 6bd515aef0b..8e9d0122e35 100755 --- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h +++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h @@ -114,6 +114,7 @@ class LIB_WINGED_EDGE_EXPORT WingedEdgeBuilder : public SceneVisitor const real *normals, vector<FrsMaterial>& iMaterials, const real *texCoords, + const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, @@ -124,6 +125,7 @@ class LIB_WINGED_EDGE_EXPORT WingedEdgeBuilder : public SceneVisitor const real *normals, vector<FrsMaterial>& iMaterials, const real *texCoords, + const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, @@ -134,6 +136,7 @@ class LIB_WINGED_EDGE_EXPORT WingedEdgeBuilder : public SceneVisitor const real *normals, vector<FrsMaterial>& iMaterials, const real *texCoords, + const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h index 3eec6a97172..08b4f406223 100644 --- a/source/blender/makesdna/DNA_freestyle_types.h +++ b/source/blender/makesdna/DNA_freestyle_types.h @@ -51,12 +51,15 @@ struct FreestyleLineStyle; #define FREESTYLE_LINESET_FE_NOT 4 #define FREESTYLE_LINESET_FE_AND 8 #define FREESTYLE_LINESET_GR_NOT 16 +#define FREESTYLE_LINESET_FM_NOT 32 +#define FREESTYLE_LINESET_FM_BOTH 64 /* FreestyleLineSet::selection */ #define FREESTYLE_SEL_VISIBILITY 1 #define FREESTYLE_SEL_EDGE_TYPES 2 #define FREESTYLE_SEL_GROUP 4 #define FREESTYLE_SEL_IMAGE_BORDER 8 +#define FREESTYLE_SEL_FACE_MARK 16 /* FreestyleLineSet::fedge_types */ #define FREESTYLE_FE_SILHOUETTE 1 @@ -68,6 +71,7 @@ struct FreestyleLineStyle; #define FREESTYLE_FE_MATERIAL_BOUNDARY 64 #define FREESTYLE_FE_CONTOUR 128 #define FREESTYLE_FE_EXTERNAL_CONTOUR 512 +#define FREESTYLE_FE_EDGE_MARK 1024 /* FreestyleLineSet::qi */ #define FREESTYLE_QI_VISIBLE 1 diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 25bb4958c97..51829d464a1 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -157,6 +157,9 @@ typedef struct TFace { #define ME_DRAWEXTRA_FACEAREA (1 << 11) #define ME_DRAWEXTRA_FACEANG (1 << 12) +#define ME_DRAW_FREESTYLE_EDGE (1 << 13) +#define ME_DRAW_FREESTYLE_FACE (1 << 14) + /* old global flags: #define G_DRAWEDGES (1 << 18) #define G_DRAWFACES (1 << 7) diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 9d7375b6755..d62907d48cf 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -204,6 +204,7 @@ typedef struct MRecast{ #define ME_LOOSEEDGE (1<<7) #define ME_SEAM_LAST (1<<8) #define ME_SHARP (1<<9) +#define ME_FREESTYLE_EDGE (1<<10) /* puno = vertexnormal (mface) */ /* render assumes flips to be ordered like this */ @@ -225,6 +226,7 @@ typedef struct MRecast{ /* flag (mface) */ #define ME_SMOOTH 1 #define ME_FACE_SEL 2 +#define ME_FREESTYLE_FACE 4 /* flag ME_HIDE==16 is used here too */ /* mselect->type */ #define ME_VSEl 0 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 9bcaf46f0d7..790f1bf542f 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1241,6 +1241,7 @@ typedef enum SculptFlags { #define EDGE_MODE_TAG_SHARP 2 #define EDGE_MODE_TAG_CREASE 3 #define EDGE_MODE_TAG_BEVEL 4 +#define EDGE_MODE_TAG_FREESTYLE 5 /* toolsettings->gpencil_flags */ #define GP_TOOL_FLAG_PAINTSESSIONS_ON (1<<0) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 05b16f869a8..9b28f55a139 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -210,6 +210,7 @@ typedef struct ThemeSpace { char bone_solid[4], bone_pose[4]; char strip[4], strip_select[4]; char cframe[4]; + char freestyle_edge_mark[4], freestyle_face_mark[4]; char nurb_uline[4], nurb_vline[4]; char act_spline[4], nurb_sel_uline[4], nurb_sel_vline[4], lastsel_point[4]; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 67bb7bffcfb..45094e3cf7a 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -1284,6 +1284,11 @@ static void rna_def_medge(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Sharp", "Sharp edge for the EdgeSplit modifier"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + prop= RNA_def_property(srna, "use_freestyle_edge_mark", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FREESTYLE_EDGE); + RNA_def_property_ui_text(prop, "Freestyle Edge Mark", "Edge mark for Freestyle feature edge detection"); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + prop= RNA_def_property(srna, "is_loose", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_LOOSEEDGE); RNA_def_property_ui_text(prop, "Loose", "Loose edge"); @@ -1344,6 +1349,11 @@ static void rna_def_mface(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Smooth", ""); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + prop= RNA_def_property(srna, "use_freestyle_face_mark", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FREESTYLE_FACE); + RNA_def_property_ui_text(prop, "Freestyle Face Mark", "Face mark for Freestyle feature edge detection"); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + prop= RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1.0f, 1.0f); @@ -2080,6 +2090,16 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Sharp", "Display sharp edges, used with the EdgeSplit modifier"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + prop= RNA_def_property(srna, "show_freestyle_edge_marks", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_FREESTYLE_EDGE); + RNA_def_property_ui_text(prop, "Draw Freestyle Edge Marks", "Display Freestyle edge marks, used with the Freestyle renderer"); + RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + + prop= RNA_def_property(srna, "show_freestyle_face_marks", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_FREESTYLE_FACE); + RNA_def_property_ui_text(prop, "Draw Freestyle Face Marks", "Display Freestyle face marks, used with the Freestyle renderer"); + RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + prop= RNA_def_property(srna, "show_extra_edge_length", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_EDGELEN); RNA_def_property_ui_text(prop, "Edge Length", diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 2058edc6736..6e413f26206 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1168,6 +1168,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) {EDGE_MODE_TAG_SHARP, "SHARP", 0, "Tag Sharp", ""}, {EDGE_MODE_TAG_CREASE, "CREASE", 0, "Tag Crease", ""}, {EDGE_MODE_TAG_BEVEL, "BEVEL", 0, "Tag Bevel", ""}, + {EDGE_MODE_TAG_FREESTYLE, "FREESTYLE", 0, "Tag Freestyle Edge Mark", ""}, {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "ToolSettings", NULL); @@ -1788,6 +1789,16 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) {FREESTYLE_LINESET_GR_NOT, "EXCLUSIVE", 0, "Exclusive", "Select feature edges not belonging to any object in the group."}, {0, NULL, 0, NULL, NULL}}; + static EnumPropertyItem face_mark_negation_items[] = { + {0, "INCLUSIVE", 0, "Inclusive", "Select feature edges satisfying the given face mark conditions."}, + {FREESTYLE_LINESET_FM_NOT, "EXCLUSIVE", 0, "Exclusive", "Select feature edges not satisfying the given face mark conditions."}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem face_mark_condition_items[] = { + {0, "ONE", 0, "One Face", "Select feature edges if one of faces on the right and left has a face mark."}, + {FREESTYLE_LINESET_FM_BOTH, "BOTH", 0, "Both Faces", "Select feature edges if both faces on the right and left faces have a face mark."}, + {0, NULL, 0, NULL, NULL}}; + static EnumPropertyItem freestyle_ui_mode_items[] = { {FREESTYLE_CONTROL_SCRIPT_MODE, "SCRIPT", 0, "Python Scripting Mode", "Advanced mode for using style modules in Python"}, {FREESTYLE_CONTROL_EDITOR_MODE, "EDITOR", 0, "Parameter Editor Mode", "Basic mode for interactive style parameter editing"}, @@ -1855,6 +1866,11 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Selection by Image Border", "Select feature edges by image border (less memory consumption)."); RNA_def_property_update(prop, NC_SCENE, NULL); + prop= RNA_def_property(srna, "select_by_face_marks", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_FACE_MARK); + RNA_def_property_ui_text(prop, "Selection by Face Marks", "Select feature edges by face marks."); + RNA_def_property_update(prop, NC_SCENE, NULL); + prop= RNA_def_property(srna, "edge_type_negation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); RNA_def_property_enum_items(prop, edge_type_negation_items); @@ -1877,7 +1893,19 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) prop= RNA_def_property(srna, "group_negation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); RNA_def_property_enum_items(prop, group_negation_items); - RNA_def_property_ui_text(prop, "Edge Type Negation", "Set the negation operation for conditions on feature edge types."); + RNA_def_property_ui_text(prop, "Group Negation", "Set the negation operation for conditions on feature edge types."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "face_mark_negation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); + RNA_def_property_enum_items(prop, face_mark_negation_items); + RNA_def_property_ui_text(prop, "Face Mark Negation", "Set the negation operation for the condition on face marks."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "face_mark_condition", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); + RNA_def_property_enum_items(prop, face_mark_condition_items); + RNA_def_property_ui_text(prop, "Face Mark Condition", "Set a feature edge selection condition on face marks."); RNA_def_property_update(prop, NC_SCENE, NULL); prop= RNA_def_property(srna, "select_silhouette", PROP_BOOLEAN, PROP_NONE); @@ -1925,6 +1953,11 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "External Contour", "Select external contours."); RNA_def_property_update(prop, NC_SCENE, NULL); + prop= RNA_def_property(srna, "select_edge_mark", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EDGE_MARK); + RNA_def_property_ui_text(prop, "Edge Mark", "Select edge marks."); + RNA_def_property_update(prop, NC_SCENE, NULL); + prop= RNA_def_property(srna, "visibility", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "qi"); RNA_def_property_enum_items(prop, visibility_items); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 44d645f970f..35c7b26b49a 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -778,6 +778,11 @@ static void rna_def_userdef_theme_spaces_edge(StructRNA *srna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Edge UV Face Select", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "freestyle_edge_mark", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Freestyle Edge Mark", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_spaces_face(StructRNA *srna) @@ -803,6 +808,11 @@ static void rna_def_userdef_theme_spaces_face(StructRNA *srna) RNA_def_property_range(prop, 1, 10); RNA_def_property_ui_text(prop, "Face Dot Size", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "freestyle_face_mark", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Freestyle Face Mark", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, short incl_nurbs) diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 7a38cd4ae4d..1fd377b2afc 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -385,6 +385,7 @@ typedef struct VlakRen { struct Material *mat; char puno; char flag, ec; + char freestyle_edge_mark; int index; } VlakRen; @@ -620,6 +621,13 @@ typedef struct LampRen { #define R_TANGENT 64 #define R_TRACEBLE 128 +/* vlakren->freestyle_edge_mark */ +#define R_EDGE_V1V2 1 +#define R_EDGE_V2V3 2 +#define R_EDGE_V3V4 4 +#define R_EDGE_V3V1 4 +#define R_EDGE_V4V1 8 + /* strandbuffer->flag */ #define R_STRAND_BSPLINE 1 #define R_STRAND_B_UNITS 2 diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 27c825ebdeb..310fc516a16 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -44,6 +44,7 @@ #include "BLI_rand.h" #include "BLI_memarena.h" #include "BLI_ghash.h" +#include "BLI_edgehash.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" @@ -2735,7 +2736,7 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr, v2= mface->v2; v3= mface->v3; v4= mface->v4; - flag= mface->flag & ME_SMOOTH; + flag= mface->flag & (ME_SMOOTH | ME_FREESTYLE_FACE); vlr= RE_findOrAddVlak(obr, obr->totvlak++); vlr->v1= RE_findOrAddVert(obr, vertofs+v1); @@ -3235,6 +3236,24 @@ static void add_volume(Render *re, ObjectRen *obr, Material *ma) BLI_addtail(&re->volumes, vo); } +static EdgeHash *make_freestyle_edge_mark_hash(MEdge *medge, int totedge) +{ + EdgeHash *edge_hash= BLI_edgehash_new(); + int a; + + for(a=0; a<totedge; a++) { + if(medge[a].flag & ME_FREESTYLE_EDGE) + BLI_edgehash_insert(edge_hash, medge[a].v1, medge[a].v2, medge+a); + } + return edge_hash; +} + +static int has_freestyle_edge_mark(EdgeHash *edge_hash, int v1, int v2) +{ + MEdge *medge= BLI_edgehash_lookup(edge_hash, v1, v2); + return (!medge) ? 0 : 1; +} + static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; @@ -3365,6 +3384,15 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) } if(!timeoffset) { + EdgeHash *edge_hash; + MEdge *medge; + int totedge; + + /* create a hash table of Freestyle edge marks */ + medge= dm->getEdgeArray(dm); + totedge= dm->getNumEdges(dm); + edge_hash= make_freestyle_edge_mark_hash(medge, totedge); + /* store customdata names, because DerivedMesh is freed */ RE_set_customdata_names(obr, &dm->faceData); @@ -3407,12 +3435,13 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if( mface->mat_nr==a1 ) { float len; + int edge_mark= 0; v1= mface->v1; v2= mface->v2; v3= mface->v3; v4= mface->v4; - flag= mface->flag & ME_SMOOTH; + flag= mface->flag & (ME_SMOOTH | ME_FREESTYLE_FACE); vlr= RE_findOrAddVlak(obr, obr->totvlak++); vlr->v1= RE_findOrAddVert(obr, vertofs+v1); @@ -3421,6 +3450,17 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if(v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4); else vlr->v4= 0; + /* Freestyle edge marks */ + if(has_freestyle_edge_mark(edge_hash, v1, v2)) edge_mark |= R_EDGE_V1V2; + if(has_freestyle_edge_mark(edge_hash, v2, v3)) edge_mark |= R_EDGE_V2V3; + if (!v4) { + if(has_freestyle_edge_mark(edge_hash, v3, v1)) edge_mark |= R_EDGE_V3V1; + } else { + if(has_freestyle_edge_mark(edge_hash, v3, v4)) edge_mark |= R_EDGE_V3V4; + if(has_freestyle_edge_mark(edge_hash, v4, v1)) edge_mark |= R_EDGE_V4V1; + } + vlr->freestyle_edge_mark= edge_mark; + /* render normals are inverted in render */ if(use_original_normals) { MFace *mf= me->mface+a; @@ -3486,6 +3526,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) } } } + + /* release the hash table of Freestyle edge marks */ + BLI_edgehash_free(edge_hash, NULL); /* exception... we do edges for wire mode. potential conflict when faces exist... */ end= dm->getNumEdges(dm); @@ -4271,6 +4314,23 @@ static void check_non_flat_quads(ObjectRen *obr) /* new normals */ normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); normal_tri_v3( vlr1->n,vlr1->v3->co, vlr1->v2->co, vlr1->v1->co); + + /* Freestyle edge marks */ + if (vlr->flag & R_DIVIDE_24) { + vlr1->freestyle_edge_mark= + ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V1V2 : 0) | + ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0); + vlr->freestyle_edge_mark= + ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) | + ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0); + } else { + vlr1->freestyle_edge_mark= + ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0) | + ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0); + vlr->freestyle_edge_mark= + ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) | + ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V2V3 : 0); + } } /* clear the flag when not divided */ else vlr->flag &= ~R_DIVIDE_24; |