Ejemplo n.º 1
0
 def loadFlatQuad(self, fullFilename):
     cm = CardMaker("cm-%s" % fullFilename)
     cm.setColor(1.0, 1.0, 1.0, 1.0)
     aspect = base.camLens.getAspectRatio()
     htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH)
     htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT)
     cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0)
     bottomRightX = WEB_WIDTH_PIXELS / float(WEB_WIDTH + 1)
     bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1)
     cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1))
     card = cm.generate()
     quad = NodePath(card)
     jpgFile = PNMImage(WEB_WIDTH, WEB_HEIGHT)
     smallerJpgFile = PNMImage()
     readFile = smallerJpgFile.read(Filename(fullFilename))
     if readFile:
         jpgFile.copySubImage(smallerJpgFile, 0, 0)
         guiTex = Texture("guiTex")
         guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba)
         guiTex.setMinfilter(Texture.FTLinear)
         guiTex.load(jpgFile)
         guiTex.setWrapU(Texture.WMClamp)
         guiTex.setWrapV(Texture.WMClamp)
         ts = TextureStage("webTS")
         quad.setTexture(ts, guiTex)
         quad.setTransparency(0)
         quad.setTwoSided(True)
         quad.setColor(1.0, 1.0, 1.0, 1.0)
         result = quad
     else:
         result = None
     Texture.setTexturesPower2(1)
     return result
Ejemplo n.º 2
0
 def loadFlatQuad(self, fullFilename):
     cm = CardMaker('cm-%s' % fullFilename)
     cm.setColor(1.0, 1.0, 1.0, 1.0)
     aspect = base.camLens.getAspectRatio()
     htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH)
     htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT)
     cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0,
                 htmlHeight / 2.0)
     bottomRightX = WEB_WIDTH_PIXELS / float(WEB_WIDTH + 1)
     bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1)
     cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1))
     card = cm.generate()
     quad = NodePath(card)
     jpgFile = PNMImage(WEB_WIDTH, WEB_HEIGHT)
     smallerJpgFile = PNMImage()
     readFile = smallerJpgFile.read(Filename(fullFilename))
     if readFile:
         jpgFile.copySubImage(smallerJpgFile, 0, 0)
         guiTex = Texture('guiTex')
         guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1,
                             Texture.TUnsignedByte, Texture.FRgba)
         guiTex.setMinfilter(Texture.FTLinear)
         guiTex.load(jpgFile)
         guiTex.setWrapU(Texture.WMClamp)
         guiTex.setWrapV(Texture.WMClamp)
         ts = TextureStage('webTS')
         quad.setTexture(ts, guiTex)
         quad.setTransparency(0)
         quad.setTwoSided(True)
         quad.setColor(1.0, 1.0, 1.0, 1.0)
         result = quad
     else:
         result = None
     Texture.setTexturesPower2(1)
     return result
Ejemplo n.º 3
0
    def loadFlatQuad(self, fullFilename):
        """Load the flat jpg into a quad."""
        assert self.notify.debugStateCall(self)
        #Texture.setTexturesPower2(AutoTextureScale.ATSUp)
        #Texture.setTexturesPower2(2)
        
        cm = CardMaker('cm-%s'%fullFilename)
        cm.setColor(1.0, 1.0, 1.0, 1.0)
        aspect = base.camLens.getAspectRatio()
        htmlWidth = 2.0*aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH)		
        htmlHeight = 2.0*float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT) 

        # the html area will be center aligned and vertically top aligned
        #cm.setFrame(-htmlWidth/2.0, htmlWidth/2.0, 1.0 - htmlHeight, 1.0)
        cm.setFrame(-htmlWidth/2.0, htmlWidth/2.0, - htmlHeight / 2.0, htmlHeight / 2.0)

        bottomRightX = (WEB_WIDTH_PIXELS) / float( WEB_WIDTH +1)
        bottomRightY = WEB_HEIGHT_PIXELS / float (WEB_HEIGHT+1)

        #cm.setUvRange(Point2(0,0), Point2(bottomRightX, bottomRightY))
        cm.setUvRange(Point2(0,1-bottomRightY), Point2(bottomRightX,1))
        
        card = cm.generate()
        quad = NodePath(card)
        #quad.reparentTo(self.parent)

        jpgFile = PNMImage(WEB_WIDTH, WEB_HEIGHT)
        smallerJpgFile = PNMImage()
        readFile = smallerJpgFile.read(Filename(fullFilename))
        if readFile:
            jpgFile.copySubImage(smallerJpgFile, 0, 0)

            guiTex = Texture("guiTex")
            guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba)
            guiTex.setMinfilter(Texture.FTLinear)
            guiTex.load(jpgFile)
            #guiTex.setKeepRamImage(True)		
            #guiTex.makeRamImage()				
            guiTex.setWrapU(Texture.WMClamp)
            guiTex.setWrapV(Texture.WMClamp)

            ts = TextureStage('webTS')
            quad.setTexture(ts, guiTex)
            #quad.setTexScale(ts, 1.0, -1.0)

            quad.setTransparency(0)
            quad.setTwoSided(True)
            quad.setColor(1.0, 1.0, 1.0, 1.0)
            result= quad
        else:
            # if we have an error loading the file, return None to signify an error
            result = None

        #Texture.setTexturesPower2(AutoTextureScale.ATSDown)
        Texture.setTexturesPower2(1)
        return result
Ejemplo n.º 4
0
  def make_data(self, hmapfile):
    # open heightmap for reading pixel data
    heightmap = PNMImage()
    heightmap.read(Filename(hmapfile))
    xs = heightmap.getXSize()
    ys = heightmap.getYSize()

    # generate data bi-dimensional array
    data = []
    for x in range(xs):
      data.append([])
      for y in range(ys):
        # set data dictionary properties
        # name
        name = "cell_" + str(x) + "_" + str(y)
        # height
        height = (heightmap.getXel(x, ys - y - 1)[0] * 10)

        if self.retro == True:
          if height < 1 :
            height = height / 5
            height = int(height)
        # c and rgb
        c = [random.random(), random.random(), random.random()]
        rgb = (int(c[0] * 255), int(c[1] * 255), int(c[2] * 255))
        # default texture
        texture = self.tiles[0]['tex']
        texturenum = 0
        score = self.tiles[0]['score']

        # from rgb we assign tex and score
        for n in range(len(self.tiles)):
          if rgb == self.tiles[n]['rgb']:
            texture = self.tiles[n]['tex']
            texturenum = n
            score = self.tiles[n]['score']
            break

        # set terrain data dictionary
        data[x].append({'name':name, 'h':height, 'c':c, 'rgb':rgb, 'tex':texture,
                        'texnum':texturenum, 'score':score})
    return data
Ejemplo n.º 5
0
    def fromImageFile(self,
                      filename,
                      tolerance=2,
                      max_depth=5,
                      debugOutput=False):
        # the source image
        img = PNMImage()

        if not img.read(Filename(filename)):
            self.log.error('Failed to read %s' % filename)
            return None
Ejemplo n.º 6
0
    def __init__(self, image_path, rowPerFace, name=None,\
         rows=1, cols=1, scale=1.0,\
         twoSided=False, alpha=TRANS_ALPHA,\
         repeatX=1, repeatY=1,\
         anchorX=ALIGN_CENTER, anchorY=ALIGN_BOTTOM):
        """
		Create a card textured with an image. The card is sized so that the ratio between the
		card and image is the same.
		"""

        global SpriteId
        self.spriteNum = str(SpriteId)
        SpriteId += 1

        scale *= self.PIXEL_SCALE

        self.animations = {}

        self.scale = scale
        self.repeatX = repeatX
        self.repeatY = repeatY
        self.flip = {'x': False, 'y': False}
        self.rows = rows
        self.cols = cols

        self.currentFrame = 0
        self.currentAnim = None
        self.loopAnim = False
        self.frameInterrupt = True

        # Create the NodePath
        if name:
            self.node = NodePath("Sprite2d:%s" % name)
        else:
            self.node = NodePath("Sprite2d:%s" % image_path)

        # Set the attribute for transparency/twosided
        self.node.node().setAttrib(TransparencyAttrib.make(alpha))
        if twoSided:
            self.node.setTwoSided(True)

        # Make a filepath
        self.imgFile = Filename(image_path)
        if self.imgFile.empty():
            raise IOError, "File not found"

        # Instead of loading it outright, check with the PNMImageHeader if we can open
        # the file.
        imgHead = PNMImageHeader()
        if not imgHead.readHeader(self.imgFile):
            raise IOError, "PNMImageHeader could not read file. Try using absolute filepaths"

        # Load the image with a PNMImage
        image = PNMImage()
        image.read(self.imgFile)

        self.sizeX = image.getXSize()
        self.sizeY = image.getYSize()

        # We need to find the power of two size for the another PNMImage
        # so that the texture thats loaded on the geometry won't have artifacts
        textureSizeX = self.nextsize(self.sizeX)
        textureSizeY = self.nextsize(self.sizeY)

        # The actual size of the texture in memory
        self.realSizeX = textureSizeX
        self.realSizeY = textureSizeY

        self.paddedImg = PNMImage(textureSizeX, textureSizeY)
        if image.hasAlpha():
            self.paddedImg.alphaFill(0)
        # Copy the source image to the image we're actually using
        self.paddedImg.blendSubImage(image, 0, 0)
        # We're done with source image, clear it
        image.clear()

        # The pixel sizes for each cell
        self.colSize = self.sizeX / self.cols
        self.rowSize = self.sizeY / self.rows

        # How much padding the texture has
        self.paddingX = textureSizeX - self.sizeX
        self.paddingY = textureSizeY - self.sizeY

        # Set UV padding
        self.uPad = float(self.paddingX) / textureSizeX
        self.vPad = float(self.paddingY) / textureSizeY

        # The UV dimensions for each cell
        self.uSize = (1.0 - self.uPad) / self.cols
        self.vSize = (1.0 - self.vPad) / self.rows

        self.cards = []
        self.rowPerFace = rowPerFace
        for i in range(len(rowPerFace)):
            card = CardMaker("Sprite2d-Geom")

            # The positions to create the card at
            if anchorX == self.ALIGN_LEFT:
                posLeft = 0
                posRight = (self.colSize / scale) * repeatX
            elif anchorX == self.ALIGN_CENTER:
                posLeft = -(self.colSize / 2.0 / scale) * repeatX
                posRight = (self.colSize / 2.0 / scale) * repeatX
            elif anchorX == self.ALIGN_RIGHT:
                posLeft = -(self.colSize / scale) * repeatX
                posRight = 0

            if anchorY == self.ALIGN_BOTTOM:
                posTop = 0
                posBottom = (self.rowSize / scale) * repeatY
            elif anchorY == self.ALIGN_CENTER:
                posTop = -(self.rowSize / 2.0 / scale) * repeatY
                posBottom = (self.rowSize / 2.0 / scale) * repeatY
            elif anchorY == self.ALIGN_TOP:
                posTop = -(self.rowSize / scale) * repeatY
                posBottom = 0

            card.setFrame(posLeft, posRight, posTop, posBottom)
            card.setHasUvs(True)
            self.cards.append(self.node.attachNewNode(card.generate()))
            self.cards[-1].setH(i * 360 / len(rowPerFace))

        # Since the texture is padded, we need to set up offsets and scales to make
        # the texture fit the whole card
        self.offsetX = (float(self.colSize) / textureSizeX)
        self.offsetY = (float(self.rowSize) / textureSizeY)

        # self.node.setTexScale(TextureStage.getDefault(), self.offsetX * repeatX, self.offsetY * repeatY)
        # self.node.setTexOffset(TextureStage.getDefault(), 0, 1-self.offsetY)

        self.texture = Texture()

        self.texture.setXSize(textureSizeX)
        self.texture.setYSize(textureSizeY)
        self.texture.setZSize(1)

        # Load the padded PNMImage to the texture
        self.texture.load(self.paddedImg)

        self.texture.setMagfilter(Texture.FTNearest)
        self.texture.setMinfilter(Texture.FTNearest)

        #Set up texture clamps according to repeats
        if repeatX > 1:
            self.texture.setWrapU(Texture.WMRepeat)
        else:
            self.texture.setWrapU(Texture.WMClamp)
        if repeatY > 1:
            self.texture.setWrapV(Texture.WMRepeat)
        else:
            self.texture.setWrapV(Texture.WMClamp)

        self.node.setTexture(self.texture)
        self.setFrame(0)
Ejemplo n.º 7
0
	def __init__(self, image_path, rowPerFace, name=None,\
				  rows=1, cols=1, scale=1.0,\
				  twoSided=False, alpha=TRANS_ALPHA,\
				  repeatX=1, repeatY=1,\
				  anchorX=ALIGN_CENTER, anchorY=ALIGN_BOTTOM):
		"""
		Create a card textured with an image. The card is sized so that the ratio between the
		card and image is the same.
		"""

		global SpriteId
		self.spriteNum = str(SpriteId)
		SpriteId += 1

		scale *= self.PIXEL_SCALE

		self.animations = {}

		self.scale = scale
		self.repeatX = repeatX
		self.repeatY = repeatY
		self.flip = {'x':False,'y':False}
		self.rows = rows
		self.cols = cols

		self.currentFrame = 0
		self.currentAnim = None
		self.loopAnim = False
		self.frameInterrupt = True

		# Create the NodePath
		if name:
			self.node = NodePath("Sprite2d:%s" % name)
		else:
			self.node = NodePath("Sprite2d:%s" % image_path)

		# Set the attribute for transparency/twosided
		self.node.node().setAttrib(TransparencyAttrib.make(alpha))
		if twoSided:
			self.node.setTwoSided(True)

		# Make a filepath
		self.imgFile = Filename(image_path)
		if self.imgFile.empty():
			raise IOError, "File not found"

		# Instead of loading it outright, check with the PNMImageHeader if we can open
		# the file.
		imgHead = PNMImageHeader()
		if not imgHead.readHeader(self.imgFile):
			raise IOError, "PNMImageHeader could not read file. Try using absolute filepaths"

		# Load the image with a PNMImage
		image = PNMImage()
		image.read(self.imgFile)

		self.sizeX = image.getXSize()
		self.sizeY = image.getYSize()

		# We need to find the power of two size for the another PNMImage
		# so that the texture thats loaded on the geometry won't have artifacts
		textureSizeX = self.nextsize(self.sizeX)
		textureSizeY = self.nextsize(self.sizeY)

		# The actual size of the texture in memory
		self.realSizeX = textureSizeX
		self.realSizeY = textureSizeY

		self.paddedImg = PNMImage(textureSizeX, textureSizeY)
		if image.hasAlpha():
			self.paddedImg.alphaFill(0)
		# Copy the source image to the image we're actually using
		self.paddedImg.blendSubImage(image, 0, 0)
		# We're done with source image, clear it
		image.clear()

		# The pixel sizes for each cell
		self.colSize = self.sizeX/self.cols
		self.rowSize = self.sizeY/self.rows

		# How much padding the texture has
		self.paddingX = textureSizeX - self.sizeX
		self.paddingY = textureSizeY - self.sizeY

		# Set UV padding
		self.uPad = float(self.paddingX)/textureSizeX
		self.vPad = float(self.paddingY)/textureSizeY

		# The UV dimensions for each cell
		self.uSize = (1.0 - self.uPad) / self.cols
		self.vSize = (1.0 - self.vPad) / self.rows
	
		self.cards = []
		self.rowPerFace = rowPerFace
		for i in range(len(rowPerFace)):
			card = CardMaker("Sprite2d-Geom")

			# The positions to create the card at
			if anchorX == self.ALIGN_LEFT:
				posLeft = 0
				posRight = (self.colSize/scale)*repeatX
			elif anchorX == self.ALIGN_CENTER:
				posLeft = -(self.colSize/2.0/scale)*repeatX
				posRight = (self.colSize/2.0/scale)*repeatX
			elif anchorX == self.ALIGN_RIGHT:
				posLeft = -(self.colSize/scale)*repeatX
				posRight = 0

			if anchorY == self.ALIGN_BOTTOM:
				posTop = 0
				posBottom = (self.rowSize/scale)*repeatY
			elif anchorY == self.ALIGN_CENTER:
				posTop = -(self.rowSize/2.0/scale)*repeatY
				posBottom = (self.rowSize/2.0/scale)*repeatY
			elif anchorY == self.ALIGN_TOP:
				posTop = -(self.rowSize/scale)*repeatY
				posBottom = 0

			card.setFrame(posLeft, posRight, posTop, posBottom)
			card.setHasUvs(True)
			self.cards.append(self.node.attachNewNode(card.generate()))
			self.cards[-1].setH(i * 360/len(rowPerFace))

		# Since the texture is padded, we need to set up offsets and scales to make
		# the texture fit the whole card
		self.offsetX = (float(self.colSize)/textureSizeX)
		self.offsetY = (float(self.rowSize)/textureSizeY)

		# self.node.setTexScale(TextureStage.getDefault(), self.offsetX * repeatX, self.offsetY * repeatY)
		# self.node.setTexOffset(TextureStage.getDefault(), 0, 1-self.offsetY)
		
		self.texture = Texture()

		self.texture.setXSize(textureSizeX)
		self.texture.setYSize(textureSizeY)
		self.texture.setZSize(1)

		# Load the padded PNMImage to the texture
		self.texture.load(self.paddedImg)

		self.texture.setMagfilter(Texture.FTNearest)
		self.texture.setMinfilter(Texture.FTNearest)

		#Set up texture clamps according to repeats
		if repeatX > 1:
			self.texture.setWrapU(Texture.WMRepeat)
		else:
			self.texture.setWrapU(Texture.WMClamp)
		if repeatY > 1:
			self.texture.setWrapV(Texture.WMRepeat)
		else:
			self.texture.setWrapV(Texture.WMClamp)

		self.node.setTexture(self.texture)
		self.setFrame(0)
Ejemplo n.º 8
0
class Region(DirectObject.DirectObject):
    '''Stuff'''
    def __init__(self):
        self.tiles = []
        self.cities = {}
        self.accept('loadRegion', self.load)
        self.accept("updatedTiles", self.updateTiles)
        self.accept("newCity", self.newCity)
        self.accept("clickForCity", self.checkCity)
        self.accept("unfoundCity", self.unfoundCity)
        self.accept("enterCity", self.enterCity)

    def load(self, container, name="New Region"):
        '''Loads a new region, usually from connecting to a server
        Or starting a new or previously saved region.
        '''
        import base64
        self.heightmap = PNMImage()
        imageString = base64.b64decode(container.heightmap)
        self.heightmap.read(StringStream(imageString))
        self.region_size = (self.heightmap.getXSize() - 1,
                            self.heightmap.getYSize() - 1)

        position = 0
        tileid = 0
        total_tiles = self.region_size[0] * self.region_size[1]
        ranges = []
        tiles = []

        for tile in container.tiles:
            tiles.append((tile.id, tile.cityid))
        for n in range(len(tiles)):
            try:
                ranges.append((tiles[n][0], tiles[n + 1][0] - 1, tiles[n][1]))
            except:
                ranges.append((tiles[n][0], total_tiles, tiles[n][1]))
        for r in ranges:
            for x in range(r[0], r[1] + 1):
                #print "r0, r1, x", r[0], r[1], x
                self.tiles.append(Tile(tileid, r[2]))
                #print "Len", len(self.tiles)
                tileid += 1

        position = 0
        for y in range(self.region_size[1]):
            for x in range(self.region_size[0]):
                self.tiles[position].coords = (x, y)
                position += 1

        for city in container.cities:
            self.newCity(city)
        messenger.send("generateRegion",
                       [self.heightmap, self.tiles, self.cities, container])

    def updateTiles(self, container):
        x = 0
        for tile in container:
            x += 1
            self.tiles[tile.id].cityid = tile.cityid
        print x, "tiles updated from server."
        messenger.send("updateRegion",
                       [self.heightmap, self.tiles, self.cities])

    def newCity(self, city):
        self.cities[city.id] = {
            "name": city.name,
            "mayor": city.mayor,
            "funds": city.funds,
            "population": city.population
        }

    def checkCity(self, cell):
        '''Checks for city in given cell for region gui display'''
        if not cell: return
        tile = self.getTile(cell[0], cell[1])
        if tile.cityid:
            messenger.send("showRegionCityWindow",
                           [tile.cityid, self.cities[tile.cityid]])

    def getTile(self, x, y):
        '''Returns tile by coordinate. 
        Thankfully smart enough to find a way to not iterate
        '''
        value = y * self.region_size[0] + x
        return self.tiles[value]

    def unfoundCity(self, ident):
        '''Unfounds a city'''
        del self.cities[ident]

    def enterCity(self, ident):
        '''Processess information needed for graphical elements to enter city view.'''
        # We need to send list of tiles for terrain manager
        tiles = []
        xsum = 0
        ysum = 0
        n = 0
        for tile in self.tiles:
            if tile.cityid is ident:
                tiles.append(tile)
                # We need to compute center of city to target camera there
                xsum += tile.coords[0]
                ysum += tile.coords[1]
                n += 1
        xavg = xsum / n
        yavg = ysum / n
        position = (xavg, yavg)
        # We need to send city info so gui elements can be drawn
        city = self.cities[ident]
        messenger.send('enterCityView', [ident, city, position, tiles])
class TerrainTile(GeoMipTerrain):
    """TerrainTiles are the building blocks of a terrain."""
    def __init__(self, terrain, x, y):
        """Builds a Tile for the terrain at input coordinates.

        Important settings are used directly from the terrain.
        This allows for easier setting changes, and reduces memory overhead.
        x and y parameters give the appropriate world coordinates of this tile.

        """

        self.terrain = terrain
        self.xOffset = x
        self.yOffset = y
        self.heightMapDetail = 1  # higher means greater detail

        self.name = "ID" + str(terrain.id) + "_X" + str(x) + "_Y" + str(y)
        GeoMipTerrain.__init__(self, name=self.name)

        self.image = PNMImage()

        #self.setAutoFlatten(GeoMipTerrain.AFMOff)
        self.setFocalPoint(self.terrain.focus)
        self.setAutoFlatten(GeoMipTerrain.AFMOff)
        self.getRoot().setPos(x, y, 0)
        if self.terrain.bruteForce:
            GeoMipTerrain.setBruteforce(self, True)
            GeoMipTerrain.setBlockSize(
                self, self.terrain.heightMapSize * self.heightMapDetail)
        else:
            GeoMipTerrain.setBlockSize(self, self.terrain.blockSize / 2)
            #self.setBorderStitching(1)
            self.setNear(self.terrain.near)
            self.setFar(self.terrain.far)

    def update(self):
        """Updates the GeoMip to use the correct LOD on each block."""

        #logging.info("TerrainTile.update()")
        GeoMipTerrain.update(self)

    @pstat
    def updateTask(self, task):
        """Updates the GeoMip to use the correct LOD on each block."""

        self.update()
        return task.again

    #@pstat
    def setHeightField(self, filename):
        """Set the GeoMip heightfield from a heightmap image."""

        GeoMipTerrain.setHeightfield(self, filename)

    @pstat
    def generate(self):
        GeoMipTerrain.generate(self)

    @pstat
    def setHeight(self):
        """Sets the height field to match the height map image."""

        self.setHeightField(self.image)

    @pstat
    def makeHeightMap(self):
        """Generate a new heightmap image.

        Panda3d GeoMipMaps require an image from which to build and update
        their height field. This function creates the correct image using the
        tile's position and the Terrain's getHeight() function.

        """

        if SAVED_HEIGHT_MAPS:
            fileName = "maps/height/" + self.name + ".png"
            self.getRoot().setTag('EditableTerrain', '1')
            if self.image.read(Filename(fileName)):
                logging.info("read heightmap from " + fileName)
                return

        heightMapSize = self.terrain.tileSize * self.heightMapDetail + 1
        self.image = PNMImage(heightMapSize, heightMapSize, 1, 65535)

        ySize = self.image.getYSize() - 1
        getHeight = self.terrain.getHeight
        setGray = self.image.setGray
        xo = self.xOffset
        yo = self.yOffset
        d = self.heightMapDetail

        for x in range(self.image.getXSize()):
            for y in range(ySize + 1):
                height = getHeight(x / d + xo, y / d + yo)
                #  feed pixel into image
                # why is it necessary to invert the y axis I wonder?
                setGray(x, ySize - y, height)
        #self.postProcessImage()
        if SAVED_HEIGHT_MAPS:
            fileName = "maps/height/" + self.name + ".png"
            logging.info("saving heightmap to " + fileName)
            self.image.write(Filename(fileName))

    def postProcessImage(self):
        """Perform filters and manipulations on the heightmap image."""

        #self.image.gaussianFilter()

    def setWireFrame(self, state):
        self.getRoot().setRenderModeWireframe()

    def makeSlopeMap(self):

        self.slopeMap = PNMImage()
        if SAVED_SLOPE_MAPS:
            fileName = "maps/slope/" + self.name + ".png"
            if self.slopeMap.read(Filename(fileName)):
                logging.info("read slopemap from " + fileName)
                return

        self.slopeMap = PNMImage(self.terrain.heightMapSize,
                                 self.terrain.heightMapSize)
        self.slopeMap.makeGrayscale()
        self.slopeMap.setMaxval(65535)

        size = self.slopeMap.getYSize()
        getNormal = self.getNormal
        setGray = self.slopeMap.setGray

        for x in range(size):
            for y in range(size):
                #note getNormal works at the same resolution as the heightmap
                normal = getNormal(x, y)
                #  feed pixel into image
                # why is it necessary to invert the y axis I wonder?
                #logging.info( normal)
                normal.z /= self.terrain.getSz()
                normal.normalize()
                slope = 1.0 - normal.dot(Vec3(0, 0, 1))
                setGray(x, y, slope)

        if SAVED_SLOPE_MAPS:
            fileName = "maps/slope/" + self.name + ".png"
            logging.info("saving slopemap to " + fileName)
            self.slopeMap.write(Filename(fileName))

    def createGroups(self):
        self.statics = self.getRoot().attachNewNode(self.name + "_statics")
        self.statics.setSz(1.0 / self.terrain.getSz())
        self.statics.setSx(1.0 / self.terrain.getSx())
        self.statics.setSy(1.0 / self.terrain.getSy())

        self.statics.setShaderAuto()

    @pstat
    def make(self):
        """Build a finished renderable heightMap."""

        # apply shader
        #logging.info( "applying shader")
        self.terrain.texturer.apply(self.getRoot())

        # detail settings
        #self.getRoot().setSx(1.0 / self.heightMapDetail)
        #self.getRoot().setSy(1.0 / self.heightMapDetail)

        #logging.info( "making height map")
        self.makeHeightMap()
        #logging.info( "setHeight()")
        self.setHeight()
        #self.getRoot().setSz(self.maxHeight)

        #http://www.panda3d.org/forums/viewtopic.php?t=12054
        self.calcAmbientOcclusion()
        #logging.info( "generate()")
        self.generate()
        self.getRoot().setCollideMask(BitMask32.bit(1))

        #self.makeSlopeMap()
        #logging.info( "createGroups()")
        self.createGroups()
        self.terrain.populator.populate(self)
Ejemplo n.º 10
0
class TerrainTile(GeoMipTerrain):
	"""TerrainTiles are the building blocks of a terrain."""
	
	def __init__(self, terrain, x, y):
		"""Builds a Tile for the terrain at input coordinates.
		
		Important settings are used directly from the terrain.
		This allows for easier setting changes and reduces memory overhead.
		x and y parameters give the appropriate world coordinates of this tile.
		
		"""
		
		self.terrain = terrain
		self.xOffset = x
		self.yOffset = y
		self.heightMapDetail = 1 # higher means greater detail
		
		self.name = "ID" + str(terrain.id) + "_X" + str(x) + "_Y" + str(y)
		GeoMipTerrain.__init(self, name=self.name)
		
		self.image = PNImage()
		
		#self.setAutoFlatten(GeoMipTerrain.AFMOff
		self.setFocalPoint(self.terrain.focus)
		self.setAutoFlatten(GeoMipTerrain.AFMOff)
		self.getRoot().setPos(x, y, 0)
		if self.terrain.bruteForce:
			GeoMipTerrain.setBruteForce(self, True)
			GeoMipTerrain.setBlockSize(self, self.terrain.heightMapSize * self.heightMapDetail)
		else:
			GeoMipTerrain.setBlockSize(self, self.terrain.blockSize/2)
			#self.setBorderStitching(1)
			self.setNear(self.terrain.near)
			self.setFar(self.terrain.far)
			
		
	def update(self):
		"""Updates the GeoMip to use the correct LOD on each block."""
		
		#logging.info("TerrainTile.update()")
		GeoMipTerrain.update(self)
		
	@pstat
	def updateTask(self, task):
		"""Updates the GeoMip to use the correct LOD on each block."""
		
		self.update()
		return task.again
		
	#@pstat
	def setHeightField(self, filename):
		"Set the GeoMip heightfield from a heightmap image."""
		
		GeoMipTerrain.setHeightfield(self, filename)
		
	@pstat
	def generate(self):
		GeoMipTerrain.generate(self)
		
	@pstat
	def setHeight(self):
		"""Sets the height field to match the height map image."""
		
		self.setHeightField(self.image)
		
	@pstat
	def makeHeightMap(self):
		"""Generate a new heightmap image.
		
		Panda3d GeoMipMaps require an image from which to build and update
        their height field. This function creates the correct image using the
        tile's position and the Terrain's getHeight() function.
		
		"""
		
		if SAVED_HEIGHT_MAPS:
			fileName = "maps/height/" + self.name + ".png"
			self.getRoot().setTag('EditableTerrain', '1')
			if self.image.read(Filename(fileName)):
				logging.info( "read heightmap from " + fileName)
				return
				
		heightMapSize = self.terrain.tileSize * self.heightMapDetail + 1
		self.image = PNMImage(heightMapSize, heightMapSize, 1, 65535)
		
		ySize = self.image.getYSize() - 1
		getHeight = self.terrain.getHeight
		setGray = self.image.setGray
		xo = self.xOffset
		yo = self.yOffset
		d = self.heightMapDetail
		
		for x in range(self.image.getXSize()):
			for y in range(ySize + 1):
				height = getHeight(x / d + xo, y / d + yo)
				# feed pixel into image
				# why is it necessary to invert the y axis I wonder?
				setGray(x, ySize - y, height)
		#self.postProcessImage()
		if SAVED_HEIGHT_MAPS:	
			fileName = "maps/height/" + self.name + ".png"
			logging.info( "saving heightmap to " + fileName)
			self.image.write(Filename(fileName))
			
	
	def postProcessImage(self):
		"""Perform filters and manipulations on the heightmap image."""
		
		#self.image.gaussianFilter()
		
	def setWireFrame(self, state):
		self.getRoot().setRenderModeWireframe()
		
	def makeSlopeMap(self):
		
		self.slopeMap = PNMImage()
		if SAVED_SLOPE_MAPS:
			fileName = "maps/slope/" + self.name + ".png"
			if self.slopeMap.read(Filename(fileName)):
				logging.info( "read slopemap from " + fileName)
				return
				
		self.slopeMap = PNMImage(self.terrain.heightMapSize, self.terrain.heightMapSize)
		self.slopeMap.makeGrayscale()
		self.slopeMap.setMaxval(65535)
		
		size = self.slopeMap.getYSize()
		getNormal = self.getNormal
		setGray = self.slopeMap.setGray
		
		for x in range(size):
			for y in range(size):
				#note getNormal works at the same resolution as the heightmap
				normal = getNormal(x, y)
				# feed pixel into image
				# why is it necessary to invert the y axis I wonder?
				#logging.info( normal)
				normal.z /= self.terrain.getSz()
				normal.normalize()
				slope = 1.0 - normal.dot(Vec3(0, 0, 1))
				setGray(x, y, slope)
				
		if SAVED_SLOPE_MAPS:
			fileName = "maps/slope/" + self.name + ".png"
			logging.info( "saving slopemap to " + fileName)
			self.slopeMap.write(Filename(fileName))
			
	def createGroups(self):
		self.statics = self.getRoot().attachNewNode(self.name + "_statics")
		self.statics.setSz(1.0 / self.terrain.getSz())
		self.statics.setSx(1.0 / self.terrain.getSz())
		self.statics.setSy(1.0 / self.terrain.getSy())
		
		self.statics.setShaderAuto()
		
	@pstat
	def make(self):
		"""Build a finished renderable heightMap."""
		
		# apply shader
		#logging.info( "applying shader")
		self.terrain.texturer.apply(self.getRoot())
		
		# detail settings
		#self.getRoot().setSz(1.0 / self.heightMapDetail)
		#self.getRoot().setSy(1.0 / self.heightMapDetail)
		
		#logging.info( "making height map")
		self.makeHeightMap()
		#logging.info( "setHeight()")
		self.setHeight()
		#self.getRoot().setSz(self.maxHeight)
		
		#http://www.panda3d.org/forums/viewtopic.php?=t=12054
		self.calcAmbientOcclusion()
		#loggin.info( "generate()")
		self.generate()
		self.getRoot().setCollideMask(BitMask32.bit(1))
		
		#self.makeSlopeMap()
		#logging.info( "createGroups()")
		self.createGroups()
		self.terrain.populator.populate(self)
Ejemplo n.º 11
0
	def import_(self, file_name, palettes):
		from pandac.PandaModules import PNMImage, Filename, VBase4D
		from pandac.PandaModules import Texture as P3DTexture
		
		pnm = PNMImage()
		pnm.read(Filename.fromOsSpecific(file_name))
		
		tex_pnm = PNMImage(17*256, 1024)
		tex_pnm.addAlpha()
		
		
		#convert data to same sequence as files
		texdata = []
		for y in range(1024):
			row = []
			for x in range(256):
				gray = pnm.getXel(x, y)
				pal_i = int(gray[0] * 15.0)
				row.append(pal_i)
			texdata.append(row)
		
		#update saving texture
		testpnm = PNMImage(256, 1024)
		
		palette = [(x, x, x, 1) for x in range(16)]
		colors = []
		for color in palette:
			color_list = [c / 15.0 for c in color[:3]]
			color_list.append(0 if color == (0, 0, 0, 0) else 1)
			colors.append(VBase4D(*color_list))
			
		for y in range(1024):
			row = texdata[y]
			for x in range(256):
				testpnm.setXelA(x, y, colors[row[x]])
		
		self.texture2.load(testpnm)
		self.texture2.setMagfilter(P3DTexture.FTNearest)
		self.texture2.setMinfilter(P3DTexture.FTLinear)

		
		#update texture visible on map


		self.palettes = []
		temp = []
		for x in range (16):
			temp.append((x, x, x, 1))
			
		self.palettes.append(temp)
		
		for y, palette in enumerate(palettes):
			selfpalette = []
			for x, color in enumerate(palette.colors.colors):
				selfpalette.append((color[0],color[1],color[2],1))
			self.palettes.append(selfpalette)
		
		i = 0
		for palette in self.palettes:
			colors = []
			for color in palette:
				color_list = [c / 15.0 for c in color[:3]]
				color_list.append(0 if color == (0, 0, 0, 0) else 1)
				colors.append(VBase4D(*color_list))
				
			for y in range(1024):
				row = texdata[y]
				for x in range(256):
					tex_pnm.setXelA(x + (256*i), y, colors[row[x]])	
			i += 1
			
		self.texture.load(tex_pnm)
		self.texture.setMagfilter(P3DTexture.FTNearest)
		self.texture.setMinfilter(P3DTexture.FTLinear)	
Ejemplo n.º 12
0
class Region(DirectObject.DirectObject):
    '''Stuff'''
    def __init__(self):
        self.tiles = []
        self.cities = {}
        self.accept('loadRegion', self.load)
        self.accept("updatedTiles", self.updateTiles)
        self.accept("newCity", self.newCity)
        self.accept("clickForCity", self.checkCity)
        self.accept("unfoundCity", self.unfoundCity)
        self.accept("enterCity", self.enterCity)
        
    def load(self, container, name="New Region"):
        '''Loads a new region, usually from connecting to a server
        Or starting a new or previously saved region.
        '''
        import base64
        self.heightmap = PNMImage()
        imageString = base64.b64decode(container.heightmap)
        self.heightmap.read(StringStream(imageString))
        self.region_size = (self.heightmap.getXSize()-1, self.heightmap.getYSize()-1)
        
        position = 0
        tileid = 0
        total_tiles = self.region_size[0] * self.region_size[1]
        ranges = []
        tiles = []
        
        for tile in container.tiles:
            tiles.append((tile.id, tile.cityid))
        for n in range(len(tiles)):
            try:
                ranges.append((tiles[n][0], tiles[n+1][0]-1, tiles[n][1]))
            except:
                ranges.append((tiles[n][0], total_tiles, tiles[n][1]))
        for r in ranges:
            for x in range(r[0], r[1]+1):
                #print "r0, r1, x", r[0], r[1], x
                self.tiles.append(Tile(tileid, r[2]))
                #print "Len", len(self.tiles)
                tileid += 1
        
        position = 0
        for y in range(self.region_size[1]):
            for x in range(self.region_size[0]):
                self.tiles[position].coords = (x,y)
                position += 1
                
        for city in container.cities:
            self.newCity(city)
        messenger.send("generateRegion", [self.heightmap, self.tiles, self.cities, container])
    
    def updateTiles(self, container):
        x = 0
        for tile in container:
            x += 1
            self.tiles[tile.id].cityid = tile.cityid
        print x, "tiles updated from server."
        messenger.send("updateRegion", [self.heightmap, self.tiles, self.cities])
    
    def newCity(self, city):
        self.cities[city.id] = {"name": city.name, "mayor": city.mayor, "funds": city.funds, "population": city.population}
    
    def checkCity(self, cell):
        '''Checks for city in given cell for region gui display'''
        if not cell: return
        tile = self.getTile(cell[0], cell[1])
        if tile.cityid:
            messenger.send("showRegionCityWindow", [tile.cityid, self.cities[tile.cityid]])
        
    def getTile(self, x, y):
        '''Returns tile by coordinate. 
        Thankfully smart enough to find a way to not iterate
        '''
        value = y * self.region_size[0] + x
        return self.tiles[value]
    
    def unfoundCity(self, ident):
        '''Unfounds a city'''
        del self.cities[ident]
    
    def enterCity(self, ident):
        '''Processess information needed for graphical elements to enter city view.'''
        # We need to send list of tiles for terrain manager
        tiles = []
        xsum = 0
        ysum = 0
        n = 0
        for tile in self.tiles:
            if tile.cityid is ident:
                tiles.append(tile)
                # We need to compute center of city to target camera there
                xsum += tile.coords[0]
                ysum += tile.coords[1]
                n += 1
        xavg = xsum/n
        yavg = ysum/n
        position = (xavg, yavg)
        # We need to send city info so gui elements can be drawn
        city = self.cities[ident]
        messenger.send('enterCityView', [ident, city, position, tiles])
Ejemplo n.º 13
0
    def _loadInternal(self,
                      resType,
                      filename,
                      locationName=None,
                      preloading=False):
        '''
        Manages the actual loading of a resource given the resource filename and the resource location
        that contains it.

        @param resType: A constant that identifies the type of the resource.
        @param filename: The filename of the resource.
        @param locationName: The name of the resource location containing the resource. This is optional.
        @return: A pano.resources.Resource instance if preloading is True, or the actual resource instance
        if preloading is False or finally None if the resource couldn't be found.
        '''

        self.requests += 1

        if locationName is not None:
            location = self.locationsByName.get(locationName)
        else:
            location = self.locateResource(resType, filename)
        if location is None:
            self.log.error('Failed to locate resource %s' % filename)
            return None

        # get the full path to query the cache, sticky and preload stores
        fullPath = location.getResourceFullPath(filename)
        if fullPath is None:
            self.log.error('Failed to get full path to resource %s' % filename)
            return None

        # resource locations can be sticky
        if location.sticky:
            resource = self._getStickyResource(fullPath, resType)
            if resource is not None:
                if self.log.isEnabledFor(logging.DEBUG):
                    self.log.debug('Returning sticky resource %s' % fullPath)

                self.stickyLoads += 1
                if not preloading:
                    resource.requested = True
                return resource.data if not preloading else resource

        # if the location has a preload flag, then search first in the preload store
        if location.preload:
            resource = self._fetchPreloaded(fullPath, location.name)
            if resource is not None:
                self.preloadHits += 1
                if not preloading:
                    resource.requested = True
                return resource.data if not preloading else resource
            else:
                self.preloadMisses += 1

        # then search in our cache
#        resource = self._cacheLookup(fullPath, location.name)
#        if resource is not None:
#            if self.log.isEnabledFor(logging.DEBUG):
#                self.log.debug('Returning cached instance of resource %s' % fullPath)
#            if not preloading:
#                resource.requested = True
#            return resource.data if not preloading else resource

# finally load it from the resource location
        if ResourcesTypes.isParsedResource(resType):
            # Convention: construct resource name from the basename of the filename and by dropping the extension.
            resName = os.path.basename(filename)
            extIndex = resName.rfind('.')
            if extIndex >= 0:
                resName = resName[:extIndex]

            resData = self._loadParsedResource(resType, resName, fullPath,
                                               location)

        else:
            if ResourcesTypes.isPandaResource(resType):
                # for Panda resources we use the BaseLoader
                resName = filename
                try:
                    if resType == PanoConstants.RES_TYPE_MODELS:
                        resData = loader.loadModel(fullPath)

                    elif resType == PanoConstants.RES_TYPE_TEXTURES or resType == PanoConstants.RES_TYPE_VIDEOS:
                        resData = loader.loadTexture(fullPath)

                    elif resType == PanoConstants.RES_TYPE_IMAGES:
                        img = PNMImage()
                        img.read(fullPath)
                        resData = img

                    elif resType == PanoConstants.RES_TYPE_MUSIC:
                        resData = loader.loadMusic(fullPath)

                    elif resType == PanoConstants.RES_TYPE_SFX:
                        resData = loader.loadSfx(fullPath)

                    elif resType == PanoConstants.RES_TYPE_SHADERS:
                        resData = Shader.load(fullPath)

                except Exception:
                    self.log.exception(
                        'Panda loader failed to load resource %s' % fullPath)
                    return None

            elif ResourcesTypes.isStreamResource(resType):
                # we consider character based and binary based streams
                # by handling stream resources in a special way we can perhaps provide more efficient
                # handling of streams, i.e. memory mapped files, compressed streams, decryption, etc.
                resName = filename
                if resType == PanoConstants.RES_TYPE_SCRIPTS or resType == PanoConstants.RES_TYPE_TEXTS:
                    resData = self._loadCharacterStream(fullPath, location)
                else:
                    resData = self._loadBinaryStream(fullPath, location)

            elif ResourcesTypes.isOpaqueResource(resType):
                # opaque resources perform their own loading, we only load the file's contents without caring
                # about how it looks and pass it to the read() method.
                resName = os.path.basename(filename)
                resData = ResourcesTypes.constructOpaqueResource(
                    resType, resName, filename)
                opaque = self._loadBinaryStream(fullPath, location)
                fp = StringIO.StringIO(opaque)
                resData.read(fp)

            if resData is None:
                self.log.error('Failed to load resource %s' % fullPath)
                return None

        resource = Resource(resName, resData, resType, fullPath, location.name)
        resource.sticky = location.sticky
        resource.preload = location.preload
        if not preloading:
            resource.requested = True

        # consider caching the resource
        if not resource.sticky and not resource.preload:
            self._cacheResource(fullPath, resource, location.name)

        elif resource.sticky:
            self._addStickyResource(fullPath, resource, location.name)

        # when we are preloading, return the Resource instance instead
        return resource.data if not preloading else resource