After a lot of thinking and experimentation I have the answer!
First we add a 4th point to each triangle in to make them into tetrahedrons with a volume centroid. We calculate the volumes and centres of masses and multiply them by each other to get our moments. We sum the moments and divide by total volume to get our overall centroid.
We calculate volumes using the determinate method shown here (equation 32): http://mathworld.wolfram.com/Tetrahedron.html
The centroids of each of the tetrahedrons is simply the average of the 4 points.
The trick here is that due to the way the STL file is created, the triangles have a normal that point outwards from the part surface, following the right hand rule of the 3 verticies used to create the triangle. we can use this to our advantage by allowing us to have a consistent convention in which to determine if a volume of the tetrahedron should be added or subtracted from our net part (this is because the reference point we chose may not necessarily be inside the part and the overall part is not necessarily convex, it is, however a closed object).
Using the determine method to calculate the volume, the first three coordinate points will represent the three points of our triangle. The fourth point would be our common origin. If the normal created by the triangle (following the right hand rule going from point 1, 2, 3) points towards our common reference point, that volume will be calculated as not part of our overall solid, or negative volume (by pointing towards, i mean the vector created by the triangle's normal is pointing loosely towards the same side as a normal plane created by the vector from our reference point to the centroid of the tetrahedron). If the vector is pointing away from the reference point, it is then positive volume or inside the part. If it is normal, then the volume goes to zero as the triangle is in the same plane as the reference point.
We don't need to worry about actually keeping track of any of this as if we are consistent with our inputs (as in the triangles follow the right hand rule with normal facing outwards from the part) the determine will give us the correct sign.
Anyways, heres the code (its even more simple than the explanation).
class data // 3 vertices of each triangle
{
public:
float x1,y1,z1;
float x2,y2,z2;
float x3,y3,z3;
};
int main ()
{
int numTriangles; // pull in the STL file and determine number of triangles
data * triangles = new triangles [numTriangles];
// fill the triangles array with the data in the STL file
double totalVolume = 0, currentVolume;
double xCenter = 0, yCenter = 0, zCenter = 0;
for (int i = 0; i < numTriangles; i++)
{
totalVolume += currentVolume = (triangles[i].x1*triangles[i].y2*triangles[i].z3 - triangles[i].x1*triangles[i].y3*triangles[i].z2 - triangles[i].x2*triangles[i].y1*triangles[i].z3 + triangles[i].x2*triangles[i].y3*triangles[i].z1 + triangles[i].x3*triangles[i].y1*triangles[i].z2 - triangles[i].x3*triangles[i].y2*triangles[i].z1) / 6;
xCenter += ((triangles[i].x1 + triangles[i].x2 + triangles[i].x3) / 4) * currentVolume;
yCenter += ((triangles[i].y1 + triangles[i].y2 + triangles[i].y3) / 4) * currentVolume;
zCenter += ((triangles[i].z1 + triangles[i].z2 + triangles[i].z3) / 4) * currentVolume;
}
cout << endl << "Total Volume = " << totalVolume << endl;
cout << endl << "X center = " << xCenter/totalVolume << endl;
cout << endl << "Y center = " << yCenter/totalVolume << endl;
cout << endl << "Z center = " << zCenter/totalVolume << endl;
}
Extremely fast for calculating centres of mass for STL files.