def ResetModelPath(self): """ Clears the model path, making sure to restore the current working directory (so editor models can still be found). """ pm.getModelPath().clear() pm.getModelPath().prependDirectory('.')
def _startMoveIval(self, entranceId, startT): self._stopMoveIval() unitVecs = (PM.Vec3(1, 0, 0), PM.Vec3(0, 1, 0), PM.Vec3(-1, 0, 0), PM.Vec3(0, -1, 0)) machineDistance = 4 entranceDistance = 60 startPos = unitVecs[entranceId] * entranceDistance endPos = unitVecs[entranceId] * machineDistance walkDur = (endPos - startPos ).length() / GameConsts.CogSettings.CogWalkSpeed.get() sceneRoot = self.getGame().getSceneRoot() moveIval = IG.Sequence( IG.Func(self.reparentTo, sceneRoot), IG.Func(self.setPos, startPos), IG.Func(self.lookAt, sceneRoot), IG.Func(self.loop, 'walk'), IG.LerpPosInterval(self, walkDur, endPos, startPos=startPos)) interactIval = IG.Sequence( IG.Func(self.loop, 'neutral'), IG.Wait(GameConsts.CogSettings.CogMachineInteractDuration.get())) flyIval = IG.Sequence( IG.Func(self.pose, 'landing', 0), IG.LerpPosInterval(self, GameConsts.CogSettings.CogFlyAwayDuration.get(), self._getFlyAwayDest, blendType='easeIn')) self._moveIval = IG.Sequence(moveIval, interactIval, flyIval) self._moveIval.start(globalClock.getFrameTime() - startT)
def ResetModelPath( self ): """ Clears the model path, making sure to restore the current working directory (so editor models can still be found). """ pm.getModelPath().clear() pm.getModelPath().prependDirectory( '.' )
def privGotSpec(self, levelSpec): DistCogdoLevelGame.privGotSpec(self, levelSpec) levelMgr = self.getEntity(LevelConstants.LevelMgrEntId) self.endVault = levelMgr.geom self.endVault.reparentTo(self.geomRoot) self.endVault.findAllMatches('**/MagnetArms').detach() self.endVault.findAllMatches('**/Safes').detach() self.endVault.findAllMatches('**/MagnetControlsAll').detach() cn = self.endVault.find('**/wallsCollision').node() cn.setIntoCollideMask(OTPGlobals.WallBitmask | ToontownGlobals.PieBitmask | PM.BitMask32.lowerOn(3) << 21) walls = self.endVault.find('**/RollUpFrameCillison') walls.detachNode() self.evWalls = self.replaceCollisionPolysWithPlanes(walls) self.evWalls.reparentTo(self.endVault) self.evWalls.stash() floor = self.endVault.find('**/EndVaultFloorCollision') floor.detachNode() self.evFloor = self.replaceCollisionPolysWithPlanes(floor) self.evFloor.reparentTo(self.endVault) self.evFloor.setName('floor') plane = PM.CollisionPlane( PM.Plane(PM.Vec3(0, 0, 1), PM.Point3(0, 0, -50))) planeNode = PM.CollisionNode('dropPlane') planeNode.addSolid(plane) planeNode.setCollideMask(ToontownGlobals.PieBitmask) self.geomRoot.attachNewNode(planeNode)
def Frame(self, nps): # Get a list of bounding spheres for each NodePath in world space. allBnds = [] allCntr = pm.Vec3() for np in nps: bnds = np.getBounds() if bnds.isInfinite(): continue mat = np.getParent().getMat(self.rootNp) bnds.xform(mat) allBnds.append(bnds) allCntr += bnds.getCenter() # Now create a bounding sphere at the center point of all the # NodePaths and extend it to encapsulate each one. bnds = pm.BoundingSphere(pm.Point3(allCntr / len(nps)), 0) for bnd in allBnds: bnds.extendBy(bnd) # Move the camera and the target the the bounding sphere's center. self.target.setPos(bnds.getCenter()) self.setPos(bnds.getCenter()) # Now move the camera back so the view accomodates all NodePaths. # Default the bounding radius to something reasonable if the object # has no size. fov = self.GetLens().getFov() radius = bnds.getRadius() or 0.5 dist = radius / math.tan(math.radians(min(fov[0], fov[1]) * 0.5)) self.setY(self, -dist)
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 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 __init__(self, avatar, offset=P.Point3.zero(), dist=10, rot=20, zoom=(30, 400), pitch=(-15, 0)): # Disable default camera interface. base.disableMouse() # Set parameters self.zoomLvl = dist #camera starting distance self.speed = 1.0 / rot # Controls speed of camera rotation. self.zoomClamp = zoom #clamp zoom in this range self.clampP = pitch #clamp pitch in this range self.target = avatar.attachNewNode('camera target') self.target.setPos(offset) #offset target from avatar. #Load the camera self.__loadCamera() #Enable new camera interface self.accept('arrow_up', self.cameraZoom, [0.7]) #Translated. For zooming. self.accept('arrow_down', self.cameraZoom, [1.3]) self.accept('arrow_left', self.rotateCam, [P.Point2(-10, 0)]) self.accept('arrow_right', self.rotateCam, [P.Point2(10, 0)]) taskMgr.add(self.mousecamTask, "mousecamTask") #For edge screen tracking
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 Set( self, dirPath ): # Check project definition file exists if not os.path.exists( os.path.join( dirPath, PROJECT_DEF_NAME ) ): self.path = None return # Set the project directory oldPath = self.path self.path = dirPath # Clear the model search path and add the new project path. Make sure # to prepend the new directory or else Panda might search in-built # paths first and supply the incorrect model. base.ResetModelPath() modelPath = pm.Filename.fromOsSpecific( self.path ) pm.getModelPath().prependDirectory( modelPath ) # Remove the old project path from sys.path and add the new one if oldPath in sys.path: sys.path.remove( oldPath ) sys.path.insert( 0, self.path ) # Set paths self.SetDirectories() # Set directory watcher root path and start it self.dirWatcher.setDirectory( self.path ) if not self.dirWatcher.running: self.dirWatcher.start()
def mousecamTask(self, task): """Rotate camera when the pointer moves to the edges of the screen. Also temporarily zooms in past an obstructing CameraM'ed object.""" self.setDist(self.zoomLvl) #preset dist to current zoom level. if self.Q.getNumEntries() > 0: #if there was a collision self.Q.sortEntries() #so we get the closest collision to avatar point = self.Q.getEntry(0).getSurfacePoint( self.target) #get the point if point.lengthSquared() < camera.getPos().lengthSquared( ): #not out. self.setDist(point.length()) #Temporarily zoom to point. camera.lookAt(self.target) # always point camera at target if not base.mouseWatcherNode.hasMouse( ): #See if the mouse is available. return Task.cont #if no, just loop again. # Get the relative mouse position, its always between 1 and -1 mpos = base.mouseWatcherNode.getMouse() if mpos.getX() > 0.99: self.rotateCam(P.Point2(-10, 0)) elif mpos.getX() < -0.99: self.rotateCam(P.Point2(10, 0)) if mpos.getY() > 0.9: self.rotateCam(P.Point2(0, -3)) elif mpos.getY() < -0.9: self.rotateCam(P.Point2(0, 3)) return Task.cont #loop again.
def __init__(self, *args, **kwargs): PrimitiveNPO.__init__(self, *args, **kwargs) self._radius = 1 self._height = 2 self._numSegs = 16 self._degrees = 360 self._axis = pm.Vec3(0, 0, 1) self._origin = pm.Point3(0, 0, 0)
def Line(start, end, thickness=1.0): """Return a geom node representing a simple line.""" # Create line segments ls = pm.LineSegs() ls.setThickness(thickness) ls.drawTo(pm.Point3(start)) ls.drawTo(pm.Point3(end)) # Return the geom node return ls.create()
def makeQuad(renderVP, collisionVP, bl=None, tr=None, br=None, tl=None): """Return a tuple of EggPolygons (renderQuad,collisionQuad): renderable and collision geometry for a 4-vertex polygon. Keyword arguments: renderVP -- EggVertexPool to which vertices will be added for the renderable quad collisionVP -- EggVertexPool to which vertices will be added for the collidable quad bl -- bottom-left vertex of quad (Point3D). Default (-10,-10,0) tr -- top-right vertex of quad (Point3D). Default (10,10,0) br -- bottom-right vertex of quad (Point3D) tl -- top-left vertex of quad (Point3D) If either of br or tl is None then sensible defaults will be computed according to the values of bl and tr. """ if bl is None: bl = P.Point3D(-10, -10, 0) if tr is None: tr = P.Point3D(10, 10, 0) if br is None: l = tr.getX() - bl.getX() br = bl + P.Vec3D(l, 0, 0) if tl is None: w = tr.getY() - bl.getY() tl = bl + P.Vec3D(0, w, 0) renderQuad = P.EggPolygon() collisionQuad = P.EggPolygon() for corner in [bl, br, tr, tl]: vertex = P.EggVertex() vertex.setPos(corner) collisionVertex = P.EggVertex() collisionVertex.setPos(corner) renderQuad.addVertex(renderVP.addVertex(vertex)) collisionQuad.addVertex(collisionVP.addVertex(collisionVertex)) # A bug in Panda3D means that auto-triangulation of concave polygons # fails for some combinations of vertices (the polygon is not properly # transformed into triangles) creating gaps in a model where polygons are # missing. We can check for this failure by calling # EggPolygon.triangulateInto() and checking its return value. If False is # returned we reverse the vertex order of the polygon (so it now faces # downward instead of up) and reverse the backface flag so the downside # (which is now facing up) is rendered instead of the upside (which is now # facing down). The result looks more or less the same as if the polygon # had triangulated correctly in the first place (except the shading will be # different). Thanks to ynjh_jo for this workaround. egn = P.EggGroupNode( ) # triangulateInto() stores the resulting polygons in # an EggGroupNode, which we discard, we only care # about the True or False return value if not renderQuad.triangulateInto(egn, 0): # Triangulation failed, fix it. renderQuad.reverseVertexOrdering() renderQuad.setBfaceFlag(1) collisionQuad.reverseVertexOrdering() collisionQuad.setBfaceFlag(1) renderQuad.recomputePolygonNormal() # Use faceted not smoothed lighting return renderQuad, collisionQuad
def SetupRenderMask(self): """ Set the draw mask for the render node to be visible to all cameras. Since we are adjusting the draw mask of the render node's parent we need to manually set this node's mask or it will inherit those properties. """ showMask = pm.BitMask32().allOn() hideMask = pm.BitMask32() clearMask = pm.BitMask32() render.node().adjustDrawMask(showMask, hideMask, clearMask)
def GetEditorRenderMasks(self): """ Return the show, hide and clear masks for objects that are to be rendered only in the editor viewport. """ show = pm.BitMask32() show.setRangeTo(True, 28, 4) hide = pm.BitMask32().allOn() hide.setRangeTo(False, 28, 4) clear = pm.BitMask32() return show, hide, clear
def __init__( self, *args, **kwargs ): Base.__init__( self, *args, **kwargs ) self._snp = False self._snpAmt = 0.5 # Create x, y, z and camera normal axes self.axes.append( self.CreateArrow( pm.Vec3(1, 0, 0), RED ) ) self.axes.append( self.CreateArrow( pm.Vec3(0, 1, 0), GREEN ) ) self.axes.append( self.CreateArrow( pm.Vec3(0, 0, 1), BLUE ) ) #self.axes.append( self.CreateArrow( pm.Vec3(1, 1, 0), YELLOW ) ) #self.axes.append( self.CreateArrow( pm.Vec3(-2, 1, 0), TEAL ) ) self.axes.append( self.CreateSquare( pm.Vec3(0, 0, 0), TEAL ) )
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 OnNodeMouse1Down( self, planar, collEntry ): Base.OnNodeMouse1Down( self, planar, collEntry ) self._s = pm.Vec3( 0 ) # If in planar mode, clear the billboard effect on the center square # and make it face the selected axis axis = self.GetSelectedAxis() if self.planar and not axis.planar: self.square.clearBillboard() self.square.lookAt( self, pm.Point3( axis.vector ) ) else: self.square.setHpr( pm.Vec3(0, 0, 0) ) self.square.setBillboardPointEye()
def __init__(self, *args, **kwargs): Base.__init__(self, *args, **kwargs) self.AddAttributes(Attr('Origin', pm.Point3, CR.getOrigin, CR.setOrigin, initDefault=pm.Point3(0)), Attr('Direction', pm.Vec3, CR.getDirection, CR.setDirection, initDefault=pm.Vec3(0, 0, 1)), parent='CollisionRay')
def privGotSpec(self, levelSpec): DistCogdoLevelGame.privGotSpec(self, levelSpec) levelMgr = self.getEntity(LevelConstants.LevelMgrEntId) self.endVault = levelMgr.geom self.endVault.reparentTo(self.geomRoot) # Clear out unneeded backstage models from the EndVault, if # they're in the file. self.endVault.findAllMatches('**/MagnetArms').detach() self.endVault.findAllMatches('**/Safes').detach() self.endVault.findAllMatches('**/MagnetControlsAll').detach() # Flag the collisions in the end vault so safes and magnets # don't try to go through the wall. cn = self.endVault.find('**/wallsCollision').node() cn.setIntoCollideMask(OTPGlobals.WallBitmask | ToontownGlobals.PieBitmask | (PM.BitMask32.lowerOn(3) << 21)) # Find all the wall polygons and replace them with planes, # which are solid, so there will be zero chance of safes or # toons slipping through a wall. walls = self.endVault.find('**/RollUpFrameCillison') walls.detachNode() self.evWalls = self.replaceCollisionPolysWithPlanes(walls) self.evWalls.reparentTo(self.endVault) # Initially, these new planar walls are stashed, so they don't # cause us trouble in the intro movie or in battle one. We # will unstash them when we move to battle three. self.evWalls.stash() # Also replace the floor polygon with a plane, and rename it # so we can detect a collision with it. floor = self.endVault.find('**/EndVaultFloorCollision') floor.detachNode() self.evFloor = self.replaceCollisionPolysWithPlanes(floor) self.evFloor.reparentTo(self.endVault) self.evFloor.setName('floor') # Also, put a big plane across the universe a few feet below # the floor, to catch things that fall out of the world. plane = PM.CollisionPlane( PM.Plane(PM.Vec3(0, 0, 1), PM.Point3(0, 0, -50))) planeNode = PM.CollisionNode('dropPlane') planeNode.addSolid(plane) planeNode.setCollideMask(ToontownGlobals.PieBitmask) self.geomRoot.attachNewNode(planeNode)
def __loadCamera(self): """Only seperate for organisation, treat it as is part of __init__() . Load the camera & setup segmet & queue for detecting obstructions.""" #Don't rotate the target with the avatar. self.target.node().setEffect(P.CompassEffect.make(render)) camera.reparentTo(self.target) # Attach the camera to target. camera.setPos(0, -self.zoomLvl, 50) # Position the camera self.rotateCam(P.Point2(0, 0)) # Initialize gimbal clamps. self.Q = P.CollisionHandlerQueue() # New queue for camera. self.segment = fromCol( self.target, self.Q, P.CollisionSegment(P.Point3.zero(), camera.getPos(self.target)), P.BitMask32( CameraM)) #CameraM into segment between camera & target.
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 __init__(self, name, view, up, res): self.name = name # A camera, for viewing the world under render. self.camNode = pcore.Camera('cam' + self.name) self.camNode.setScene(base.render) self.cam = cubeCam.attachNewNode(self.camNode) # A projector, for projecting the generated image of the world # onto our screen. self.projNode = pcore.LensNode('proj' + self.name) self.proj = screens.attachNewNode(self.projNode) # A perspective lens, for both of the above. The same lens is # used both to film the world and to project it onto the # screen. self.lens = pcore.PerspectiveLens() self.lens.setFov(92) self.lens.setNear(0.1) self.lens.setFar(10000) self.lens.setViewVector(view[0], view[1], view[2], up[0], up[1], up[2]) self.camNode.setLens(self.lens) self.projNode.setLens(self.lens) # Now the projection screen itself, which is tied to the # projector. self.psNode = PandaModules.ProjectionScreen('ps' + self.name) self.ps = self.proj.attachNewNode(self.psNode) self.psNode.setProjector(self.proj) # Generate a flat, rectilinear mesh to project the image onto. self.psNode.regenerateScreen(self.proj, "screen", res[0], res[1], 10, 0.97)
def create_lights(self): # function for converting cylindrical coordinates to cartesian # coordinates rtz2xyz = lambda r, t, z: (r * np.cos(t), r * np.sin(t), z) # positions for point lights plight_pos = [ rtz2xyz(1.5, 4 * np.pi / 12., 0), rtz2xyz(1.5, 12 * np.pi / 12., 0), rtz2xyz(1.5, 20 * np.pi / 12., 0), (0, 0, 1.3), ] # create point lights self.plights = p3d.NodePath("plights") for i, pos in enumerate(plight_pos): plight = pm.PointLight('plight%d' % i) plight.setColor((0.5, 0.5, 0.5, 1.0)) plight.setAttenuation((0, 0, 0.5)) plnp = self.plights.attachNewNode(plight) plnp.setPos(pos) self.render.setLight(plnp) self.plights.reparentTo(self.lights) self.plights.setPos(0, 0, 4 / 3.) # update the position and color of the spotlight slnp = self.lights.find('slight') slnp.setPos((8, 6, 20)) slnp.lookAt(self.look_at) slnp.node().setColor((1, 1, 1, 1)) # update the color of the ambient light alnp = self.lights.find('alight') alnp.node().setColor((0.2, 0.2, 0.2, 1))
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 start_new_thread(function, args, kwargs={}, name=None): def threadFunc(threadId, function=function, args=args, kwargs=kwargs): try: try: function(*args, **kwargs) except SystemExit: pass finally: _remove_thread_id(threadId) global _nextThreadId _threadsLock.acquire() try: threadId = _nextThreadId _nextThreadId += 1 if name is None: name = 'PythonThread-%s' % (threadId) thread = pm.PythonThread(threadFunc, [threadId], name, name) thread.setPythonData(threadId) _threads[threadId] = (thread, {}, None) thread.start(pm.TPNormal, False) return threadId finally: _threadsLock.release()
def __init__(self, *args, **kwargs): PrimitiveNPO.__init__(self, *args, **kwargs) self._width = 1 self._depth = 1 self._height = 1 self._origin = pm.Point3(0, 0, 0)
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 _Snap( self, vec ): if vec.length(): snpLen = ROUND_TO( vec.length(), self._snpAmt ) snapVec = vec / vec.length() * snpLen return snapVec else: return pm.Vec3( 0 )
def GetRelModelPath( self, pandaPath ): """ Attempt to find the indicated file path on one of the model search paths. If found then return a path relative to it. Also make sure to remove all extensions so we can load both egg and bam files. """ relPath = pm.Filename( pandaPath ) index = relPath.findOnSearchpath( pm.getModelPath().getValue() ) if index >= 0: basePath = pm.getModelPath().getDirectories()[index] relPath.makeRelativeTo( basePath ) # Remove all extensions modelPath = str( relPath ) while True: modelPath, ext = os.path.splitext( modelPath ) if not ext: break return modelPath
def setP3DFilename(self, p3dFilename, tokens, argv, instanceId, interactiveConsole, p3dOffset = 0): """ Called by the browser to specify the p3d file that contains the application itself, along with the web tokens and/or command-line arguments. Once this method has been called, the application is effectively started. """ # One day we will have support for multiple instances within a # Python session. Against that day, we save the instance ID # for this instance. self.instanceId = instanceId self.tokens = tokens self.argv = argv # We build up a token dictionary with care, so that if a given # token appears twice in the token list, we record only the # first value, not the second or later. This is consistent # with the internal behavior of the core API. self.tokenDict = {} for token, keyword in tokens: self.tokenDict.setdefault(token, keyword) # Also store the arguments on sys, for applications that # aren't instance-ready. sys.argv = argv # That means we now know the altHost in effect. self.altHost = self.tokenDict.get('alt_host', None) # Tell the browser that Python is up and running, and ready to # respond to queries. self.notifyRequest('onpythonload') # Now go load the applet. fname = Filename.fromOsSpecific(p3dFilename) vfs = VirtualFileSystem.getGlobalPtr() if not vfs.exists(fname): raise ArgumentError, "No such file: %s" % (p3dFilename) fname.makeAbsolute() mf = Multifile() if p3dOffset == 0: if not mf.openRead(fname): raise ArgumentError, "Not a Panda3D application: %s" % (p3dFilename) else: if not mf.openRead(fname, p3dOffset): raise ArgumentError, "Not a Panda3D application: %s at offset: %s" % (p3dFilename, p3dOffset) # Now load the p3dInfo file. self.p3dInfo = None self.p3dPackage = None self.p3dConfig = None self.allowPythonDev = False i = mf.findSubfile('p3d_info.xml') if i >= 0 and hasattr(PandaModules, 'readXmlStream'): stream = mf.openReadSubfile(i) self.p3dInfo = PandaModules.readXmlStream(stream) mf.closeReadSubfile(stream) if self.p3dInfo: self.p3dPackage = self.p3dInfo.FirstChildElement('package') if self.p3dPackage: self.p3dConfig = self.p3dPackage.FirstChildElement('config') xhost = self.p3dPackage.FirstChildElement('host') while xhost: self.__readHostXml(xhost) xhost = xhost.NextSiblingElement('host') if self.p3dConfig: allowPythonDev = self.p3dConfig.Attribute('allow_python_dev') if allowPythonDev: self.allowPythonDev = int(allowPythonDev) guiApp = self.p3dConfig.Attribute('gui_app') if guiApp: self.guiApp = int(guiApp) trueFileIO = self.p3dConfig.Attribute('true_file_io') if trueFileIO: self.trueFileIO = int(trueFileIO) # The interactiveConsole flag can only be set true if the # application has allow_python_dev set. if not self.allowPythonDev and interactiveConsole: raise StandardError, "Impossible, interactive_console set without allow_python_dev." self.interactiveConsole = interactiveConsole if self.allowPythonDev: # Set the fps text to remind the user that # allow_python_dev is enabled. ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps') if self.guiApp: initAppForGui() self.initPackedAppEnvironment() # Mount the Multifile under self.multifileRoot. vfs.mount(mf, self.multifileRoot, vfs.MFReadOnly) VFSImporter.reloadSharedPackages() self.loadMultifilePrcFiles(mf, self.multifileRoot) self.gotP3DFilename = True # Send this call to the main thread; don't call it directly. messenger.send('AppRunner_startIfReady', taskChain = 'default')
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
import os import os.path from panda3d.core import Filename from pandac import PandaModules as PM #set up some loading constants DIR = str(Filename.fromOsSpecific(os.path.dirname(os.path.abspath(__file__)))) #convert back to base string from panda type ASSET_DIR = DIR + "/assets/" PM.getModelPath().appendPath(ASSET_DIR) class TextureManager(object): def __init__(self, app): self.rocks = app.loader.loadTexture('rocks.png') for icon in ['arrow_out', 'asterisk_orange', 'bug', 'user']: setattr(self, icon, app.loader.loadTexture('icons/' + icon + '.png')) TEXTURES = None def init(app): global TEXTURES TEXTURES = TextureManager(app)