Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2011-10-06 06:04:43 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2011-10-06 06:04:43 +0400
commitf84e8e76406a30bd15e6e55e41714e62826315aa (patch)
treee4a077ee05de21155421b35854162ad5f29c53b3 /source/blender
parentcb4f6629279ba9792cc46114fe603bebff11c6a3 (diff)
Fine control of feature edge selection with mesh face and edge marks.
New "face marks" and "edge marks" have been introduced in mesh data blocks. In the edit mode of a mesh object, face marks can be put to selected faces by choosing Mesh >> Faces >> Mark Freestyle Face from the menu of a 3D View window or Ctrl-F >> Mark Freestyle Face from the context menu. Similarly, edge marks can be put to selected edges by Mesh >> Edges >> Mark Freestyle Edge or Ctrl-E >> Mark Freestyle Edge. These marks should work fine with the Subdivision surface modifier. Moreover, two new conditions for feature edge selection have been added to the Parameter Editor mode as described below: 1. The Selection by Edge Types option has now the new Edge Mark type, which can be used to (de)select feature edges having edge marks. This option can be used to add to (or remove from) the view map arbitrary edges of mesh objects. 2. Selection by Face Marks option has been newly introduced, in which face marks are used for feature edge selection in two ways. One option is called "One Face" which is to (de)select feature edges if one of faces on the left and right of each feature edge has a face mark. The other option is "Both Faces" to (de)select feature edges if both faces on the left and right have a face mark.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/intern/BME_conversions.c2
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c2
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c1
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c4
-rw-r--r--source/blender/blenlib/BLI_editVert.h2
-rw-r--r--source/blender/editors/include/UI_resources.h5
-rw-r--r--source/blender/editors/interface/resources.c19
-rw-r--r--source/blender/editors/mesh/editface.c6
-rw-r--r--source/blender/editors/mesh/editmesh.c7
-rw-r--r--source/blender/editors/mesh/editmesh_mods.c71
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c52
-rw-r--r--source/blender/editors/mesh/mesh_intern.h2
-rw-r--r--source/blender/editors/mesh/mesh_ops.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c58
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp51
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h7
-rw-r--r--source/blender/freestyle/intern/python/BPy_Nature.cpp9
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp68
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp33
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp15
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/IndexedFaceSet.h11
-rwxr-xr-xsource/blender/freestyle/intern/view_map/FEdgeXDetector.cpp21
-rwxr-xr-xsource/blender/freestyle/intern/view_map/FEdgeXDetector.h11
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Silhouette.h25
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp8
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/Nature.h2
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WEdge.cpp18
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WEdge.h12
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdge.cpp8
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdge.h4
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp28
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h3
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h4
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h3
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c20
-rw-r--r--source/blender/makesrna/intern/rna_scene.c35
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c10
-rw-r--r--source/blender/render/intern/include/render_types.h8
-rw-r--r--source/blender/render/intern/source/convertblender.c64
42 files changed, 664 insertions, 51 deletions
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;