def __init__(self, name, model, game, pos): self.name = name self.game = game self.model = model self.geomNode = self.model.node() self.geom = self.geomNode.getGeom(0) # with triangle mesh it crashes #mesh = BulletTriangleMesh() #mesh.addGeom(self.geom) #self.shape = BulletTriangleMeshShape(mesh, dynamic=True) # with convex hull self.shape = BulletConvexHullShape() self.shape.addGeom(self.geom) self.node = BulletRigidBodyNode(self.name) self.node.setMass(10.0) self.node.addShape(self.shape) self.np = self.game.render.attachNewNode(self.node) self.np.setPos(pos) self.game.world.attachRigidBody(self.node) self.model.reparentTo(self.np) self.node.setCcdMotionThreshold(1e-7) self.node.setCcdSweptSphereRadius(0.5) self.slice_able = True
def __init__(self, name, modelPath, game, pos): self.name = name self.modelPath = modelPath self.game = game self.model = self.game.loader.loadModel(self.modelPath) geomNodes = self.model.findAllMatches('**/+GeomNode') self.geomNode = geomNodes.getPath(0).node() self.geom = self.geomNode.getGeom(0) self.shape = BulletConvexHullShape() self.shape.addGeom(self.geom) self.node = BulletRigidBodyNode(self.name) self.node.setMass(10.0) self.node.addShape(self.shape) self.np = self.game.render.attachNewNode(self.node) self.np.setPos(pos) self.game.world.attachRigidBody(self.node) self.model.reparentTo(self.np) self.node.setCcdMotionThreshold(1e-7) self.node.setCcdSweptSphereRadius(0.5) self.slice_able = True
def add_solid(self, node): mesh = BulletConvexHullShape() mesh.add_geom(GeomBuilder().add_ramp(self.color, self.base, self.top, self.width, self.thickness, LRotationf(*self.hpr)).get_geom()) node.add_shape(mesh) return node
def addMeshConvexRB(self,vertices, faces,ghost=False,**kw): #step 1) create GeomVertexData and add vertex information format=GeomVertexFormat.getV3() vdata=GeomVertexData("vertices", format, Geom.UHStatic) vertexWriter=GeomVertexWriter(vdata, "vertex") [vertexWriter.addData3f(v[0],v[1],v[2]) for v in vertices] #step 2) make primitives and assign vertices to them tris=GeomTriangles(Geom.UHStatic) [self.setGeomFaces(tris,face) for face in faces] #step 3) make a Geom object to hold the primitives geom=Geom(vdata) geom.addPrimitive(tris) #step 4) create the bullet mesh and node mesh = BulletTriangleMesh() mesh.addGeom(geom) shape = BulletConvexHullShape(mesh, dynamic=not ghost)# if ghost : inodenp = self.worldNP.attachNewNode(BulletGhostNode('Mesh')) else : inodenp = self.worldNP.attachNewNode(BulletRigidBodyNode('Mesh')) inodenp.node().addShape(shape) # inodenp.setPos(0, 0, 0.1) self.setRB(inodenp,**kw) inodenp.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(inodenp.node()) return inodenp
def getCollisionShapeFromModel(model, mode='box', defaultCentered=False): #NOTE: make sure the position is relative to the center of the object minBounds, maxBounds = model.getTightBounds() offset = minBounds + (maxBounds - minBounds) / 2.0 transform = TransformState.makeIdentity() if mode == 'mesh': # Use exact triangle mesh approximation mesh = BulletTriangleMesh() geomNodes = model.findAllMatches('**/+GeomNode') for nodePath in geomNodes: geomNode = nodePath.node() for n in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(n) mesh.addGeom(geom) shape = BulletTriangleMeshShape(mesh, dynamic=False) transform = model.getTransform() elif mode == "sphere": minBounds, maxBounds = model.getTightBounds() dims = maxBounds - minBounds radius = np.sqrt(np.square(dims[0]) + np.square(dims[1])) / 2.0 height = dims[2] shape = BulletCapsuleShape(radius, 2 * radius) if not defaultCentered: transform = TransformState.makePos(offset) elif mode == "hull": shape = BulletConvexHullShape() geomNodes = model.findAllMatches('**/+GeomNode') for nodePath in geomNodes: geomNode = nodePath.node() for n in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(n) shape.addGeom(geom) elif mode == 'box': # Bounding box approximation minBounds, maxBounds = model.getTightBounds() dims = maxBounds - minBounds shape = BulletBoxShape(Vec3(dims.x / 2, dims.y / 2, dims.z / 2)) if not defaultCentered: transform = TransformState.makePos(offset) elif mode == 'capsule': minBounds, maxBounds = model.getTightBounds() dims = maxBounds - minBounds radius = np.sqrt(np.square(dims[0]) + np.square(dims[1])) / 2.0 height = dims[2] shape = BulletCapsuleShape(radius, height - 2 * radius) if not defaultCentered: transform = TransformState.makePos(offset) else: raise Exception( 'Unknown mode type for physic object collision shape: %s' % (mode)) return shape, transform
def add_solid(self, node): mesh = BulletConvexHullShape() mesh.add_geom(GeomBuilder().add_dome(self.color, self.center, self.radius, self.samples, self.planes, LRotationf(*self.hpr)).get_geom()) node.add_shape(mesh) return node
def makeBulletConvexHullFromCollisionSolids(cnode): from panda3d.core import CollisionPolygon from panda3d.bullet import BulletConvexHullShape shape = BulletConvexHullShape() for solid in cnode.getSolids(): if isinstance(solid, CollisionPolygon): for point in solid.getPoints(): shape.addPoint(point) return shape
def __set_collision_mesh(self): fpath = self.props.coll_path % self.mdt.name self.coll_mesh = loader.loadModel(fpath) chassis_shape = BulletConvexHullShape() for geom in PhysMgr().find_geoms(self.coll_mesh, self.props.coll_name): chassis_shape.addGeom(geom.node().getGeom(0), geom.getTransform()) self.mdt.gfx.nodepath.node().addShape(chassis_shape) self.mdt.gfx.nodepath.setCollideMask( BitMask32.bit(1) | BitMask32.bit(2 + self.props.cars.index(self.mdt.name)))
def __init__( self, world:BulletWorld, entity:Entity, mass=0, rotation=[None, None, None] ): geomNodes = entity.model.findAllMatches('**/+GeomNode') geomNode = geomNodes.getPath(0).node() geom = geomNode.getGeom(0) shape = BulletConvexHullShape() shape.addGeom(geom) super().__init__(world, entity, shape, 'convex_hull', rotation)
def modelToConvex(model): """ :type model: panda3d.core.NodePath :return: tuple(panda3d.bullet.BulletConvexHull,transform) """ geomnodes = model.findAllMatches('**/+GeomNode') transform = model.getTransform() gn = geomnodes.getPath(0).node() geom = gn.getGeom(0) shape = BulletConvexHullShape() shape.addGeom(geom) return shape, transform
def setup_shape(self, gnodepath, bone, pname): shape = BulletConvexHullShape() gnode = gnodepath.node() geom = gnode.get_geom(0) shape.add_geom(geom) node = BulletRigidBodyNode(self.name + pname) np = self.actor.attach_new_node(node) np.node().add_shape(shape) np.node().set_kinematic(True) np.wrt_reparent_to(bone) self.world.physics.attach_rigid_body(node) return np
def __addConvexHull(self, body, model, pos=(0,0,0), hpr=(0,0,0), scale=(1,1,1) ): def one(): geom = model.node().getGeom(0) shape = BulletConvexHullShape() shape.addGeom(geom) body.addShape( shape, TransformState.makePosHprScale(pos,hpr,scale) ) return [] children = model.findAllMatches('**/+GeomNode') or one() model.flattenLight() for piece in children: shape = BulletConvexHullShape() geom = piece.node().getGeom(0) shape.addGeom(geom) body.addShape( shape, TransformState.makePosHprScale(pos,hpr,scale) )
def addBox(): # Box #shape = BulletCylinderShape(0.5, 3, 2) geomNodes = loader.loadModel('cilindroB').findAllMatches('**/+GeomNode') geomNode = geomNodes.getPath(0).node() geom = geomNode.getGeom(0) shape = BulletConvexHullShape() shape.addGeom(geom) node = BulletRigidBodyNode('Cylinder') node.setMass(random.randint(1, 10)) node.addShape(shape) np = render.attachNewNode(node) np.setPos(0, 0, 10) world.attachRigidBody(node) #model = loader.loadModel('cilindroR') model.flattenLight() model.reparentTo(np)
def setup(self): self.worldNP = render.attachNewNode('World') # World self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug')) self.debugNP.show() self.debugNP.node().showWireframe(True) self.debugNP.node().showConstraints(True) self.debugNP.node().showBoundingBoxes(False) self.debugNP.node().showNormals(False) self.world = BulletWorld() self.world.setGravity(Vec3(0, 0, -9.81)) self.world.setDebugNode(self.debugNP.node()) # Ground shape = BulletPlaneShape(Vec3(0, 0, 1), 0) body = BulletRigidBodyNode('Ground') bodyNP = self.worldNP.attachNewNode(body) bodyNP.node().addShape(shape) bodyNP.setPos(0, 0, 0) bodyNP.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(bodyNP.node()) # Bowl visNP = loader.loadModel('models/bowl.egg') geom = visNP.findAllMatches('**/+GeomNode').getPath(0).node().getGeom( 0) mesh = BulletTriangleMesh() mesh.addGeom(geom) shape = BulletTriangleMeshShape(mesh, dynamic=True) body = BulletRigidBodyNode('Bowl') bodyNP = self.worldNP.attachNewNode(body) bodyNP.node().addShape(shape) bodyNP.node().setMass(10.0) bodyNP.setPos(0, 0, 0) bodyNP.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(bodyNP.node()) visNP.reparentTo(bodyNP) self.bowlNP = bodyNP self.bowlNP.setScale(2) # Eggs self.eggNPs = [] for i in range(5): x = random.gauss(0, 0.1) y = random.gauss(0, 0.1) z = random.gauss(0, 0.1) + 1 h = random.random() * 360 p = random.random() * 360 r = random.random() * 360 visNP = loader.loadModel('models/egg.egg') geom = visNP.findAllMatches('**/+GeomNode').getPath( 0).node().getGeom(0) shape = BulletConvexHullShape() shape.addGeom(geom) body = BulletRigidBodyNode('Egg-%i' % i) bodyNP = self.worldNP.attachNewNode(body) bodyNP.node().setMass(1.0) bodyNP.node().addShape(shape) bodyNP.node().setDeactivationEnabled(False) bodyNP.setCollideMask(BitMask32.allOn()) bodyNP.setPosHpr(x, y, z, h, p, r) #bodyNP.setScale(1.5) self.world.attachRigidBody(bodyNP.node()) visNP.reparentTo(bodyNP) self.eggNPs.append(bodyNP)
def __addConvexHull(self, body, geom, pos=(0,0,0), hpr=(0,0,0), scale=(1,1,1) ): shape = BulletConvexHullShape() shape.addGeom(geom) body.addShape( shape, TransformState.makePosHprScale(pos,hpr,scale) )
def setup(self): self.worldNP = render.attachNewNode('World') # World self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug')) self.debugNP.show() self.debugNP.node().showWireframe(True) self.debugNP.node().showConstraints(True) self.debugNP.node().showBoundingBoxes(False) self.debugNP.node().showNormals(True) self.world = BulletWorld() self.world.setGravity(Vec3(0, 0, -9.81)) self.world.setDebugNode(self.debugNP.node()) # Plane (static) shape = BulletPlaneShape(Vec3(0, 0, 1), 0) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Ground')) np.node().addShape(shape) np.setPos(0, 0, -1) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) # Box (dynamic) shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5)) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Box')) np.node().setMass(1.0) np.node().addShape(shape) np.setPos(0, 0, 4) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) self.boxNP = np # For applying force & torque #np.node().notifyCollisions(True) #self.accept('bullet-contact-added', self.doAdded) #self.accept('bullet-contact-destroyed', self.doRemoved) # Sphere (dynamic) shape = BulletSphereShape(0.6) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Sphere')) np.node().setMass(1.0) np.node().addShape(shape) np.setPos(-4, 0, 4) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) # Cone (dynamic) shape = BulletConeShape(0.6, 1.2, ZUp) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Cone')) np.node().setMass(1.0) np.node().addShape(shape) np.setPos(4, 0, 4) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) # Capsule (dynamic) shape = BulletCapsuleShape(0.5, 1.0, ZUp) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Capsule')) np.node().setMass(1.0) np.node().addShape(shape) np.setPos(0, 4, 4) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) # Cyliner (dynamic) shape = BulletCylinderShape(0.7, 1.5, ZUp) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Cylinder')) np.node().setMass(1.0) np.node().addShape(shape) np.setPos(4, 4, 4) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) # Convex (dynamic) shape = BulletConvexHullShape() shape.addPoint(Point3(1, 1, 2)) shape.addPoint(Point3(0, 0, 0)) shape.addPoint(Point3(2, 0, 0)) shape.addPoint(Point3(0, 2, 0)) shape.addPoint(Point3(2, 2, 0)) # Another way to create the convex hull shape: #shape = BulletConvexHullShape() #shape.addArray([ # Point3(1, 1, 2), # Point3(0, 0, 0), # Point3(2, 0, 0), # Point3(0, 2, 0), # Point3(2, 2, 0), #]) # Yet another way to create the convex hull shape: #geom = loader.loadModel('models/box.egg')\ # .findAllMatches('**/+GeomNode')\ # .getPath(0)\ # .node()\ # .getGeom(0) #shape = BulletConvexHullShape() #shape.addGeom(geom) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Convex')) np.node().setMass(1.0) np.node().addShape(shape) np.setPos(-4, 4, 4) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) # Mesh (static) p0 = Point3(-10, -10, 0) p1 = Point3(-10, 10, 0) p2 = Point3(10, -10, 0) p3 = Point3(10, 10, 0) mesh = BulletTriangleMesh() mesh.addTriangle(p0, p1, p2) mesh.addTriangle(p1, p2, p3) shape = BulletTriangleMeshShape(mesh, dynamic=False) # Another way to create the triangle mesh shape: #geom = loader.loadModel('models/box.egg')\ # .findAllMatches('**/+GeomNode')\ # .getPath(0)\ # .node()\ # .getGeom(0) #mesh = BulletTriangleMesh() #mesh.addGeom(geom) #shape = BulletTriangleMeshShape(mesh, dynamic=False) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Mesh')) np.node().addShape(shape) np.setPos(0, 0, 0.1) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) # MutiSphere points = [Point3(-1, 0, 0), Point3(0, 0, 0), Point3(1, 0, 0)] radii = [.4, .8, .6] shape = BulletMultiSphereShape(points, radii) np = self.worldNP.attachNewNode(BulletRigidBodyNode('MultiSphere')) np.node().setMass(1.0) np.node().addShape(shape) np.setPos(8, 0, 4) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node())
def __init__(self, initor, cdtype="triangles", mass=.3, restitution=0, allow_deactivation=False, allow_ccd=True, friction=.2, dynamic=True, name="rbd"): """ TODO: triangles do not seem to work (very slow) in the github version (20210418) Use convex if possible :param initor: could be itself (copy), or an instance of collision model :param type: triangle or convex :param mass: :param restitution: bounce parameter :param friction: :param dynamic: only applicable to triangle type, if an object does not move with force, it is not dynamic :param name: author: weiwei date: 20190626, 20201119 """ super().__init__(name) if isinstance(initor, gm.GeometricModel): if initor._objtrm is None: raise ValueError("Only applicable to models with a trimesh!") self.com = initor.objtrm.center_mass * base.physics_scale self.setMass(mass) self.setRestitution(restitution) self.setFriction(friction) self.setLinearDamping(.3) self.setAngularDamping(.3) if allow_deactivation: self.setDeactivationEnabled(True) self.setLinearSleepThreshold(.01 * base.physics_scale) self.setAngularSleepThreshold(.01 * base.physics_scale) else: self.setDeactivationEnabled(False) if allow_ccd: # continuous collision detection self.setCcdMotionThreshold(1e-7) self.setCcdSweptSphereRadius(0.0005 * base.physics_scale) geom_np = initor.objpdnp.getChild(0).find("+GeomNode") geom = copy.deepcopy(geom_np.node().getGeom(0)) vdata = geom.modifyVertexData() vertices = copy.deepcopy( np.frombuffer(vdata.modifyArrayHandle(0).getData(), dtype=np.float32)) vertices.shape = (-1, 6) vertices[:, :3] = vertices[:, :3] * base.physics_scale - self.com vdata.modifyArrayHandle(0).setData( vertices.astype(np.float32).tobytes()) geomtf = geom_np.getTransform() geomtf = geomtf.setPos(geomtf.getPos() * base.physics_scale) if cdtype == "triangles": geombmesh = BulletTriangleMesh() geombmesh.addGeom(geom) bulletshape = BulletTriangleMeshShape(geombmesh, dynamic=dynamic) bulletshape.setMargin(1e-6) self.addShape(bulletshape, geomtf) elif cdtype == "convex": bulletshape = BulletConvexHullShape( ) # TODO: compute a convex hull? bulletshape.addGeom(geom, geomtf) bulletshape.setMargin(1e-6) self.addShape(bulletshape, geomtf) elif cdtype == 'box': minx = min(vertices[:, 0]) miny = min(vertices[:, 1]) minz = min(vertices[:, 2]) maxx = max(vertices[:, 0]) maxy = max(vertices[:, 1]) maxz = max(vertices[:, 2]) pcd_box = CollisionBox(Point3(minx, miny, minz), Point3(maxx, maxy, maxz)) bulletshape = BulletBoxShape.makeFromSolid(pcd_box) bulletshape.setMargin(1e-6) self.addShape(bulletshape, geomtf) else: raise NotImplementedError pd_homomat = geomtf.getMat() pd_com_pos = pd_homomat.xformPoint( Vec3(self.com[0], self.com[1], self.com[2])) np_homomat = dh.pdmat4_to_npmat4(pd_homomat) np_com_pos = dh.pdv3_to_npv3(pd_com_pos) np_homomat[:3, 3] = np_com_pos # update center to com self.setTransform( TransformState.makeMat(dh.npmat4_to_pdmat4(np_homomat))) elif isinstance(initor, BDBody): self.com = initor.com.copy() self.setMass(initor.getMass()) self.setRestitution(initor.restitution) self.setFriction(initor.friction) self.setLinearDamping(.3) self.setAngularDamping(.3) if allow_deactivation: self.setDeactivationEnabled(True) self.setLinearSleepThreshold(.01 * base.physics_scale) self.setAngularSleepThreshold(.01 * base.physics_scale) else: self.setDeactivationEnabled(False) if allow_ccd: self.setCcdMotionThreshold(1e-7) self.setCcdSweptSphereRadius(0.0005 * base.physics_scale) np_homomat = copy.deepcopy(initor.get_homomat()) np_homomat[:3, 3] = np_homomat[:3, 3] * base.physics_scale self.setTransform( TransformState.makeMat(dh.npmat4_to_pdmat4(np_homomat))) self.addShape(initor.getShape(0), initor.getShapeTransform(0))
def one(): geom = model.node().getGeom(0) shape = BulletConvexHullShape() shape.addGeom(geom) body.addShape( shape, TransformState.makePosHprScale(pos,hpr,scale) ) return []
def setup(self): self.worldNP = render.attach_new_node('World') # World self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug')) self.debugNP.show() self.debugNP.node().show_wireframe(True) self.debugNP.node().show_constraints(True) self.debugNP.node().show_bounding_boxes(False) self.debugNP.node().show_normals(False) self.world = BulletWorld() self.world.set_gravity(LVector3(0, 0, -9.81)) self.world.set_debug_node(self.debugNP.node()) # Ground shape = BulletPlaneShape(LVector3(0, 0, 1), 0) body = BulletRigidBodyNode('Ground') bodyNP = self.worldNP.attach_new_node(body) bodyNP.node().add_shape(shape) bodyNP.set_pos(0, 0, 0) bodyNP.set_collide_mask(BitMask32.all_on()) self.world.attach(bodyNP.node()) # Bowl visNP = loader.load_model('models/bowl.egg') geom = (visNP.findAllMatches('**/+GeomNode').get_path( 0).node().get_geom(0)) mesh = BulletTriangleMesh() mesh.addGeom(geom) shape = BulletTriangleMeshShape(mesh, dynamic=True) body = BulletRigidBodyNode('Bowl') bodyNP = self.worldNP.attach_new_node(body) bodyNP.node().add_shape(shape) bodyNP.node().set_mass(10.0) bodyNP.set_pos(0, 0, 0) bodyNP.set_collide_mask(BitMask32.all_on()) self.world.attach(bodyNP.node()) visNP.reparent_to(bodyNP) self.bowlNP = bodyNP self.bowlNP.set_scale(2) # Eggs self.eggNPs = [] for i in range(5): x = random.gauss(0, 0.1) y = random.gauss(0, 0.1) z = random.gauss(0, 0.1) + 1 h = random.random() * 360 p = random.random() * 360 r = random.random() * 360 visNP = loader.load_model('models/egg.egg') geom = (visNP.find_all_matches('**/+GeomNode').get_path( 0).node().get_geom(0)) shape = BulletConvexHullShape() shape.addGeom(geom) body = BulletRigidBodyNode('Egg-%i' % i) bodyNP = self.worldNP.attach_new_node(body) bodyNP.node().set_mass(1.0) bodyNP.node().add_shape(shape) bodyNP.node().set_deactivation_enabled(False) bodyNP.set_collide_mask(BitMask32.all_on()) bodyNP.set_pos_hpr(x, y, z, h, p, r) #bodyNP.set_scale(1.5) self.world.attach(bodyNP.node()) visNP.reparent_to(bodyNP) self.eggNPs.append(bodyNP)
def __init__(self, objinit, cdtype="triangle", mass=.3, restitution=0, allowdeactivation=False, allowccd=True, friction=.2, dynamic=True, name="rbd"): """ :param objinit: could be itself (copy), or an instance of collision model :param type: triangle or convex :param mass: :param restitution: bounce parameter :param friction: :param dynamic: only applicable to triangle type, if an object does not move with force, it is not dynamic :param name: author: weiwei date: 20190626, 20201119 """ super().__init__(name) if isinstance(objinit, gm.GeometricModel): if objinit._objtrm is None: raise ValueError("Only applicable to models with a trimesh!") self.com = objinit.objtrm.center_mass self.setMass(mass) self.setRestitution(restitution) self.setFriction(friction) self.setLinearDamping(.3) self.setAngularDamping(.3) if allowdeactivation: self.setDeactivationEnabled(True) self.setLinearSleepThreshold(0.001) self.setAngularSleepThreshold(0.001) else: self.setDeactivationEnabled(False) if allowccd: # continuous collision detection self.setCcdMotionThreshold(1e-6) self.setCcdSweptSphereRadius(0.0005) gnd = objinit.objpdnp.getChild(0).find("+GeomNode") geom = copy.deepcopy(gnd.node().getGeom(0)) vdata = geom.modifyVertexData() vertrewritter = GeomVertexRewriter(vdata, 'vertex') while not vertrewritter.isAtEnd(): # shift local coordinate to geom to correctly update dynamic changes v = vertrewritter.getData3f() vertrewritter.setData3f(v[0] - self.com[0], v[1] - self.com[1], v[2] - self.com[2]) geomtf = gnd.getTransform() if cdtype is "triangle": geombmesh = BulletTriangleMesh() geombmesh.addGeom(geom) bulletshape = BulletTriangleMeshShape(geombmesh, dynamic=dynamic) bulletshape.setMargin(1e-6) self.addShape(bulletshape, geomtf) elif cdtype is "convex": bulletshape = BulletConvexHullShape() # TODO: compute a convex hull? bulletshape.addGeom(geom, geomtf) bulletshape.setMargin(1e-6) self.addShape(bulletshape, geomtf) else: raise NotImplementedError pdmat4 = geomtf.getMat() pdv3 = pdmat4.xformPoint(Vec3(self.com[0], self.com[1], self.com[2])) homomat = dh.pdmat4_to_npmat4(pdmat4) pos = dh.pdv3_to_npv3(pdv3) homomat[:3, 3] = pos # update center to com self.setTransform(TransformState.makeMat(dh.npmat4_to_pdmat4(homomat))) elif isinstance(objinit, BDBody): self.com = objinit.com.copy() self.setMass(objinit.getMass()) self.setRestitution(objinit.restitution) self.setFriction(objinit.friction) self.setLinearDamping(.3) self.setAngularDamping(.3) if allowdeactivation: self.setDeactivationEnabled(True) self.setLinearSleepThreshold(0.001) self.setAngularSleepThreshold(0.001) else: self.setDeactivationEnabled(False) if allowccd: self.setCcdMotionThreshold(1e-6) self.setCcdSweptSphereRadius(0.0005) self.setTransform(TransformState.makeMat(dh.npmat4_to_pdmat4(objinit.gethomomat()))) self.addShape(objinit.getShape(0), objinit.getShapeTransform(0))
def __init__(self, app, model_name): model_file_name = 'assets/cars/{}/{}.bam'.format( model_name, model_name) self.app = app def animation_path(model, animation): base_path = 'assets/cars/animations/{}/{}-{}.bam' return base_path.format(model, model, animation) self.model = Actor( model_file_name, { # AIRBRAKE: 'assets/cars/animations/{}-{}.bam'.format(model_name, AIRBRAKE), # AIRBRAKE: animation_path(model_name, AIRBRAKE), # STABILIZER_FINS: animation_path(model_name, STABILIZER_FINS), }) self.model.enableBlend() self.model.setControlEffect(AIRBRAKE, 1) self.model.setControlEffect(STABILIZER_FINS, 1) # FIXME: This code fails due to a bug in Actor # airbrake_joints = [joint.name # for joint in self.model.getJoints() # if joint.name.startswith(AIRBRAKE) # ] # self.model.makeSubpart(AIRBRAKE, airbrake_joints) # stabilizer_joints = [joint.name # for joint in self.model.getJoints() # if joint.name.startswith(STABILIZER_FINS) # ] # self.model.makeSubpart(STABILIZER_FINS, stabilizer_joints) puppet = self.app.loader.load_model(model_file_name) puppet.find("**/armature").hide() puppet.reparentTo(self.model) # Get the vehicle data self.vehicle_data = VehicleData(puppet, model_name, 'cars') # Configure the physics node self.physics_node = BulletRigidBodyNode('vehicle') self.physics_node.set_friction(self.vehicle_data.friction) self.physics_node.set_linear_sleep_threshold(0) self.physics_node.set_angular_sleep_threshold(0) self.physics_node.setCcdMotionThreshold(1e-7) self.physics_node.setCcdSweptSphereRadius(0.5) self.physics_node.setMass(self.vehicle_data.mass) shape = BulletConvexHullShape() for geom_node in self.model.find_all_matches("**/+GeomNode"): for geom in geom_node.node().get_geoms(): vertices = GeomVertexReader(geom.get_vertex_data(), 'vertex') while not vertices.is_at_end(): v_geom = vertices.getData3f() v_model = self.model.get_relative_point(geom_node, v_geom) shape.add_point(v_model) self.physics_node.add_shape(shape) self.vehicle = NodePath(self.physics_node) self.vehicle.set_collide_mask(CM_VEHICLE | CM_COLLIDE) self.model.reparent_to(self.vehicle) # Navigational aids self.target_node = self.app.loader.load_model('models/zup-axis') self.target_node.reparent_to(self.model) self.target_node.set_scale(1) self.target_node.set_render_mode_wireframe() self.target_node.hide() self.delta_node = self.app.loader.load_model('models/smiley') self.delta_node.set_pos(1, 10, 1) self.delta_node.reparent_to(base.cam) self.delta_node.hide() self.airbrake_state = 0.0 self.airbrake_factor = 0.5 self.airbrake_speed = 1 / self.vehicle_data.airbrake_duration self.stabilizer_fins_state = 0.0 self.stabilizer_fins_speed = 1 / self.vehicle_data.stabilizer_fins_duration self.centroid = base.loader.load_model('models/smiley') self.centroid.reparent_to(self.vehicle) self.centroid.hide() # Gyro sound sound_file = 'assets/cars/{}/{}.wav'.format( model_name, GYROSCOPE_SOUND, ) sound = base.audio3d.load_sfx(sound_file) self.model.set_python_tag(GYROSCOPE_SOUND, sound) base.audio3d.attach_sound_to_object(sound, self.model) sound.set_volume(0) sound.set_play_rate(0) sound.set_loop(True) sound.play() # Thruster limiting self.thruster_state = 0.0 self.thruster_heat = 0.0 for repulsor in self.vehicle_data.repulsor_nodes: self.add_repulsor(repulsor, model_name) for thruster in self.vehicle_data.thruster_nodes: self.add_thruster(thruster, model_name) # ECU data storage from frame to frame self.last_flight_height = None # FIXME: Move into a default controller self.inputs = { # Repulsors REPULSOR_ACTIVATION: 0.0, ACCELERATE: 0.0, TURN: 0.0, STRAFE: 0.0, HOVER: 0.0, FULL_REPULSORS: False, # Gyro ACTIVE_STABILIZATION_ON_GROUND: PASSIVE, ACTIVE_STABILIZATION_CUTOFF_ANGLE: PASSIVE, ACTIVE_STABILIZATION_IN_AIR: PASSIVE, TARGET_ORIENTATION: Vec3(0, 0, 0), # Thrust THRUST: 0.0, # Air foils AIRBRAKE: 0.0, STABILIZER_FINS: 0.0, } self.sensors = {} self.commands = {}
def create_solid(self): node = BulletRigidBodyNode(self.name) mesh = BulletConvexHullShape() mesh.add_geom(self.geom.get_geom(0)) node.add_shape(mesh) return node