[SOLVED] Calculating the normal of a triangle.

I’m having a bit of trouble with this, I have a script that takes a triangle on a collision mesh and tries to calculate the normal, but for some reason the normals are not at all in the right direction.

RaycastHit hit;
if (!Physics.Raycast(Camera.GetComponent<Camera>().ScreenPointToRay(Input.mousePosition), out hit))
    return;

MeshCollider meshCollider = hit.collider as MeshCollider;
if (meshCollider == null || meshCollider.sharedMesh == null)
    return;

Mesh mesh = meshCollider.sharedMesh;
Vector3[] vertices = mesh.vertices;
Vector3[] normals = mesh.normals;
int[] triangles = mesh.triangles;
Vector3 p0 = vertices[triangles[hit.triangleIndex * 3 + 0]];
Vector3 p1 = vertices[triangles[hit.triangleIndex * 3 + 1]];
Vector3 p2 = vertices[triangles[hit.triangleIndex * 3 + 2]];
Vector3 p0N = normals[triangles[hit.triangleIndex * 3 + 0]];
Vector3 p1N = normals[triangles[hit.triangleIndex * 3 + 1]];
Vector3 p2N = normals[triangles[hit.triangleIndex * 3 + 2]];
Transform hitTransform = hit.collider.transform;
p0 = hitTransform.TransformPoint(p0);
p1 = hitTransform.TransformPoint(p1);
p2 = hitTransform.TransformPoint(p2);
Vector3 pNorm = (Vector3.Cross(p1-p0, p2N-p0)).normalized;
Vector3 pMid = (p0+p1+p2)/3;
Debug.DrawLine(p0, p1);  // These draw the sides
Debug.DrawLine(p1, p2);
Debug.DrawLine(p2, p0);
Debug.DrawLine(pMid, pMid+(pNorm*5));  // This draws the Normal line
Debug.Log(pNorm);

As you can see in the image, the normal for that particular tri is off to the side.
Is there something that I’m doing wrong here in the code, or is it probably my mesh that is broken?

5449443--555921--BrokenNormalCalc.PNG

I’m not sure that I understand your code:

Vector3 pNorm = (Vector3.Cross(p1-p0, p2N-p0)).normalized;

The normal for the triangle (more precisely: plane) defined by p0 p1 p2 would be the cross product of p0p1 and p0p2

You seem to use p2n, a normalized vector. Why?

1 Like

Ahh, thank you! I need to check for errors like this more often!
This was unintentional, and now that I have switched it to just p2, it works perfectly.

@JupiterSky , You will only get the normal from a cross product if the two vectors are orthogonal (perpendicular). The way it will work 100% regardless of the angle is if you do the following:

Vector3 pointA = new Vector3(...);
Vector3 pointB = new Vector3(...);
Vector3 pointC = new Vector3(...);

Plane plane = new Plane(pointA, pointB, pointC);

Vector3 norm = plane.normal;

where pointA, pointB, and pointC are the vertices of the triangle.

Edit: Furthermore, normalizing your vector does not have anything to do with a surface normal vector.

Please be advised that above is not true, you may want to check your source (see here, Method 3). Any three non-collinear points p1, p2, p3 define a plane, and that plane’s normal vector can be calculated by (p2-p1) x (p3-p1). The resulting normal vector may not be normalized (i.e. may not have a length of 1.0), but neither will be the cross product of any two arbitrary perpendicular vectors.

I stand corrected. It seems I remembered incorrectly. Still though, I think plane.normal is easier than typing out that cross product.