Usually point caching systems will only deal with objects that are driven by deformation (eg, nCache) – hence the name, point caching. Other bigger, badder systems (eg, alembic) can cope with both transforms and deformations. However, what if you have a transform driven object that you desperately need to export to a point cache?

It’s fairly easy to make a copy of the object that has the same animation, but is driven by deformation, using the “transformGeometry” node. This wee bugger usually crops up when you freeze transfoms on an object, but you can also feed it a transform matrix from a moving object to move it’s points about.

Consider the following: a sphere (“pSphere1”) animated with a few lovingly crafted keyframes. Looks like my study at AnimationMentor really paid off, huh?

Now, if we wanted to cache this out to nCache, it would stubbornly sit at the origin, staring, mocking us. That’s because the points aren’t actually doing any moving, only the object’s transform.

To give us something that we *can* cache out, we first
* Duplicate pSphere1 – this will give us pSphere2
* Zero the transforms on pSphere2
* In one of the node editors, create a “transformGeometry” node
* Connect pSphere1’s “worldMatrix” attribute to the transformGeometry’s “transform” attribute
* Connect pSphere1.outMesh to transformGeometry1.inputGeometry
* connect transformGeometry1.outGeometry to pSphere2.inMesh

What you should have is an object with no keyframes on it’s transforms, but that has the same motion regardless. This object can then be point cached quite happily.

And here’s some code:

def getShape(node):
    Finds the shape node from a transform

    @param node: Object
    @type node: String

    @return: Shape node

    if cmds.nodeType(node) == 'transform':
        shapes = [x for x in cmds.listRelatives(node, shapes=True, fullPath=True) if cmds.getAttr(x + '.intermediateObject') != True]
        if not shapes:
            raise RuntimeError, '%s has no shape' % node
        return shapes[0]
    elif cmds.nodeType(node) in ['mesh', 'nurbsCurve', 'nurbsSurface']:
        return node

selection =
for sel in selection:
    shapeNode = getShape(sel)
    dupObj = cmds.duplicate(sel)
    cmds.xform(dupObj, absolute=True, rotation=(0, 0, 0), translation=(0,0,0), scale=(1,1,1) )
    dupShape = getShape(dupObj)
    xformGeoNode = cmds.createNode('transformGeometry')
    cmds.connectAttr(sel + '.worldMatrix', xformGeoNode + '.transform')
    cmds.connectAttr(shapeNode +' .outMesh', xformGeoNode + '.inputGeometry')
    cmds.connectAttr(xformGeoNode + '.outputGeometry', dupShape + '.inMesh')