Hello,
I’m working on a ‘ship builder’ where the user places cubes to create a vehicle. During this process, the meshes of the cubes are merged and then a convex hull is generated from those merged cubes.
I’m using ConvexHull.cs from MIConvexHull/MIConvexHull at master · DesignEngrLab/MIConvexHull · GitHub and the mesh produced is fine with the exception of the normals which don’t seem to be correct. Admittedly, I do not really understand this code but I’d really like to avoid spending a few weeks learning about minimal bounding boxes and the like! 
Here you can see 1. the original merged cubes, 2. the mesh produced by the MIConvexHull script, 3. the mesh from the .obj exported from Unity and 4. the mesh after I’ve exported it from Blender.
I’m not really doing anything to the mesh in Blender except exporting it so clearly the normal generation algorithm in Blender is different from the one in MIConvexHull.cs. My question therefore is how can I generate normals for the convex hull mesh manually to produce the same result as I get from Blender?
Thank you for any help you can provide.
edit:
Here is the raw vertex normal data from 1. the .obj file exported from Unity and 2. the .obj file exported from Blender. There appears to be a clear difference.
vn 0 -0.919145 0.3939193
vn 0.3310423 -0.2482818 -0.9103665
vn 0.7427813 -0.3713907 0.557086
vn -0.3481553 -0.8703883 -0.3481553
vn -0.4082483 -0.8164966 0.4082483
vn -0.3333333 0.6666667 0.6666667
vn 0.3810004 -0.2540002 0.8890009
vn -0.3244428 -0.4866642 0.8111071
vn 0.4082483 0.4082483 0.8164966
vn 0.2857143 0.4285715 -0.8571429
vn 0.5568901 0.7955573 0.2386672
vn -0.4423259 0.8846517 0.147442
vn -0.09205746 0.5523447 -0.8285171
vn -0.5070925 -0.1690308 -0.8451542
vn -0.8164966 -0.4082483 0.4082483
vn 0.000000 -1.000000 -0.000000
vn 0.707100 0.000000 -0.707100
vn 1.000000 0.000000 0.000000
vn 0.000000 -0.000000 1.000000
vn -1.000000 0.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.707100 0.707100 0.000000
vn 0.000000 0.000000 -1.000000
vn -0.707100 0.000000 -0.707100
vn 0.000000 0.707100 -0.707100
vn 0.577400 0.577400 -0.577400
Update: I’m following through the code from http://schemingdeveloper.com/2014/10/17/better-method-recalculate-normals-unity/. So far I’ve tried recalculating the vertex normals based on average of face normals as follows:
[ContextMenu("Recalculate Normals")]
public void recalculateNormals() {
MeshFilter filter = GetComponent(typeof (MeshFilter)) as MeshFilter;
Mesh mesh = filter.mesh;
//set normals to 0, 0, 0
//TODO forgotten how to create list of zero vectors
List<Vector3> reset = new List<Vector3>();
for (int i = 0; i < mesh.vertexCount; i++) {
reset.Add(Vector3.zero);
}
mesh.SetNormals(reset);
//calculate normals
Vector3[] newNormals = new Vector3[mesh.normals.Length];
for (int i = 0; i < mesh.triangles.Length; i+=3) {
int index1 = mesh.triangles[i];
int index2 = mesh.triangles[i+1];
int index3 = mesh.triangles[i+2];
Vector3 normal = calculateSurfaceNormal(mesh.vertices[index1], mesh.vertices[index2], mesh.vertices[index3]);
newNormals[index1] += normal;
newNormals[index2] += normal;
newNormals[index3] += normal;
}
for(int i = 0; i < newNormals.Length; i++) {
newNormals[i] = Vector3.Normalize(newNormals[i]);
}
//set normals
mesh.SetNormals(new List<Vector3>(newNormals));
}
public Vector3 calculateSurfaceNormal(Vector3 a, Vector3 b, Vector3 c) {
return Vector3.Cross(b - a, c - b);
}
As expected it gives the same results.
Update 2: I used the code from http://schemingdeveloper.com/2017/03/26/better-method-recalculate-normals-unity-part-2/. This DOES change the normals but they are still messed up and look roughly the same (forum won’t let me post a screenshot for some reason).
Perhaps the normals are not the problem.
Update 3: OK so I’ve figured the problem is that in the original merged cubes mesh and in the mesh exported from Blender I have multiple normals for each vertex shared by multiple faces. I need to work out how to go from averaged normals to separate ones. Or at least stop the convex hull algorithm from merging them in the first place. What I don’t quite understand is that both .obj files have the same number of vertices and the same number of normals.
OK, solved.
Found the solution here: Flat shading - Questions & Answers - Unity Discussions. Specifically, the code:
Vector3[] oldVerts = mesh.vertices;
int[] triangles = mesh.triangles;
Vector3[] vertices = new Vector3[triangles.Length];
for (int i = 0; i < triangles.Length; i++) {
vertices[i] = oldVerts[triangles[i]];
triangles[i] = i;
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
I now know what flat faces are. 
3 Likes