[Bf-blender-cvs] [9a79178c2eb] blender2.8: Armature: Add back Stick bone draw type.

Clément Foucault noreply at git.blender.org
Tue May 8 12:18:37 CEST 2018


Commit: 9a79178c2eb79e724077d38cd2dd964d0b6ca0ea
Author: Clément Foucault
Date:   Tue May 8 12:05:06 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB9a79178c2eb79e724077d38cd2dd964d0b6ca0ea

Armature: Add back Stick bone draw type.

The actual code is a bit convoluted but allows good and "pseudo efficient"
drawing. (pseudo efficient because rendering instances with that amount of
vertices is really inneficient. We should go full procedural but need to
have bufferTexture implemented first) But drawing speed is not a bottleneck
here and it's already a million time less crappy than the old (2.79) immediate
mode method.

Instead of drawing actual wires with different width we render a triangle
fan batch (containing 3 fans: bone, head, tail) which is then oriented in
screen space to the bone direction. We then interpolate a float value
accross vertices giving us a nice blend factor to blend the colors and
gives us really smooth interpolation inside the bone.

The outside edge still being geometry will be antialiased by MSAA if enabled.

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/intern/draw_armature.c
M	source/blender/draw/intern/draw_cache.c
M	source/blender/draw/intern/draw_cache.h
M	source/blender/draw/intern/draw_common.c
M	source/blender/draw/intern/draw_common.h
A	source/blender/draw/modes/shaders/armature_stick_frag.glsl
A	source/blender/draw/modes/shaders/armature_stick_vert.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 53d46575a62..71285d7ba04 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -236,6 +236,8 @@ data_to_c_simple(modes/shaders/armature_shape_solid_vert.glsl SRC)
 data_to_c_simple(modes/shaders/armature_shape_solid_frag.glsl SRC)
 data_to_c_simple(modes/shaders/armature_shape_outline_vert.glsl SRC)
 data_to_c_simple(modes/shaders/armature_shape_outline_geom.glsl SRC)
+data_to_c_simple(modes/shaders/armature_stick_vert.glsl SRC)
+data_to_c_simple(modes/shaders/armature_stick_frag.glsl SRC)
 data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC)
 data_to_c_simple(modes/shaders/edit_mesh_overlay_vert.glsl SRC)
 data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_tri.glsl SRC)
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 1a2ff70624b..efbf1143c16 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -82,6 +82,7 @@ static struct {
 	DRWShadingGroup *bone_box_wire;
 	DRWShadingGroup *bone_box_outline;
 	DRWShadingGroup *bone_wire_wire;
+	DRWShadingGroup *bone_stick;
 	DRWShadingGroup *bone_envelope_solid;
 	DRWShadingGroup *bone_envelope_distance;
 	DRWShadingGroup *bone_envelope_wire;
@@ -181,6 +182,20 @@ static void drw_shgroup_bone_wire_wire(const float (*bone_mat)[4], const float c
 	DRW_shgroup_call_dynamic_add(g_data.bone_wire_wire, final_bonemat, color);
 }
 
+static void drw_shgroup_bone_stick(
+        const float (*bone_mat)[4],
+        const float col_wire[4], const float col_bone[4], const float col_head[4], const float col_tail[4])
+{
+	if (g_data.bone_stick == NULL) {
+		g_data.bone_stick = shgroup_instance_bone_stick(g_data.passes.bone_wire);
+	}
+	float final_bonemat[4][4], tail[4];
+	mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+	add_v3_v3v3(tail, final_bonemat[3], final_bonemat[1]);
+	DRW_shgroup_call_dynamic_add(g_data.bone_stick, final_bonemat[3], tail, col_wire, col_bone, col_head, col_tail);
+}
+
+
 /* Envelope */
 static void drw_shgroup_bone_envelope_distance(
         const float (*bone_mat)[4],
@@ -1192,11 +1207,62 @@ static void draw_bone_envelope(
 }
 
 static void draw_bone_line(
-        EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm),
-        const int UNUSED(boneflag), const short UNUSED(constflag),
-        const int UNUSED(select_id))
+        EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
+        const int boneflag, const short constflag, const int select_id)
 {
-	/* work in progress  -- fclem */
+	const float *col_bone = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag);
+	const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
+	const float no_display[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+	const float *col_head = no_display;
+	const float *col_tail = col_bone;
+
+	if (eBone) {
+		if (eBone->flag & BONE_TIPSEL) {
+			col_tail = g_theme.vertex_select_color;
+		}
+		if (boneflag & BONE_SELECTED) {
+			col_bone = g_theme.edge_select_color;
+		}
+		col_wire = g_theme.wire_color;
+	}
+
+	/*	Draw root point if we are not connected and parent are not hidden */
+	if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) {
+		if (eBone && !(eBone->parent && !EBONE_VISIBLE(arm, eBone->parent))) {
+			col_head = (eBone->flag & BONE_ROOTSEL) ? g_theme.vertex_select_color : col_bone;
+		}
+		else if (pchan) {
+			Bone *bone = pchan->bone;
+			if (!(bone->parent && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) {
+				col_head = col_bone;
+			}
+		}
+	}
+
+	if (g_theme.const_color != NULL) {
+		col_wire = no_display; /* actually shrink the display. */
+		col_bone = col_head = col_tail = g_theme.const_color;
+	}
+
+	if (select_id == -1) {
+		/* Not in selection mode, draw everything at once. */
+		drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, col_bone, col_head, col_tail);
+	}
+	else {
+		/* In selection mode, draw bone, root and tip separatly. */
+		DRW_select_load_id(select_id | BONESEL_BONE);
+		drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, col_bone, no_display, no_display);
+
+		if (col_head[3] > 0.0f) {
+			DRW_select_load_id(select_id | BONESEL_ROOT);
+			drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, no_display, col_head, no_display);
+		}
+
+		DRW_select_load_id(select_id | BONESEL_TIP);
+		drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, no_display, no_display, col_tail);
+
+		DRW_select_load_id(-1);
+	}
 }
 
 static void draw_bone_wire(
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 1a4a9be00bd..2366fa556b9 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -88,6 +88,7 @@ static struct DRWShapeCache {
 	Gwn_Batch *drw_bone_envelope_outline;
 	Gwn_Batch *drw_bone_point;
 	Gwn_Batch *drw_bone_point_wire;
+	Gwn_Batch *drw_bone_stick;
 	Gwn_Batch *drw_bone_arrows;
 	Gwn_Batch *drw_camera;
 	Gwn_Batch *drw_camera_frame;
@@ -2104,6 +2105,82 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void)
 	return SHC.drw_bone_point_wire;
 }
 
+/* keep in sync with armature_stick_vert.glsl */
+#define COL_WIRE (1 << 0)
+#define COL_HEAD (1 << 1)
+#define COL_TAIL (1 << 2)
+#define COL_BONE (1 << 3)
+
+#define POS_HEAD (1 << 4)
+#define POS_TAIL (1 << 5)
+#define POS_BONE (1 << 6)
+
+Gwn_Batch *DRW_cache_bone_stick_get(void)
+{
+	if (!SHC.drw_bone_stick) {
+#define CIRCLE_RESOL 12
+		unsigned int v = 0;
+		unsigned int flag;
+		const float radius = 2.0f; /* head/tail radius */
+		float pos[2];
+
+		/* Position Only 2D format */
+		static Gwn_VertFormat format = { 0 };
+		static struct { uint pos, flag; } attr_id;
+		if (format.attrib_ct == 0) {
+			attr_id.pos  = GWN_vertformat_attr_add(&format, "pos",  GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+			attr_id.flag = GWN_vertformat_attr_add(&format, "flag", GWN_COMP_U32, 1, GWN_FETCH_INT);
+		}
+
+		const unsigned int vcount = (CIRCLE_RESOL + 1) * 2 + 6;
+
+		Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+		GWN_vertbuf_data_alloc(vbo, vcount);
+
+		Gwn_IndexBufBuilder elb;
+		GWN_indexbuf_init_ex(&elb, GWN_PRIM_TRI_FAN, (CIRCLE_RESOL + 2) * 2 + 6 + 2, vcount, true);
+
+		/* head/tail points */
+		for (int i = 0; i < 2; ++i) {
+			/* center vertex */
+			copy_v2_fl(pos, 0.0f);
+			flag  = (i == 0) ? POS_HEAD : POS_TAIL;
+			flag |= (i == 0) ? COL_HEAD : COL_TAIL;
+			GWN_vertbuf_attr_set(vbo, attr_id.pos,  v, pos);
+			GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
+			GWN_indexbuf_add_generic_vert(&elb, v++);
+			/* circle vertices */
+			flag |= COL_WIRE;
+			for (int a = 0; a < CIRCLE_RESOL; a++) {
+				pos[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+				pos[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+				GWN_vertbuf_attr_set(vbo, attr_id.pos,  v, pos);
+				GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
+				GWN_indexbuf_add_generic_vert(&elb, v++);
+			}
+			/* Close the circle */
+			GWN_indexbuf_add_generic_vert(&elb, v - CIRCLE_RESOL);
+
+			GWN_indexbuf_add_primitive_restart(&elb);
+		}
+
+		/* Bone rectangle */
+		pos[0] = 0.0f;
+		for (int i = 0; i < 6; ++i) {
+			pos[1] = (i == 0 || i == 3) ? 0.0f : ((i < 3) ? 1.0f : -1.0f);
+			flag   = ((i <  2 || i >  4) ? POS_HEAD : POS_TAIL) |
+			         ((i == 0 || i == 3) ? 0 : COL_WIRE) | COL_BONE | POS_BONE;
+			GWN_vertbuf_attr_set(vbo, attr_id.pos,  v, pos);
+			GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag);
+			GWN_indexbuf_add_generic_vert(&elb, v++);
+		}
+
+		SHC.drw_bone_stick = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, GWN_indexbuf_build(&elb), GWN_BATCH_OWNS_VBO);
+#undef CIRCLE_RESOL
+	}
+	return SHC.drw_bone_stick;
+}
+
 static void set_bone_axis_vert(
         Gwn_VertBuf *vbo, uint axis, uint pos, uint col,
         unsigned int *v, const float *a, const float *p, const float *c)
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 22a5588599f..18bff56920e 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -105,6 +105,7 @@ struct Gwn_Batch *DRW_cache_bone_envelope_outline_get(void);
 struct Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void);
 struct Gwn_Batch *DRW_cache_bone_point_get(void);
 struct Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void);
+struct Gwn_Batch *DRW_cache_bone_stick_get(void);
 struct Gwn_Batch *DRW_cache_bone_arrows_get(void);
 
 /* Meshes */
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index 2c606aa57d7..ba5e04df512 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -165,6 +165,8 @@ extern char datatoc_armature_shape_solid_vert_glsl[];
 extern char datatoc_armature_shape_solid_frag_glsl[];
 extern char datatoc_armature_shape_outline_vert_glsl[];
 extern char datatoc_armature_shape_outline_geom_glsl[];
+extern char datatoc_armature_stick_vert_glsl[];
+extern char datatoc_armature_stick_frag_glsl[];
 extern char datatoc_gpu_shader_flat_color_frag_glsl[];
 
 extern char datatoc_object_mball_handles_vert_glsl[];
@@ -178,6 +180,7 @@ static struct {
 	struct GPUShader *bone_envelope_outline;
 	struct GPUShader *bone_sphere;
 	struct GPUShader *bone_sphere_outline;
+	struct GPUShader *bone_stick;
 
 	struct GPUShader *mball_handles;
 } g_shaders = {NULL};
@@ -194,6 +197,7 @@ static struct {
 	struct Gwn_VertFormat *instance_distance_lines;
 	struct Gwn_VertFormat *instance_spot;
 	struct Gwn_VertFormat *instance_bone;
+	struct Gwn_VertFormat *instance_bone_stick;
 	struct Gwn_VertFormat *instance_bone_outline;
 	struct Gwn_VertFormat *instance_bone_envelope;
 	struct Gwn_VertFormat *instance_bone_envelope_distance;
@@ -638,6 +642,30 @@ DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass)
 	return grp;
 }
 
+DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass)
+{
+	if (g_shaders.bone_stick == NULL) {
+		g_shaders.bone_stick = DRW_shader_create(
+		            datatoc_armatu

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list