def loadModel(path, parent): """Load a model from the file given by path, parent it to the given parent node and return the NodePath to the newly loaded model. Maintains a global dictionary of loaded models and if a model if called twice for the same model the model is instanced instead of being loaded again. """ global models if models.has_key(path): model = models[path].copyTo(parent) scale = 0.75 + random.random() / 2 model.setScale(scale) setRadiusTag(model) else: modelRoot = loader.loadModelCopy(path) # New models are loaded in a non-standard way to allow flattenStrong # to work effectively over them. model = P.NodePath('model') scale = 0.75 + random.random() / 2 model.setScale(scale) modelRoot.getChildren().reparentTo(model) model.reparentTo(parent) setRadiusTag(model) models[path] = model return model
def CreateArrow( self, vec, colour ): # Create the geometry and collision vec.normalize() line = pm.NodePath( Line( (0, 0, 0), vec ) ) cone = pm.NodePath( Cone( 0.05, 0.25, axis=vec, origin=vec * 0.125 ) ) collTube = pm.CollisionTube( (0,0,0), pm.Point3( vec ) * 0.95, 0.05 ) # Create the axis, add the geometry and collision axis = Axis( self.name, vec, colour ) axis.AddGeometry( line, sizeStyle=SCALE ) axis.AddGeometry( cone, vec, colour ) axis.AddCollisionSolid( collTube, sizeStyle=TRANSLATE_POINT_B ) axis.reparentTo( self ) return axis
def replaceCollisionPolysWithPlanes(self, model): newCollisionNode = PM.CollisionNode('collisions') newCollideMask = PM.BitMask32(0) planes = [] collList = model.findAllMatches('**/+CollisionNode') if not collList: collList = [model] for cnp in collList: cn = cnp.node() if not isinstance(cn, PM.CollisionNode): self.notify.warning('Not a collision node: %s' % repr(cnp)) break newCollideMask = newCollideMask | cn.getIntoCollideMask() for i in range(cn.getNumSolids()): solid = cn.getSolid(i) if isinstance(solid, PM.CollisionPolygon): plane = PM.Plane(solid.getPlane()) planes.append(plane) else: self.notify.warning('Unexpected collision solid: %s' % repr(solid)) newCollisionNode.addSolid(plane) newCollisionNode.setIntoCollideMask(newCollideMask) threshold = 0.1 planes.sort(lambda p1, p2: p1.compareTo(p2, threshold)) lastPlane = None for plane in planes: if lastPlane == None or plane.compareTo(lastPlane, threshold) != 0: cp = PM.CollisionPlane(plane) newCollisionNode.addSolid(cp) lastPlane = plane return PM.NodePath(newCollisionNode)
def SetupEdRender(self): """ Create editor root node behind render node so we can keep editor only nodes out of the scene. """ self.edRender = pm.NodePath('edRender') render.reparentTo(self.edRender)
def RebuildGeomNodesToColPolys(incomingNodes): """ Converts GeomNodes into CollisionPolys in a straight 1-to-1 conversion Returns a new NodePath containing the CollisionNodes """ parent = pm.NodePath('cGeomConversionParent') for c in incomingNodes: gni = 0 geomNode = c.node() for g in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(g).decompose() vdata = geom.getVertexData() vreader = pm.GeomVertexReader(vdata, 'vertex') cChild = pm.CollisionNode('cGeom-%s-gni%i' % (c.getName(), gni)) gni += 1 for p in range(geom.getNumPrimitives()): prim = geom.getPrimitive(p) for p2 in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p2) e = prim.getPrimitiveEnd(p2) v = [] for vi in range(s, e): vreader.setRow(prim.getVertex(vi)) v.append(vreader.getData3f()) colPoly = pm.CollisionPolygon(*v) cChild.addSolid(colPoly) parent.attachNewNode(cChild) return parent
def __init__(self, size=(256, 256), lbase=None, output=None): """ Prepares graphics context in which to render synthetic images.""" if lbase is None: # Create the renderer window_type = "texture" self.lbase, self.output = gr.setup_renderer(window_type, size=size) else: # Use the supplied lbase instance self.lbase = lbase if output is None: # Default to last output in lbase.output_list self.output = self.lbase.output_list[-1] # Get the RTT target self.tex = self.output.getTexture() # Initialization self.models = {} self.bgs = {} # Make the scene and attach it to lbase's rootnode self.scene = pm.NodePath("scene") self.scene.reparentTo(self.lbase.rootnode) # Initialize local copies of all of the models and bgs self.init_models() self.init_bgs()
def enterLoaded(self): DistCogdoLevelGame.enterLoaded(self) self.lightning = loader.loadModel( 'phase_10/models/cogHQ/CBLightning.bam') self.magnet = loader.loadModel('phase_10/models/cogHQ/CBMagnet.bam') self.craneArm = loader.loadModel( 'phase_10/models/cogHQ/CBCraneArm.bam') self.controls = loader.loadModel( 'phase_10/models/cogHQ/CBCraneControls.bam') self.stick = loader.loadModel('phase_10/models/cogHQ/CBCraneStick.bam') self.cableTex = self.craneArm.findTexture('MagnetControl') self.geomRoot = PM.NodePath('geom') # Set up a physics manager for the cables and the objects # falling around in the room. self.physicsMgr = PM.PhysicsManager() integrator = PM.LinearEulerIntegrator() self.physicsMgr.attachLinearIntegrator(integrator) fn = PM.ForceNode('gravity') self.fnp = self.geomRoot.attachNewNode(fn) gravity = PM.LinearVectorForce(0, 0, -32) fn.addForce(gravity) self.physicsMgr.addLinearForce(gravity)
def enterLoaded(self): DistCogdoLevelGame.enterLoaded(self) self.lightning = loader.loadModel( 'phase_10/models/cogHQ/CBLightning.bam') self.magnet = loader.loadModel('phase_10/models/cogHQ/CBMagnet.bam') self.craneArm = loader.loadModel( 'phase_10/models/cogHQ/CBCraneArm.bam') self.controls = loader.loadModel( 'phase_10/models/cogHQ/CBCraneControls.bam') self.stick = loader.loadModel('phase_10/models/cogHQ/CBCraneStick.bam') self.cableTex = self.craneArm.findTexture('MagnetControl') self.moneyBag = loader.loadModel('phase_10/models/cashbotHQ/MoneyBag') self.geomRoot = PM.NodePath('geom') self.sceneRoot = self.geomRoot.attachNewNode('sceneRoot') self.sceneRoot.setPos(35.84, -115.46, 6.46) self.physicsMgr = PM.PhysicsManager() integrator = PM.LinearEulerIntegrator() self.physicsMgr.attachLinearIntegrator(integrator) fn = PM.ForceNode('gravity') self.fnp = self.geomRoot.attachNewNode(fn) gravity = PM.LinearVectorForce(0, 0, GameConsts.Settings.Gravity.get()) fn.addForce(gravity) self.physicsMgr.addLinearForce(gravity) self._gravityForce = gravity self._gravityForceNode = fn
def Create(cls, *args, **kwargs): if 'inputNp' in kwargs: inputNp = kwargs['inputNp'] elif 'path' in kwargs: inputNp = cls(cls.FindChild(kwargs['path'], kwargs['parent'])) return inputNp else: return cls(pm.NodePath(blt.BulletRigidBodyNode(''))) # Get all geom nodes at this level and below. #geomNps = inputNp.findAllMatches( '**/+GeomNode' ) #if inputNp.node().isOfType( pm.GeomNode ): # geomNps.addPath( inputNp ) geomNps = [inputNp] # Get a flat list of all geoms. geoms = [] for geomNp in geomNps: geoms.extend(geomNp.node().getGeoms()) mesh = blt.BulletTriangleMesh() for geom in geoms: mesh.addGeom(geom) shape = blt.BulletTriangleMeshShape(mesh, dynamic=False) rBody = blt.BulletRigidBodyNode(inputNp.getName()) rBody.addShape(shape) # Swap the original NodePath for the one we just created. np = pm.NodePath(rBody) np.reparentTo(inputNp.getParent()) np.setTag(game.nodes.TAG_NODE_TYPE, TAG_EMBEDDED_BULLET_TRIANGLE_MESH_SHAPE) inputNp.detachNode() wrpr = cls(np) wrpr.CreateNewId() return wrpr
def Create(cls, *args, **kwargs): """ Create a NodePath with the indicated type and name, set it up and return it. """ path = kwargs.pop('path', None) if path is None: wrpr = super(NodePath, cls).Create(*args, **kwargs) wrpr.SetData(pm.NodePath(wrpr.data)) wrpr.SetupNodePath() else: wrpr = cls(cls.FindChild(path, kwargs.pop('parent'))) return wrpr
def CreateSquare( self, vec, colour ): # Create the geometry and collision self.square = pm.NodePath( Square( 0.2, 0.2, pm.Vec3(0, 1, 0) ) ) self.square.setBillboardPointEye() collSphere = pm.CollisionSphere( 0, 0.125 ) # Create the axis, add the geometry and collision axis = Axis( self.name, CAMERA_VECTOR, colour, planar=True, default=True ) axis.AddGeometry( self.square, sizeStyle=NONE ) axis.AddCollisionSolid( collSphere, sizeStyle=NONE ) axis.reparentTo( self ) return axis
def Create(cls, *args, **kwargs): modelPath = kwargs.pop('modelPath', '') if not modelPath: np = pm.NodePath(pm.ModelRoot('')) else: filePath = pm.Filename.fromOsSpecific(modelPath) try: np = loader.loadModel(filePath) except: try: np = loader.loadModel(filePath + '.bam') except IOError: print 'Failed to load: ', filePath np = pm.NodePath(pm.ModelRoot('')) np.setName(filePath.getBasenameWoExtension()) wrpr = cls(np) wrpr.SetupNodePath() # Iterate over child nodes wrpr.extraNps = [] def Recurse(node): nTypeStr = node.getTag(TAG_NODE_TYPE) cWrprCls = base.game.nodeMgr.GetWrapperByName(nTypeStr) if cWrprCls is not None: cWrpr = cWrprCls.Create(inputNp=node) wrpr.extraNps.append(cWrpr.data) # Recurse for child in node.getChildren(): Recurse(child) Recurse(np) return wrpr
def enterLoaded(self): DistCogdoLevelGameAI.enterLoaded(self) self.scene = PM.NodePath('scene') cn = PM.CollisionNode('walls') cs = PM.CollisionSphere(0, 0, 0, 13) cn.addSolid(cs) cs = PM.CollisionInvSphere(0, 0, 0, 42) cn.addSolid(cs) self.attachNewNode(cn) for i in xrange(CogdoGameConsts.MaxPlayers): crane = DistCogdoCraneAI(self.air, self, i) crane.generateWithRequired(self.zoneId) self._cranes[i] = crane for i in xrange(len(self._moneyBags)): mBag = DistCogdoCraneMoneyBagAI(self.air, self, i) mBag.generateWithRequired(self.zoneId) self._moneyBags[i] = mBag
def replaceCollisionPolysWithPlanes(self, model): newCollisionNode = PM.CollisionNode('collisions') newCollideMask = PM.BitMask32(0) planes = [] collList = model.findAllMatches('**/+CollisionNode') if not collList: collList = [model] for cnp in collList: cn = cnp.node() if not isinstance(cn, PM.CollisionNode): self.notify.warning("Not a collision node: %s" % (repr(cnp))) break newCollideMask = newCollideMask | cn.getIntoCollideMask() for i in range(cn.getNumSolids()): solid = cn.getSolid(i) if isinstance(solid, PM.CollisionPolygon): # Save the plane defined by this polygon plane = PM.Plane(solid.getPlane()) planes.append(plane) else: self.notify.warning("Unexpected collision solid: %s" % (repr(solid))) newCollisionNode.addSolid(plane) newCollisionNode.setIntoCollideMask(newCollideMask) # Now sort all of the planes and remove the nonunique ones. # We can't use traditional dictionary-based tricks, because we # want to use Plane.compareTo(), not Plane.__hash__(), to make # the comparison. threshold = 0.1 planes.sort(lambda p1, p2: p1.compareTo(p2, threshold)) lastPlane = None for plane in planes: if lastPlane == None or plane.compareTo(lastPlane, threshold) != 0: cp = PM.CollisionPlane(plane) newCollisionNode.addSolid(cp) lastPlane = plane return PM.NodePath(newCollisionNode)
def __init__(self, pos=None, color=(0.6, 0.8, 0.5, 1), scale=12, h=8, size=33, trees=0.7): # Initialise primary NodePath which everything else is parented to if pos is None: pos = P.Vec3(0, 0, 0) self.pos = pos self.prime = P.NodePath('Terrain primary NodePath') self.prime.setPos(self.pos) # Create terrain models (rendering and collision) self.tnp, self.collnp = makeTerrain(size=size, h=h) self.tnp.reparentTo(self.prime) self.tnp.setColor(*color) self.tnp.setScale(scale) # Shift the collision terrain a bit so rays from trees hit self.collnp.setPos(self.collnp, .0001, .0001, 0) self.collnp.setCollideMask(C.floorMASK) # All trees in the scene are parented to one NodePath for flattening self.trees = self.prime.attachNewNode(P.PandaNode('trees')) self.treesColl = self.prime.attachNewNode(P.CollisionNode('treesColl')) self.treesColl.node().setIntoCollideMask(offMASK) self.treesColl.node().setFromCollideMask(obstacleMASK) #self.treesColl.show() vehicleCTrav.addCollider(self.treesColl, obstacleHandler) # Initialise trees img = greenNoise(imgSize=(size, size), scale=0.25) for x in range(0, size - 1): for y in range(0, size - 1): if img.getGreen(x, y) > trees: treepos = P.Vec3(x * scale + 0.5 * scale, y * scale + 0.5 * scale, 50) tree = Tree(pos=treepos) tree.prime.reparentTo(self.trees) taskMgr.add(self.flatten, "Terrain flatten task")
def OnDuplicate(self, origNp, dupeNp): # Duplicate doesn't work for rigid body nodes... foo = blt.BulletRigidBodyNode(origNp.getName()) bar = pm.NodePath(foo) bar.reparentTo(self.data.getParent()) self.data.detachNode() self.data = bar self.data.setTag(game.nodes.TAG_NODE_TYPE, TAG_EMBEDDED_BULLET_TRIANGLE_MESH_SHAPE) #self.SetupNodePath() #print 'DUPE: ', self.data #print 'new: ', dupeNp, ' : ', self.data #print 'from: ', dupeNp for shape in origNp.node().getShapes(): copShape = copy.copy(shape) self.data.node().addShape(copShape) BulletRigidBodyNode.OnDuplicate(self, origNp, dupeNp) return self.data
def __init__(self, name='camera', *args, **kwargs): pos = kwargs.pop('pos', (0, 0, 0)) targetPos = kwargs.pop('targetPos', (0, 0, 0)) style = kwargs.pop('style', CAM_DEFAULT_STYLE) p3d.SingleTask.__init__(self, name, *args, **kwargs) self.zoomLevel = 2 self.defaultPos = pos self.style = style # Use Panda's default camera if self.style & CAM_USE_DEFAULT: self.cam = getBase().cam #self.camNode = getBase().camNode # Otherwise create a new one else: # Create camera self.cam = NodePath(PCamera(name)) # Create lens lens = PerspectiveLens() lens.setAspectRatio(800.0 / 300.0) self.cam.node().setLens(lens) # Wrap the camera in this node path class NodePath.__init__(self, self.cam) # Create camera styles if self.style & CAM_VIEWPORT_AXES: self.axes = pm.NodePath(p3d.geometry.Axes()) self.axes.reparentTo(self.rootP2d) # Create camera target self.target = self.Target(pos=targetPos) self.Reset()
def Group(nps): """ Create the group action, execute it and push it onto the undo queue. """ # Find the lowest common ancestor for all NodePaths - this will be the # parent for the group NodePath. cmmnNp = nps[0].getParent() for np in nps: cmmnNp = cmmnNp.getCommonAncestor(np) grpNp = pm.NodePath('group') grpNp.reparentTo(cmmnNp) actns = [] actns.append(actions.Add(grpNp)) actns.extend([actions.Parent(np, grpNp) for np in nps]) actns.append(actions.Deselect(nps)) actns.append(actions.Select([grpNp])) actn = actions.Composite(actns) wx.GetApp().actnMgr.Push(actn) actn() wx.GetApp().doc.OnModified(nps.append(grpNp))
def SetupEdRender2d(self): """ Creates the render2d scene graph, the primary scene graph for 2-d objects and gui elements that are superimposed over the 3-d geometry in the window. """ self.edRender2d = pm.NodePath('edRender2d') # Set up some overrides to turn off certain properties which we # probably won't need for 2-d objects. self.edRender2d.setDepthTest(0) self.edRender2d.setDepthWrite(0) self.edRender2d.setMaterialOff(1) self.edRender2d.setTwoSided(1) # This special root, pixel2d, uses units in pixels that are relative # to the window. The upperleft corner of the window is (0, 0), # the lowerleft corner is (xsize, -ysize), in this coordinate system. xsize, ysize = self.getSize() self.edPixel2d = self.edRender2d.attachNewNode(pm.PGTop('edPixel2d')) self.edPixel2d.setPos(-1, 0, 1) if xsize > 0 and ysize > 0: self.edPixel2d.setScale(2.0 / xsize, 1.0, 2.0 / ysize)
def __init__(self, pos=None): """Initialise the tree.""" # Models and CollisionSolids are parented to one prime NodePath if pos is None: pos = P.Vec3(0, 0, 0) self.pos = pos self.prime = P.NodePath('tree') self.prime.setPos(self.pos) dir = "models/trees" # FIXME: hardcoded models dir # Choose a random model from dir and load it. trees = [ f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f)) and f.endswith('.egg') ] tree = random.choice(trees) self.np = loadModel(os.path.join(dir, tree), self.prime) # TODO: Give each tree a random orientation # Initialise the Tree's CollisionRay which is used with a # CollisionHandlerQueue to find the height of the terrain below the # tree and move the tree to that height (see self.step) self.raynp = self.prime.attachNewNode(P.CollisionNode('colNode')) self.raynp.node().addSolid(P.CollisionRay(0, 0, 3, 0, 0, -1)) self.handler = P.CollisionHandlerQueue() cTrav.addCollider(self.raynp, self.handler) #self.raynp.show() # We only want our CollisionRay to collide with the collision # geometry of the terrain, se we set a mask here. self.raynp.node().setFromCollideMask(C.floorMASK) self.raynp.node().setIntoCollideMask(C.offMASK) # Add a task for this Tree to the global task manager. taskMgr.add(self.step, "Tree step task")
from direct.gui.DirectGui import * from pandac.PandaModules import TextNode from pandac.PandaModules import AmbientLight, Spotlight, PerspectiveLens, Fog from pandac import PandaModules as P from direct.task.Task import Task # Custom imports from camera import Camera, EdgeScreenTracker from terrain import Terrain from obstacles import SphereObstacle from containers import ContainerSquare from steerVec import SteerVec import character as C # CollisionTraverser for Plants base.cTrav = P.CollisionTraverser('CollisionTraverser of scene.py') plantNode = P.NodePath( 'plantNode') # All plants are parented to one node for flattening plantNode.reparentTo(render) class Sea: def __init__(self): sea = loader.loadModel("models/sea1.egg") sea.reparentTo(render) sea.setScale(2000, 2000, 100) class Scene(DirectObject): def __init__(self): """Initialise the scene.""" # Show the framerate
def makeTerrainFromHeightMap(heightmap): """Return a tuple of NodePaths (renderNodePath,collisionNodePath) to renderable and collision geometry for a chainable terrain model built from the given heightmap. collisionNodePath is parented to renderNodePath. renderNodePath is not parented to anything by this function. Every 3x3 group of quads in the collision geometry is collected under a PandaNode for efficient collision detection. This could be improved on by building both the renderable and collision geometry as octrees. Keyword arguments: heightmap -- a 2D list of height values. """ size = len(heightmap) renderNodePath = P.NodePath('') renderEggData = P.EggData() renderVertexPool = P.EggVertexPool('') collisionNodePath = renderNodePath.attachNewNode('') # Supply the EggGroup & EggVertexPool for the first node. collisionVertexPool = P.EggVertexPool('') collisionEggGroup = P.EggGroup('') collisionEggGroup.addObjectType('barrier') # We group every (numQuadGrid x numQuadGrid) quads under 1 collision node. numQuadGrid = 3 # The modulo of (size-2)/numQuadGrid marks when the quads must be grouped # into 1 geom. edgeMod = (size - 2) % numQuadGrid for i in range(0, len(heightmap) - 1, numQuadGrid): # Limit nextIrange to avoid it from jump over the edge. nextIrange = min(numQuadGrid, len(heightmap) - 1 - i) for j in range(0, len(heightmap) - 1): for nextI in range(0, nextIrange): bl = P.Point3D(i + nextI, j, heightmap[i + nextI][j]) tr = P.Point3D(i + nextI + 1, j + 1, heightmap[i + nextI + 1][j + 1]) br = P.Point3D(i + nextI + 1, j, heightmap[i + nextI + 1][j]) tl = P.Point3D(i + nextI, j + 1, heightmap[i + nextI][j + 1]) # Construct polygons (quads) with makeQuads. renderQuad, collisionQuad = makeQuad(renderVertexPool, collisionVertexPool, bl, tr, br, tl) renderEggData.addChild(renderQuad) collisionEggGroup.addChild(collisionQuad) if j % numQuadGrid == edgeMod and nextI == nextIrange - 1: # Group the previous (numQuadGrid x numQuadGrid) quads under # collision node. collisionEggData = P.EggData() collisionEggData.addChild(collisionEggGroup) pandaNode = P.loadEggData(collisionEggData) nodePath = collisionNodePath.attachNewNode( pandaNode.getChild(0).getChild(0)) # Uncomment the next line to see the collision geom. #nodePath.show() # Supply the EggGroup & EggVertexPool for the next node. collisionEggGroup = P.EggGroup('') collisionEggGroup.addObjectType('barrier') collisionVertexPool = P.EggVertexPool('') pandaNode = P.loadEggData(renderEggData) renderNodePath.attachNewNode(pandaNode) return renderNodePath, collisionNodePath
def Create(cls, *args, **kwargs): wrpr = cls(pm.NodePath(p3d.geometry.Box())) wrpr.SetupNodePath() return wrpr