- Home /
Source code for library function "RecalculateNormals()"?
Hiya all,
Is there any way I can get the source code for the "RecalculateNormals()" library function? The function is found in the Mesh class.
I want to make a version which is optimized for what I require it for; it would save me re-writing it all from scratch if I could get the source code!
Regards, Joel.
I'm doing some simple mesh deformation, but I'd like to only calculate the vertex normals for vertices that have been modified.
Answer by Jesse Anders · Oct 06, 2010 at 05:05 PM
I doubt anyone is going to post the engine source code for recalculating mesh normals, but here's a couple of things to consider.
First, you said your code isn't producing the same results as RecalculateNormals(). How are you determining this? If you're looking at the numerical values for the normals in text form, don't forget to take floating-point error into account. (Even if you're using basically the same algorithm that Unity is, the results are unlikely to be exactly the same due to operation order and so forth.)
Second, how are you computing the normals? One possible reason why your normals wouldn't match Unity's would be that there's a bug in your code. If that isn't the case, it may be that you're using a different method than Unity is. The most common methods that I'm aware of are:
- Add up the unit-length normals of all the triangles incident on each vertex and normalize the result
- Add up the unnormalized normals of all the triangles incident on each vertex and normalize the result (this will weight the normals by triangle area)
So, you might try both of those methods and see if one matches Unity's results better than the other.
Thanks for the response. I deter$$anonymous$$ed it visually (and by using Debug.DrawLine() to view the normals). And I've used both of those methods you mentioned above; I don't think that the new normals are affecting the lighting. I'll post my code in another thread and see if I'm doing anything obviously wrong.
Answer by Mike 3 · Oct 06, 2010 at 01:37 PM
There isn't actually any code in the Mesh class really (besides extern function definitions) - it's all done via native code in the engine itself. The c++ code itself probably won't be of any use to you, as it'll hook into code you can't use yourself
The C++ code might be useful in seeing how Unity calculates vertex normals. At the moment my own function for calculating vertex normals doesn't produce the same results as RecalculateNormals(). Could anyone provide any info on how RecalculateNormals() works?
Answer by MountDoomTeam · Apr 28, 2013 at 05:09 PM
good question there, it's also useful for multithreading.
I found this which is a basic example, there is lots of different code for this online, if you use every triangle it gives you two neighbouring points to do a crossproduct from and then normalise.
// Some standard mesh information that you should have lying around.
// vertex is your vertex structure that just contains a normal and position here.
// vertices is a pointer to the first vertex
// indices is a pointer to the first index
// num_verts is number of vertices
// num_indices is number of indices
// each face of the mesh is made up of three vertices.
std::vector<Vector3>* normal_buffer = new std::vector<Vector3>[num_vertices];
for( int i = 0; i < num_indices; i += 3 )
{
// get the three vertices that make the faces
Vector3 p1 = vertices[indices[i+0]];
Vector3 p2 = vertices[indices[i+1]];
Vector3 p3 = vertices[indices[i+2]];
Vector3 v1 = p2 - p1;
Vector3 v2 = p3 - p1;
Vector3 normal = v1.Cross( v2 );
normal.Normalize();
// Store the face's normal for each of the vertices that make up the face.
normal_buffer[indices[i+0]].push_back( normal );
normal_buffer[indices[i+1]].push_back( normal );
normal_buffer[indices[i+2]].push_back( normal );
}
// Now loop through each vertex vector, and avarage out all the normals stored.
for( int i = 0; i < num_vertices; ++i )
{
for( int j = 0; j < normal_buffer[i].size(); ++j )
vertices[i].normal += normal_buffer[i][j];
vertices[i].normal /= normal_buffer[i].size();
This works for any triangle based mesh. works but doesn't make the same normals I think they are less good:
function simple_normals ( ){
var mesh : Mesh = gameObject.GetComponent(MeshFilter).mesh;
var indicies: int[] = mesh.triangles;
var vertices : Vector3[] = mesh.vertices;
var normals: Vector3[] = mesh.vertices;
for(var i :int= 0; i < indicies.Length; i += 3)
{
var v0: Vector3= vertices[indicies[i]];
var v1 :Vector3= vertices[indicies[i+1]];
var v2 :Vector3= vertices[indicies[i+2]];
var normal : Vector3= Vector3.Normalize(Vector3.Cross(v2 - v0, v1 - v0));
normals[indicies[i]] += normal;
normals[indicies[i+1]] += normal;
normals[indicies[i+2]] += normal;
}
for(i = 0; i < vertices.Length; i++)
{
normals[i] = Vector3.Normalize(normals[i]);
}
mesh.normals = normals ;
}
Heres a stripped down version of the Vector3 struct
public struct Vector3
{
float X, Y, Z;
public Vector3(float x, float y, float z)
{
X = x; Y = y; Z = z;
}
public static Vector3 Cross(Vector3 v1, Vector3 v2)
{
Vector3 result;
result.X = (v1.Y * v2.Z) - (v1.Z * v2.Y);
result.Y = (v1.Z * v2.X) - (v1.X * v2.Z);
result.Z = (v1.X * v2.Y) - (v1.Y * v2.X);
return result;
}
public static Vector3 Normalize(Vector3 v1)
{
float length = v1.X * v1.X + v1.Y * v1.Y + v1.Z * v1.Z;
length = Math.Sqrt(length);
v1.X /= length; v1.Y /= length; v1.Z /= length;
}
}
Answer by frogsbo · Jan 24, 2014 at 10:54 AM
solution! same as u3d for shared verts:
function simple_normals (go: GameObject ){
var mesh : Mesh = go.GetComponent(MeshFilter).mesh;
var indicies: int[] = mesh.triangles;
var myvertices : Vector3[] = mesh.vertices;
var mynormals: Vector3[] = mesh.vertices;
mynormals = new Vector3[mesh.vertices.length];
for(var i :int= 0; i < indicies.Length; i += 3)
{
var v0: Vector3= myvertices[indicies[i]];
var v1 :Vector3= myvertices[indicies[i+1]];
var v2 :Vector3= myvertices[indicies[i+2]];
var normal : Vector3= Vector3.Normalize(Vector3.Cross(v1 - v0, v2 - v0));
mynormals[indicies[i]] += normal;
mynormals[indicies[i+1]] += normal;
mynormals[indicies[i+2]] += normal;
}
for(i = 0; i < myvertices.Length; i++)
{
mynormals[i] = Vector3.Normalize(mynormals[i]);
}
mesh.normals = mynormals ;
}
COMPARISON: donate frogsbo.com /aka mtdoom plz (site not finished, this on sale in a week:
Your answer
Follow this Question
Related Questions
Why pass parameters into a function? 2 Answers
Camera Move 1 Answer
Array Problem - Error Code BCE0022 1 Answer