def __call__(self, node): # Would use NodePath.findAllVertexColumns (string name) # but that also searchs child nodes # And does not require all geoms to have it. n = node.node() if not n.isOfType(GeomNode.getClassType()): return False for p in self.requiredPeoperties: for g in n.getGeoms(): found = False for a in g.getVertexData().getArrays(): if a.hasColumn(p): found = True break if not found: return False return True
def __call__(self,node): # Would use NodePath.findAllVertexColumns (string name) # but that also searchs child nodes # And does not require all geoms to have it. n=node.node() if not n.isOfType(GeomNode.getClassType()): return False for p in self.requiredPeoperties: for g in n.getGeoms(): found=False for a in g.getVertexData().getArrays(): if a.hasColumn(p): found=True break if not found: return False return True
def makeBulletCollFromGeoms(rootNode, exclusions=[], enableNow=True, world=None): """ Creates and attaches bullet triangle mesh nodes underneath each GeomNode of `rootNode`, which contains the same mesh as the Geoms. This can be expensive if the geometry contains lots of triangles or GeomNodes. """ if not world: world = base.physicsWorld # BulletRigidBodyNode -> triangle index -> surfaceprop # (it's so we know which surface we are walking on) result = {} for faceNp in rootNode.findAllMatches("**"): if faceNp.getName() in exclusions: continue if faceNp.node().getType() != GeomNode.getClassType(): continue # Create a separate list of geoms for each possible face type # ( a wall or floor ) type2geoms = {} for i in xrange(faceNp.node().getNumGeoms()): geom = faceNp.node().getGeom(i) state = faceNp.node().getGeomState(i) if not geom.getPrimitive(0).isIndexed(): continue if state.hasAttrib(BSPFaceAttrib.getClassSlot()): bca = state.getAttrib(BSPFaceAttrib.getClassSlot()) facetype = bca.getFaceType() else: facetype = BSPFaceAttrib.FACETYPE_WALL if not type2geoms.has_key(facetype): type2geoms[facetype] = [(geom, state)] else: type2geoms[facetype].append((geom, state)) # Now create a separate body node to group each face type, # and assign the correct bit for facetype, geoms in type2geoms.items(): data = {} numGeoms = 0 mesh = BulletTriangleMesh() for i in xrange(len(geoms)): geom, state = geoms[i] mesh.addGeom(geom, True) surfaceprop = "default" if state.hasAttrib(BSPMaterialAttrib.getClassSlot()): mat = state.getAttrib( BSPMaterialAttrib.getClassSlot()).getMaterial() if mat: surfaceprop = mat.getSurfaceProp() for j in xrange(geom.getNumPrimitives()): prim = geom.getPrimitive(j) prim = prim.decompose() tris = prim.getNumVertices() / 3 for tidx in xrange(tris): data[numGeoms] = surfaceprop numGeoms += 1 shape = BulletTriangleMeshShape(mesh, False) rbnode = BulletRigidBodyNode(faceNp.getName() + "_bullet_type" + str(facetype)) rbnode.setKinematic(True) rbnode.addShape(shape) rbnodeNp = NodePath(rbnode) rbnodeNp.reparentTo(faceNp) if facetype == BSPFaceAttrib.FACETYPE_WALL: rbnodeNp.setCollideMask(CIGlobals.WallGroup) elif facetype == BSPFaceAttrib.FACETYPE_FLOOR: rbnodeNp.setCollideMask(CIGlobals.FloorGroup) if enableNow: world.attachRigidBody(rbnode) result[rbnode] = data return result