def togglePerPixelLighting(self): if self.perPixelEnabled: self.perPixelEnabled = False if self.shadowsEnabled: self.shadowsEnabled = False self.light.setShadowCaster(False) # self.light2.setShadowCaster(False) render().clearShader() else: self.perPixelEnabled = True render().setShaderAuto() self.updateStatusLabel()
def _mouseTask(self, task): # This task deals with the highlighting and dragging based on the mouse # First, clear the current highlight if self.hiSq is not False: self.squares[self.hiSq].setColor(SquareColour(self.hiSq)) self.hiSq = False # Check to see if we can access the mouse. We need it to do anything else if base().mouseWatcherNode.hasMouse(): # get the mouse position mpos = base().mouseWatcherNode.getMouse() # Set the position of the ray based on the mouse position base().pickerRay.setFromLens(base().camNode, mpos.getX(), mpos.getY()) # If we are dragging something, set the position of the object # to be at the appropriate point over the plane of the board if self.dragging is not False: # Gets the point described by pickerRay.getOrigin(), which is relative to # camera, relative instead to render nearPoint = render().getRelativePoint( base().camera, base().pickerRay.getOrigin()) # Same thing with the direction of the ray nearVec = render().getRelativeVector( base().camera, base().pickerRay.getDirection()) self.pieces[self.dragging].obj.setPos( PointAtZ(.5, nearPoint, nearVec)) # Do the actual collision pass (Do it only on the squares for efficiency purposes) base().picker.traverse(self.squareRoot) if base().pq.getNumEntries() > 0: # if we have hit something, sort the hits so that the closest is first, and highlight that node base().pq.sortEntries() i = int(base().pq.getEntry(0).getIntoNode().getTag('square')) # Set the highlight on the picked square self.squares[i].setColor(HIGHLIGHT) self.hiSq = i return Task.cont
def makeForrest(self): self.forest = p3dc.NodePath(p3dc.PandaNode("Forest Root")) self.forest.reparentTo(render()) #self.forest.hide(p3dc.BitMask32(self.lightMask | self.plainMask)) loader().loadModel([ "fireflies_models/background", "fireflies_models/foliage01", "fireflies_models/foliage02", "fireflies_models/foliage03", "fireflies_models/foliage04", "fireflies_models/foliage05", "fireflies_models/foliage06", "fireflies_models/foliage07", "fireflies_models/foliage08", "fireflies_models/foliage09" ], callback=self.finishLoadingForrest)
def __init__(self, square, colour): self.obj = loader().loadModel(self.model) self.obj.reparentTo(render()) self.obj.setColor(colour) self.obj.setPos(SquarePos(square))
def setupLights( self ): # This function sets up some default lighting with simple shadows #ambientLight = p3dc.AmbientLight("ambientLight") #ambientLight.setColor((.8, .8, .8, 1)) #directionalLight = p3dc.DirectionalLight("directionalLight") #directionalLight.setDirection(p3dc.LVector3(0, 45, -45)) #directionalLight.setColor((0.2, 0.2, 0.2, 1)) #render().setLight(render().attachNewNode(directionalLight)) #render().setLight(render().attachNewNode(ambientLight)) # Shadows self.light = p3dc.Spotlight("Spot") self.light_node = render().attachNewNode( self.light) # generates instance of p3dc.NodePath self.light.setScene(render()) self.light.setShadowCaster(True, 1024 * 4, 1024 * 4) #.setShadowCaster(True) #self.light.showFrustum() # This exponent value sets how soft the edge of the spotlight is. # 0 means a hard edge. 128 means a very soft edge. #self.light.setExponent(60.0) # Attenuation controls how the light fades with distance. # The three values represent the three attenuation constants (constant, linear and quadratic) # in the internal lighting equation. The higher the numbers the shorter the light goes. self.light.setAttenuation(p3dc.LVector3(0.3, 0.0, 0.0)) # The cone of a spotlight is controlled by it's lens. This creates the lens self.light.setLens(p3dc.PerspectiveLens()) # This sets the Field of View (fov) of the lens, in degrees for width # and height. The lower the numbers, the tighter the spotlight. self.light.getLens().setFov(40, 40) #self.light.getLens().setFov(40) self.light.getLens().setNearFar(0.5, 500) self.light.setColor((0.6, 0.6, 0.8, 1)) ############################################################ ####\/########\/########\/########\/########\/########\/#### #self.light_node.setPosHpr(0, -10, 15, 0, -50, 0) #This does not light the tiles... (similar to https://discourse.panda3d.org/t/shadows-with-directional-light-source-strange-behaviour/10025 ) #self.light_node.setPosHpr(0, 10, 15, 180, -50, 0) #This works as intended #self.light_node.setPosHpr(0, 0, 8, 0, -80, 0) #This lights half the tiles but I don't know why this works to a degree but the first one doesn't at all self.light_node.setPosHpr(0, 8, 12, 180, -50, 0) #This is now used ####/\########/\########/\########/\########/\########/\#### ############################################################ render().setLight(self.light_node) # # # #self.light2 = p3dc.Spotlight("Spot") #self.light2_node = render().attachNewNode(self.light2) # generates instance of p3dc.NodePath #self.light2.setScene(render()) #self.light2.setShadowCaster(True, 1024, 1024)#.setShadowCaster(True) ##self.light.showFrustum() ## This exponent value sets how soft the edge of the spotlight is. ## 0 means a hard edge. 128 means a very soft edge. #self.light2.setExponent(60.0) ## Attenuation controls how the light fades with distance. ## The three values represent the three attenuation constants (constant, linear and quadratic) ## in the internal lighting equation. The higher the numbers the shorter the light goes. #self.light2.setAttenuation(p3dc.LVector3(0.3, 0.0, 0.0)) ## The cone of a spotlight is controlled by it's lens. This creates the lens #self.light2.setLens(p3dc.PerspectiveLens()) ## This sets the Field of View (fov) of the lens, in degrees for width ## and height. The lower the numbers, the tighter the spotlight. #self.light2.getLens().setFov(40, 40) ##self.light2.getLens().setFov(40) #self.light2.getLens().setNearFar(0.5, 50) #self.light2.setColor((0.6, 0.6, 0.8, 1)) #self.light2_node.setPosHpr(0, -10, 15, 0, -50, 0) #render().setLight(self.light2_node) self.alight = render().attachNewNode(p3dc.AmbientLight("Ambient")) self.alight.node().setColor(p3dc.LVector4(0.1, 0.1, 0.1, 1)) render().setLight(self.alight) # Important! Enable the shader generator. render().setShaderAuto()
def start(self): self.setupLights() # Setup default lighting # Now we create the chess board and its pieces # We will attach all of the squares to their own root. This way we can do the # collision pass just on the squares and save the time of checking the rest of the scene self.squareRoot = render().attachNewNode("squareRoot") self.squareRoot.setPos((0, 0, 0)) # For each square self.squares = [None for i in range(64)] self.pieces = [None for i in range(64)] for i in range(64): # Load, parent, colour and position the model (a single square polygon) self.squares[i] = loader().loadModel("chessboard_models/square") self.squares[i].reparentTo(self.squareRoot) self.squares[i].setPos(SquarePos(i)) self.squares[i].setColor(SquareColour(i)) # Set the model itself to be collideable with the ray. If this model was # any more complex than a single polygon, you should set up a collision # sphere around it instead. But for single polygons this works fine. self.squares[i].find("**/polygon").node().setIntoCollideMask( p3dc.BitMask32.bit(1)) # Set a tag on the square's node so we can look up what square this is later during the collision pass self.squares[i].find("**/polygon").node().setTag('square', str(i)) # We will use this variable as a pointer to whatever piece is currently in this square # The order of pieces on a chessboard from white's perspective. This list # contains the constructor functions for the piece classes defined below pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook) for i in range(8, 16): # Load the white pawns self.pieces[i] = Pawn(i, WHITE) for i in range(48, 56): # load the black pawns self.pieces[i] = Pawn(i, PIECEBLACK) for i in range(8): # Load the special pieces for the front row and colour them white self.pieces[i] = pieceOrder[i](i, WHITE) # Load the special pieces for the back row and colour them black self.pieces[i + 56] = pieceOrder[i](i + 56, PIECEBLACK) # This will represent the index of the currently highlighted square self.hiSq = False # This wil represent the index of the square where currently dragged piece was grabbed from self.dragging = False # Per-pixel lighting and shadows are initially on self.perPixelEnabled = True self.shadowsEnabled = True # This code puts the standard title and instruction text on screen self.mouseText = self.makeStatusLabel(0) self.mouseText.setText("Left-click and drag: Pick up and drag piece") self.spaceText = self.makeStatusLabel(1) self.spaceText.setText("SPACE: Cycle camera positions") self.lightingPerPixelText = self.makeStatusLabel(2) self.lightingShadowsText = self.makeStatusLabel(3) # Finally call the function that builds the instruction texts self.updateStatusLabel() # Start the task that handles the picking self.mouseTask = base().taskMgr.add(self._mouseTask, 'mouseTask') base().accept("mouse1", self.grabPiece) # left-click grabs a piece base().accept("mouse1-up", self.releasePiece) # releasing places it self.nextCamPos = 1 base().accept("space", self.toggleCam) # releasing places it base().accept("l", self.togglePerPixelLighting) base().accept("e", self.toggleShadows) self.makeForrest()