[Bf-blender-cvs] [b733d44] GPU_data_request: WIP: fancy wireframe display

Mike Erwin noreply at git.blender.org
Wed Apr 29 01:48:30 CEST 2015


Commit: b733d44f04bd69e64ae9dec4c3fec282d08cb5bb
Author: Mike Erwin
Date:   Tue Apr 28 19:45:58 2015 -0400
Branches: GPU_data_request
https://developer.blender.org/rBb733d44f04bd69e64ae9dec4c3fec282d08cb5bb

WIP: fancy wireframe display

Exploring some possibilities with wireframe rendering beyond solid
color.

New effect: color edges based on angle between the faces joined. Loose
edges, perimeter edges, and edges joining 3+ faces are colored
differently.

Some of this code will move to Workflow Shaders. Other parts will move
to DerivedMesh data requests — AdjacentFaces (struct) and/or angle made
by adjacent faces (float).

The (incomplete) shader version uses VertexBuffer’s generic attribute
API, which we want to switch everything to eventually. There is a GLSL
vertex shader *not* included in this commit because I don’t know where
to put it…

The CPU version is temporary — it’s equivalent to the shader setup +
matching GLSL shader.

This particular effect is view independent, so can be done CPU-side
once and drawn many times. Other effects I’m working on are view
dependent, so really need the setup + shader split.

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

M	source/blender/editors/space_view3d/drawobject.c

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

diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 3af8fb3..3d2f3c8 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -47,6 +47,7 @@
 #include "BLI_link_utils.h"
 #include "BLI_string.h"
 #include "BLI_math.h"
+#include "BLI_math_color_blend.h" /* temporary, for fancy CPU-side wireframes */
 #include "BLI_memarena.h"
 
 #include "BKE_anim.h"  /* for the where_on_path function */
@@ -4968,6 +4969,8 @@ static bool draw_mesh_object_new_new(Scene *scene, ARegion *ar, View3D *v3d, Reg
 
 				dm->gpux_batch->prim_type = GL_LINES;
 
+#if 0
+				/* draw plain wireframe (single color) */
 				verts = GPUx_vertex_buffer_create(1, vert_ct);
 				GPUx_specify_attrib(verts, 0, GL_VERTEX_ARRAY, GL_FLOAT, 3, KEEP_FLOAT);
 				GPUx_fill_attrib_stride(verts, 0, mverts, sizeof(MVert));
@@ -4978,10 +4981,131 @@ static bool draw_mesh_object_new_new(Scene *scene, ARegion *ar, View3D *v3d, Reg
 					const MEdge *edge = edges + i;
 					GPUx_set_line_vertices(elem, i, edge->v1, edge->v2);
 				}
+#else
+				/* draw wireframe with color based on angle */
+				const MPoly *polys = dm->getPolyArray(dm);
+				const MLoop *loops = dm->getLoopArray(dm);
+
+				float (*face_normal)[3] = MEM_mallocN(poly_ct * 3 * sizeof(float), "face_normal");
+
+				/* TODO: rename? FacesAdjacentToEdge, FacesJoinedByEdge, FacesMeetingAtEdge */
+				typedef struct {
+					int count;
+					int face_index[2];
+				} AdjacentFaces;
+
+				AdjacentFaces *adj_faces = MEM_callocN(edge_ct * sizeof(AdjacentFaces), "adj_faces");
+
+				for (i = 0; i < poly_ct; ++i) {
+					const MPoly *poly = polys + i;
+					int j;
+
+					BKE_mesh_calc_poly_normal(poly, loops + poly->loopstart, mverts, face_normal[i]);
+
+					for (j = poly->loopstart; j < (poly->loopstart + poly->totloop); ++j) {
+						AdjacentFaces *adj = adj_faces + loops[j].e;
+						if (adj->count < 2)
+							adj->face_index[adj->count] = i;
+						adj->count++;
+					}
+				}
+
+				/* color by how many faces join at this edge */
+				const float line_color[4][3] = {
+					{0.0f, 1.0f, 0.4f}, /* 0, loose edge */
+					{1.0f, 1.0f, 1.0f}, /* 1, perimeter edge */
+					{0.0f /*ignored*/}, /* 2, regular edge */
+					{1.0f, 0.0f, 0.0f}, /* 3 or more, overbooked (legal but weird) */
+				};
+
+				const float min_angle_color[3] = {0.2f, 0.2f, 0.2f};
+				const float max_angle_color[3] = {0.0f, 0.6f, 1.5f};
+				const float min_angle = 0.0f; /* don't draw lines with angle < this */
+  #if 1 /* CPU edition */
+				const float max_angle = M_PI;
+				const float nowhere[3] = {0.0f};
+
+				verts = GPUx_vertex_buffer_create(2, 2 * edge_ct);
+
+				GPUx_specify_attrib(verts, 0, GL_VERTEX_ARRAY, GL_FLOAT, 3, KEEP_FLOAT);
+				GPUx_specify_attrib(verts, 1, GL_COLOR_ARRAY, GL_FLOAT, 3, KEEP_FLOAT);
+
+				for (i = 0; i < edge_ct; ++i) {
+					const MEdge *edge = edges + i;
+					const AdjacentFaces *adj = adj_faces + i;
+					const int v1 = 2 * i,
+					          v2 = 2 * i + 1;
+
+					GPUx_set_attrib(verts, 0, v1, &mverts[edge->v1].co);
+					GPUx_set_attrib(verts, 0, v2, &mverts[edge->v2].co);
+
+					if (adj->count == 2) {
+						const int f1 = adj->face_index[0],
+						          f2 = adj->face_index[1];
+//						float angle = acosf(dot_v3v3(face_normal[adj->f[0]], face_normal[adj->f[1]]));
+						const float angle = angle_normalized_v3v3(face_normal[f1], face_normal[f2]);
+						if (angle < min_angle) {
+							/* rasterize no fragments (essentially discards the line) */
+							GPUx_set_attrib(verts, 0, v1, nowhere);
+							GPUx_set_attrib(verts, 0, v2, nowhere);
+						}
+						else {
+							/* calculate color based on angle */
+							const float factor = (angle - min_angle) / (max_angle - min_angle);
+							float angle_color[3];
+							blend_color_interpolate_float(angle_color, min_angle_color, max_angle_color, factor);
+							GPUx_set_attrib(verts, 1, v2, angle_color);
+						}
+					}
+					else {
+						GPUx_set_attrib(verts, 1, v2, adj->count > 2 ? line_color[3] : line_color[adj->count]);
+					}
+				}
+  #else /* shader edition */
+				/* -- uniforms -- */
+
+				/* vec3 adj_0_color
+				 * vec3 adj_1_color
+				 * vec3 adj_many_color
+				 * vec3 min_angle_color
+				 * vec3 max_angle_color
+				 * float min_angle
+				 */
+
+				/* -- attributes -- */
+				verts = GPUx_vertex_buffer_create(3, 2 * edge_ct);
+
+				GPUx_specify_attrib(verts, 0, "pos",       GL_FLOAT, 3, KEEP_FLOAT);
+				GPUx_specify_attrib(verts, 1, "adj_count", GL_INT,   1, KEEP_INT);
+				GPUx_specify_attrib(verts, 2, "angle",     GL_FLOAT, 1, KEEP_FLOAT);
+
+				for (i = 0; i < edge_ct; ++i) {
+					const MEdge *edge = edges + i;
+					const AdjacentFaces *adj = adj_faces + i;
+					const int v1 = 2 * i,
+					          v2 = 2 * i + 1;
+
+					GPUx_set_attrib(verts, 0, v1, &mverts[edge->v1].co);
+					GPUx_set_attrib(verts, 0, v2, &mverts[edge->v2].co);
+
+					GPUx_set_attrib(verts, 1, v2, &adj->count);
+
+					if (adj->count == 2) {
+						const int f1 = adj->face_index[0],
+						          f2 = adj->face_index[1];
+						const float angle = angle_normalized_v3v3(face_normal[f1], face_normal[f2]);
+						GPUx_set_attrib(verts, 2, v2, &angle);
+					}
+				}
+  #endif /* CPU vs shader */
+
+				MEM_freeN(face_normal);
+				MEM_freeN(adj_faces);
+#endif
 			}
 
 			GPUx_vertex_buffer_prime(verts);
-			GPUx_element_list_prime(elem);
+			if (elem) GPUx_element_list_prime(elem);
 
 			dm->gpux_batch->buff = verts;
 			dm->gpux_batch->elem = elem;




More information about the Bf-blender-cvs mailing list