class DynamicNp(DynamicObject): 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 add_solid(self, node): mesh = BulletConvexHullShape() mesh.add_geom( GeomBuilder().add_wedge(self.color, self.base, self.top, self.width, LRotationf(*self.hpr)).get_geom() ) node.add_shape(mesh) return node
class DynamicModel(DynamicObject): 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_dome(self.color, self.center, self.radius, self.samples, self.planes, LRotationf(*self.hpr)).get_geom()) node.add_shape(mesh) return node
def add_solid(self, node): mesh = BulletConvexHullShape() mesh.add_geom( GeomBuilder().add_wedge(self.color, self.base, self.top, self.width, LRotationf(*self.hpr)).get_geom()) node.add_shape(mesh) return node
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 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 __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 create_solid(self): node = BulletRigidBodyNode(self.name) mesh = BulletConvexHullShape() mesh.add_geom(self.geom.get_geom(0)) node.add_shape(mesh) return node
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 __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 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, 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 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, mainReference, name, position, regionID): super(Enemy, self).__init__(mainReference) # unique enemy name self.name = name # If enemy is alive self.alive = True # enemy's pursue speed P-units/s self.speed = 2.9 # enemy's rotation speed angles/s self.rotSpeed = 10 # enemy's current convex region; for pursue purposes self.currentRegionID = regionID # Hit Points of each part of zombie self.hitPoints = {'leg_lr':2, 'leg_ll':2, 'arm_lr':2, 'arm_ll':2} self.lifePoints = 100 # enemy NodePath self.enemyNP = self.mainRef.render.attachNewNode(self.name) self.enemyNP.setPos(position) # the name of the task the zombie is currently performing self.enemyActiveState = "" self.isEnemyAttacking = False # the cross point of the portal that the zombie is trying to cross self.currentCrossPointGoal = None # the time that the enemy will spend confused self.lostTargetTotalTime = 1.0 self.lostTargetTimer = self.lostTargetTotalTime # load our zombie self.enemyModel = Actor("../../models/model_zombie/zombie",{ 'walk':'../../models/model_zombie/zombie-walk', 'attack':'../../models/model_zombie/zombie-attack', }) # ****SCALE**** self.enemyModel.setScale(0.55) # ****SCALE**** #enemy's character controller self.enemyBody = CharacterBody(self.mainRef, self.enemyNP.getPos(), 0.38, 0.5 ) self.enemyBody.charBodyNP.reparentTo(self.enemyNP) # load the zombie's bounding boxes self.enemyBB = loader.loadModel("../../models/model_zombie/zombieBB") global bodyParts bodyParts = ['head', 'leg_ur', 'leg_ul', 'leg_lr', 'leg_ll', 'torso', 'arm_ur', 'arm_ul', 'arm_lr', 'arm_ll'] # List of the bullet nodes for this enemy, to be removed later self.bulletNodes = {} self.partNodes = {} # Get Joints self.joints = {} #for bodyPart in ['leg_lr', 'leg_ll', 'arm_lr', 'arm_ll']: # # Get joint control structure # self.joints[bodyPart] = self.enemyModel.controlJoint(None, 'modelRoot', bodyPart) # getting 1 by 1 and attaching them to their corresponding bones for bodyPart in bodyParts: self.bodyPartShape = BulletConvexHullShape() self.bodyPartShape.addGeom(self.enemyBB.getChild(0).find(bodyPart).node().getGeom(0)) self.bulletbodyPartNode = BulletRigidBodyNode(bodyPart+"_"+name) self.bulletbodyPartNode.addShape(self.bodyPartShape) self.bodyPartNode = self.mainRef.render.attachNewNode(self.bulletbodyPartNode) # ****SCALE**** self.bodyPartNode.setScale(0.55) # ****SCALE**** self.mainRef.world.attachRigidBody(self.bulletbodyPartNode) self.bodyPartNode.setCollideMask( BitMask32.bit( 2 ) ) self.bodyPartNode.wrtReparentTo(self.enemyModel.exposeJoint(None,"modelRoot",bodyPart)) self.bulletNodes[bodyPart] = self.bulletbodyPartNode self.partNodes[bodyPart] = self.bodyPartNode # uncomment to use triangleMesh instead of convexHull # mesh = BulletTriangleMesh() # mesh.addGeom(self.enemyBB.getChild(0).find(bodyPart).node().getGeom(0)) # self.bodyPartShape = BulletTriangleMeshShape(mesh, dynamic=True) # # self.bulletbodyPartNode = BulletRigidBodyNode(bodyPart) # self.bulletbodyPartNode.addShape(self.bodyPartShape) # # self.bodyPartNode = self.mainRef.render.attachNewNode(self.bulletbodyPartNode) # self.mainRef.world.attachRigidBody(self.bulletbodyPartNode) # # self.bodyPartNode.wrtReparentTo(self.enemyModel.exposeJoint(None,"modelRoot",bodyPart)) # initial path must be calculated self.updatePath() # adding a task to check if the enemy is leaving their region self.checkIfChangedRegionName = self.name + "cicr" self.oldPosition = self.enemyNP.getPos() taskMgr.add(self.checkIfChangedRegion, self.checkIfChangedRegionName) # walk loop # self.enemyModel.loop("walk") self.enemyModel.loop("walk") # attaching to render self.enemyModel.reparentTo(self.enemyNP) self.enemyModel.setPos(0,0,-0.51) # loading enemy roar sound zombieRoar = [None,None,None,None] for i in range( len(zombieRoar) ): zombieRoar[i] = self.mainRef.audio3d.loadSfx('../../sounds/zombie_roar_' + str(i+1) + '.mp3') # initialize first zombie roar self.zombieRoarFX = zombieRoar[0] self.mainRef.audio3d.attachSoundToObject(self.zombieRoarFX, self.enemyNP) self.zombieRoarFX.play() # random zombie roar def roarSort(task): if(self.zombieRoarFX.status() != self.zombieRoarFX.PLAYING): random.seed() value = random.choice(range(3)) self.zombieRoarFX = zombieRoar[value] self.mainRef.audio3d.attachSoundToObject(self.zombieRoarFX, self.enemyNP) self.zombieRoarFX.play() return task.again self.mainRef.taskMgr.doMethodLater(2, roarSort,self.name+'roar sort')
class Enemy(Creature): def __init__(self, mainReference, name, position, regionID): super(Enemy, self).__init__(mainReference) # unique enemy name self.name = name # If enemy is alive self.alive = True # enemy's pursue speed P-units/s self.speed = 2.9 # enemy's rotation speed angles/s self.rotSpeed = 10 # enemy's current convex region; for pursue purposes self.currentRegionID = regionID # Hit Points of each part of zombie self.hitPoints = {'leg_lr':2, 'leg_ll':2, 'arm_lr':2, 'arm_ll':2} self.lifePoints = 100 # enemy NodePath self.enemyNP = self.mainRef.render.attachNewNode(self.name) self.enemyNP.setPos(position) # the name of the task the zombie is currently performing self.enemyActiveState = "" self.isEnemyAttacking = False # the cross point of the portal that the zombie is trying to cross self.currentCrossPointGoal = None # the time that the enemy will spend confused self.lostTargetTotalTime = 1.0 self.lostTargetTimer = self.lostTargetTotalTime # load our zombie self.enemyModel = Actor("../../models/model_zombie/zombie",{ 'walk':'../../models/model_zombie/zombie-walk', 'attack':'../../models/model_zombie/zombie-attack', }) # ****SCALE**** self.enemyModel.setScale(0.55) # ****SCALE**** #enemy's character controller self.enemyBody = CharacterBody(self.mainRef, self.enemyNP.getPos(), 0.38, 0.5 ) self.enemyBody.charBodyNP.reparentTo(self.enemyNP) # load the zombie's bounding boxes self.enemyBB = loader.loadModel("../../models/model_zombie/zombieBB") global bodyParts bodyParts = ['head', 'leg_ur', 'leg_ul', 'leg_lr', 'leg_ll', 'torso', 'arm_ur', 'arm_ul', 'arm_lr', 'arm_ll'] # List of the bullet nodes for this enemy, to be removed later self.bulletNodes = {} self.partNodes = {} # Get Joints self.joints = {} #for bodyPart in ['leg_lr', 'leg_ll', 'arm_lr', 'arm_ll']: # # Get joint control structure # self.joints[bodyPart] = self.enemyModel.controlJoint(None, 'modelRoot', bodyPart) # getting 1 by 1 and attaching them to their corresponding bones for bodyPart in bodyParts: self.bodyPartShape = BulletConvexHullShape() self.bodyPartShape.addGeom(self.enemyBB.getChild(0).find(bodyPart).node().getGeom(0)) self.bulletbodyPartNode = BulletRigidBodyNode(bodyPart+"_"+name) self.bulletbodyPartNode.addShape(self.bodyPartShape) self.bodyPartNode = self.mainRef.render.attachNewNode(self.bulletbodyPartNode) # ****SCALE**** self.bodyPartNode.setScale(0.55) # ****SCALE**** self.mainRef.world.attachRigidBody(self.bulletbodyPartNode) self.bodyPartNode.setCollideMask( BitMask32.bit( 2 ) ) self.bodyPartNode.wrtReparentTo(self.enemyModel.exposeJoint(None,"modelRoot",bodyPart)) self.bulletNodes[bodyPart] = self.bulletbodyPartNode self.partNodes[bodyPart] = self.bodyPartNode # uncomment to use triangleMesh instead of convexHull # mesh = BulletTriangleMesh() # mesh.addGeom(self.enemyBB.getChild(0).find(bodyPart).node().getGeom(0)) # self.bodyPartShape = BulletTriangleMeshShape(mesh, dynamic=True) # # self.bulletbodyPartNode = BulletRigidBodyNode(bodyPart) # self.bulletbodyPartNode.addShape(self.bodyPartShape) # # self.bodyPartNode = self.mainRef.render.attachNewNode(self.bulletbodyPartNode) # self.mainRef.world.attachRigidBody(self.bulletbodyPartNode) # # self.bodyPartNode.wrtReparentTo(self.enemyModel.exposeJoint(None,"modelRoot",bodyPart)) # initial path must be calculated self.updatePath() # adding a task to check if the enemy is leaving their region self.checkIfChangedRegionName = self.name + "cicr" self.oldPosition = self.enemyNP.getPos() taskMgr.add(self.checkIfChangedRegion, self.checkIfChangedRegionName) # walk loop # self.enemyModel.loop("walk") self.enemyModel.loop("walk") # attaching to render self.enemyModel.reparentTo(self.enemyNP) self.enemyModel.setPos(0,0,-0.51) # loading enemy roar sound zombieRoar = [None,None,None,None] for i in range( len(zombieRoar) ): zombieRoar[i] = self.mainRef.audio3d.loadSfx('../../sounds/zombie_roar_' + str(i+1) + '.mp3') # initialize first zombie roar self.zombieRoarFX = zombieRoar[0] self.mainRef.audio3d.attachSoundToObject(self.zombieRoarFX, self.enemyNP) self.zombieRoarFX.play() # random zombie roar def roarSort(task): if(self.zombieRoarFX.status() != self.zombieRoarFX.PLAYING): random.seed() value = random.choice(range(3)) self.zombieRoarFX = zombieRoar[value] self.mainRef.audio3d.attachSoundToObject(self.zombieRoarFX, self.enemyNP) self.zombieRoarFX.play() return task.again self.mainRef.taskMgr.doMethodLater(2, roarSort,self.name+'roar sort') def hide(self): self.enemyModel.hide() def show(self): self.mainRef.world.attachRigidBody(self.enemyBulletNode) self.enemyModel.show() self.enemyModel.loop("walk") def setNewCourse(self): # Simply follow the player if (len(self.portalsPathList) == 0): taskMgr.remove( self.enemyActiveState ) self.enemyActiveState = self.name + "pt" taskMgr.add(self.pursueTargetStep, self.enemyActiveState) # Go to the cross point that makes you closer to your target elif (self.portalsPathList[0].connectedRegionsIDs[0] == self.mainRef.player.currentRegionID or self.portalsPathList[0].connectedRegionsIDs[1] == self.mainRef.player.currentRegionID): self.setOptimalCrossPoint() taskMgr.remove( self.enemyActiveState ) self.enemyActiveState = self.name + "htp" taskMgr.add(self.headToPortalStep, self.enemyActiveState) # Go to the middle cross point else: self.currentCrossPointGoal = self.portalsPathList[0].middleCrossPoint taskMgr.remove( self.enemyActiveState ) self.enemyActiveState = self.name + "htp" taskMgr.add(self.headToPortalStep, self.enemyActiveState) # ======================================================================== # ======================== STATE MACHINE METHODS ========================== def pursueTargetStep(self, task): if (self.mainRef.player.currentRegionID == self.currentRegionID): if ( self.mainRef.player.playerNP.getPos(self.enemyNP).length() < 4.0): if (not self.isEnemyAttacking): self.speed += 1.0 self.isEnemyAttacking = True self.enemyModel.loop("attack") elif (self.isEnemyAttacking): self.speed -= 1.0 self.isEnemyAttacking = False self.enemyModel.loop("walk") targetDirection = Vec2( self.mainRef.player.playerNP.getPos(self.enemyNP).getXy() ) targetDirectionAngle = Vec2(-sin(radians(self.enemyModel.getH())), cos(radians(self.enemyModel.getH())) ).signedAngleDeg(targetDirection) rotationAngle = targetDirectionAngle * self.rotSpeed * globalClock.getDt() self.enemyModel.setH(self.enemyModel.getH() + rotationAngle) targetDirection.normalize() playerMoveSpeedVec = targetDirection * self.speed * globalClock.getDt() self.enemyNP.setPos( self.enemyBody.move(Vec3(playerMoveSpeedVec.getX(), playerMoveSpeedVec.getY(), 0) ) ) if (abs(rotationAngle) > 120 * globalClock.getDt()): self.lostTargetTimer = self.lostTargetTotalTime self.enemyActiveState = self.name + "lt" taskMgr.add(self.lostTargetStep, self.enemyActiveState) return task.done return task.cont def lostTargetStep(self, task): self.enemyNP.setPos( self.enemyBody.move(Vec3(-sin(radians(self.enemyModel.getH())), cos(radians(self.enemyModel.getH())), 0) * self.speed * globalClock.getDt() ) ) self.lostTargetTimer -= globalClock.getDt() if (self.lostTargetTimer < 0): self.enemyActiveState = self.name + "rt" taskMgr.add(self.recoverTargetStep, self.enemyActiveState) return task.done return task.cont def recoverTargetStep(self, task): targetDirection = Vec2( self.mainRef.player.playerNP.getPos(self.enemyNP).getXy() ) targetDirectionAngle = Vec2(-sin(radians(self.enemyModel.getH())), cos(radians(self.enemyModel.getH())) ).signedAngleDeg(targetDirection) rotationAngle = targetDirectionAngle * self.rotSpeed * globalClock.getDt() self.enemyModel.setH(self.enemyModel.getH() + rotationAngle) if (abs(targetDirectionAngle) < 5): self.enemyActiveState = self.name + "pt" taskMgr.add(self.pursueTargetStep, self.enemyActiveState) return task.done return task.cont def headToPortalStep(self, task): directionVec = Vec3(self.currentCrossPointGoal.getX() - self.enemyNP.getX(), self.currentCrossPointGoal.getY() - self.enemyNP.getY(), 0) directionVec.normalize() targetDirection = Vec2( self.currentCrossPointGoal - self.enemyNP.getPos().getXy() ) targetDirectionAngle = Vec2(-sin(radians(self.enemyModel.getH())), cos(radians(self.enemyModel.getH())) ).signedAngleDeg(targetDirection) rotationAngle = targetDirectionAngle * self.rotSpeed * globalClock.getDt() self.enemyModel.setH(self.enemyModel.getH() + rotationAngle) self.enemyNP.setPos( self.enemyBody.move( directionVec * self.speed * globalClock.getDt() ) ) return task.cont # ====================== END OF STATE MACHINE METHODS ======================== # ============================================================================ def destroy(self): self.alive = False taskMgr.remove(self.name+'roar sort') # removing sound for node in self.bulletNodes.keys(): self.mainRef.world.removeRigidBody(self.bulletNodes[node]) self.partNodes[node].removeNode() taskMgr.remove( self.enemyActiveState ) # removing state machine task self.enemyModel.cleanup() self.enemyBB.removeNode() self.enemyBody.destroy() def detachLimb(self,limb): # Detaches a limb from the enemy and makes it drop on the floor print "[Detach] Detach %s" % limb # self.partNodes[limb].wrtReparentTo(self.mainRef.render) # # shape = BulletSphereShape(10.0) # node = BulletRigidBodyNode('Sphere') # node.setMass(1.0) # node.addShape(shape) # playerNP = self.mainRef.render.attachNewNode(node) # playerNP.setPos(self.enemyModel.exposeJoint(None,"modelRoot",limb).getPos()) # playerNP.setPos(playerNP.getRelativePoint(self.partNodes[limb],self.partNodes[limb].getPos())) # playerNP.setPos(60,0,-60) # print playerNP.getRelativePoint(self.partNodes[limb],self.partNodes[limb].getPos()) # print self.partNodes[limb].getPos() # self.mainRef.world.attachRigidBody(node) # # self.bulletNodes[limb].applyCentralForce(Vec3(0, 0, -5)) # self.mainRef.world.removeRigidBody(self.bulletNodes[limb]) def updatePath(self): convexRegionsList = self.mainRef.map.convexRegions self.portalsPathList = [] # this is what we want for enemy's correct pursue path discoveredRegionsList = [] # part of the BFS algorithm visitedRegionsList = [False for item in range( len(convexRegionsList))] regionFatherList = [None for item in range( len(convexRegionsList))] # this list keeps track of a region's father AND the portalEntrance connecting them # from now, we'll execute a BFS to find each region that enemy will cross to reach player's position discoveredRegionsList.append( convexRegionsList[self.currentRegionID] ) visitedRegionsList[self.currentRegionID] = True regionFatherList[self.currentRegionID] = [-1, None] while(discoveredRegionsList): analisedRegion = discoveredRegionsList.pop(0) for portalEntrance in analisedRegion.portalEntrancesList: neighbourRegionID = portalEntrance.connectedRegionID if (not visitedRegionsList[neighbourRegionID]): regionFatherList[neighbourRegionID] = [analisedRegion.regionID, portalEntrance.portal] if (neighbourRegionID == self.mainRef.player.currentRegionID): discoveredRegionsList = [] # break while statement trick break visitedRegionsList[neighbourRegionID] = True discoveredRegionsList.append( convexRegionsList[neighbourRegionID] ) # now that we have all regions necessary , we'll just put all portals on the correct order lastRegionFatherID = self.mainRef.player.currentRegionID while (lastRegionFatherID != -1): lastRegionFather = regionFatherList[lastRegionFatherID] lastRegionFatherID = lastRegionFather[0] self.portalsPathList.append(lastRegionFather[1]) # putting portals path on the right order for enemy pursuing algorithm self.portalsPathList.pop() self.portalsPathList.reverse() # Debug # print "lista de portais:" # for portal in self.portalsPathList: # print portal.connectedRegionsIDs self.setNewCourse() def checkIfChangedRegion(self, task, lastRegion=0): for portalEntrance in self.mainRef.map.convexRegions[self.currentRegionID].portalEntrancesList: if ( self.intersect( self.oldPosition, self.enemyNP.getPos(), portalEntrance.portal.frontiers[0], portalEntrance.portal.frontiers[1] ) and portalEntrance.portal.connectedRegionsIDs[0] != lastRegion and portalEntrance.portal.connectedRegionsIDs[1] != lastRegion ): oldRegion = self.mainRef.player.currentRegionID self.currentRegionID = portalEntrance.connectedRegionID # Debug # print self.name + " region changed: ", oldRegion, ">", self.currentRegionID # erase last item of portalsPathList (if it isn't empty) if (len(self.portalsPathList) != 0): self.portalsPathList.pop(0) # new course must be calculated if the enemy changed it's region self.setNewCourse() self.oldPosition = self.enemyNP.getPos() return task.cont def ccw(self, A,B,C): return (C.getY()-A.getY())*(B.getX()-A.getX()) > (B.getY()-A.getY())*(C.getX()-A.getX()) def intersect(self, A,B,C,D): return self.ccw(A,C,D) != self.ccw(B,C,D) and self.ccw(A,B,C) != self.ccw(A,B,D) def setOptimalCrossPoint(self): deltaPositionVec = self.mainRef.player.playerNP.getPos() - self.enemyNP.getPos() positionPoint = self.enemyNP.getPos() deltaFrontiersVec = self.portalsPathList[0].frontiersVec frontierPoint = self.portalsPathList[0].frontiers[0] if (deltaPositionVec.getX() == 0): tang2 = deltaFrontiersVec.getY() / deltaFrontiersVec.getX() b2 = frontierPoint.getY() - tang2 * frontierPoint.getX() xRes = positionPoint.getX() yRes = tang2 * xRes + b2 if (deltaFrontiersVec.getX() == 0): tang1 = deltaPositionVec.getY() / deltaPositionVec.getX() b1 = positionPoint.getY() - tang1 * positionPoint.getX() xRes = frontierPoint.getX() yRes = tang1 * xRes + b1 else: tang1 = deltaPositionVec.getY() / deltaPositionVec.getX() tang2 = deltaFrontiersVec.getY() / deltaFrontiersVec.getX() b1 = positionPoint.getY() - tang1 * positionPoint.getX() b2 = frontierPoint.getY() - tang2 * frontierPoint.getX() xRes = (b1 - b2) / (tang1 - tang2) yRes = tang1 * xRes + b1 if (deltaFrontiersVec.getX() == 0): if ( ( yRes > self.portalsPathList[0].crossPoints[0].getY() and yRes < self.portalsPathList[0].crossPoints[1].getY() ) or ( yRes < self.portalsPathList[0].crossPoints[0].getY() and yRes > self.portalsPathList[0].crossPoints[1].getY() ) ) : self.currentCrossPointGoal = Vec2(xRes, yRes) elif (yRes > self.portalsPathList[0].crossPoints[0].getY() and yRes > self.portalsPathList[0].crossPoints[1].getY() ): if ( self.portalsPathList[0].crossPoints[0].getY() > self.portalsPathList[0].crossPoints[1].getY()): self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[0] else: self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[1] else: if ( self.portalsPathList[0].crossPoints[0].getY() < self.portalsPathList[0].crossPoints[1].getY()): self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[0] else: self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[1] else: if ( ( xRes > self.portalsPathList[0].crossPoints[0].getX() and xRes < self.portalsPathList[0].crossPoints[1].getX() ) or ( xRes < self.portalsPathList[0].crossPoints[0].getX() and xRes > self.portalsPathList[0].crossPoints[1].getX() ) ) : self.currentCrossPointGoal = Vec2(xRes, yRes) elif (xRes > self.portalsPathList[0].crossPoints[0].getX() and xRes > self.portalsPathList[0].crossPoints[1].getX()): if ( self.portalsPathList[0].crossPoints[0].getX() > self.portalsPathList[0].crossPoints[1].getX()): self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[0] else: self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[1] else: if ( self.portalsPathList[0].crossPoints[0].getX() < self.portalsPathList[0].crossPoints[1].getX()): self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[0] else: self.currentCrossPointGoal = self.portalsPathList[0].crossPoints[1]
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 []