center of gravity panel center of gravity panel png 08/15/2013 12:24:44

Center of Gravity

This is a tool script that calculates the center of gravity for a solid object on the assumption it is made of some uniformly dense material (in other words, it's the center of "volume" rather than the center of gravity).

It's a refinement of an earlier script that calculated the center of "area" of a group of selected faces (because I assumed calculating the center of volume would be hard — and it was!).

Objects with hollow interiors are explicitly supported (that's the whole point of it).

Algorithm

The volume of the object is calculated by forming a tetrahedron out of each triangle in the object's surface along with the origin. The volume is inverted (treated as negative) if the triangle in question faces the origin.

The volume of each tetrahedron is easy to calculate — |(a.(bxc))|/6. The center of volume is the mean of the centroids of these tetrahedra weighted by the associated volume (which can be negative).

This algorithm is based on a post on StackOverflow, the Wikipedia article on calculating the volume of a tetrahedron. I also looked up the formula for calculating a cross-product because I couldn't remember it or be bothered to calculate it from first principles.

The trickiest part of the implementation is that Cheetah 3D's built-in Vec3D object's methods have weird behavior, so the script includes replacements for most of them. Here's the relevant code for your edification.

function add( /* takes any number of vectors */ ){
    var x = 0, y = 0, z = 0;
    for( var i = 0; i < arguments.length; i++ ){
        x += arguments[i].x;
        y += arguments[i].y;
        z += arguments[i].z;
    }
    return new Vec3D( x, y, z );
}

function mult(a, s){
    return new Vec3D( a.x * s, a.y * s, a.z * s );
}

function dot(a, b){
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

function norm(a){
    return Math.sqrt( a.x * a.x + a.y * a.y + a.z * a.z );
}

function cross(a, b){
    return new Vec3D(
        a.y * b.z - a.z * b.y,
        a.z * b.x - a.x * b.z,
        a.x * b.y - a.y * b.x
    );
}

Testing

I haven't tested this script extensively (or written unit tests) but it does correctly calculate the volumes of primitive spheres and cubes, and correctly calculate the volume of a test sphere with a hollow sphere embedded in it, so I'm pretty sure it works.

Aside

Another weird thing I encountered when implementing this script was that creating my own complete replacement for Vec3D (I tried to create a JavaScript "class" called vec) doesn't appear to work in Cheetah 3D's scripting environment. In particular, the class's methods were not "visible" at runtime. I'm not sure what the deal is. In the end, I simply implemented global functions (seen above). If anyone has a clue what's going on here, I'd love to know.

index markdown 08/16/2013 13:18:16

center of gravity.js zip2.3kB

center of gravity.js zip 08/15/2013 12:17:36

http://loewald.com/c3dbook/Scripts/Center-of-Gravity/

Powered by FolderMark