def __init__(self,name,parent_np , physics_world, tr = TransformState.makeIdentity()): """ Sector(NodePath parent_np, TransformState tr = TransformState.makeIdentity() Creates a level Sector object which ensures that all objects in it only move in the x and z directions relative to the sector. The z and x vectors lie on the plane with +X pointing to the right and +Z pointing up. +Y is perpedicular to the plane into the screen from the user's perspective @param parent_np: NodePath to the parent of the sector, usually is the Level object that contains the sector. @param physics_world: The physics world @param tf: Transform of the sector relative to the parent_np NodePath """ NodePath.__init__(self,name) self.reparentTo(parent_np) self.setTransform(self,tr) self.physics_world_ = physics_world # creating 2d motion plane self.motion_plane_np_ = self.attachNewNode(BulletRigidBodyNode(self.getName() + '-motion-plane')) self.motion_plane_np_.node().setMass(0) self.motion_plane_np_.node().setIntoCollideMask(CollisionMasks.NO_COLLISION) self.motion_plane_np_.node().addShape(BulletPlaneShape(Vec3(0,1,0),0)) self.physics_world_.attach(self.motion_plane_np_.node()) self.motion_plane_np_.reparentTo(parent_np) self.motion_plane_np_.setTransform(self,TransformState.makeIdentity()) # game objects self.object_constraints_dict_ = {} # stores tuples of the form (String,BulletConstraint) # sector transitions self.sector_transitions_ = [] self.destination_sector_dict_ = {}
def createConstraints(self,bodyA,bodyB): left_constraint = BulletGenericConstraint(bodyA,bodyB,TransformState.makeIdentity(),TransformState.makeHpr(Vec3(180,0,0)),False) right_constraint = BulletGenericConstraint(bodyA,bodyB,TransformState.makeIdentity(),TransformState.makeIdentity(),False) left_constraint.setEnabled(False) right_constraint.setEnabled(False) return (right_constraint,left_constraint)
def addBox(self,name,size,pos,visual): # Box (dynamic) box = NodePath(BulletRigidBodyNode(name)) box.node().setMass(1.0) box.node().addShape(BulletBoxShape(size)) box.setCollideMask(GAME_OBJECT_BITMASK) #box.node().setLinearFactor((1,0,1)) #box.node().setAngularFactor((0,1,0)) visual.instanceTo(box) box.reparentTo(self.getParent()) box.setPos(self,pos) box.setHpr(self,Vec3.zero()) self.physics_world_.attachRigidBody(box.node()) self.object_nodes_.append(box) # adding constraint motion2d_constraint = BulletGenericConstraint(self.constraint_plane_.node(),box.node(), TransformState.makeIdentity(), TransformState.makeIdentity(), False) rot_constraint = BulletGenericConstraint(self.constraint_plane_.node(),box.node(), TransformState.makeIdentity(), TransformState.makeIdentity(), False) motion2d_constraint.setLinearLimit(0,-sys.float_info.max,sys.float_info.max) motion2d_constraint.setLinearLimit(1,0,0) motion2d_constraint.setLinearLimit(2,-sys.float_info.max,sys.float_info.max) # All angular constraints must be either locked or released for the simulation to be stable #motion2d_constraint.setAngularLimit(0,-0.1,0.1) #motion2d_constraint.setAngularLimit(1,-100,100) #motion2d_constraint.setAngularLimit(2,-0.1,0.1) #motion2d_constraint.setBreakingThreshold(1000) motion2d_constraint.setDebugDrawSize(0) # for axis in range(0,6): # motion2d_constraint.setParam(BulletGenericConstraint.CP_cfm,0,axis) # motion2d_constraint.setParam(BulletGenericConstraint.CP_erp,0.4,axis) self.physics_world_.attach(motion2d_constraint) self.box_contraints_.append(motion2d_constraint) return box
def __create2DConstraint__(self,obj): obj.setQuat(self,LQuaternion.identQuat()) obj.setY(self,0) constraint = BulletGenericConstraint(self.motion_plane_np_.node(),obj.node(), TransformState.makeIdentity(),TransformState.makeIdentity(),False) max_float = sys.float_info.max constraint.setLinearLimit(0,-max_float,max_float) constraint.setLinearLimit(1,0,0) constraint.setLinearLimit(2,-max_float,max_float) constraint.setDebugDrawSize(0) return constraint
def __activateConstraint__(self,constraint): if self.selected_constraint_ != constraint: # disabling active constraint self.__deactivateConstraint__() if not constraint.isEnabled(): # placing actor rigid body relative to character's rigid body actorrb_np = self.animator_.getRigidBody() static = actorrb_np.node().isStatic() actorrb_np.node().setStatic(True) actorrb_np.setTransform(self,TransformState.makeIdentity()) if constraint == self.right_constraint_: actorrb_np.setH(self,0) else: actorrb_np.setH(self,180) actorrb_np.node().setStatic(static) self.node().setStatic(static) self.selected_constraint_ = constraint self.selected_constraint_.setEnabled(True) self.physics_world_.attach(self.selected_constraint_)
def getSwapVisibleIval(self, wait=5.0, tFadeOut=3.0, tFadeIn=3.0): loader = base.cr.playGame.hood.loader npl = render.findAllMatches('**/=DNARoot=holiday_prop;+s') p = Parallel() for i in range(npl.getNumPaths()): np = npl.getPath(i) np.setTransparency(TransparencyAttrib.MDual, 1) if not np.hasTag('DNACode'): continue dnaCode = np.getTag('DNACode') dnaNode = self.dnaStore.findNode(dnaCode) if dnaNode.isEmpty(): continue newNP = dnaNode.copyTo(np.getParent()) newNP.setTag('DNARoot', 'holiday_prop') newNP.setTag('DNACode', dnaCode) newNP.setColorScale(1, 1, 1, 0) newNP.setTransparency(TransparencyAttrib.MDual, 1) if np.hasTag('transformIndex'): index = int(np.getTag('transformIndex')) transform = loader.holidayPropTransforms.get(index, TransformState.makeIdentity()) newNP.setTransform(NodePath(), transform) newNP.setTag('transformIndex', `index`) s = Sequence(Wait(wait), np.colorScaleInterval(tFadeOut, Vec4(1, 1, 1, 0), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut'), Func(np.detachNode), Func(np.clearTransparency), newNP.colorScaleInterval(tFadeOut, Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0), blendType='easeInOut'), Func(newNP.clearTransparency), Func(newNP.clearColorScale)) p.append(s) return p
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 _initAgents(self): # Load agents for agent in self.scene.scene.findAllMatches('**/agents/agent*'): transform = TransformState.makeIdentity() if self.agentMode == 'capsule': shape = BulletCapsuleShape( self.agentRadius, self.agentHeight - 2 * self.agentRadius) elif self.agentMode == 'sphere': shape = BulletCapsuleShape(self.agentRadius, 2 * self.agentRadius) # XXX: use BulletCharacterControllerNode class, which already handles local transform? node = BulletRigidBodyNode('physics') node.setMass(self.agentMass) node.setStatic(False) node.setFriction(self.defaultMaterialFriction) node.setRestitution(self.defaultMaterialRestitution) node.addShape(shape) self.bulletWorld.attach(node) # Constrain the agent to have fixed position on the Z-axis node.setLinearFactor(Vec3(1.0, 1.0, 0.0)) # Constrain the agent not to be affected by rotations node.setAngularFactor(Vec3(0.0, 0.0, 0.0)) node.setIntoCollideMask(BitMask32.allOn()) node.setDeactivationEnabled(True) # Enable continuous collision detection (CCD) node.setCcdMotionThreshold(1e-7) node.setCcdSweptSphereRadius(0.50) if node.isStatic(): agent.setTag('physics-mode', 'static') else: agent.setTag('physics-mode', 'dynamic') # Attach the physic-related node to the scene graph physicsNp = NodePath(node) physicsNp.setTransform(transform) # Reparent all child nodes below the new physic node for child in agent.getChildren(): child.reparentTo(physicsNp) physicsNp.reparentTo(agent) # NOTE: we need this to update the transform state of the internal bullet node physicsNp.node().setTransformDirty() # Validation assert np.allclose( mat4ToNumpyArray(physicsNp.getNetTransform().getMat()), mat4ToNumpyArray(agent.getNetTransform().getMat()), atol=1e-6)
def __setupConstraints__(self,actor_rigid_body_np): self.__cleanupConstraints__() self.left_constraint_ = BulletGenericConstraint(self.node(), actor_rigid_body_np.node(), TransformState.makeIdentity(), TransformState.makeHpr(Vec3(180,0,0)),False) self.right_constraint_ = BulletGenericConstraint(self.node(), actor_rigid_body_np.node(), TransformState.makeIdentity(), TransformState.makeIdentity(),False) self.left_constraint_.setEnabled(False) self.right_constraint_.setEnabled(False) for axis in range(0,6): self.left_constraint_.setParam(BulletGenericConstraint.CP_cfm,0,axis) self.right_constraint_.setParam(BulletGenericConstraint.CP_cfm,0,axis)
def constrainCharacter(self,char_np): char_np.setY(self,0) if self.character_constraint_ is None: self.character_constraint_ = BulletGenericConstraint(self.constraint_plane_.node(),char_np.node(), TransformState.makeIdentity(), TransformState.makeIdentity(), False) self.character_constraint_.setLinearLimit(0,-sys.float_info.max,sys.float_info.max) self.character_constraint_.setLinearLimit(1,0,0) self.character_constraint_.setLinearLimit(2,-sys.float_info.max,sys.float_info.max) #self.character_constraint_.setAngularLimit(0,0,0) #self.character_constraint_.setAngularLimit(1,-10000,10000) #self.character_constraint_.setAngularLimit(2,0,0) self.character_constraint_.setDebugDrawSize(0) self.physics_world_.attach(self.character_constraint_) self.character_constraint_.setEnabled(True)
def __createBulletGhostNodeFromBoxes__(self,boxes,scale, name ): ghost_node = BulletGhostNode(name) transform = TransformState.makeIdentity() for box in boxes: box.scale = scale size = box.size center = box.center box_shape = BulletBoxShape(Vec3(0.5*size[0],0.5*AnimationActor.DEFAULT_WIDTH,0.5 * size[1])) #box_shape.setMargin(AnimationActor.COLLISION_MARGIN) transform = transform.setPos(Vec3(center[0],0,center[1])) ghost_node.addShape(box_shape,transform) return ghost_node
def genBullectCDMeshFromGeom(geom, name='autogen'): """ generate the collision mesh of a nodepath using geom :param geom: the panda3d geom of the object :param basenodepath: the nodepath to compute relative transform :return: bulletrigidbody author: weiwei date: 20161212, tsukuba """ geomtf = TransformState.makeIdentity() geombullmesh = BulletTriangleMesh() geombullmesh.addGeom(geom) geombullnode = BulletRigidBodyNode(name) bullettmshape = BulletTriangleMeshShape(geombullmesh, dynamic=True) bullettmshape.setMargin(0) geombullnode.addShape(bullettmshape, geomtf) return geombullnode
def attach(self,obj,pos = None): """ attach(GameObject obj, Vec3 pos = None) Attaches the game obj to this sector at the designated position pos relative to this sector. """ if pos is not None: obj.setX(self,pos.getX()) logging.debug('Sector Entered at Pos %s'%(str(pos))) else: logging.warn("Sector Entrance Position is invalid, val: %s"%(str(pos))) if not self.motion_plane_np_.getTransform(self).isIdentity(): self.motion_plane_np_.setTransform(self,TransformState.makeIdentity()) constraint = self.__create2DConstraint__(obj) self.physics_world_.attach(constraint) constraint.setEnabled(True) self.object_constraints_dict_[obj.getObjectID()] = constraint obj.setReferenceNodePath(self)
def __createRigidBody__(self,scale): self.rigid_body_np_ = NodePath(BulletRigidBodyNode(self.character_name_ + '-' + self.getName()+ '-rb')) rigid_body = self.rigid_body_np_.node() rigid_body.setIntoCollideMask(CollisionMasks.GAME_OBJECT_RIGID_BODY) rigid_body.setFriction(0) # collection all boxes collision_boxes = [] if len(self.animation_info_.rigid_body_boxes) > 0: # use existing collision boxes collision_boxes = self.animation_info_.rigid_body_boxes AnimationActor.LOGGER.info("Using existing rigid body boxes: %s "%( ';'.join(str(x) for x in collision_boxes ) )) else: # compute bounding box of all collision boxes from every sprite AnimationActor.LOGGER.warning("Rigid body boxes not found for this animation, creating AABB from damage boxes in all frames") boxes = [] for elemt in self.animation_info_.animation_elements: boxes = boxes + elemt.damage_boxes if len(boxes) > 0: collision_boxes = [Box2D.createBoundingBox(boxes)] # create rigid body with capsule shape for box in collision_boxes: box.scale = scale size = box.size center = box.center transform = TransformState.makeIdentity() radius = 0.5 * size[0] height = size[1] - 2.0* radius height = height if height >= 0 else 0.0 #bullet_collision_shape = BulletBoxShape(Vec3(0.5*size[0],0.5*AnimationActor.DEFAULT_WIDTH,0.5 * size[1])) bullet_collision_shape = BulletCapsuleShape(radius,height,ZUp) transform = transform.setPos(Vec3(center[0],0,center[1])) rigid_body.addShape(bullet_collision_shape,transform) # completing rigid body setup rigid_body.setMass(self.mass_) rigid_body.setLinearFactor((1,1,1)) rigid_body.setAngularFactor((0,0,0)) rigid_body.setBoundsType(BoundingVolume.BT_box) # creating bounding box self.rigid_body_bbox_ = Box2D.createBoundingBox(collision_boxes) aabb = self.rigid_body_bbox_ # creating bounding boxes around rigid body offsetx = aabb.center[0] offsety = aabb.center[1] top = Box2D(aabb.width, AnimationActor.BOUND_PADDING ,(offsetx, offsety + 0.5*aabb.height + 0.5*AnimationActor.BOUND_PADDING)) bottom = Box2D(aabb.width, AnimationActor.BOUND_PADDING ,(offsetx, offsety - 0.5*aabb.height -0.5*AnimationActor.BOUND_PADDING)) left = Box2D(AnimationActor.BOUND_PADDING, aabb.height,(offsetx + -0.5*aabb.width - 0.5*AnimationActor.BOUND_PADDING , offsety )) right = Box2D(AnimationActor.BOUND_PADDING, aabb.height ,(offsetx + 0.5*aabb.width + 0.5*AnimationActor.BOUND_PADDING , offsety )) logging.info("Animation %s Box Center %s"%(self.getName(),str(aabb.center))) scale = (1,1) self.bbox_top_np_ = self.rigid_body_np_.attachNewNode( self.__createBulletGhostNodeFromBoxes__([top], scale,self.getName() + '-actor-bbtop-gn')) self.bbox_bottom_np_ = self.rigid_body_np_.attachNewNode( self.__createBulletGhostNodeFromBoxes__([bottom], scale,self.getName() + '-actor-bbbottom-gn')) self.bbox_back_np_ = self.rigid_body_np_.attachNewNode( self.__createBulletGhostNodeFromBoxes__([left], scale, self.getName() + '-actor-bbback-gn')) self.bbox_front_np_ = self.rigid_body_np_.attachNewNode( self.__createBulletGhostNodeFromBoxes__([right], scale, self.getName() + '-actor-bbfront-gn')) self.bbox_top_np_.node().setIntoCollideMask(CollisionMasks.GAME_OBJECT_TOP) self.bbox_bottom_np_.node().setIntoCollideMask(CollisionMasks.GAME_OBJECT_BOTTOM) self.bbox_back_np_.node().setIntoCollideMask(CollisionMasks.GAME_OBJECT_LEFT) self.bbox_front_np_.node().setIntoCollideMask(CollisionMasks.GAME_OBJECT_RIGHT)
def getSwapVisibleIval(self, wait=5.0, tFadeOut=3.0, tFadeIn=3.0): # NJF loader = base.cr.playGame.hood.loader npl = render.findAllMatches('**/*light*') npl += render.findAllMatches('**/*lamp*') npl += render.findAllMatches('**/*prop_tree*') npl += render.findAllMatches('**/*prop_snow_tree*') npl += render.findAllMatches('**/*prop_palm_tree_topflat*') #render.ls() p = Parallel() for i in range(npl.getNumPaths()): np = npl.getPath(i) geomNodeCollection = np.findAllMatches('**/+GeomNode') for nodePath in geomNodeCollection: try: newPosX = nodePath.getPos(nodePath.getParent()) if newPosX != (0, 0, 0): newPos = newPosX newHprX = nodePath.getHpr(nodePath.getParent()) if newHprX != (0, 0, 0): newHpr = newHprX else: newHpr = (0, 0, 0) newScaleX = nodePath.getScale() if newScaleX != LVecBase3f(1, 1, 1): newScale = newScaleX else: newScale = LVecBase3f(1, 1, 1) except: newPos = (0, 0, 0) newHpr = (0, 0, 0) newScale = LVecBase3f(1, 1, 1) DDLHalloween = np.findAllMatches('**/+GeomNode') # NJF for nodePathA in DDLHalloween: print(nodePathA) try: print(nodePathA.getPos()) except: print("no pos") np.setTransparency(TransparencyAttrib.MDual, 1) if not np.hasTag('DNACode'): continue dnaCode = np.getTag('DNACode') dnaNode = self.dnaStore.findNode(dnaCode) if dnaNode.isEmpty(): continue newNP = dnaNode.copyTo(np.getParent()) newNP.setTag('DNARoot', 'holiday_prop') newNP.setTag('DNACode', dnaCode) newNP.setColorScale(1, 1, 1, 0) newNP.setTransparency(TransparencyAttrib.MDual, 1) if np.hasTag('transformIndex'): index = int(np.getTag('transformIndex')) transform = loader.holidayPropTransforms.get( index, TransformState.makeIdentity()) newNP.setTransform(NodePath(), transform) newNP.setTag('transformIndex', 'index') if newPos != (0, 0, 0): if dnaCode == 'prop_palm_tree_topflat': # Donald's dock is... a wreck. newNP.setX(newPos[0]) newNP.setY(newPos[1]) correctedZ = newPos[2] / newScale[ 2] / 7.4 # This is such a hackjob ugh newNP.setZ(correctedZ) else: newNP.setPos(newPos) if newHpr != (0, 0, 0): newNP.setHpr(newHpr) if newScale != LVecBase3f(1, 1, 1): newNP.setScale(newScale) if dnaCode == 'streetlight_DD_left' or dnaCode == 'streetlight_DD_right': # Donald's dock is... a wreck. if newPos[2] > 7: newNP.setZ(5.68) if dnaCode == 'prop_tree_large_ur' or dnaCode == 'prop_tree_large_ul': correctedZ = newPos[2] + 0.25 newNP.setZ(correctedZ) s = Sequence( Wait(wait), np.colorScaleInterval(tFadeOut, Vec4(1, 1, 1, 0), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut'), Func(np.detachNode), Func(np.clearTransparency), newNP.colorScaleInterval(tFadeOut, Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0), blendType='easeInOut'), Func(newNP.clearTransparency), Func(newNP.clearColorScale)) p.append(s) return p
def getSwapVisibleIval(self, wait = 5.0, tFadeOut = 3.0, tFadeIn = 3.0): # NJF loader = base.cr.playGame.hood.loader npl = render.findAllMatches('**/*light*') npl += render.findAllMatches('**/*lamp*') npl += render.findAllMatches('**/*prop_tree*') npl += render.findAllMatches('**/*prop_snow_tree*') npl += render.findAllMatches('**/*prop_palm_tree_topflat*') #render.ls() p = Parallel() for i in xrange(npl.getNumPaths()): np = npl.getPath(i) geomNodeCollection = np.findAllMatches('**/+GeomNode') for nodePath in geomNodeCollection: try: newPosX = nodePath.getPos(nodePath.getParent()) if newPosX != (0,0,0): newPos = newPosX newHprX = nodePath.getHpr(nodePath.getParent()) if newHprX != (0,0,0): newHpr = newHprX else: newHpr = (0,0,0) newScaleX = nodePath.getScale() if newScaleX != LVecBase3f(1, 1, 1): newScale = newScaleX else: newScale = LVecBase3f(1, 1, 1) except: newPos = (0,0,0) newHpr = (0,0,0) newScale = LVecBase3f(1, 1, 1) DDLHalloween = np.findAllMatches('**/+GeomNode') # NJF for nodePathA in DDLHalloween: print nodePathA try: print nodePathA.getPos() except: print "no pos" np.setTransparency(TransparencyAttrib.MDual, 1) if not np.hasTag('DNACode'): continue dnaCode = np.getTag('DNACode') dnaNode = self.dnaStore.findNode(dnaCode) if dnaNode.isEmpty(): continue newNP = dnaNode.copyTo(np.getParent()) newNP.setTag('DNARoot', 'holiday_prop') newNP.setTag('DNACode', dnaCode) newNP.setColorScale(1, 1, 1, 0) newNP.setTransparency(TransparencyAttrib.MDual, 1) if np.hasTag('transformIndex'): index = int(np.getTag('transformIndex')) transform = loader.holidayPropTransforms.get(index, TransformState.makeIdentity()) newNP.setTransform(NodePath(), transform) newNP.setTag('transformIndex', 'index') if newPos != (0,0,0): if dnaCode == 'prop_palm_tree_topflat': # Donald's dock is... a wreck. newNP.setX(newPos[0]) newNP.setY(newPos[1]) correctedZ = newPos[2] / newScale[2] / 7.4 # This is such a hackjob ugh newNP.setZ(correctedZ) else: newNP.setPos(newPos) if newHpr != (0,0,0): newNP.setHpr(newHpr) if newScale != LVecBase3f(1, 1, 1): newNP.setScale(newScale) if dnaCode == 'streetlight_DD_left' or dnaCode == 'streetlight_DD_right': # Donald's dock is... a wreck. if newPos[2] > 7: newNP.setZ(5.68) if dnaCode == 'prop_tree_large_ur' or dnaCode == 'prop_tree_large_ul': correctedZ = newPos[2] + 0.25 newNP.setZ(correctedZ) s = Sequence(Wait(wait), np.colorScaleInterval(tFadeOut, Vec4(1, 1, 1, 0), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut'), Func(np.detachNode), Func(np.clearTransparency), newNP.colorScaleInterval(tFadeOut, Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0), blendType='easeInOut'), Func(newNP.clearTransparency), Func(newNP.clearColorScale)) p.append(s) return p