Here is the excerpt of my script which is calculating the surface area and face area of a mesh on OnMouseDown
Event.
private void OnMouseDown()
{
Mesh selectedMesh = this.gameObject.GetComponent<MeshFilter>().mesh;
float surfaceArea = CalculateSurfaceArea(selectedMesh);
float areaFromXFace = CalculateFacingArea(selectedMesh, new Vector3(1, 0, 0));
float areaFromYFace = CalculateFacingArea(selectedMesh, new Vector3(0, 1, 0));
float areaFromZFace = CalculateFacingArea(selectedMesh, new Vector3(0, 0, 1));
float areaFromClickedFace = ProjectionPlaneClickedArea(selectedMesh);
string areas = "\n Surface Area : " + surfaceArea;
areas += "\n Area From X-axis Face : " + areaFromXFace;
areas += "\n Area From Y-axis Face : " + areaFromYFace;
areas += "\n Area From Z-axis Face : " + areaFromZFace;
areas += "\n Area From Selected Face : " + areaFromClickedFace;
Debug.Log("Areas :"+ areas);
}
float ProjectionPlaneClickedArea(Mesh selcectedMesh)
{
Camera c = Camera.main;
Ray ray = c.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f))
{
Debug.DrawRay(ray.origin, ray.direction * 100, Color.yellow);
Debug.Log("normal :" + hit.normal);
Debug.Log("Area from normal/direction : " + CalculateFacingArea(selcectedMesh, hit.normal));
return CalculateFacingArea(selcectedMesh, hit.normal);
}
return 0f;
}
float CalculateSurfaceArea(Mesh mesh)
{
//Limitation: Note that if your mesh has any double-sided faces or internal faces, they can bias this result.
var triangles = mesh.triangles;
var vertices = mesh.vertices;
double sum = 0.0;
for (int i = 0; i < triangles.Length; i += 3) //iterate over the triangles of the mesh
{
Vector3 corner = vertices[triangles[i]]; //for each triangle, we'll compute vectors representing the two edges
Vector3 a = vertices[triangles[i + 1]] - corner;
Vector3 b = vertices[triangles[i + 2]] - corner;
sum += Vector3.Cross(a, b).magnitude; //half the magnitude of the cross product of these edges gives us the area of the triangle
}
return (float)(sum / 2.0);
}
/// <summary>
/// compute just the area of the mesh facing in a particular direction, you can try this version instead.
/// Pass the direction you want to view the mesh from and it should compute the projected surface area of
/// the faces facing at least partially in that direction.
/// </summary>
/// <param name="mesh"></param>
/// <param name="direction"></param>
/// <returns></returns>
float CalculateFacingArea(Mesh mesh, Vector3 direction)
{
direction = direction.normalized;
var triangles = mesh.triangles;
var vertices = mesh.vertices;
double sum = 0.0;
for (int i = 0; i < triangles.Length; i += 3) //iterate over the triangles of the mesh
{
//"Subtracting each 2nd & 3rd vertex" just gives the two edges of the triangle radiating from the initial corner.
Vector3 corner = vertices[triangles[i]];
Vector3 a = vertices[triangles[i + 1]] - corner;
Vector3 b = vertices[triangles[i + 2]] - corner;
//The cross product divided by two gives the area of the triangle.
//The dot product is what handles projecting this area onto the plane of interest.
float projection = Vector3.Dot(Vector3.Cross(b, a), direction);
if (projection > 0f)//only sum projected triangles
sum += projection;
}
return (float)(sum / 2.0);
}
I am able calculate face area by CalculateFacingArea
method it needs a mesh and direction which is working fine, as if i want to calculate the area of x direction i can use it
float areaFromXFace = CalculateFacingArea(selectedMesh, new Vector3(1, 0, 0));
BUT I have to provide the face/direction information dynamically which is i am doing in this function ProjectionPlaneClickedArea
using a raycast
. It is getting a hit point normals which i am using as a direction and passing it to the function. It is working well with some of the meshes but not with all meshes, for example below image:
As you can see if I click this object from the front then it should calculate Y Face area but it is calculating with X direction. The click point normal value is (1.0, 0.0, 0.1)
.
While it is working fine if my clicked object axis are something like this:
In this case x is the facing are and it is working fine. I have this value of normal (1.0, 0.0, 0.0)
.
I am neither geometry/math expert nor a modeler so I cannot identify that its Object's normal problem or it is calculation problem.
Remember I don't want to model all the objects in the same direction/axis, where i can get the direction hard-coded. I want to calculate the direction dynamically but correctly.