pulled this code in from elsewhere, it’s two functions actually. It accurately calculates the volume of a mesh, which is what i need.
it seems to work perfectly for my purposes, but it takes a little while. In my benchmarking it seems to average out around 0.0002 seconds per call, for the size of mesh i’m using it on. which isn’t much, but it’s something. I’m using it to calculate the volume of lots of little objects at authortime and it’s adding a bit of an annoying wait. The stopwatch calls are in there for testing its speed.
It’s a bit too slow for runtime use at present i think, but i don’t need it for that. still i’m repeating these calculations frequently and speeding this up would speed me up. I used it to replace volume-approximation code in an editor extension i’m using. The extension previously just multiplied the bounds of the collider together, which always gave a too-large result. Fine for most purposes, but i need more precision.
Can anyone improve on this, or is it already just about perfect?
public static float SignedVolumeOfTriangle(Vector3 p1, Vector3 p2, Vector3 p3)
{
float v321 = p3.x * p2.y * p1.z;
float v231 = p2.x * p3.y * p1.z;
float v312 = p3.x * p1.y * p2.z;
float v132 = p1.x * p3.y * p2.z;
float v213 = p2.x * p1.y * p3.z;
float v123 = p1.x * p2.y * p3.z;
return (1.0f / 6.0f) * (-v321 + v231 + v312 - v132 - v213 + v123);
}
public static float MeshVolume(MeshFilter meshFilter)
{
Stopwatch timer = new Stopwatch();
timer.Start();
Mesh mesh = meshFilter.sharedMesh;
float volume = 0;
Vector3[] vertices = mesh.vertices;
int[] triangles = mesh.triangles;
for (int i = 0; i < mesh.triangles.Length; i += 3)
{
Vector3 p1 = vertices[triangles[i + 0]];
Vector3 p2 = vertices[triangles[i + 1]];
Vector3 p3 = vertices[triangles[i + 2]];
volume += SignedVolumeOfTriangle(p1, p2, p3);
}
volume *= meshFilter.gameObject.transform.localScale.x * meshFilter.gameObject.transform.localScale.y * meshFilter.gameObject.transform.localScale.z;
timer.Stop();
print("Meshvolume calculated, time spent so far: " + timer.Elapsed);
return Mathf.Abs(volume);
}