Ejemplo n.º 1
0
    def _add_side_walk2bullet(self, lane_start, lane_end, middle, radius=0.0, direction=0):
        length = norm(lane_end[0] - lane_start[0], lane_end[1] - lane_start[1])
        body_node = BulletRigidBodyNode(BodyName.Side_walk)
        body_node.setActive(False)
        body_node.setKinematic(False)
        body_node.setStatic(True)
        side_np = self.side_walk_node_path.attachNewNode(body_node)
        shape = BulletBoxShape(Vec3(1 / 2, 1 / 2, 1 / 2))
        body_node.addShape(shape)
        body_node.setIntoCollideMask(BitMask32.bit(Block.LANE_LINE_COLLISION_MASK))
        self.dynamic_nodes.append(body_node)

        if radius == 0:
            factor = 1
        else:
            if direction == 1:
                factor = (1 - self.SIDE_WALK_LINE_DIST / radius)
            else:
                factor = (1 + self.SIDE_WALK_WIDTH / radius) * (1 + self.SIDE_WALK_LINE_DIST / radius)
        direction_v = lane_end - lane_start
        vertical_v = (-direction_v[1], direction_v[0]) / numpy.linalg.norm(direction_v)
        middle += vertical_v * (self.SIDE_WALK_WIDTH / 2 + self.SIDE_WALK_LINE_DIST)
        side_np.setPos(panda_position(middle, 0))
        theta = -numpy.arctan2(direction_v[1], direction_v[0])
        side_np.setQuat(LQuaternionf(numpy.cos(theta / 2), 0, 0, numpy.sin(theta / 2)))
        side_np.setScale(
            length * factor, self.SIDE_WALK_WIDTH, self.SIDE_WALK_THICKNESS * (1 + 0.1 * numpy.random.rand())
        )
        if self.render:
            side_np.setTexture(self.ts_color, self.side_texture)
            self.side_walk.instanceTo(side_np)
Ejemplo n.º 2
0
    def setupPhysics(self, radius=None, height=None):
        if not radius:
            radius = self.getWidth()
        if not height:
            height = self.getHeight()
        self.notify.debug("setupPhysics(r{0}, h{1}) hitboxData: {2}".format(
            radius, height, self.hitboxData))

        # When the height is passed into BulletCapsuleShape, it's
        # talking about the height only of the cylinder part.
        # But what we want is the height of the entire capsule.
        #height -= (radius * 2)
        # The middle of the capsule is the origin by default. Push the capsule shape up
        # so the very bottom of the capsule is the origin.
        zOfs = (height / 2.0) + radius

        capsule = BulletCapsuleShape(radius, height)
        bodyNode = BulletRigidBodyNode('avatarBodyNode')
        bodyNode.addShape(capsule, TransformState.makePos(Point3(0, 0, zOfs)))
        bodyNode.setKinematic(True)
        bodyNode.setPythonTag("avatar", self)

        BasePhysicsObject.setupPhysics(self, bodyNode, True)

        self.stopWaterCheck()
Ejemplo n.º 3
0
def makeVPPhysics(multipart=False):
    from panda3d.core import TransformState
    from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode

    carriage = BulletBoxShape((4.40625, 7.125, 2.75))
    tread = BulletBoxShape((1.9, 10.34, 2.75))
    legs = BulletBoxShape((3.375, 3.375, 2.1875))
    gear = BulletBoxShape((6.72, 6.72, 1.1))
    torso = BulletBoxShape((4.44, 3.625, 4.125))
    head = BulletBoxShape((2, 2, 2.22))
    torsoTrans = TransformState.makePos((0, 0, 13.93))
    headTrans = TransformState.makePos((0, 0, 20.28))

    bodyNode = BulletRigidBodyNode("VPPhysics")
    bodyNode.addShape(carriage, TransformState.makePos((0, 0, 2.75)))
    bodyNode.addShape(tread, TransformState.makePos((6.3, 0, 2.75)))
    bodyNode.addShape(tread, TransformState.makePos((-6.3, 0, 2.75)))
    bodyNode.addShape(legs, TransformState.makePos((0, 0, 7.75)))
    bodyNode.addShape(gear, TransformState.makePos((0, 0, 10.94)))
    if not multipart:
        bodyNode.addShape(torso, torsoTrans)
        bodyNode.addShape(head, headTrans)
    bodyNode.setKinematic(True)
    bodyNode.setMass(0.0)

    if multipart:
        upperNode = BulletRigidBodyNode("VPPhysics-upper")
        upperNode.addShape(torso, torsoTrans)
        upperNode.addShape(head, headTrans)
        upperNode.setKinematic(True)
        upperNode.setMass(0.0)

    if multipart:
        return [bodyNode, upperNode]
    return bodyNode
Ejemplo n.º 4
0
 def getPhysBody(self):
     shape = BulletCylinderShape(0.3925, 1.4, ZUp)
     body = BulletRigidBodyNode('tntBody')
     body.addShape(shape)
     body.setKinematic(True)
     body.setCcdMotionThreshold(1e-7)
     body.setCcdSweptSphereRadius(0.3925)
     return body
Ejemplo n.º 5
0
def makeBulletBoxColl(node, extents):

    shape = BulletBoxShape(extents)
    rbnode = BulletRigidBodyNode(node.getName() + "_bulletBoxColl")
    rbnode.addShape(shape)
    rbnode.setKinematic(True)
    rbnodeNp = node.attachNewNode(rbnode)
    rbnodeNp.setCollideMask(WallGroup)
    base.physicsWorld.attachRigidBody(rbnode)
Ejemplo n.º 6
0
 def getPhysBody(self):
     shape = BulletCylinderShape(0.3925, 1.4, ZUp)
     body = BulletRigidBodyNode('tntBody')
     body.addShape(shape)
     body.setCcdMotionThreshold(1e-7)
     body.setCcdSweptSphereRadius(0.3925)
     body.setKinematic(False)
     body.setMass(5.0)
     body.setAngularDamping(0.3)
     body.setLinearDamping(0.8)
     return body
    def load(self):
        SafeZoneLoader.SafeZoneLoader.load(self, False)
        self.geom.find('**/ground_center').setBin('ground', 18)
        self.geom.find('**/ground_sidewalk').setBin('ground', 18)
        self.geom.find('**/ground').setBin('ground', 18)
        self.geom.find('**/ground_center_coll').setCollideMask(
            CIGlobals.FloorGroup)
        self.geom.find('**/ground_sidewalk_coll').setCollideMask(
            CIGlobals.FloorGroup)
        self.geom.find('**/ground_coll').setCollideMask(CIGlobals.FloorGroup)
        for tree in self.geom.findAllMatches('**/prop_green_tree_*_DNARoot'):
            tree.wrtReparentTo(hidden)

            # Make corrected collisions
            tree.find("**/+BulletRigidBodyNode").removeNode()
            capsule = BulletCapsuleShape(2.0, 6.0, ZUp)
            bnode = BulletRigidBodyNode("tree_collision")
            bnode.addShape(capsule, TransformState.makePos((0, 0, 3.0)))
            bnode.setKinematic(True)
            bnode.setIntoCollideMask(CIGlobals.WallGroup)
            tree.attachNewNode(bnode)

            self.trees.append(tree)
            newShadow = loader.loadModel(
                "phase_3/models/props/drop_shadow.bam")
            newShadow.reparentTo(tree)
            newShadow.setScale(1.5)
            newShadow.setBillboardAxis(2)
            newShadow.setColor(0, 0, 0, 0.5, 1)
            #tree.clearModelNodes()
            #tree.flattenStrong()

        # Fix bank door trigger
        bank = self.geom.find('**/*toon_landmark_TT_bank_DNARoot')
        doorTrigger = bank.find('**/door_trigger*')
        doorTrigger.setY(doorTrigger.getY() - 1.0)

        #self.telescope = Actor(self.geom.find('**/*animated_prop_HQTelescopeAnimatedProp*'), copy = 0)
        #{'chan': 'phase_3.5/models/props/HQ_telescope-chan.bam'}, copy=0)
        #self.telescope.reparentTo(self.geom.find('**/tb20:toon_landmark_hqTT_DNARoot'))
        #self.telescope.setPos(1, 0.46, 0)

        #self.geom.setMaterialOff()

        water = self.geom.find("**/pond_water")
        water.removeNode()

        self.doFlatten()
Ejemplo n.º 8
0
 def getPhysBody(self):
     bsph = BulletSphereShape(0.6)
     bcy = BulletCylinderShape(0.25, 0.35, ZUp)
     body = BulletRigidBodyNode('tntBody')
     body.addShape(
         bsph,
         TransformState.makePosHpr((0.05, 0, 0.43),
                                   (86.597, 24.5539, 98.1435)))
     body.addShape(
         bcy,
         TransformState.makePosHpr((0.05, 0.655, 0.35),
                                   (86.597, 24.5539, 98.1435)))
     body.setKinematic(True)
     body.setCcdMotionThreshold(1e-7)
     body.setCcdSweptSphereRadius(0.6)
     return body
Ejemplo n.º 9
0
    def _add_lane_line2bullet(
        self,
        lane_start,
        lane_end,
        middle,
        parent_np: NodePath,
        color: Vec4,
        line_type: LineType,
        straight_stripe=False
    ):
        length = norm(lane_end[0] - lane_start[0], lane_end[1] - lane_start[1])
        if length <= 0:
            return
        if LineType.prohibit(line_type):
            node_name = BodyName.Continuous_line
        else:
            node_name = BodyName.Stripped_line

        # add bullet body for it
        if straight_stripe:
            body_np = parent_np.attachNewNode(node_name)
        else:
            scale = 2 if line_type == LineType.STRIPED else 1
            body_node = BulletRigidBodyNode(node_name)
            body_node.setActive(False)
            body_node.setKinematic(False)
            body_node.setStatic(True)
            body_np = parent_np.attachNewNode(body_node)
            shape = BulletBoxShape(Vec3(scale / 2, Block.LANE_LINE_WIDTH / 2, Block.LANE_LINE_THICKNESS))
            body_np.node().addShape(shape)
            body_np.node().setIntoCollideMask(BitMask32.bit(Block.LANE_LINE_COLLISION_MASK))
            self.dynamic_nodes.append(body_np.node())

        # position and heading
        body_np.setPos(panda_position(middle, 0))
        direction_v = lane_end - lane_start
        theta = -numpy.arctan2(direction_v[1], direction_v[0])
        body_np.setQuat(LQuaternionf(numpy.cos(theta / 2), 0, 0, numpy.sin(theta / 2)))

        if self.render:
            # For visualization
            lane_line = self.loader.loadModel(AssetLoader.file_path("models", "box.bam"))
            lane_line.getChildren().reparentTo(body_np)
        body_np.setScale(length, Block.LANE_LINE_WIDTH, Block.LANE_LINE_THICKNESS)
        body_np.set_color(color)
    def setupPhysics(self):
        if not self.NeedsPhysics:
            return

        bodyNode = BulletRigidBodyNode(self.uniqueName('avatarBodyNode'))

        radius = self.getWidth()
        height = self.getHeight()  # - (radius * 2)
        zOfs = (height / 2.0) + radius
        capsule = BulletCapsuleShape(radius, height)
        bodyNode.addShape(capsule, TransformState.makePos(Point3(0, 0, zOfs)))
        bodyNode.setKinematic(True)
        bodyNode.setMass(0.0)

        self.notify.debug("setupPhysics(r{0}, h{1}) hitboxData: {2}".format(
            radius, height, self.hitboxData))

        BasePhysicsObjectAI.setupPhysics(self, bodyNode, True)
Ejemplo n.º 11
0
    def _add_box_body(self, lane_start, lane_end, middle, parent_np: NodePath, line_type):
        length = norm(lane_end[0] - lane_start[0], lane_end[1] - lane_start[1])
        if LineType.prohibit(line_type):
            node_name = BodyName.Continuous_line
        else:
            node_name = BodyName.Stripped_line
        body_node = BulletRigidBodyNode(node_name)
        body_node.setActive(False)
        body_node.setKinematic(False)
        body_node.setStatic(True)
        body_np = parent_np.attachNewNode(body_node)
        shape = BulletBoxShape(Vec3(length / 2, Block.LANE_LINE_WIDTH / 2, Block.LANE_LINE_THICKNESS))
        body_np.node().addShape(shape)
        body_np.node().setIntoCollideMask(BitMask32.bit(Block.LANE_LINE_COLLISION_MASK))
        self.dynamic_nodes.append(body_np.node())

        body_np.setPos(panda_position(middle, 0))
        direction_v = lane_end - lane_start
        theta = -numpy.arctan2(direction_v[1], direction_v[0])
        body_np.setQuat(LQuaternionf(numpy.cos(theta / 2), 0, 0, numpy.sin(theta / 2)))
Ejemplo n.º 12
0
def makeBulletBoundingBoxColl(node):
    """
    Creates and attaches a BulletRigidBodyNode underneath `node` which contains
    a BulletBoxShape that covers the tight bounds of `node`.
    Useful for quick prop collisions and such.
    """
    mins = Point3(0)
    maxs = Point3(0)
    node.calcTightBounds(mins, maxs)

    extents = extentsFromMinMax(mins, maxs)
    tsCenter = TransformState.makePos(centerFromMinMax(mins, maxs))

    shape = BulletBoxShape(extents)
    rbnode = BulletRigidBodyNode(node.getName() + "_bulletBoundingBoxColl")
    rbnode.addShape(shape, tsCenter)
    rbnode.setKinematic(True)
    rbnodeNp = render.attachNewNode(rbnode)
    rbnodeNp.wrtReparentTo(node)
    rbnodeNp.setCollideMask(WallGroup)
    base.physicsWorld.attachRigidBody(rbnode)
class DistributedRestockBarrel(DistributedEntity, DistributedNode):
    notify = directNotify.newCategory('DistributedRestockBarrel')
    
    def __init__(self, cr):
        DistributedEntity.__init__(self, cr)
        DistributedNode.__init__(self, cr)
        NodePath.__init__(self, 'restock_barrel')
        self.grabSfx = None
        self.rejectSfx = None
        self.grabSoundPath = 'phase_4/audio/sfx/SZ_DD_treasure.ogg'
        self.rejectSoundPath = 'phase_4/audio/sfx/ring_miss.ogg'
        self.animTrack = None
        self.barrelScale = 0.5
        self.radius = 1.5
        self.height = 4.275
        self.playSoundForRemoteToons = 1
        self.barrel = None
        self.gagNode = None
        self.gagModel = None
        
        # Collision nodes
        self.collSphere = None
        self.collNode = None
        self.collNodePath = None
        
    def load(self):
        DistributedEntity.load(self)
        self.setPos(self.cEntity.getOrigin())
        self.setHpr(self.cEntity.getAngles())
        
    def announceGenerate(self):
        DistributedEntity.announceGenerate(self)
        DistributedNode.announceGenerate(self)
        self.build()
        
        # Build collisions
        self.collSphere = BulletCylinderShape(self.radius, self.height, ZUp)
        self.collNode = BulletRigidBodyNode(self.uniqueName('barrelSphere'))
        self.collNode.setKinematic(True)
        self.collNode.addShape(self.collSphere, TransformState.makePos(Point3(0, 0, self.height / 2)))
        self.collNode.setIntoCollideMask(WallGroup)
        self.collNodePath = self.attachNewNode(self.collNode)
        base.physicsWorld.attach(self.collNodePath.node())
        self.accept('enter' + self.collNodePath.getName(), self.__handleCollision)
        
        self.reparentTo(render)
        
    def disable(self):
        DistributedEntity.disable(self)
        DistributedNode.disable(self)
        self.ignoreAll()
        
        if self.animTrack:
            self.animTrack.pause()
            self.animTrack = None
        return
    
    def delete(self):
        self.gagNode.removeNode()
        self.barrel.removeNode()
        base.physicsWorld.remove(self.collNode)
        self.collNodePath.removeNode()
        del self.barrel
        del self.gagNode
        del self.grabSfx
        del self.rejectSfx
        del self.grabSoundPath
        del self.rejectSoundPath
        del self.animTrack
        del self.barrelScale
        del self.radius
        del self.height
        del self.playSoundForRemoteToons
        del self.gagModel
        del self.collNode
        del self.collNodePath
        del self.collSphere
        DistributedNode.delete(self)
        DistributedEntity.delete(self)
        
    def setLabel(self, labelId):
        if labelId == 0:
            self.gagModel = loader.loadModel('phase_4/models/props/icecream.bam')
            self.gagModel.reparentTo(self.gagNode)
            self.gagModel.find('**/p1_2').clearBillboard()
            self.gagModel.setScale(0.6)
            self.gagModel.setPos(0, -0.1, -0.1 - 0.6)
        elif labelId == 1:
            purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui.bam')
            self.gagModel = purchaseModels.find('**/Jar')
            self.gagModel.reparentTo(self.gagNode)
            self.gagModel.setScale(3.0)
            self.gagModel.setPos(0, -0.1, 0)
            purchaseModels.removeNode()
        elif labelId < 1000:
            gagId = labelId - 2
            iconName = GagGlobals.InventoryIconByName.get(self.cr.attackMgr.getAttackName(gagId))
            invModel = loader.loadModel('phase_3.5/models/gui/inventory_icons.bam').find('**/%s' % iconName)
            if invModel:
                self.gagModel = invModel
                self.gagModel.reparentTo(self.gagNode)
                self.gagModel.setScale(13.0)
                self.gagModel.setPos(0, -0.1, 0)
            else:
                self.notify.warning('Failed to find gag label %s.' % (str(labelId)))
        else:
            # Provided a hood id, the restock barrel will select the model of the
            # treasure for that playground and use it as the label.
            hoodName = ZoneUtil.ZoneId2Hood.get(labelId)
            modelPath = 'phase_4/models/props/icecream.bam'
            
            if hoodName is ZoneUtil.DonaldsDreamland:
                modelPath = 'phase_8/models/props/zzz_treasure.bam'
            elif hoodName is ZoneUtil.TheBrrrgh:
                modelPath = 'phase_8/models/props/snowflake_treasure.bam'
            elif hoodName is ZoneUtil.MinniesMelodyland:
                modelPath = 'phase_6/models/props/music_treasure.bam'
            elif hoodName is ZoneUtil.DaisyGardens:
                modelPath = 'phase_8/models/props/flower_treasure.bam'
            elif hoodName is ZoneUtil.DonaldsDock:
                modelPath = 'phase_6/models/props/starfish_treasure.bam'
            
            self.gagModel = loader.loadModel(modelPath)
            self.gagModel.reparentTo(self.gagNode)
            self.gagModel.find('**/p1_2').clearBillboard()
            self.gagModel.setScale(0.6)
            self.gagModel.setPos(0, -0.1, -0.7)
        
    def __handleCollision(self, _ = None):
        self.sendUpdate('requestGrab', [])
        
    def setGrab(self, avId):
        local = (avId == base.localAvatar.getDoId())
        if local:
            self.ignore(self.uniqueName('enterbarrelSphere'))
            self.barrel.setColorScale(0.5, 0.5, 0.5, 1)
        if self.playSoundForRemoteToons or local:
            base.playSfx(self.grabSfx)
        if self.animTrack:
            self.animTrack.finish()
            self.animTrack = None
        self.animTrack = Sequence(
            LerpScaleInterval(self.barrel, 0.2, 1.1 * self.barrelScale, blendType='easeInOut'), 
            LerpScaleInterval(self.barrel, 0.2, self.barrelScale, blendType='easeInOut'), 
            Func(self.reset), 
        name=self.uniqueName('animTrack'))
        self.animTrack.start()
        
    def setReject(self):
        base.playSfx(self.rejectSfx)
        self.notify.warning('Pickup rejected.')
        
    def build(self):
        self.grabSfx = base.audio3d.loadSfx(self.grabSoundPath)
        self.rejectSfx = base.audio3d.loadSfx(self.rejectSoundPath)
        base.audio3d.attachSoundToObject(self.grabSfx, self)
        base.audio3d.attachSoundToObject(self.rejectSfx, self)
        self.barrel = loader.loadModel('phase_4/models/cogHQ/gagTank.bam')
        self.barrel.setScale(self.barrelScale)
        self.barrel.reparentTo(self)
        self.barrel.setH(180)
        
        # Set the label background color.
        lblBg = self.barrel.find('**/gagLabelDCS')
        lblBg.setColor(0.15, 0.15, 0.1)
        
        self.gagNode = self.barrel.attachNewNode('gagNode')
        self.gagNode.setPosHpr(0.0, -2.62, 4.0, 0, 0, 0)
        self.gagNode.setColorScale(0.7, 0.7, 0.6, 1)
        
    def reset(self):
        self.barrel.setScale(self.barrelScale)
        self.accept(self.uniqueName('enterbarrelSphere'), self.__handleCollision)
Ejemplo n.º 14
0
def makeBulletCollFromGeoms(rootNode,
                            exclusions=[],
                            enableNow=True,
                            world=None):
    """
    Creates and attaches bullet triangle mesh nodes underneath each GeomNode
    of `rootNode`, which contains the same mesh as the Geoms.
    This can be expensive if the geometry contains lots of triangles or GeomNodes.
    """

    if not world:
        world = base.physicsWorld

    # BulletRigidBodyNode -> triangle index -> surfaceprop
    # (it's so we know which surface we are walking on)
    result = {}

    for faceNp in rootNode.findAllMatches("**"):
        if faceNp.getName() in exclusions:
            continue
        if faceNp.node().getType() != GeomNode.getClassType():
            continue

        # Create a separate list of geoms for each possible face type
        # ( a wall or floor )
        type2geoms = {}
        for i in xrange(faceNp.node().getNumGeoms()):
            geom = faceNp.node().getGeom(i)
            state = faceNp.node().getGeomState(i)
            if not geom.getPrimitive(0).isIndexed():
                continue
            if state.hasAttrib(BSPFaceAttrib.getClassSlot()):
                bca = state.getAttrib(BSPFaceAttrib.getClassSlot())
                facetype = bca.getFaceType()
            else:
                facetype = BSPFaceAttrib.FACETYPE_WALL

            if not type2geoms.has_key(facetype):
                type2geoms[facetype] = [(geom, state)]
            else:
                type2geoms[facetype].append((geom, state))

        # Now create a separate body node to group each face type,
        # and assign the correct bit
        for facetype, geoms in type2geoms.items():
            data = {}
            numGeoms = 0
            mesh = BulletTriangleMesh()
            for i in xrange(len(geoms)):
                geom, state = geoms[i]
                mesh.addGeom(geom, True)
                surfaceprop = "default"
                if state.hasAttrib(BSPMaterialAttrib.getClassSlot()):
                    mat = state.getAttrib(
                        BSPMaterialAttrib.getClassSlot()).getMaterial()
                    if mat:
                        surfaceprop = mat.getSurfaceProp()
                for j in xrange(geom.getNumPrimitives()):
                    prim = geom.getPrimitive(j)
                    prim = prim.decompose()
                    tris = prim.getNumVertices() / 3
                    for tidx in xrange(tris):
                        data[numGeoms] = surfaceprop
                        numGeoms += 1
            shape = BulletTriangleMeshShape(mesh, False)
            rbnode = BulletRigidBodyNode(faceNp.getName() + "_bullet_type" +
                                         str(facetype))
            rbnode.setKinematic(True)
            rbnode.addShape(shape)
            rbnodeNp = NodePath(rbnode)
            rbnodeNp.reparentTo(faceNp)
            if facetype == BSPFaceAttrib.FACETYPE_WALL:
                rbnodeNp.setCollideMask(CIGlobals.WallGroup)
            elif facetype == BSPFaceAttrib.FACETYPE_FLOOR:
                rbnodeNp.setCollideMask(CIGlobals.FloorGroup)
            if enableNow:
                world.attachRigidBody(rbnode)
            result[rbnode] = data

    return result