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