[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [35646] trunk/blender/source/blender: Fix/ change in normal computation, now the viewport uses the same angle

Brecht Van Lommel brechtvanlommel at pandora.be
Sun Mar 20 14:35:35 CET 2011


Revision: 35646
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=35646
Author:   blendix
Date:     2011-03-20 13:35:35 +0000 (Sun, 20 Mar 2011)
Log Message:
-----------
Fix/change in normal computation, now the viewport uses the same angle
weighted normals as the render engine, and the render engine will copy
normals from the mesh rather than always recalculating them.

Subsurf/multires still use regular vertex normals, but they are expected
to be sufficiently high resolution to not need this.

This means that normal maps displayed in the viewport actually match the
render engine exactly and don't have artifacts due to this discrepancy.
It of course also avoids unexpected surprises where your render normals
look different than your viewport normals.

Subversion bumped to 4 for version patch to recalculate normals.

Patch by Morten Mikkelsen, with some small changes.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_DerivedMesh.h
    trunk/blender/source/blender/blenkernel/BKE_blender.h
    trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c
    trunk/blender/source/blender/blenkernel/intern/mesh.c
    trunk/blender/source/blender/blenlib/BLI_math_geom.h
    trunk/blender/source/blender/blenlib/intern/math_geom.c
    trunk/blender/source/blender/blenloader/intern/readfile.c
    trunk/blender/source/blender/editors/mesh/editmesh_lib.c
    trunk/blender/source/blender/render/intern/source/convertblender.c

Modified: trunk/blender/source/blender/blenkernel/BKE_DerivedMesh.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_DerivedMesh.h	2011-03-20 12:19:21 UTC (rev 35645)
+++ trunk/blender/source/blender/blenkernel/BKE_DerivedMesh.h	2011-03-20 13:35:35 UTC (rev 35646)
@@ -206,7 +206,7 @@
 	/* Fill the array (of length .getNumVerts()) with all vertex locations */
 	void (*getVertCos)(DerivedMesh *dm, float (*cos_r)[3]);
 
-	/* Get vertex normal, undefined if index is not valid */
+	/* Get smooth vertex normal, undefined if index is not valid */
 	void (*getVertNo)(DerivedMesh *dm, int index, float no_r[3]);
 
 	/* Get a map of vertices to faces

Modified: trunk/blender/source/blender/blenkernel/BKE_blender.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_blender.h	2011-03-20 12:19:21 UTC (rev 35645)
+++ trunk/blender/source/blender/blenkernel/BKE_blender.h	2011-03-20 13:35:35 UTC (rev 35646)
@@ -44,7 +44,7 @@
  * and keep comment above the defines.
  * Use STRINGIFY() rather then defining with quotes */
 #define BLENDER_VERSION			256
-#define BLENDER_SUBVERSION		3
+#define BLENDER_SUBVERSION		4
 
 #define BLENDER_MINVERSION		250
 #define BLENDER_MINSUBVERSION	0

Modified: trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c	2011-03-20 12:19:21 UTC (rev 35645)
+++ trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c	2011-03-20 13:35:35 UTC (rev 35646)
@@ -1798,7 +1798,7 @@
 	int i;
 	int numVerts = dm->numVertData;
 	int numFaces = dm->numFaceData;
-	MFace *mf;
+	MFace *mfaces;
 	MVert *mv;
 
 	if(numVerts == 0) return;
@@ -1817,27 +1817,43 @@
 										 NULL, dm->numFaceData);
 
 	/* calculate face normals and add to vertex normals */
-	mf = CDDM_get_faces(dm);
-	for(i = 0; i < numFaces; i++, mf++) {
+	mfaces = CDDM_get_faces(dm);
+	for(i = 0; i < numFaces; i++) {
+		MFace * mf = &mfaces[i];
 		float *f_no = face_nors[i];
 
 		if(mf->v4)
-			normal_quad_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
+			normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
 		else
-			normal_tri_v3( f_no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
+			normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
 		
-		add_v3_v3(temp_nors[mf->v1], f_no);
-		add_v3_v3(temp_nors[mf->v2], f_no);
-		add_v3_v3(temp_nors[mf->v3], f_no);
-		if(mf->v4)
-			add_v3_v3(temp_nors[mf->v4], f_no);
+		if((mf->flag&ME_SMOOTH)!=0) {
+			float *n4 = (mf->v4)? temp_nors[mf->v4]: NULL;
+			float *c4 = (mf->v4)? mv[mf->v4].co: NULL;
+
+			accumulate_vertex_normals(temp_nors[mf->v1], temp_nors[mf->v2], temp_nors[mf->v3], n4,
+				f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, c4);
+		}
 	}
 
+	for(i = 0; i < numFaces; i++) {
+		MFace * mf = &mfaces[i];
+
+		if((mf->flag&ME_SMOOTH)==0) {
+			float *f_no = face_nors[i];
+
+			if(is_zero_v3(temp_nors[mf->v1])) copy_v3_v3(temp_nors[mf->v1], f_no);
+			if(is_zero_v3(temp_nors[mf->v2])) copy_v3_v3(temp_nors[mf->v2], f_no);
+			if(is_zero_v3(temp_nors[mf->v3])) copy_v3_v3(temp_nors[mf->v3], f_no);
+			if(mf->v4 && is_zero_v3(temp_nors[mf->v4])) copy_v3_v3(temp_nors[mf->v4], f_no);
+		}
+	}
+
 	/* normalize vertex normals and assign */
 	for(i = 0; i < numVerts; i++, mv++) {
 		float *no = temp_nors[i];
 		
-		if (normalize_v3(no) == 0.0)
+		if(normalize_v3(no) == 0.0f)
 			normalize_v3_v3(no, mv->co);
 
 		normal_float_to_short_v3(mv->no, no);

Modified: trunk/blender/source/blender/blenkernel/intern/mesh.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/mesh.c	2011-03-20 12:19:21 UTC (rev 35645)
+++ trunk/blender/source/blender/blenkernel/intern/mesh.c	2011-03-20 13:35:35 UTC (rev 35646)
@@ -1278,26 +1278,42 @@
 	float *fnors= MEM_callocN(sizeof(*fnors)*3*numFaces, "meshnormals");
 	int i;
 
-	for (i=0; i<numFaces; i++) {
+	for(i=0; i<numFaces; i++) {
 		MFace *mf= &mfaces[i];
 		float *f_no= &fnors[i*3];
 
-		if (mf->v4)
-			normal_quad_v3( f_no,mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co);
+		if(mf->v4)
+			normal_quad_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co);
 		else
-			normal_tri_v3( f_no,mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co);
-		
-		add_v3_v3(tnorms[mf->v1], f_no);
-		add_v3_v3(tnorms[mf->v2], f_no);
-		add_v3_v3(tnorms[mf->v3], f_no);
-		if (mf->v4)
-			add_v3_v3(tnorms[mf->v4], f_no);
+			normal_tri_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co);
+
+		if((mf->flag&ME_SMOOTH)!=0) {
+			float *n4 = (mf->v4)? tnorms[mf->v4]: NULL;
+			float *c4 = (mf->v4)? mverts[mf->v4].co: NULL;
+
+			accumulate_vertex_normals(tnorms[mf->v1], tnorms[mf->v2], tnorms[mf->v3], n4,
+				f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, c4);
+		}
 	}
-	for (i=0; i<numVerts; i++) {
+
+	for(i=0; i<numFaces; i++) {
+		MFace *mf= &mfaces[i];
+
+		if((mf->flag&ME_SMOOTH)==0) {
+			float *f_no= &fnors[i*3];
+			if(is_zero_v3(tnorms[mf->v1])) copy_v3_v3(tnorms[mf->v1], f_no);
+			if(is_zero_v3(tnorms[mf->v2])) copy_v3_v3(tnorms[mf->v2], f_no);
+			if(is_zero_v3(tnorms[mf->v3])) copy_v3_v3(tnorms[mf->v3], f_no);
+			if(mf->v4 && is_zero_v3(tnorms[mf->v4])) copy_v3_v3(tnorms[mf->v4], f_no);
+		}
+	}
+
+	/* following Mesh convention; we use vertex coordinate itself for normal in this case */
+	for(i=0; i<numVerts; i++) {
 		MVert *mv= &mverts[i];
 		float *no= tnorms[i];
 		
-		if (normalize_v3(no)==0.0)
+		if(normalize_v3(no) == 0.0f)
 			normalize_v3_v3(no, mv->co);
 
 		normal_float_to_short_v3(mv->no, no);
@@ -1305,11 +1321,10 @@
 	
 	MEM_freeN(tnorms);
 
-	if (faceNors_r) {
+	if(faceNors_r)
 		*faceNors_r = fnors;
-	} else {
+	else
 		MEM_freeN(fnors);
-	}
 }
 
 float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3]

Modified: trunk/blender/source/blender/blenlib/BLI_math_geom.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_math_geom.h	2011-03-20 12:19:21 UTC (rev 35645)
+++ trunk/blender/source/blender/blenlib/BLI_math_geom.h	2011-03-20 13:35:35 UTC (rev 35646)
@@ -169,6 +169,12 @@
 void map_to_tube(float *u, float *v, float x, float y, float z);
 void map_to_sphere(float *u, float *v, float x, float y, float z);
 
+/********************************** Normals **********************************/
+
+void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3],
+	float n4[3], const float f_no[3], const float co1[3], const float co2[3],
+	const float co3[3], const float co4[3]);
+
 /********************************* Tangents **********************************/
 
 typedef struct VertexTangent {

Modified: trunk/blender/source/blender/blenlib/intern/math_geom.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_geom.c	2011-03-20 12:19:21 UTC (rev 35645)
+++ trunk/blender/source/blender/blenlib/intern/math_geom.c	2011-03-20 13:35:35 UTC (rev 35646)
@@ -1980,6 +1980,49 @@
 	}
 }
 
+/********************************* Normals **********************************/
+
+void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3],
+	float n4[3], const float f_no[3], const float co1[3], const float co2[3],
+	const float co3[3], const float co4[3])
+{
+	float vdiffs[4][3];
+	const int nverts= (n4!=NULL && co4!=NULL)? 4: 3;
+
+	/* compute normalized edge vectors */
+	sub_v3_v3v3(vdiffs[0], co2, co1);
+	sub_v3_v3v3(vdiffs[1], co3, co2);
+
+	if(nverts==3) {
+		sub_v3_v3v3(vdiffs[2], co1, co3);
+	}
+	else {
+		sub_v3_v3v3(vdiffs[2], co4, co3);
+		sub_v3_v3v3(vdiffs[3], co1, co4);
+		normalize_v3(vdiffs[3]);
+	}
+
+	normalize_v3(vdiffs[0]);
+	normalize_v3(vdiffs[1]);
+	normalize_v3(vdiffs[2]);
+
+	/* accumulate angle weighted face normal */
+	{
+		float *vn[]= {n1, n2, n3, n4};
+		const float *prev_edge = vdiffs[nverts-1];
+		int i;
+
+		for(i=0; i<nverts; i++) {
+			const float *cur_edge= vdiffs[i];
+			const float fac= saacos(-dot_v3v3(cur_edge, prev_edge));
+
+			// accumulate
+			madd_v3_v3fl(vn[i], f_no, fac);
+			prev_edge = cur_edge;
+		}
+	}
+}
+
 /********************************* Tangents **********************************/
 
 /* For normal map tangents we need to detect uv boundaries, and only average

Modified: trunk/blender/source/blender/blenloader/intern/readfile.c
===================================================================
--- trunk/blender/source/blender/blenloader/intern/readfile.c	2011-03-20 12:19:21 UTC (rev 35645)
+++ trunk/blender/source/blender/blenloader/intern/readfile.c	2011-03-20 13:35:35 UTC (rev 35646)
@@ -11551,6 +11551,13 @@
 		}
 	}
 
+	if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile <4)){
+		Mesh *me;
+
+		for(me= main->mesh.first; me; me= me->id.next)
+			mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+	}
+
 	/* put compatibility code here until next subversion bump */
 
 	{

Modified: trunk/blender/source/blender/editors/mesh/editmesh_lib.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_lib.c	2011-03-20 12:19:21 UTC (rev 35645)
+++ trunk/blender/source/blender/editors/mesh/editmesh_lib.c	2011-03-20 13:35:35 UTC (rev 35646)
@@ -2010,21 +2010,34 @@
 		if(efa->v4) {
 			normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
 			cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
-			add_v3_v3(efa->v4->no, efa->n);
 		}
 		else {
 			normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co);
 			cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
 		}
-		add_v3_v3(efa->v1->no, efa->n);
-		add_v3_v3(efa->v2->no, efa->n);
-		add_v3_v3(efa->v3->no, efa->n);
+
+		if((efa->flag&ME_SMOOTH)!=0) {
+			float *n4= (efa->v4)? efa->v4->no: NULL;
+			float *c4= (efa->v4)? efa->v4->co: NULL;
+
+			accumulate_vertex_normals(efa->v1->no, efa->v2->no, efa->v3->no, n4,
+				efa->n, efa->v1->co, efa->v2->co, efa->v3->co, c4);
+		}
 	}
 
+	for(efa= em->faces.first; efa; efa=efa->next) {
+		if((efa->flag&ME_SMOOTH)==0) {
+			if(is_zero_v3(efa->v1->no)) copy_v3_v3(efa->v1->no, efa->n);
+			if(is_zero_v3(efa->v2->no)) copy_v3_v3(efa->v2->no, efa->n);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list