Why is my center of mass not calculating correctly?
What Blender's "origin to center of mass" does is compute the center of mass of the faces, i.e. it treats the object as a hollow shell with infinitely thin faces.

This is not the same as the center of mass of a solid object with constant density, as this example illustrates:



Blender's CM is the yellow dot, closest to the broad faces of the base
"solid" CM is at cursor's location, closest to the massive cube on top.

Unfortunately, I don't think there is a simple builtin way to compute the "solid" center of mass.

I have written a Python script that does the actual computation, but it will only give a correct result on meshes that define enclosed volumes (possibly with holes, but the outer boundaries must be continuous). It works by summing signed volumes of tetrahedrons defined by all the mesh triangles.



import bpy
import mathutils
from mathutils import Vector

def triangles (verts):
    """enumerate triangles in a face"""
    for i in range (1, len(verts)-1):
        yield (verts[0], verts[i], verts[i+1])

def cg_mesh (obj):
    """center of mass (and volume) of a mesh"""

    center = Vector()
    volume = 0
    mesh = obj.to_mesh (bpy.context.scene, True, 'PREVIEW')
    for face in mesh.polygons:
        f = face.vertices
        for t in triangles (f):
            a,b,c = (mesh.vertices[v].co for v in t)
            v = a.cross(b).dot(c) / 6
            center += v * (a+b+c) / 4
            volume += v
    bpy.data.meshes.remove(mesh)

    if volume == 0: print ("ZERO VOLUME", obj.name)
    else          : center /= volume

    return obj.matrix_world * center

# puts the cursor at the active object's center of mass
bpy.context.scene.cursor_location = cg_mesh (bpy.context.scene.objects.active)


This example will put the 3D cursor at the "solid" CM location, but you can adapt the script to do whatever you want.

The script applies all modifiers to the object, converting it to a mesh. If you want the CM of your primitive object, disable the modifiers first.

On the other hand, you can use it on a flat object by adding a "solidify" modifier first.

Again, no checks are made to insure the mesh defines a valid volume. If not, the result will be wrong.