[Bf-blender-cvs] [72efee07ff8] blender2.8: Draw Manager: draw curve normals

Campbell Barton noreply at git.blender.org
Wed Apr 19 21:32:31 CEST 2017


Commit: 72efee07ff837ca4651e25b63c0029b81e2d61b1
Author: Campbell Barton
Date:   Thu Apr 20 05:23:48 2017 +1000
Branches: blender2.8
https://developer.blender.org/rB72efee07ff837ca4651e25b63c0029b81e2d61b1

Draw Manager: draw curve normals

===================================================================

M	source/blender/blenkernel/BKE_curve_render.h
M	source/blender/blenkernel/intern/curve_render.c
M	source/blender/draw/intern/draw_cache.c
M	source/blender/draw/intern/draw_cache.h
M	source/blender/draw/modes/edit_curve_mode.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_curve_render.h b/source/blender/blenkernel/BKE_curve_render.h
index f05dc691d06..6c37b6e875b 100644
--- a/source/blender/blenkernel/BKE_curve_render.h
+++ b/source/blender/blenkernel/BKE_curve_render.h
@@ -32,6 +32,8 @@ void BKE_curve_batch_selection_dirty(struct Curve *cu);
 void BKE_curve_batch_cache_clear(struct Curve *cu);
 void BKE_curve_batch_cache_free(struct Curve *cu);
 struct Batch *BKE_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache);
+struct Batch *BKE_curve_batch_cache_get_normal_edge(
+        struct Curve *cu, struct CurveCache *ob_curve_cache, float normal_size);
 struct Batch *BKE_curve_batch_cache_get_overlay_edges(struct Curve *cu);
 struct Batch *BKE_curve_batch_cache_get_overlay_verts(struct Curve *cu);
 
diff --git a/source/blender/blenkernel/intern/curve_render.c b/source/blender/blenkernel/intern/curve_render.c
index 09e1cee6f11..31ec2ccc760 100644
--- a/source/blender/blenkernel/intern/curve_render.c
+++ b/source/blender/blenkernel/intern/curve_render.c
@@ -107,6 +107,26 @@ static void curve_render_wire_verts_edges_len_get(
 	}
 }
 
+static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
+{
+	int normal_len = 0;
+	const BevList *bl;
+	const Nurb *nu;
+	for (bl = ob_curve_cache->bev.first, nu = lb->first; nu && bl; bl = bl->next, nu = nu->next) {
+		int nr = bl->nr;
+		int skip = nu->resolu / 16;
+#if 0
+		while (nr-- > 0) { /* accounts for empty bevel lists */
+			normal_len += 1;
+			nr -= skip;
+		}
+#else
+		normal_len += max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0);
+#endif
+	}
+	return normal_len;
+}
+
 /* ---------------------------------------------------------------------- */
 /* Curve Interface, indirect, partially cached access to complex data. */
 
@@ -123,7 +143,15 @@ typedef struct CurveRenderData {
 		int edge_len;
 	} wire;
 
+	/* edit mode normal's */
+	struct {
+		/* 'edge_len == len * 2'
+		 * 'vert_len == len * 3' */
+		int len;
+	} normal;
+
 	bool hide_handles;
+	bool hide_normals;
 
 	/* borrow from 'Object' */
 	CurveCache *ob_curve_cache;
@@ -143,6 +171,8 @@ enum {
 	CU_DATATYPE_WIRE        = 1 << 0,
 	/* Edit-mode verts and optionally handles */
 	CU_DATATYPE_OVERLAY     = 1 << 1,
+	/* Edit-mode normals */
+	CU_DATATYPE_NORMAL      = 1 << 2,
 };
 
 /*
@@ -155,6 +185,8 @@ static CurveRenderData *curve_render_data_create(Curve *cu, CurveCache *ob_curve
 	ListBase *nurbs;
 
 	lrdata->hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0;
+	lrdata->hide_normals = (cu->drawflag & CU_HIDE_NORMALS) != 0;
+
 	lrdata->actnu = cu->actnu;
 	lrdata->actvert = cu->actvert;
 
@@ -181,6 +213,9 @@ static CurveRenderData *curve_render_data_create(Curve *cu, CurveCache *ob_curve
 			lrdata->actnu = cu->actnu;
 			lrdata->actvert = cu->actvert;
 		}
+		if (types & CU_DATATYPE_NORMAL) {
+			lrdata->normal.len = curve_render_normal_len_get(nurbs, lrdata->ob_curve_cache);
+		}
 	}
 	else {
 		nurbs = &cu->nurb;
@@ -225,13 +260,11 @@ static int curve_render_data_wire_edges_len_get(const CurveRenderData *lrdata)
 	return lrdata->wire.edge_len;
 }
 
-#if 0
-static const BPoint *curve_render_data_vert_bpoint(const CurveRenderData *lrdata, const int vert_idx)
+static int curve_render_data_normal_len_get(const CurveRenderData *lrdata)
 {
-	BLI_assert(lrdata->types & CU_DATATYPE_VERT);
-	return &lrdata->bp[vert_idx];
+	BLI_assert(lrdata->types & CU_DATATYPE_NORMAL);
+	return lrdata->normal.len;
 }
-#endif
 
 enum {
 	VFLAG_VERTEX_SELECTED = 1 << 0,
@@ -250,6 +283,14 @@ typedef struct CurveBatchCache {
 		ElementList *elem;
 	} wire;
 
+	/* normals */
+	struct {
+		VertexBuffer *verts;
+		VertexBuffer *edges;
+		Batch *batch;
+		ElementList *elem;
+	} normal;
+
 	/* control handles and vertices */
 	struct {
 		Batch *edges;
@@ -260,6 +301,9 @@ typedef struct CurveBatchCache {
 	bool is_dirty;
 
 	bool hide_handles;
+	bool hide_normals;
+
+	float normal_size;
 
 	bool is_editmode;
 } CurveBatchCache;
@@ -289,6 +333,9 @@ static bool curve_batch_cache_valid(Curve *cu)
 		else if ((cache->hide_handles != ((cu->drawflag & CU_HIDE_HANDLES) != 0))) {
 			return false;
 		}
+		else if ((cache->hide_normals != ((cu->drawflag & CU_HIDE_NORMALS) != 0))) {
+			return false;
+		}
 	}
 
 	return true;
@@ -306,6 +353,7 @@ static void curve_batch_cache_init(Curve *cu)
 	}
 
 	cache->hide_handles = (cu->flag & CU_HIDE_HANDLES) != 0;
+	cache->hide_normals = (cu->flag & CU_HIDE_NORMALS) != 0;
 
 #if 0
 	ListBase *nurbs;
@@ -368,6 +416,15 @@ void BKE_curve_batch_cache_clear(Curve *cu)
 		VERTEXBUFFER_DISCARD_SAFE(cache->wire.edges);
 		ELEMENTLIST_DISCARD_SAFE(cache->wire.elem);
 	}
+
+	if (cache->normal.batch) {
+		BATCH_DISCARD_ALL_SAFE(cache->normal.batch);
+	}
+	else {
+		VERTEXBUFFER_DISCARD_SAFE(cache->normal.verts);
+		VERTEXBUFFER_DISCARD_SAFE(cache->normal.edges);
+		ELEMENTLIST_DISCARD_SAFE(cache->normal.elem);
+	}
 }
 
 void BKE_curve_batch_cache_free(Curve *cu)
@@ -417,7 +474,7 @@ static ElementList *curve_batch_cache_get_wire_edges(CurveRenderData *lrdata, Cu
 	if (cache->wire.edges == NULL) {
 		const int vert_len = curve_render_data_wire_verts_len_get(lrdata);
 		const int edge_len = curve_render_data_wire_edges_len_get(lrdata);
-		int edge_len_real = 0;
+		int edge_len_used = 0;
 
 		ElementListBuilder elb;
 		ElementListBuilder_init(&elb, PRIM_LINES, edge_len, vert_len);
@@ -437,16 +494,16 @@ static ElementList *curve_batch_cache_get_wire_edges(CurveRenderData *lrdata, Cu
 				}
 				for (; i < i_end; i_prev = i++) {
 					add_line_vertices(&elb, i_prev, i);
-					edge_len_real += 1;
+					edge_len_used += 1;
 				}
 			}
 		}
 
 		if (lrdata->hide_handles) {
-			BLI_assert(edge_len_real <= edge_len);
+			BLI_assert(edge_len_used <= edge_len);
 		}
 		else {
-			BLI_assert(edge_len_real == edge_len);
+			BLI_assert(edge_len_used == edge_len);
 		}
 
 		cache->wire.elem = ElementList_build(&elb);
@@ -455,6 +512,99 @@ static ElementList *curve_batch_cache_get_wire_edges(CurveRenderData *lrdata, Cu
 	return cache->wire.elem;
 }
 
+static VertexBuffer *curve_batch_cache_get_normal_verts(CurveRenderData *lrdata, CurveBatchCache *cache)
+{
+	BLI_assert(lrdata->types & CU_DATATYPE_NORMAL);
+	BLI_assert(lrdata->ob_curve_cache != NULL);
+
+	if (cache->normal.verts == NULL) {
+		static VertexFormat format = { 0 };
+		static unsigned pos_id;
+		if (format.attrib_ct == 0) {
+			/* initialize vertex format */
+			pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+		}
+
+		const int normal_len = curve_render_data_normal_len_get(lrdata);
+		const int vert_len = normal_len * 3;
+
+		VertexBuffer *vbo = cache->normal.verts = VertexBuffer_create_with_format(&format);
+		VertexBuffer_allocate_data(vbo, vert_len);
+		int vbo_len_used = 0;
+
+		const BevList *bl;
+		const Nurb *nu;
+
+		for (bl = lrdata->ob_curve_cache->bev.first, nu = lrdata->nurbs->first;
+		     nu && bl;
+		     bl = bl->next, nu = nu->next)
+		{
+			const BevPoint *bevp = bl->bevpoints;
+			int nr = bl->nr;
+			int skip = nu->resolu / 16;
+
+			while (nr-- > 0) { /* accounts for empty bevel lists */
+				const float fac = bevp->radius * cache->normal_size;
+				float vec_a[3]; /* Offset perpendicular to the curve */
+				float vec_b[3]; /* Delta along the curve */
+
+				vec_a[0] = fac;
+				vec_a[1] = 0.0f;
+				vec_a[2] = 0.0f;
+
+				vec_b[0] = -fac;
+				vec_b[1] = 0.0f;
+				vec_b[2] = 0.0f;
+
+				mul_qt_v3(bevp->quat, vec_a);
+				mul_qt_v3(bevp->quat, vec_b);
+				add_v3_v3(vec_a, bevp->vec);
+				add_v3_v3(vec_b, bevp->vec);
+
+				madd_v3_v3fl(vec_a, bevp->dir, -fac);
+				madd_v3_v3fl(vec_b, bevp->dir, -fac);
+
+				VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used++, vec_a);
+				VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used++, bevp->vec);
+				VertexBuffer_set_attrib(vbo, pos_id, vbo_len_used++, vec_b);
+
+				bevp += skip + 1;
+				nr -= skip;
+			}
+		}
+		BLI_assert(vbo_len_used == vert_len);
+	}
+
+	return cache->normal.verts;
+}
+
+static ElementList *curve_batch_cache_get_normal_edges(CurveRenderData *lrdata, CurveBatchCache *cache)
+{
+	BLI_assert(lrdata->types & CU_DATATYPE_NORMAL);
+	BLI_assert(lrdata->ob_curve_cache != NULL);
+
+	if (cache->normal.edges == NULL) {
+		const int normal_len = curve_render_data_normal_len_get(lrdata);
+		const int edge_len = normal_len * 2;
+
+		ElementListBuilder elb;
+		ElementListBuilder_init(&elb, PRIM_LINES, edge_len, normal_len * 2);
+
+		int vbo_len_used = 0;
+		for (int i = 0; i < normal_len; i++) {
+			add_line_vertices(&elb, vbo_len_used + 0, vbo_len_used + 1);
+			add_line_vertices(&elb, vbo_len_used + 1, vbo_len_used + 2);
+			vbo_len_used += 3;
+		}
+
+		BLI_assert(vbo_len_used == normal_len * 3);
+
+		cache->normal.elem = ElementList_build(&elb);
+	}
+
+	return cache->normal.elem;
+}
+
 static void curve_batch_cache_create_overlay_batches(Curve *cu)
 {
 	/* Since CU_DATATYPE_OVERLAY is slow to generate, generate them all at once */
@@ -618,10 +768,36 @@ Batch *BKE_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache
 
 		curve_render_data_free(lrdata);
 	}
-
 	return cache->wire.batch;
 }
 
+Batch *BKE_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve_cache, float normal_size)
+{
+	CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+	if (cache->normal.batch != NULL) {
+		cache->normal_size = normal_size;
+		if (cache->normal_size != normal_size) {
+			BATCH_DISCARD_ALL_SAFE(cache->normal.batch);
+		}
+	}
+	cache->normal_size = normal_size;
+
+	if (cache->normal.batch == NULL) {
+		/* create batch from Curve */
+		CurveRenderData *lrdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_NORMAL);
+
+		cache->normal.batch = Batch_create(
+		        PRIM_LINES,
+		        curve_batch_cache_get_normal_verts(lrdata, cache),
+		        curve_batch_cache_get_normal_edges(lrdata, cache));
+
+		curve_render_data_free(lrdata);
+		cache->normal_size = normal_size;
+	}
+	return cache->normal.batch;
+}
+
 Batch *BKE_curve_batch_cache_get_overlay_edges(Curve *cu)
 {
 	CurveBatchCache *cache = curve_batch_cache_get(cu);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index fdd0cc189e5..4

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list