[tuhopuu-devel] Z-shading in edit mode

Hans Toernqvist coelurus at thorntwig.se
Tue Jun 21 14:30:24 CEST 2005


Hi,

we've created a patch for Z-shading in edit mode for wireframe meshes 
(also with subsurfaces enabled). The idea is that the edges connecting 
vertices in a mesh are "shaded" depending on the local distance in a 
mesh with respect to the viewport to make it easier to distinguish 
vertices from eachother. It was hard to set default colors for the 
default theme. If you use the default theme, we recommend that you 
change the viewport background color to see the effect better.

The patch is mostly a hack right now and all function definitions from 
the 2.37a source code are untouched. A list of what we did:

*) Added some UI entries (Z Shade Near/Far)
*) Added Z-testing for all wires
*) Set the OpenGL primary and fog color to the Z-shading colors (hum :) 
it works)
*) Changed 'drawMappedEdgesEM' to fetch the OpenGL color states and draw 
interpolated edges
*) Added a routine to calculate the colors for all edges

For screenshots and some further info on the coloring routine, check:
http://coelurus.thorntwig.se/

Would anybody like to test it and maybe even commit it to CVS?

-- 
Hans Törnqvist
E-Mail: coelurus [at] thorntwig se
-------------- next part --------------
diff -urN blender.old/source/blender/blenkernel/intern/DerivedMesh.c blender/source/blender/blenkernel/intern/DerivedMesh.c
--- blender.old/source/blender/blenkernel/intern/DerivedMesh.c	2005-06-06 09:52:44.000000000 +0000
+++ blender/source/blender/blenkernel/intern/DerivedMesh.c	2005-06-21 10:52:34.000000000 +0000
@@ -437,19 +437,133 @@
 	glVertex3fv(eed->v2->co);
 	glEnd();
 }
+
+static void transform(float *v, float *m, float *u) {
+	v[0] = u[0] * m[0] + u[1] * m[4] + u[2] * m[8] + m[12];
+	v[1] = u[0] * m[1] + u[1] * m[5] + u[2] * m[9] + m[13];
+	v[2] = u[0] * m[2] + u[1] * m[6] + u[2] * m[10] + m[14];
+}
+
+#define DIAGRAM_SIZE		100
+#define DIAGRAM_THRESHOLD	10
+
+/* Calculates near and far Z for mesh with a few twists */
+static void calcExtreme(DerivedMesh *dm, float *matrix, float *min, float *max) {
+	EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+	EditEdge *eed;
+	int		diagram[DIAGRAM_SIZE],
+			diagramSize,
+			numVertices = 0,
+			maxColumn = 0,
+			maxColumnIdx = -1,
+			threshold,
+			i;
+
+	float	diagramSpans[DIAGRAM_SIZE][2],
+			vert[3],
+			minZ, maxZ, invZSpan;
+
+	/* Find correct extremes */
+	minZ = 1e9;
+	maxZ = -1e9;
+	for (eed = emdm->em->edges.first; eed != NULL; eed = eed->next) {
+		transform(vert, matrix, eed->v1->co);
+
+		if (vert[2] < minZ) minZ = vert[2];
+		if (vert[2] > maxZ) maxZ = vert[2];
+		numVertices++;
+	}
+	invZSpan = 1 / (maxZ - minZ);
+
+	/* Adapt diagram size */
+	diagramSize = numVertices / (2 * DIAGRAM_THRESHOLD) + 1;
+	if (diagramSize > DIAGRAM_SIZE) diagramSize = DIAGRAM_SIZE;
+
+	/* Reset and create diagram */
+	for (i = 0; i <= diagramSize; i++) {
+		diagram[i] = 0;
+		diagramSpans[i][0] = ((float)i + 1) / diagramSize / invZSpan + minZ;
+		diagramSpans[i][1] = (float)i / diagramSize / invZSpan + minZ;
+	}
+
+	for (eed = emdm->em->edges.first; eed != NULL; eed = eed->next) {
+		transform(vert, matrix, eed->v1->co);
+
+		i = (int)(diagramSize * (vert[2] - minZ) * invZSpan);
+
+		diagram[i]++;
+		if (diagram[i] > maxColumn) {
+			maxColumn = diagram[i];
+			maxColumnIdx = i;
+		}
+
+		if (vert[2] < diagramSpans[i][0]) diagramSpans[i][0] = vert[2];
+		if (vert[2] > diagramSpans[i][1]) diagramSpans[i][1] = vert[2];
+	}
+	threshold = maxColumn / DIAGRAM_THRESHOLD;
+
+	/* Calculate extreme columns */
+	for (i = 0; diagram[i] < threshold && i <= diagramSize; i++);
+	if (i > diagramSize) i = 0;
+	if (diagram[i] > threshold && i > 0) i--;
+	*min = diagramSpans[i][0];
+
+	for (i = diagramSize; diagram[i] < threshold && i >= 0; i--);
+	if (i < 0) i = diagramSize;
+	if (diagram[i] > threshold && i < diagramSize) i++;
+	*max = diagramSpans[i][1];
+}
+
 static void emDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void *userData) 
 {
 	EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
 	EditEdge *eed;
 
+	float	matrix[16],
+			color1[4],
+			color2[4],
+			vert[3],
+			minZ,
+			maxZ;
+
+	glGetFloatv(GL_CURRENT_COLOR, color1);
+	glGetFloatv(GL_FOG_COLOR, color2);
+
+	glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
+	calcExtreme(dm, matrix, &minZ, &maxZ);
+	glShadeModel(GL_SMOOTH);
+	glDepthFunc(GL_LEQUAL);
+
 	glBegin(GL_LINES);
 	for(eed= emdm->em->edges.first; eed; eed= eed->next) {
 		if(!setDrawOptions || setDrawOptions(userData, eed)) {
+
+			float	c;
+
+			transform(vert, matrix, eed->v1->co);
+			c = (vert[2] - minZ) / (maxZ - minZ);
+			if (c < 0) c = 0;
+			if (c > 1) c = 1;
+
+			glColor3f(color1[0] * (1 - c) + color2[0] * c,
+						color1[1] * (1 - c) + color2[1] * c,
+						color1[2] * (1 - c) + color2[2] * c);
 			glVertex3fv(eed->v1->co);
+
+			transform(vert, matrix, eed->v2->co);
+			c = (vert[2] - minZ) / (maxZ - minZ);
+			if (c < 0) c = 0;
+			if (c > 1) c = 1;
+
+			glColor3f(color1[0] * (1 - c) + color2[0] * c,
+						color1[1] * (1 - c) + color2[1] * c,
+						color1[2] * (1 - c) + color2[2] * c);
 			glVertex3fv(eed->v2->co);
 		}
 	}
 	glEnd();
+
+	glShadeModel(GL_FLAT);
 }
 static void emDM_drawMappedEdgesInterpEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void (*setDrawInterpOptions)(void *userData, EditEdge *edge, float t), void *userData) 
 {
diff -urN blender.old/source/blender/include/BIF_resources.h blender/source/blender/include/BIF_resources.h
--- blender.old/source/blender/include/BIF_resources.h	2005-06-04 16:22:49.000000000 +0000
+++ blender/source/blender/include/BIF_resources.h	2005-06-19 13:09:42.000000000 +0000
@@ -427,6 +427,8 @@
 	TH_FACE,
 	TH_FACE_SELECT,
 	TH_NORMAL,
+	TH_ZSHADE,
+	TH_ZSHADE_HI,
 	TH_FACE_DOT,
 	TH_FACEDOT_SIZE,
 
diff -urN blender.old/source/blender/makesdna/DNA_userdef_types.h blender/source/blender/makesdna/DNA_userdef_types.h
--- blender.old/source/blender/makesdna/DNA_userdef_types.h	2005-06-11 16:30:36.000000000 +0000
+++ blender/source/blender/makesdna/DNA_userdef_types.h	2005-06-19 13:09:42.000000000 +0000
@@ -86,6 +86,8 @@
 	char face[4], face_select[4];	// solid faces
 	char face_dot[4];	// selected color
 	char normal[4];
+	char zshade[4];
+	char zshade_hi[4];
 	
 	char vertex_size, facedot_size;
 	char bpad[2];
diff -urN blender.old/source/blender/python/api2_2x/windowTheme.c blender/source/blender/python/api2_2x/windowTheme.c
--- blender.old/source/blender/python/api2_2x/windowTheme.c	2005-06-11 05:30:14.000000000 +0000
+++ blender/source/blender/python/api2_2x/windowTheme.c	2005-06-19 13:09:42.000000000 +0000
@@ -169,6 +169,8 @@
 		ELSEIF_TSP_RGBA( face_select )
 		ELSEIF_TSP_RGBA( face_dot )
 		ELSEIF_TSP_RGBA( normal )
+		ELSEIF_TSP_RGBA( zshade )
+		ELSEIF_TSP_RGBA( zshade_hi )
 		ELSEIF_TSP_RGBA( syntaxl )
 		ELSEIF_TSP_RGBA( syntaxn )
 		ELSEIF_TSP_RGBA( syntaxb )
@@ -186,7 +188,7 @@
 					"transform", "vertex", "vertex_select",
 					"edge", "edge_select", "edge_seam",
 					"edge_facesel", "face", "face_select",
-					"face_dot", "normal",
+					"face_dot", "normal", "zshade", "zshade_hi",
 					"syntaxl", "syntaxn", "syntaxb", "syntaxv", "syntaxc",
 					"vertex_size", "facedot_size" );
 
@@ -228,6 +230,8 @@
 		ELSEIF_TSP_RGBA( face_select )
 		ELSEIF_TSP_RGBA( face_dot )
 		ELSEIF_TSP_RGBA( normal )
+		ELSEIF_TSP_RGBA( zshade )
+		ELSEIF_TSP_RGBA( zshade_hi )
 		ELSEIF_TSP_RGBA( syntaxl )
 		ELSEIF_TSP_RGBA( syntaxn )
 		ELSEIF_TSP_RGBA( syntaxb )
diff -urN blender.old/source/blender/src/drawobject.c blender/source/blender/src/drawobject.c
--- blender.old/source/blender/src/drawobject.c	2005-06-01 18:36:58.000000000 +0000
+++ blender/source/blender/src/drawobject.c	2005-06-21 10:53:23.000000000 +0000
@@ -1428,7 +1428,14 @@
 			}
 		}
 		else {
-			glColor4ubv(wire);
+/*			glColor4ubv(wire);*/
+			float	color1[4] = { 0, 0, 0, 0 },
+					color2[4] = { 0, 0, 0, 0 };
+
+			BIF_GetThemeColor3fv(TH_ZSHADE, color1);
+			BIF_GetThemeColor3fv(TH_ZSHADE_HI, color2);
+			glColor3fv(color1);
+			glFogfv(GL_FOG_COLOR, color2);
 			draw_dm_edges(cageDM);
 		}
 
@@ -3771,8 +3778,9 @@
 {
 	
 	if(G.vd==NULL || base==NULL) return;
-	
-	if(G.vd->drawtype > OB_WIRE) {
+
+	/* Enable Z-testing for wires now that they are colored */
+	if(G.vd->drawtype > OB_BOUNDBOX) {
 		G.zbuf= 1;
 		glEnable(GL_DEPTH_TEST);
 	}
diff -urN blender.old/source/blender/src/drawview.c blender/source/blender/src/drawview.c
--- blender.old/source/blender/src/drawview.c	2005-06-12 12:44:51.000000000 +0000
+++ blender/source/blender/src/drawview.c	2005-06-21 10:56:15.000000000 +0000
@@ -1807,7 +1807,8 @@
 	Mat4Invert(G.vd->persinv, G.vd->persmat);
 	Mat4Invert(G.vd->viewinv, G.vd->viewmat);
 
-	if(G.vd->drawtype > OB_WIRE) {
+	/* Make sure the Z-buffer is cleaned up */
+	if(G.vd->drawtype > OB_BOUNDBOX) {
 		G.zbuf= TRUE;
 		glEnable(GL_DEPTH_TEST);
 		if(G.f & G_SIMULATION) {
@@ -2073,7 +2074,8 @@
 	Mat4Invert(v3d->persinv, v3d->persmat);
 	Mat4Invert(v3d->viewinv, v3d->viewmat);
 
-	if(v3d->drawtype > OB_WIRE) {
+	/* Enable Z-testing for wires now that they are colored */
+	if(v3d->drawtype > OB_BOUNDBOX) {
 		G.zbuf= TRUE;
 		glEnable(GL_DEPTH_TEST);
 	}
diff -urN blender.old/source/blender/src/resources.c blender/source/blender/src/resources.c
--- blender.old/source/blender/src/resources.c	2005-05-13 16:11:28.000000000 +0000
+++ blender/source/blender/src/resources.c	2005-06-21 10:57:50.000000000 +0000
@@ -509,6 +509,10 @@
 				cp= &ts->facedot_size; break;
 			case TH_NORMAL:
 				cp= ts->normal; break;
+			case TH_ZSHADE:
+				cp= ts->zshade; break;
+			case TH_ZSHADE_HI:
+				cp= ts->zshade_hi; break;
 
 			case TH_SYNTAX_B:
 				cp= ts->syntaxb; break;
@@ -598,6 +602,8 @@
 	SETCOL(btheme->tv3d.face, 	0, 50, 150, 30);
 	SETCOL(btheme->tv3d.face_select, 200, 100, 200, 60);
 	SETCOL(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
+	SETCOL(btheme->tv3d.zshade, 160, 140, 120, 255);
+	SETCOL(btheme->tv3d.zshade_hi, 0, 200, 255, 255);
 	SETCOL(btheme->tv3d.face_dot, 255, 138, 48, 255);
 	btheme->tv3d.facedot_size= 4;
 	
@@ -758,7 +764,9 @@
 			sprintf(str, "Face Selected (transp) %%x%d|", TH_FACE_SELECT); strcat(cp, str);
 			sprintf(str, "Face Dot Selected %%x%d|", TH_FACE_DOT); strcat(cp, str);
 			sprintf(str, "Face Dot Size %%x%d|", TH_FACEDOT_SIZE); strcat(cp, str);
-			sprintf(str, "Normal %%x%d", TH_NORMAL); strcat(cp, str);
+			sprintf(str, "Normal %%x%d|", TH_NORMAL); strcat(cp, str);
+			sprintf(str, "Z Shade Far %%x%d|", TH_ZSHADE); strcat(cp, str);
+			sprintf(str, "Z Shade Near %%x%d", TH_ZSHADE_HI); strcat(cp, str);
 		}
 		else if(spacetype==SPACE_IPO) {
 			sprintf(str, "Panel %%x%d|", TH_PANEL); strcat(cp, str);


More information about the tuhopuu-devel mailing list