Mesh.RecalculateNormals()

I am doing some Mesh deformation where recalculating normals is necessary. I wanted to be able to specify what part of the mesh’s normals are recalculated based on what i deformed.

So I started out reconstructing the RecalculateNormals() in hopes that I could tweak how it works. What I found was that whatever I am doing… is wrong… the normals come out incorrect.

So the question is what does the RecalculateNormals() formula actually do (code preferably) and if i roll my own, can it ever be as fast as the original function?

Well i guess i will post some code to see if anyone can pick where the problem is. This is actually a c++ external plugin, but i am considered over whether the logic of my code is correct, not syntax.

first i fill a 2D array (AdjacentVerts), each “row” of the array represents a vert and the columns represent other verts which share the same triangles as this vert.

void FindVerts(){
	AdjacentVerts.resize(Vertices_Num);
	for (int i = 0 ; i < Vertices_Num ; i++){
		for (int j = 0 ; j < Triangles_Num ; j++){
			if(Triangles[j] == i)	{
				if((j+3)%3==0){		AdjacentVerts[i].push(Triangles[j+1]);		AdjacentVerts[i].push( Triangles[j+2]);	} else 
					if((j+2)%3==0){		AdjacentVerts[i].push(Triangles[j-1]);		AdjacentVerts[i].push( Triangles[j+1]);	} else 
						if((j+1)%3==0){		AdjacentVerts[i].push(Triangles[j-1]);		AdjacentVerts[i].push( Triangles[j-2]);	}		   
			}
		}
	}
}

From here I run a function which recalculates the normals for each vert. Normalizing the normal at the end.

void Recalculate_Normals(){
	float iN;
	Vector3 n, vec1, vec2, vec3, d1, d2;
	for (int i = 0; i < Normals_Num	; i+=3){
		n = Vector3(0,0,0);	
		vec1 =Vertices[i]);
		for(int j = 0, k = AdjacentVerts[i].size(); j<k;j+=2){
			vec2 = Vector3(Vertices[AdjacentVerts[i][j]])
			vec3 = Vector3(Vertices[AdjacentVerts[i][j+1]])
			d1 = vec2 - vec1;
			d2 = vec3 - vec1;
			n += d1.cross(d2);
		}
		normlize(n);
		Normals[i] = n;
	}
}

Is there something wrong with the logic of all of this? My impression was that you calculate all triangle normals, add the normals up for each triangle the vert is part of and normal the result.

I also tried another method for calculating the triangle normal based upon vert positions, this yielded similar (incorrect) results.

Vector3 calculateTriangleSurfaceNormal(int v1, int v2, int v3){
	Vector3 surfaceNormal;
	surfaceNormal.x = (Vertices[v1].y * Vertices[v2].z) - (Vertices[v1].z * Vertices[v2].y);
	surfaceNormal.y = -((Vertices[v2].z * Vertices[v1].x) - (Vertices[v2].x * Vertices[v1+2]));
	surfaceNormal.z = (Vertices[v1].x * Vertices[v2].y) - (Vertices[v1].y * Vertices[v2].x);
	normalize(surfaceNormal);
	return surfaceNormal;
}

What am I doing wrong here? How are vert normals supposed to be calculated?

Vector3 calculateTriangleSurfaceNormal(int v1, int v2, int v3){
	Vector3 surfaceNormal;
	surfaceNormal.x = (Vertices[v1].y * Vertices[v2].z) - (Vertices[v1].z * Vertices[v2].y);
	surfaceNormal.y = -((Vertices[v2].z * Vertices[v1].x) - (Vertices[v2].x * Vertices[v1+2]));
	surfaceNormal.z = (Vertices[v1].x * Vertices[v2].y) - (Vertices[v1].y * Vertices[v2].x);
	normalize(surfaceNormal);
	return surfaceNormal;
}

I don’t know about your code, but I would calculate normal like this :

private Mesh myMesh;
private Vector3 calculateNormal ( int v0, int v1, int v2 )
{
  Vector3 vert0 = myMesh.vertices[v0];
  Vector3 vert1 = myMesh.vertices[v1];
  Vector3 vert2 = myMesh.vertices[v2];

  Vector3 va = vert1 - vert0;
  Vector3 vb = vert2 - vert1;
    
  float xh = va.y*vb.z - va.z*vb.y;
  float yh = va.z*vb.x - va.x*vb.z;
  float zh = va.x*vb.y - va.y*vb.x;
		
  return new Vector3( xh, yh, zh );
}

and simpler code would be :

private Mesh myMesh;
private Vector3 calculateNormal2 ( int v0, int v1, int v2 )
{
  Vector3 v0pos = myMesh.vertices[v0];
  Vector3 v1pos = myMesh.vertices[v1];
  Vector3 v2pos = myMesh.vertices[v2];
  return Vector3.Cross(v1pos - v0pos, v2pos - v1pos).normalized;
}

Good luck.

1 Like