flattenReallyStrong

map.flattenStrong() was leaving me with over 2000 nodes, so I wrote this to be more aggressive, and get me down to 1 node.

def flattenReallyStrong(n):
    """
    force the passed nodepath into a single geomNode, then flattens the
    geomNode to minimize geomCount.

    In many cases, flattenStrong is not enough, and for good reason.
    This code ignores all potential issues and forces it into one node.
    It will alwayse do so.

    RenderStates are preserved, transformes are applied, but tags,
    special node classes and any other such data is all lost.

    This modifies the passed NodePath as a side effect and returns the
    new NodePath.
    """
    # make sure all the transforms are applied to the geoms
    n.flattenLight()
    # make GeomNode to store results in.
    g=GeomNode("flat_"+n.getName())
    g.setState(n.getState())
    
    # a little helper to process GeomNodes since we need it in 2 places
    def f(c):
        rs=c.getState(n)
        gg=c.node()
        for i in xrange(gg.getNumGeoms()):
            g.addGeom(gg.modifyGeom(i),rs.compose(gg.getGeomState(i)))
    
    # special case this node being a GeomNode so we don't skips its geoms.
    if n.node().isGeomNode(): f(n)
    # proccess all GeomNodes
    for c in n.findAllMatches('**/+GeomNode'): f(c)
        
    nn=NodePath(g)
    nn.setMat(n.getMat())
    # merge geoms
    nn.flattenStrong()
    return nn

And here is a sloppy bit of code that uses it to flatten any nodes with bounds smaller than a passed size (relative to a passed reference (ref) node):

def flattenBig(n,ref,size):
    a=Point3()
    b=Point3()
    n.calcTightBounds(a,b)
    a=ref.getRelativePoint(n,a)
    b=ref.getRelativePoint(n,b)
    if (a-b).length()<size:
        #n.flattenStrong()
        nn=flattenReallyStrong(n)
        return nn
    else:
        for nn in n.getChildren():
            nn2=flattenBig(nn,ref,size)
            if nn2!=nn:
                nn.removeNode()
                nn2.reparentTo(n)
        return n

flattenStrong() won’t flatten past a ModelNode, which is at the top of any loaded model. You can remove the model nodes first with something like:

root.clearModelNodes()
root.flattenStrong()

which should indeed get you to one node.

David

That works as promised (well, I get 2 nodes, but thats not unexpected). Thanks.

Thanks for bringing this up!

This is very useful with this [url]Points on and in spheres] snippet.