Exemple #1
0
class ZMap(DirectObject):
    COLORS = [
        VBase3D(0.7, 0.7, 0.9),  # AIR
        VBase3D(0.4, 0.5, 0.1),  # DIRT
        VBase3D(0.6, 0.6, 0.6)  # STONE
    ]

    def __init__(self, world, app):
        self.world = world

        self.image = PNMImage(self.world.width, 256)

        for z in self.world.zlevels():
            for x in range(self.world.height):
                mix = sum([
                    ZMap.COLORS[self.world.get_block(x, y, z).substance]
                    for y in range(self.world.height)
                ], VBase3D(0.0))
                color_block = mix / float(self.world.height)
                #print(color_block)
                #self.image.setXel(int(x), int(z), mix / float(self.world.height))
                self.image.setXel(
                    int(x), int(z),
                    LRGBColorf(color_block[0], color_block[1], color_block[2]))

        self.texture = Texture()
        self.texture.load(self.image)
        self.texture.setMagfilter(Texture.FTNearest)
        self.texture.setMinfilter(Texture.FTNearest)

        cm = CardMaker('zmap')
        cm.setFrame(0.95, 1, -1, 1)
        cm.setUvRange(Point2(1.0, 1.0),
                      Point2(0.0, 1.0 - self.world.depth / 256.0))
        self.zcard = app.render2d.attachNewNode(cm.generate())
        self.zcard.setTexture(self.texture)

        cm = CardMaker('zpointer')
        cm.setFrame(0, 0.05, 0, 1.0 / self.world.depth)
        self.zpointer = app.render2d.attachNewNode(cm.generate())
        self.zpointer.setColorScale(1.0, 0.0, 0.0, 0.4)

        self.accept('slice-changed', self.slice_changed)

    def slice_changed(self, slice, explore):
        self.zpointer.setPos(0.95, 0.0, slice * 2.0 / self.world.depth - 1.0)
Exemple #2
0
    def __init__(self):
        ShowBase.__init__(self)
        base.setBackgroundColor(0, 0, 0)
        # render.setShaderAuto()

        img = PNMImage("data/textures/vehicle01_body.png")
        for y in range(img.getReadYSize()):
            for x in range(img.getReadXSize()):
                r, g, b = img.getXel(x, y)
                h, s, v = colorsys.rgb_to_hsv(r, g, b)
                h += 0.9
                # print "#", r,g,b
                r, g, b = colorsys.hsv_to_rgb(h, s, v)
                img.setXel(x, y, r, g, b)


# print "-", r,g,b
        img.write("data/textures/vehicle01_body2.png")
class WaterManager(DebugObject):

    """ Simple wrapper arround WaterDisplacement which combines 3 displacement
    maps into one, and also generates a normal map """

    def __init__(self):
        DebugObject.__init__(self, "WaterManager")
        self.options = OceanOptions()
        self.options.size = 512
        self.options.windDir.normalize()
        self.options.waveAmplitude *= 1e-7

        self.displacementTex = Texture("Displacement")
        self.displacementTex.setup2dTexture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)

        self.normalTex = Texture("Normal")
        self.normalTex.setup2dTexture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)

        self.combineShader = Shader.loadCompute(Shader.SLGLSL,
            "Shader/WaterFFT/Combine.compute")

        self.ptaTime = PTAFloat.emptyArray(1)

        # Create a gaussian random texture, as shaders aren't well suited
        # for that
        setRandomSeed(523)
        self.randomStorage = PNMImage(self.options.size, self.options.size, 4)
        self.randomStorage.setMaxval((2 ** 16) - 1)

        for x in xrange(self.options.size):
            for y in xrange(self.options.size):
                rand1 = self._getGaussianRandom() / 10.0 + 0.5
                rand2 = self._getGaussianRandom() / 10.0 + 0.5
                self.randomStorage.setXel(x, y, float(rand1), float(rand2), 0)
                self.randomStorage.setAlpha(x, y, 1.0)

        self.randomStorageTex = Texture("RandomStorage")
        self.randomStorageTex.load(self.randomStorage)
        self.randomStorageTex.setFormat(Texture.FRgba16)
        self.randomStorageTex.setMinfilter(Texture.FTNearest)
        self.randomStorageTex.setMagfilter(Texture.FTNearest)

        # Create the texture wwhere the intial height (H0 + Omega0) is stored.
        self.texInitialHeight = Texture("InitialHeight")
        self.texInitialHeight.setup2dTexture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)
        self.texInitialHeight.setMinfilter(Texture.FTNearest)
        self.texInitialHeight.setMagfilter(Texture.FTNearest)

        # Create the shader which populates the initial height texture
        self.shaderInitialHeight = Shader.loadCompute(Shader.SLGLSL,
            "Shader/WaterFFT/InitialHeight.compute")
        self.nodeInitialHeight = NodePath("initialHeight")
        self.nodeInitialHeight.setShader(self.shaderInitialHeight)
        self.nodeInitialHeight.setShaderInput("dest", self.texInitialHeight)
        self.nodeInitialHeight.setShaderInput(
            "N", LVecBase2i(self.options.size))
        self.nodeInitialHeight.setShaderInput(
            "patchLength", self.options.patchLength)
        self.nodeInitialHeight.setShaderInput("windDir", self.options.windDir)
        self.nodeInitialHeight.setShaderInput(
            "windSpeed", self.options.windSpeed)
        self.nodeInitialHeight.setShaderInput(
            "waveAmplitude", self.options.waveAmplitude)
        self.nodeInitialHeight.setShaderInput(
            "windDependency", self.options.windDependency)
        self.nodeInitialHeight.setShaderInput(
            "randomTex", self.randomStorageTex)

        self.attrInitialHeight = self.nodeInitialHeight.getAttrib(ShaderAttrib)

        self.heightTextures = []
        for i in xrange(3):

            tex = Texture("Height")
            tex.setup2dTexture(self.options.size, self.options.size,
                               Texture.TFloat, Texture.FRgba16)
            tex.setMinfilter(Texture.FTNearest)
            tex.setMagfilter(Texture.FTNearest)
            tex.setWrapU(Texture.WMClamp)
            tex.setWrapV(Texture.WMClamp)
            self.heightTextures.append(tex)

        # Also create the shader which updates the spectrum
        self.shaderUpdate = Shader.loadCompute(Shader.SLGLSL,
            "Shader/WaterFFT/Update.compute")
        self.nodeUpdate = NodePath("update")
        self.nodeUpdate.setShader(self.shaderUpdate)
        self.nodeUpdate.setShaderInput("outH0x", self.heightTextures[0])
        self.nodeUpdate.setShaderInput("outH0y", self.heightTextures[1])
        self.nodeUpdate.setShaderInput("outH0z", self.heightTextures[2])
        self.nodeUpdate.setShaderInput("initialHeight", self.texInitialHeight)
        self.nodeUpdate.setShaderInput("N", LVecBase2i(self.options.size))
        self.nodeUpdate.setShaderInput("time", self.ptaTime)
        self.attrUpdate = self.nodeUpdate.getAttrib(ShaderAttrib)

        # Create 3 FFTs
        self.fftX = GPUFFT(self.options.size, self.heightTextures[0],
                           self.options.normalizationFactor)
        self.fftY = GPUFFT(self.options.size, self.heightTextures[1],
                           self.options.normalizationFactor)
        self.fftZ = GPUFFT(self.options.size, self.heightTextures[2],
                           self.options.normalizationFactor)

        self.combineNode = NodePath("Combine")
        self.combineNode.setShader(self.combineShader)
        self.combineNode.setShaderInput(
            "displacementX", self.fftX.getResultTexture())
        self.combineNode.setShaderInput(
            "displacementY", self.fftY.getResultTexture())
        self.combineNode.setShaderInput(
            "displacementZ", self.fftZ.getResultTexture())
        self.combineNode.setShaderInput("normalDest", self.normalTex)
        self.combineNode.setShaderInput(
            "displacementDest", self.displacementTex)
        self.combineNode.setShaderInput(
            "N", LVecBase2i(self.options.size))
        self.combineNode.setShaderInput(
            "choppyScale", self.options.choppyScale)
        self.combineNode.setShaderInput(
            "gridLength", self.options.patchLength)
        # Store only the shader attrib as this is way faster
        self.attrCombine = self.combineNode.getAttrib(ShaderAttrib)

    def _getGaussianRandom(self):
        """ Returns a gaussian random number """
        u1 = generateRandom()
        u2 = generateRandom()
        if u1 < 1e-6:
            u1 = 1e-6
        return sqrt(-2 * log(u1)) * cos(2 * pi * u2)

    def setup(self):
        """ Setups the manager """

        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size / 16,
             self.options.size / 16, 1), self.attrInitialHeight,
            Globals.base.win.get_gsg())

    def getDisplacementTexture(self):
        """ Returns the displacement texture, storing the 3D Displacement in
        the RGB channels """
        return self.displacementTex

    def getNormalTexture(self):
        """ Returns the normal texture, storing the normal in world space in
        the RGB channels """
        return self.normalTex

    def update(self):
        """ Updates the displacement / normal map """

        self.ptaTime[0] = 1 + \
            Globals.clock.getFrameTime() * self.options.timeScale

        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size / 16,
             self.options.size / 16, 1), self.attrUpdate,
            Globals.base.win.get_gsg())

        self.fftX.execute()
        self.fftY.execute()
        self.fftZ.execute()

        # Execute the shader which combines the 3 displacement maps into
        # 1 displacement texture and 1 normal texture. We could use dFdx in
        # the fragment shader, however that gives no accurate results as
        # dFdx returns the same value for a 2x2 pixel block
        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size / 16,
             self.options.size / 16, 1), self.attrCombine,
            Globals.base.win.get_gsg())
Exemple #4
0
class WaterManager(DebugObject):
    """ Simple wrapper arround WaterDisplacement which combines 3 displacement
    maps into one, and also generates a normal map """
    def __init__(self):
        DebugObject.__init__(self, "WaterManager")
        self.options = OceanOptions()
        self.options.size = 512
        self.options.windDir.normalize()
        self.options.waveAmplitude *= 1e-7

        self.displacementTex = Texture("Displacement")
        self.displacementTex.setup2dTexture(self.options.size,
                                            self.options.size, Texture.TFloat,
                                            Texture.FRgba16)

        self.normalTex = Texture("Normal")
        self.normalTex.setup2dTexture(self.options.size, self.options.size,
                                      Texture.TFloat, Texture.FRgba16)

        self.combineShader = BetterShader.loadCompute(
            "Shader/Water/Combine.compute")

        self.ptaTime = PTAFloat.emptyArray(1)

        # Create a gaussian random texture, as shaders aren't well suited
        # for that
        setRandomSeed(523)
        self.randomStorage = PNMImage(self.options.size, self.options.size, 4)
        self.randomStorage.setMaxval((2**16) - 1)

        for x in xrange(self.options.size):
            for y in xrange(self.options.size):
                rand1 = self._getGaussianRandom() / 10.0 + 0.5
                rand2 = self._getGaussianRandom() / 10.0 + 0.5
                self.randomStorage.setXel(x, y, LVecBase3d(rand1, rand2, 0))
                self.randomStorage.setAlpha(x, y, 1.0)

        self.randomStorageTex = Texture("RandomStorage")
        self.randomStorageTex.load(self.randomStorage)
        self.randomStorageTex.setFormat(Texture.FRgba16)
        self.randomStorageTex.setMinfilter(Texture.FTNearest)
        self.randomStorageTex.setMagfilter(Texture.FTNearest)

        # Create the texture wwhere the intial height (H0 + Omega0) is stored.
        self.texInitialHeight = Texture("InitialHeight")
        self.texInitialHeight.setup2dTexture(self.options.size,
                                             self.options.size, Texture.TFloat,
                                             Texture.FRgba16)
        self.texInitialHeight.setMinfilter(Texture.FTNearest)
        self.texInitialHeight.setMagfilter(Texture.FTNearest)

        # Create the shader which populates the initial height texture
        self.shaderInitialHeight = BetterShader.loadCompute(
            "Shader/Water/InitialHeight.compute")
        self.nodeInitialHeight = NodePath("initialHeight")
        self.nodeInitialHeight.setShader(self.shaderInitialHeight)
        self.nodeInitialHeight.setShaderInput("dest", self.texInitialHeight)
        self.nodeInitialHeight.setShaderInput("N",
                                              LVecBase2i(self.options.size))
        self.nodeInitialHeight.setShaderInput("patchLength",
                                              self.options.patchLength)
        self.nodeInitialHeight.setShaderInput("windDir", self.options.windDir)
        self.nodeInitialHeight.setShaderInput("windSpeed",
                                              self.options.windSpeed)
        self.nodeInitialHeight.setShaderInput("waveAmplitude",
                                              self.options.waveAmplitude)
        self.nodeInitialHeight.setShaderInput("windDependency",
                                              self.options.windDependency)
        self.nodeInitialHeight.setShaderInput("randomTex",
                                              self.randomStorageTex)

        self.attrInitialHeight = self.nodeInitialHeight.getAttrib(ShaderAttrib)

        self.heightTextures = []
        for i in xrange(3):

            tex = Texture("Height")
            tex.setup2dTexture(self.options.size, self.options.size,
                               Texture.TFloat, Texture.FRgba16)
            tex.setMinfilter(Texture.FTNearest)
            tex.setMagfilter(Texture.FTNearest)
            tex.setWrapU(Texture.WMClamp)
            tex.setWrapV(Texture.WMClamp)
            self.heightTextures.append(tex)

        # Also create the shader which updates the spectrum
        self.shaderUpdate = BetterShader.loadCompute(
            "Shader/Water/Update.compute")
        self.nodeUpdate = NodePath("update")
        self.nodeUpdate.setShader(self.shaderUpdate)
        self.nodeUpdate.setShaderInput("outH0x", self.heightTextures[0])
        self.nodeUpdate.setShaderInput("outH0y", self.heightTextures[1])
        self.nodeUpdate.setShaderInput("outH0z", self.heightTextures[2])
        self.nodeUpdate.setShaderInput("initialHeight", self.texInitialHeight)
        self.nodeUpdate.setShaderInput("N", LVecBase2i(self.options.size))
        self.nodeUpdate.setShaderInput("time", self.ptaTime)
        self.attrUpdate = self.nodeUpdate.getAttrib(ShaderAttrib)

        # Create 3 FFTs
        self.fftX = GPUFFT(self.options.size, self.heightTextures[0],
                           self.options.normalizationFactor)
        self.fftY = GPUFFT(self.options.size, self.heightTextures[1],
                           self.options.normalizationFactor)
        self.fftZ = GPUFFT(self.options.size, self.heightTextures[2],
                           self.options.normalizationFactor)

        self.combineNode = NodePath("Combine")
        self.combineNode.setShader(self.combineShader)
        self.combineNode.setShaderInput("displacementX",
                                        self.fftX.getResultTexture())
        self.combineNode.setShaderInput("displacementY",
                                        self.fftY.getResultTexture())
        self.combineNode.setShaderInput("displacementZ",
                                        self.fftZ.getResultTexture())
        self.combineNode.setShaderInput("normalDest", self.normalTex)
        self.combineNode.setShaderInput("displacementDest",
                                        self.displacementTex)
        self.combineNode.setShaderInput("N", LVecBase2i(self.options.size))
        self.combineNode.setShaderInput("choppyScale",
                                        self.options.choppyScale)
        self.combineNode.setShaderInput("gridLength", self.options.patchLength)
        # Store only the shader attrib as this is way faster
        self.attrCombine = self.combineNode.getAttrib(ShaderAttrib)

    def _getGaussianRandom(self):
        """ Returns a gaussian random number """
        u1 = generateRandom()
        u2 = generateRandom()
        if u1 < 1e-6:
            u1 = 1e-6
        return sqrt(-2 * log(u1)) * cos(2 * pi * u2)

    def setup(self):
        """ Setups the manager """

        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size / 16, self.options.size / 16, 1),
            self.attrInitialHeight, Globals.base.win.get_gsg())

    def getDisplacementTexture(self):
        """ Returns the displacement texture, storing the 3D Displacement in
        the RGB channels """
        return self.displacementTex

    def getNormalTexture(self):
        """ Returns the normal texture, storing the normal in world space in
        the RGB channels """
        return self.normalTex

    def update(self):
        """ Updates the displacement / normal map """

        self.ptaTime[0] = 1 + \
            Globals.clock.getFrameTime() * self.options.timeScale

        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size / 16, self.options.size / 16, 1),
            self.attrUpdate, Globals.base.win.get_gsg())

        self.fftX.execute()
        self.fftY.execute()
        self.fftZ.execute()

        # Execute the shader which combines the 3 displacement maps into
        # 1 displacement texture and 1 normal texture. We could use dFdx in
        # the fragment shader, however that gives no accurate results as
        # dFdx returns the same value for a 2x2 pixel block
        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size / 16, self.options.size / 16, 1),
            self.attrCombine, Globals.base.win.get_gsg())
Exemple #5
0
class TerrainManager(DirectObject.DirectObject):
    def __init__(self):
        self.accept("mouse1", self.lclick)
        self.waterType = 2
        self.water = None
        self.citycolors = {0: VBase3D(1, 1, 1)}

        self.accept('generateRegion', self.generateWorld)
        self.accept('regenerateRegion', self.regenerateWorld)
        self.accept("regionView_normal", self.setSurfaceTextures)
        self.accept("regionView_owners", self.setOwnerTextures)
        self.accept("regionView_foundNew", self.regionViewFound)
        self.accept("updateRegion", self.updateRegion)
        self.accept("enterCityView", self.enterCity)

        # View: 0, region, # cityid
        self.view = 0
        self.ownerview = False

    def lclick(self):
        cell = picker.getMouseCell()
        print "Cell:", cell
        blockCoords = self.terrain.getBlockFromPos(cell[0], cell[1])
        block = self.terrain.getBlockNodePath(blockCoords[0], blockCoords[1])
        print "Block coords:", blockCoords
        print "NodePath:", block
        print "Elevation:", self.terrain.getElevation(cell[0], cell[1])
        if not self.view:
            messenger.send("clickForCity", [cell])

    def switchWater(self):
        print "Switch Water"
        self.waterType += 1
        if self.waterType > 2:
            self.waterType = 0
        self.generateWater(self.waterType)

    def generateWorld(self, heightmap, tiles, cities, container):
        self.heightmap = heightmap
        self.terrain = PagedGeoMipTerrain("surface")
        #self.terrain = GeoMipTerrain("surface")
        self.terrain.setHeightfield(self.heightmap)
        #self.terrain.setFocalPoint(base.camera)
        self.terrain.setBruteforce(True)
        self.terrain.setBlockSize(64)
        self.terrain.generate()

        root = self.terrain.getRoot()
        root.reparentTo(render)
        #root.setSz(100)
        self.terrain.setSz(100)
        messenger.send('makePickable', [root])

        if self.heightmap.getXSize() > self.heightmap.getYSize():
            self.size = self.heightmap.getXSize() - 1
        else:
            self.size = self.heightmap.getYSize() - 1
        self.xsize = self.heightmap.getXSize() - 1
        self.ysize = self.heightmap.getYSize() - 1

        # Set multi texture
        # Source http://www.panda3d.org/phpbb2/viewtopic.php?t=4536
        self.generateSurfaceTextures()
        self.generateWaterMap()
        self.generateOwnerTexture(tiles, cities)
        #self.terrain.makeTextureMap()
        colormap = PNMImage(heightmap.getXSize() - 1, heightmap.getYSize() - 1)
        colormap.addAlpha()
        slopemap = self.terrain.makeSlopeImage()
        for x in range(0, colormap.getXSize()):
            for y in range(0, colormap.getYSize()):
                # Else if statements used to make sure one channel is used per pixel
                # Also for some optimization
                # Snow. We do things funky here as alpha will be 1 already.
                if heightmap.getGrayVal(x, y) < 200:
                    colormap.setAlpha(x, y, 0)
                else:
                    colormap.setAlpha(x, y, 1)
                # Beach. Estimations from http://www.simtropolis.com/omnibus/index.cfm/Main.SimCity_4.Custom_Content.Custom_Terrains_and_Using_USGS_Data
                if heightmap.getGrayVal(x, y) < 62:
                    colormap.setBlue(x, y, 1)
                # Rock
                elif slopemap.getGrayVal(x, y) > 170:
                    colormap.setRed(x, y, 1)
                else:
                    colormap.setGreen(x, y, 1)
        self.colorTexture = Texture()
        self.colorTexture.load(colormap)
        self.colorTS = TextureStage('color')
        self.colorTS.setSort(0)
        self.colorTS.setPriority(1)

        self.setSurfaceTextures()
        self.generateWater(2)
        taskMgr.add(self.updateTerrain, "updateTerrain")
        print "Done with terrain generation"
        messenger.send("finishedTerrainGen", [[self.xsize, self.ysize]])
        self.terrain.getRoot().analyze()
        self.accept("h", self.switchWater)

    def regenerateWorld(self):
        '''Regenerates world, often upon city exit.'''
        self.terrain.generate()
        root = self.terrain.getRoot()
        root.reparentTo(render)
        self.terrain.setSz(100)
        messenger.send('makePickable', [root])
        # Set multi texture
        # Source http://www.panda3d.org/phpbb2/viewtopic.php?t=4536
        #self.generateSurfaceTextures()
        self.generateWaterMap()

        self.setSurfaceTextures()
        self.generateWater(2)
        print "Done with terrain regeneration"
        messenger.send("finishedTerrainGen", [[self.xsize, self.ysize]])

    def generateWaterMap(self):
        ''' Iterate through every pix of color map. This will be very slow so until faster method is developed, use sparingly
        getXSize returns pixels length starting with 1, subtract 1 for obvious reasons
        We also slip in checking for the water card size, which should only change when the color map does
        '''
        print "GenerateWaterMap"
        self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax = -1, 0, -1, 0
        for x in range(0, self.heightmap.getXSize() - 1):
            for y in range(0, self.heightmap.getYSize() - 1):
                # Else if statements used to make sure one channel is used per pixel
                # Also for some optimization
                # Snow. We do things funky here as alpha will be 1 already.
                if self.heightmap.getGrayVal(x, y) < 62:
                    # Water card dimensions here
                    # Y axis flipped from texture space to world space
                    if self.waterXMin == -1 or x < self.waterXMin:
                        self.waterXMin = x
                    if not self.waterYMax:
                        self.waterYMax = y
                    if y < self.waterYMax:
                        self.waterYMax = y
                    if x > self.waterXMax:
                        self.waterXMax = x
                    if y > self.waterYMin:
                        self.waterYMin = y
        # Transform y coords
        self.waterYMin = self.size - 64 - self.waterYMin
        self.waterYMax = self.size - 64 - self.waterYMax

    def generateOwnerTexture(self, tiles, cities):
        '''Generates a simple colored texture to be applied to the city info region overlay.
        Due to different coordinate systems (terrain org bottom left, texture top left)
        some conversions are needed,
        
        Also creates and sends a citylabels dict for the region view
        '''
        self.citymap = PNMImage(self.xsize, self.ysize)
        citylabels = cities
        scratch = {}

        # Setup for city labels
        for ident in cities:
            scratch[ident] = []

        # conversion for y axis
        ycon = []
        s = self.ysize - 1
        for y in range(self.ysize):
            ycon.append(s)
            s -= 1
        for ident, city in cities.items():
            if ident not in self.citycolors:
                self.citycolors[ident] = VBase3D(random.random(),
                                                 random.random(),
                                                 random.random())
        for tile in tiles:
            self.citymap.setXel(tile.coords[0], ycon[tile.coords[1]],
                                self.citycolors[tile.cityid])
            # Scratch for labeling
            if tile.cityid:
                scratch[tile.cityid].append((tile.coords[0], tile.coords[1]))
        for ident, values in scratch.items():
            xsum = 0
            ysum = 0
            n = 0
            for coords in values:
                xsum += coords[0]
                ysum += coords[1]
                n += 1
            xavg = xsum / n
            yavg = ysum / n
            print "Elevation:", self.terrain.getElevation(xavg, yavg)
            z = self.terrain.getElevation(xavg, yavg) * 100
            citylabels[ident]["position"] = (xavg, yavg, z + 15)
            print "Citylabels:", citylabels
        messenger.send("updateCityLabels", [citylabels, self.terrain])

    def generateSurfaceTextures(self):
        # Textureize
        self.grassTexture = loader.loadTexture("Textures/grass.png")
        self.grassTS = TextureStage('grass')
        self.grassTS.setSort(1)

        self.rockTexture = loader.loadTexture("Textures/rock.jpg")
        self.rockTS = TextureStage('rock')
        self.rockTS.setSort(2)
        self.rockTS.setCombineRgb(TextureStage.CMAdd,
                                  TextureStage.CSLastSavedResult,
                                  TextureStage.COSrcColor,
                                  TextureStage.CSTexture,
                                  TextureStage.COSrcColor)

        self.sandTexture = loader.loadTexture("Textures/sand.jpg")
        self.sandTS = TextureStage('sand')
        self.sandTS.setSort(3)
        self.sandTS.setPriority(5)

        self.snowTexture = loader.loadTexture("Textures/ice.png")
        self.snowTS = TextureStage('snow')
        self.snowTS.setSort(4)
        self.snowTS.setPriority(0)

        # Grid for city placement and guide and stuff
        self.gridTexture = loader.loadTexture("Textures/grid.png")
        self.gridTexture.setWrapU(Texture.WMRepeat)
        self.gridTexture.setWrapV(Texture.WMRepeat)
        self.gridTS = TextureStage('grid')
        self.gridTS.setSort(5)
        self.gridTS.setPriority(10)

    def enterCity(self, ident, city, position, tiles):
        '''Identifies which terrain blocks city belogs to and disables those that are not
        A lot of uneeded for loops in here. Will need to find a better way later.'''
        #root = self.terrain.getRoot()
        children = []
        for terrain in self.terrain.terrains:
            root = terrain.getRoot()
            children += root.getChildren()
        keepBlocks = []
        # Reset water dimentions
        self.waterXMin = 0
        self.waterXMax = 0
        self.waterYMin = 0
        self.waterYMax = 0

        for tile in tiles:
            blockCoords = self.terrain.getBlockFromPos(tile.coords[0],
                                                       tile.coords[1])
            block = self.terrain.getBlockNodePath(blockCoords[0],
                                                  blockCoords[1])
            if block not in keepBlocks:
                keepBlocks.append(block)
            if self.heightmap.getGrayVal(tile.coords[0],
                                         self.size - tile.coords[1]) < 62:
                # Water card dimensions here
                # Y axis flipped from texture space to world space
                if not self.waterXMin:
                    self.waterXMin = tile.coords[0]
                if not self.waterYMin:
                    self.waterYMin = tile.coords[1]
                if tile.coords[1] > self.waterYMax:
                    self.waterYMax = tile.coords[1]
                if tile.coords[0] > self.waterXMax:
                    self.waterXMax = tile.coords[0]
                if tile.coords[0] < self.waterXMin:
                    self.waterXMin = tile.coords[0]
                if tile.coords[1] < self.waterYMin:
                    self.waterYMin = tile.coords[1]
        for child in children:
            if child not in keepBlocks:
                child.detachNode()
        self.view = ident
        self.generateWater(2)

    def newTerrainOverlay(self, task):
        root = self.terrain.getRoot()
        position = picker.getMouseCell()
        if position:
            # Check to make sure we do not go out of bounds
            if position[0] < 32:
                position = (32, position[1])
            elif position[0] > self.xsize - 32:
                position = (self.xsize - 32, position[1])
            if position[1] < 32:
                position = (position[0], 32)
            elif position[1] > self.ysize - 32:
                position = (position[0], self.size - 32)
            root.setTexOffset(self.tileTS, -(position[0] - 32) / 64,
                              -(position[1] - 32) / 64)
        return task.cont

    def regionViewFound(self):
        '''Gui for founding a new city!'''
        self.setOwnerTextures()
        root = self.terrain.getRoot()
        task = taskMgr.add(self.newTerrainOverlay, "newTerrainOverlay")
        tileTexture = loader.loadTexture("Textures/tile.png")
        tileTexture.setWrapU(Texture.WMClamp)
        tileTexture.setWrapV(Texture.WMClamp)
        self.tileTS = TextureStage('tile')
        self.tileTS.setSort(6)
        self.tileTS.setMode(TextureStage.MDecal)
        #self.tileTS.setColor(Vec4(1,0,1,1))
        root.setTexture(self.tileTS, tileTexture)
        root.setTexScale(self.tileTS, self.terrain.xchunks,
                         self.terrain.ychunks)
        self.acceptOnce("mouse1", self.regionViewFound2)
        self.acceptOnce("escape", self.cancelRegionViewFound)

    def regionViewFound2(self):
        '''Grabs cell location for founding.
        The texture coordinate is used as the mouse may enter an out of bounds area.
        '''
        root = self.terrain.getRoot()
        root_position = root.getTexOffset(self.tileTS)
        # We offset the position of the texture, so we will now put the origin of the new city not on mouse cursor but the "bottom left" of it. Just need to add 32 to get other edge
        position = [
            int(abs(root_position[0] * 64)),
            int(abs(root_position[1] * 64))
        ]
        self.cancelRegionViewFound()
        messenger.send("found_city_name", [position])

    def cancelRegionViewFound(self):
        taskMgr.remove("newTerrainOverlay")
        root = self.terrain.getRoot()
        root.clearTexture(self.tileTS)
        # Restore original mouse function
        self.accept("mouse1", self.lclick)
        messenger.send("showRegionGUI")

    def setSurfaceTextures(self):
        self.ownerview = False
        root = self.terrain.getRoot()
        root.clearTexture()
        #self.terrain.setTextureMap()
        root.setTexture(self.colorTS, self.colorTexture)
        root.setTexture(self.grassTS, self.grassTexture)
        root.setTexScale(self.grassTS, self.size / 8, self.size / 8)
        root.setTexture(self.rockTS, self.rockTexture)
        root.setTexScale(self.rockTS, self.size / 8, self.size / 8)
        root.setTexture(self.sandTS, self.sandTexture)
        root.setTexScale(self.sandTS, self.size / 8, self.size / 8)
        root.setTexture(self.snowTS, self.snowTexture)
        root.setTexScale(self.snowTS, self.size / 8, self.size / 8)
        root.setTexture(self.gridTS, self.gridTexture)
        root.setTexScale(self.gridTS, self.xsize, self.ysize)
        root.setShaderInput('size', self.xsize, self.ysize, self.size,
                            self.size)
        root.setShader(loader.loadShader('Shaders/terraintexture.sha'))

    def setOwnerTextures(self):
        self.ownerview = True
        root = self.terrain.getRoot()
        root.clearShader()
        root.clearTexture()
        cityTexture = Texture()
        cityTexture.load(self.citymap)
        cityTS = TextureStage('citymap')
        cityTS.setSort(0)
        root.setTexture(self.gridTS, self.gridTexture)
        root.setTexScale(self.gridTS, self.terrain.xchunks,
                         self.terrain.ychunks)
        root.setTexture(cityTS, cityTexture, 1)

    def updateRegion(self, heightmap, tiles, cities):
        self.generateOwnerTexture(tiles, cities)
        if self.ownerview:
            self.setOwnerTextures()

    def updateTerrain(self, task):
        '''Updates terrain and water'''
        self.terrain.update()
        # Water
        if self.waterType is 2:
            pos = base.camera.getPos()
            render.setShaderInput('time', task.time)
            mc = base.camera.getMat()
            self.water.changeCameraPos(pos, mc)
            self.water.changeCameraPos(pos, mc)
        #print "Render diagnostics"
        #render.analyze()
        #base.cTrav.showCollisions(render)
        return task.cont

    def generateWater(self, style):
        print "Generate Water:", self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax
        '''Generates water
        style 0: blue card
        style 1: reflective card
        style 2: reflective card with shaders
        '''
        self.waterHeight = 22.0
        if self.water:
            self.water.removeNode()
        if style is 0:
            cm = CardMaker("water")
            #cm.setFrame(-1, 1, -1, 1)
            cm.setFrame(self.waterXMin, self.waterXMax, self.waterYMin,
                        self.waterYMax)
            cm.setColor(0, 0, 1, 0.9)
            self.water = render.attachNewNode(cm.generate())
            if self.waterYMax > self.waterXMax:
                size = self.waterYMax
            else:
                size = self.waterXMax
            self.water.lookAt(0, 0, -1)
            self.water.setZ(self.waterHeight)
            messenger.send('makePickable', [self.water])
        elif style is 1:
            # From Prosoft's super awesome terrain demo
            cm = CardMaker("water")
            #cm.setFrame(-1, 1, -1, 1)
            cm.setFrame(self.waterXMin, self.waterXMax, self.waterYMin,
                        self.waterYMax)
            self.water = render.attachNewNode(cm.generate())
            if self.waterYMax > self.waterXMax:
                size = self.waterYMax
            else:
                size = self.waterXMax
            #self.water.setScale(size)
            self.water.lookAt(0, 0, -1)
            self.water.setZ(self.waterHeight)
            self.water.setShaderOff(1)
            self.water.setLightOff(1)
            self.water.setAlphaScale(0.5)
            self.water.setTransparency(TransparencyAttrib.MAlpha)
            wbuffer = base.win.makeTextureBuffer("water", 512, 512)
            wbuffer.setClearColorActive(True)
            wbuffer.setClearColor(base.win.getClearColor())
            self.wcamera = base.makeCamera(wbuffer)
            self.wcamera.reparentTo(render)
            self.wcamera.node().setLens(base.camLens)
            self.wcamera.node().setCameraMask(BitMask32.bit(1))
            self.water.hide(BitMask32.bit(1))
            wtexture = wbuffer.getTexture()
            wtexture.setWrapU(Texture.WMClamp)
            wtexture.setWrapV(Texture.WMClamp)
            wtexture.setMinfilter(Texture.FTLinearMipmapLinear)
            self.wplane = Plane(Vec3(0, 0, 1), Point3(0, 0, self.water.getZ()))
            wplanenp = render.attachNewNode(PlaneNode("water", self.wplane))
            tmpnp = NodePath("StateInitializer")
            tmpnp.setClipPlane(wplanenp)
            tmpnp.setAttrib(CullFaceAttrib.makeReverse())
            self.wcamera.node().setInitialState(tmpnp.getState())
            self.water.projectTexture(TextureStage("reflection"), wtexture,
                                      self.wcamera)
            messenger.send('makePickable', [self.water])
        elif style is 2:
            # From Clcheung just as super awesome demomaster
            self.water_level = Vec4(0.0, 0.0, self.waterHeight, 1.0)
            self.water = water.WaterNode(self.waterXMin, self.waterYMin,
                                         self.waterXMax, self.waterYMax,
                                         self.water_level.getZ())
            self.water.setStandardControl()
            self.water.changeParams(None)
            wl = self.water_level
            wl.setZ(wl.getZ() - 0.05)
            #root.setShaderInput('waterlevel', self.water_level)
            render.setShaderInput('time', 0)
            messenger.send('makePickable', [self.water.waterNP])
Exemple #6
0
    def generateNode(self, name, DB, parentNode):
        log.debug("Setting up " + name)
        bodyEntity = sandbox.createEntity()
        component = CelestialComponent()
        if DB["type"] == "solid":
            body = Body(name)
        elif DB["type"] == "moon":
            body = Body(name)
            body.kind = "moon"
        elif DB["type"] == "star":
            body = Star(name)
            body.absoluteM = DB["absolute magnitude"]
            body.spectral = DB["spectral"]
        elif DB["type"] == "barycenter":
            body = BaryCenter(name)

        component.kind = TYPES[DB["type"]]

        if DB["type"] != "barycenter":
            component.mass = DB["mass"]
            body.radius = DB["radius"]
            body.rotation = DB["rotation"]

        if "orbit" in DB:
            component.orbit = DB["orbit"]
            body.period = DB["period"]
            # body.setPos(self.get2DBodyPosition(component, universals.day))
            component.truePos = self.get2DBodyPosition(component, universals.day)
            if name == "Earth":
                # universals.spawn = component.truePos + LPoint3d(0, 6671, 0)
                universals.spawn = component.truePos + LPoint3d(6671, 0, 0)

        if parentNode == universals.solarSystemRoot:
            universals.defaultSOIid = bodyEntity.id
            component.soi = 0
        elif DB["type"] != "star" or DB["type"] != "barycenter":
            component.soi = self.getSOI(component.mass, self.bodies[0].mass, component.orbit["a"])

        body.type = DB["type"]
        body.reparentTo(parentNode)
        component.nodePath = body
        self.bodies.append(component)
        bodyEntity.addComponent(component)

        if universals.runClient and DB["type"] == "star":
            component = graphicsComponents.RenderComponent()
            # component.mesh = NodePath(name)
            # self.sphere.copyTo(component.mesh)
            # component.mesh = shapeGenerator.Sphere(body.radius, 128, name)
            component.mesh = shapeGenerator.Sphere(body.radius, 64, name)
            # component.mesh.setScale(body.radius)
            component.mesh.reparentTo(sandbox.base.render)
            sandbox.send("makePickable", [component.mesh])
            # texture = sandbox.base.loader.loadTexture('planets/' + DB['texture'])
            # texture.setMinfilter(Texture.FTLinearMipmapLinear)
            # ts1 = TextureStage('textures1')
            # ts1.setMode(TextureStage.MGlow)
            # component.mesh.setTexture(ts1, texture)
            # component.mesh.setTexture(texture, 1)

            component.light = component.mesh.attachNewNode(PointLight("sunPointLight"))
            component.light.node().setColor(Vec4(1, 1, 1, 1))
            sandbox.base.render.setLight(component.light)
            bodyEntity.addComponent(component)

            # Shader test
            componentStar = graphicsComponents.StarRender()
            componentStar.noise_texture = Texture("noise")
            componentStar.noise_texture.setup2dTexture()
            img = PNMImage(1024, 1024)
            for y in range(1024):
                for x in range(1024):
                    img.setXel(x, y, componentStar.noise.noise(x, y))
                    # print componentStar.noise.noise(x, y)
            componentStar.noise_texture.load(img)
            # componentStar.noise_texture.write('test.png')
            # component.mesh.setTexture(componentStar.noise_texture, 1)

            texture = sandbox.base.loader.loadTexture("planets/" + DB["texture"])
            ts1 = TextureStage("textures1")
            ts1.setMode(TextureStage.MGlow)
            component.mesh.setTexture(ts1, componentStar.noise_texture)
            # component.mesh.setTexture(ts1, texture)

            component.mesh.setShaderInput("time", universals.get_day_in_seconds())
            shaders = Shader.load(Shader.SLGLSL, "vortexVertex.glsl", "starFrag.glsl")
            component.mesh.setShader(shaders)
            sandbox.send("makePickable", [component.mesh])

        if universals.runClient and (DB["type"] == "solid" or DB["type"] == "moon"):
            component = graphicsComponents.RenderComponent()
            # component.mesh = shapeGenerator.Sphere(body.radius, 128, name)
            # component.mesh = shapeGenerator.Sphere(body.radius, 64, name)
            component.mesh = surface_mesh.make_planet(name=name, scale=body.radius)
            # sandbox.send('makePickable', [component.mesh])
            sandbox.send("makePickable", [component.mesh.node_path])
            # component.mesh.setScale(body.radius)
            component.mesh.reparent_to(sandbox.base.render)
            # Doing world text
            text = TextNode("node name")
            text.setText(name)
            # textNodePath = component.mesh.attachNewNode(text)
            textNodePath = component.mesh.node_path.attachNewNode(text)
            textNodePath.setScale(0.07)

            component.mesh.set_textures(DB["texture"], night_path=DB["night"], gloss_path=DB["spec"])

            component.mesh.set_ambient(1, 1, 1, 1)
            component.mesh.set_diffuse(1, 1, 1, 1)
            component.mesh.set_specular(1, 1, 1, 1)
            component.mesh.set_shininess(100)

            """if '#' in DB['texture']:
                component.mesh.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
                component.mesh.setTexProjector(TextureStage.getDefault(), sandbox.base.render, component.mesh)
                component.mesh.setTexScale(TextureStage.getDefault(), 1,  1, -1)
                component.mesh.setTexHpr(TextureStage.getDefault(), 90, -18, 90)
                #self.mesh.setHpr(0, 90, 0)
                texture = loader.loadCubeMap('planets/' + DB['texture'])
            else:
                texture = sandbox.base.loader.loadTexture('planets/' + DB['texture'])
            #texture.setMinfilter(Texture.FTLinearMipmapLinear)
            component.mesh.setTexture(texture, 1)"""
            """if "atmosphere" in DB:
                component.atmosphere = shapeGenerator.Sphere(-1, 128)
                component.atmosphere.reparentTo(render)
                component.atmosphere.setScale(body.radius * 1.025)
                outerRadius = component.atmosphere.getScale().getX()
                scale = 1 / (outerRadius - component.body.getScale().getX())
                component.atmosphere.setShaderInput("fOuterRadius", outerRadius)
                component.atmosphere.setShaderInput("fInnerRadius", component.mesh.getScale().getX())
                component.atmosphere.setShaderInput("fOuterRadius2", outerRadius * outerRadius)
                component.atmosphere.setShaderInput("fInnerRadius2",
                    component.mesh.getScale().getX()
                    * component.mesh.getScale().getX())

                component.atmosphere.setShaderInput("fKr4PI",
                    0.000055 * 4 * 3.14159)
                component.atmosphere.setShaderInput("fKm4PI",
                    0.000015 * 4 * 3.14159)

                component.atmosphere.setShaderInput("fScale", scale)
                component.atmosphere.setShaderInput("fScaleDepth", 0.25)
                component.atmosphere.setShaderInput("fScaleOverScaleDepth", scale / 0.25)

                # Currently hard coded in shader
                component.atmosphere.setShaderInput("fSamples", 10.0)
                component.atmosphere.setShaderInput("nSamples", 10)
                # These do sunsets and sky colors
                # Brightness of sun
                ESun = 15
                # Reyleight Scattering (Main sky colors)
                component.atmosphere.setShaderInput("fKrESun", 0.000055 * ESun)
                # Mie Scattering -- Haze and sun halos
                component.atmosphere.setShaderInput("fKmESun", 0.000015 * ESun)
                # Color of sun
                component.atmosphere.setShaderInput("v3InvWavelength", 1.0 / math.pow(0.650, 4),
                                                  1.0 / math.pow(0.570, 4),
                                                  1.0 / math.pow(0.465, 4))
                #component.atmosphere.setShader(Shader.load("atmo.cg"))"""
            bodyEntity.addComponent(component)
        log.info(name + " set Up")
        if "bodies" in DB:
            for bodyName, bodyDB in DB["bodies"].items():
                self.generateNode(bodyName, bodyDB, body)
Exemple #7
0
planet.reparentTo(sandbox.base.render)

planet.setPos(5, 20, 0)

mesh = shapeGenerator.Sphere(1, 64, 'star')
mesh.reparentTo(sandbox.base.render)

mesh.setPos(-5, 20, 0)

noise = PerlinNoise2(64, 64)
texture = Texture('noise')
texture.setup2dTexture()
img = PNMImage(1024, 1024)
for y in range(1024):
    for x in range(1024):
        img.setXel(x, y, noise.noise(x, y))
texture.load(img)
mesh.setTexture(texture, 1)

mesh.setShaderInput('time', 0)
#shaders = Shader.load(Shader.SLGLSL, 'vortexVertex.glsl', 'starFrag2.glsl')
shaders = Shader.load(Shader.SLGLSL, 'sphereVertex.glsl', 'starFrag2.glsl')
mesh.setShader(shaders)

light = mesh.attachNewNode(PointLight("sun"))
light.node().setColor(Vec4(1, 1, 1, 1))
sandbox.base.render.setLight(light)


def time_update(task):
    mesh.setShaderInput('time', task.time)
Exemple #8
0
    if channel == CHANNEL_AO:
        return img.getRed(x, y)
    elif channel == CHANNEL_ROUGHNESS:
        return img.getGreen(x, y)
    elif channel == CHANNEL_METALLIC:
        return img.getBlue(x, y)
    elif channel == CHANNEL_EMISSIVE:
        return img.getAlpha(x, y)


armeFile = raw_input("ARME file: ")
armeFilename = Filename.fromOsSpecific(armeFile)

img = PNMImage()
img.read(armeFilename)

for i in range(4):
    name = getChannelName(i).lower()
    print("Writing", name)
    chImg = PNMImage(img.getReadXSize(), img.getReadYSize())
    chImg.setNumChannels(1)
    chImg.setColorType(PNMImageHeader.CTGrayscale)
    for x in range(img.getReadXSize()):
        for y in range(img.getReadYSize()):
            val = getChannel(img, x, y, i)
            chImg.setXel(x, y, val)
    chImg.write(
        Filename(armeFilename.getFullpathWoExtension() + "_" + name + ".png"))

print("Done")
Exemple #9
0

def fBm(x, y, per, octs):
    val = 0
    for o in range(octs):
        val += 0.5**o * noise(x*2**o, y*2**o, per*2**o)
    return val

size, freq, octs, data = 128, 1/32.0, 5, []


p = PNMImage(128, 128)
for y in range(size):
    for x in range(size):
        #data.append(fBm(x*freq, y*freq, int(size*freq), octs))
        p.setXel(x, y, fBm(x*freq, y*freq, int(size*freq), octs))

#skysphere.setTexGen(TextureStage.getDefault(), TexGenAttrib.MEyeSphereMap)
tex.load(p)
skysphere.setTexture(tex)
'''skysphere.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
skysphere.setTexProjector(TextureStage.getDefault(), sandbox.base.render, skysphere)
skysphere.setTexPos(TextureStage.getDefault(), 0.5, 0.5, 0.5)
skysphere.setTexScale(TextureStage.getDefault(), 0.2)

''''''mesh = sandbox.base.loader.loadModel('ships/hyperion/hyperion')
mesh.setScale(0.001)
mesh.reparentTo(sandbox.base.render)''''''

#noise = PerlinNoise3(32, 32, 32, 256, 1)
noise = StackedPerlinNoise3(16, 16, 16, 3, 1, 0.5, 256, 1)
Exemple #10
0

def fBm(x, y, per, octs):
    val = 0
    for o in range(octs):
        val += 0.5**o * noise(x * 2**o, y * 2**o, per * 2**o)
    return val


size, freq, octs, data = 128, 1 / 32.0, 5, []

p = PNMImage(128, 128)
for y in range(size):
    for x in range(size):
        #data.append(fBm(x*freq, y*freq, int(size*freq), octs))
        p.setXel(x, y, fBm(x * freq, y * freq, int(size * freq), octs))

#skysphere.setTexGen(TextureStage.getDefault(), TexGenAttrib.MEyeSphereMap)
tex.load(p)
skysphere.setTexture(tex)
'''skysphere.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
skysphere.setTexProjector(TextureStage.getDefault(), sandbox.base.render, skysphere)
skysphere.setTexPos(TextureStage.getDefault(), 0.5, 0.5, 0.5)
skysphere.setTexScale(TextureStage.getDefault(), 0.2)

''' '''mesh = sandbox.base.loader.loadModel('ships/hyperion/hyperion')
mesh.setScale(0.001)
mesh.reparentTo(sandbox.base.render)''' '''

#noise = PerlinNoise3(32, 32, 32, 256, 1)
noise = StackedPerlinNoise3(16, 16, 16, 3, 1, 0.5, 256, 1)
Exemple #11
0
class WaterManager:
    """ Simple wrapper around WaterDisplacement which combines 3 displacement
    maps into one, and also generates a normal map """

    def __init__(self, water_options):
        self.options = water_options
        self.options.size = 512
        self.options.wind_dir.normalize()
        self.options.wave_amplitude *= 1e-7

        self.displacement_tex = Texture("Displacement")
        self.displacement_tex.setup_2d_texture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)

        self.normal_tex = Texture("Normal")
        self.normal_tex.setup_2d_texture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)

        self.combine_shader = Shader.load_compute(Shader.SLGLSL,
                                                  "/$$rp/rpcore/water/shader/combine.compute")

        self.pta_time = PTAFloat.emptyArray(1)

        # Create a gaussian random texture, as shaders aren't well suited
        # for that
        setRandomSeed(523)
        self.random_storage = PNMImage(self.options.size, self.options.size, 4)
        self.random_storage.setMaxval((2 ** 16) - 1)

        for x in range(self.options.size):
            for y in range(self.options.size):
                rand1 = self._get_gaussian_random() / 10.0 + 0.5
                rand2 = self._get_gaussian_random() / 10.0 + 0.5
                self.random_storage.setXel(x, y, float(rand1), float(rand2), 0)
                self.random_storage.setAlpha(x, y, 1.0)

        self.random_storage_tex = Texture("RandomStorage")
        self.random_storage_tex.load(self.random_storage)
        self.random_storage_tex.set_format(Texture.FRgba16)
        self.random_storage_tex.set_minfilter(Texture.FTNearest)
        self.random_storage_tex.set_magfilter(Texture.FTNearest)

        # Create the texture wwhere the intial height (H0 + Omega0) is stored.
        self.tex_initial_height = Texture("InitialHeight")
        self.tex_initial_height.setup_2d_texture(
            self.options.size, self.options.size,
            Texture.TFloat, Texture.FRgba16)
        self.tex_initial_height.set_minfilter(Texture.FTNearest)
        self.tex_initial_height.set_magfilter(Texture.FTNearest)

        # Create the shader which populates the initial height texture
        self.shader_initial_height = Shader.load_compute(Shader.SLGLSL,
                                                         "/$$rp/rpcore/water/shader/initial_height.compute")
        self.node_initial_height = NodePath("initialHeight")
        self.node_initial_height.set_shader(self.shader_initial_height)
        self.node_initial_height.set_shader_input("dest", self.tex_initial_height)
        self.node_initial_height.set_shader_input(
            "N", LVecBase2i(self.options.size))
        self.node_initial_height.set_shader_input(
            "patchLength", self.options.patch_length)
        self.node_initial_height.set_shader_input("windDir", self.options.wind_dir)
        self.node_initial_height.set_shader_input(
            "windSpeed", self.options.wind_speed)
        self.node_initial_height.set_shader_input(
            "waveAmplitude", self.options.wave_amplitude)
        self.node_initial_height.set_shader_input(
            "windDependency", self.options.wind_dependency)
        self.node_initial_height.set_shader_input(
            "randomTex", self.random_storage_tex)

        self.attr_initial_height = self.node_initial_height.get_attrib(ShaderAttrib)

        self.height_textures = []
        for i in range(3):
            tex = Texture("Height")
            tex.setup_2d_texture(self.options.size, self.options.size,
                                 Texture.TFloat, Texture.FRgba16)
            tex.set_minfilter(Texture.FTNearest)
            tex.set_magfilter(Texture.FTNearest)
            tex.set_wrap_u(Texture.WMClamp)
            tex.set_wrap_v(Texture.WMClamp)
            self.height_textures.append(tex)

        # Also create the shader which updates the spectrum
        self.shader_update = Shader.load_compute(Shader.SLGLSL,
                                                 "/$$rp/rpcore/water/shader/update.compute")
        self.node_update = NodePath("update")
        self.node_update.set_shader(self.shader_update)
        self.node_update.set_shader_input("outH0x", self.height_textures[0])
        self.node_update.set_shader_input("outH0y", self.height_textures[1])
        self.node_update.set_shader_input("outH0z", self.height_textures[2])
        self.node_update.set_shader_input("initialHeight", self.tex_initial_height)
        self.node_update.set_shader_input("N", LVecBase2i(self.options.size))
        self.node_update.set_shader_input("time", self.pta_time)
        self.attr_update = self.node_update.get_attrib(ShaderAttrib)

        # Create 3 FFTs
        self.fftX = GPUFFT(self.options.size, self.height_textures[0],
                           self.options.normalization_factor)
        self.fftY = GPUFFT(self.options.size, self.height_textures[1],
                           self.options.normalization_factor)
        self.fftZ = GPUFFT(self.options.size, self.height_textures[2],
                           self.options.normalization_factor)

        self.combine_node = NodePath("Combine")
        self.combine_node.set_shader(self.combine_shader)
        self.combine_node.set_shader_input(
            "displacementX", self.fftX.get_result_texture())
        self.combine_node.set_shader_input(
            "displacementY", self.fftY.get_result_texture())
        self.combine_node.set_shader_input(
            "displacementZ", self.fftZ.get_result_texture())
        self.combine_node.set_shader_input("normalDest", self.normal_tex)
        self.combine_node.set_shader_input(
            "displacementDest", self.displacement_tex)
        self.combine_node.set_shader_input(
            "N", LVecBase2i(self.options.size))
        self.combine_node.set_shader_input(
            "choppyScale", self.options.choppy_scale)
        self.combine_node.set_shader_input(
            "gridLength", self.options.patch_length)
        # Store only the shader attrib as this is way faster
        self.attr_combine = self.combine_node.get_attrib(ShaderAttrib)

    def _get_gaussian_random(self):
        """ Returns a gaussian random number """
        u1 = generateRandom()
        u2 = generateRandom()
        if u1 < 1e-6:
            u1 = 1e-6
        return sqrt(-2 * log(u1)) * cos(2 * pi * u2)

    def setup(self):
        """ Setups the manager """

        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size // 16, self.options.size // 16, 1),
            self.attr_initial_height,
            Globals.base.win.get_gsg())

    def get_displacement_texture(self):
        """ Returns the displacement texture, storing the 3D Displacement in
        the RGB channels """
        return self.displacement_tex

    def get_normal_texture(self):
        """ Returns the normal texture, storing the normal in world space in
        the RGB channels """
        return self.normal_tex

    def update(self):
        """ Updates the displacement / normal map """

        self.pta_time[0] = 1 + Globals.clock.get_frame_time() * self.options.time_scale

        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size // 16, self.options.size // 16, 1),
            self.attr_update,
            Globals.base.win.get_gsg())

        self.fftX.execute()
        self.fftY.execute()
        self.fftZ.execute()

        # Execute the shader which combines the 3 displacement maps into
        # 1 displacement texture and 1 normal texture. We could use dFdx in
        # the fragment shader, however that gives no accurate results as
        # dFdx returns the same value for a 2x2 pixel block
        Globals.base.graphicsEngine.dispatch_compute(
            (self.options.size // 16, self.options.size // 16, 1),
            self.attr_combine,
            Globals.base.win.get_gsg())
Exemple #12
0
class TerrainManager(DirectObject.DirectObject):
    def __init__(self):
        self.accept("mouse1", self.lclick)
        self.waterType = 2
        self.water = None
        self.citycolors = {0: VBase3D(1, 1, 1)}
    
        self.accept('generateRegion', self.generateWorld)
        self.accept('regenerateRegion', self.regenerateWorld)
        self.accept("regionView_normal", self.setSurfaceTextures)
        self.accept("regionView_owners", self.setOwnerTextures)
        self.accept("regionView_foundNew", self.regionViewFound)
        self.accept("updateRegion", self.updateRegion)
        self.accept("enterCityView", self.enterCity)
        
        # View: 0, region, # cityid
        self.view = 0
        self.ownerview = False
    
    def lclick(self):
        cell = picker.getMouseCell()
        print "Cell:", cell
        blockCoords = self.terrain.getBlockFromPos(cell[0], cell[1])
        block = self.terrain.getBlockNodePath(blockCoords[0], blockCoords[1])
        print "Block coords:", blockCoords
        print "NodePath:", block
        print "Elevation:", self.terrain.getElevation(cell[0], cell[1])
        if not self.view:
            messenger.send("clickForCity", [cell])
    
    def switchWater(self):
        print "Switch Water"
        self.waterType += 1
        if self.waterType > 2:
            self.waterType = 0
        self.generateWater(self.waterType)
    
    def generateWorld(self, heightmap, tiles, cities, container):
        self.heightmap = heightmap
        self.terrain = PagedGeoMipTerrain("surface")
        #self.terrain = GeoMipTerrain("surface")
        self.terrain.setHeightfield(self.heightmap)
        #self.terrain.setFocalPoint(base.camera)
        self.terrain.setBruteforce(True)
        self.terrain.setBlockSize(64)
        self.terrain.generate()

        root = self.terrain.getRoot()
        root.reparentTo(render)
        #root.setSz(100)
        self.terrain.setSz(100)
        messenger.send('makePickable', [root])   
        
        if self.heightmap.getXSize() > self.heightmap.getYSize():
            self.size = self.heightmap.getXSize()-1
        else:
            self.size = self.heightmap.getYSize()-1
        self.xsize = self.heightmap.getXSize()-1
        self.ysize = self.heightmap.getYSize()-1
                
        # Set multi texture
        # Source http://www.panda3d.org/phpbb2/viewtopic.php?t=4536
        self.generateSurfaceTextures()
        self.generateWaterMap()
        self.generateOwnerTexture(tiles, cities)
        #self.terrain.makeTextureMap()
        colormap = PNMImage(heightmap.getXSize()-1, heightmap.getYSize()-1)
        colormap.addAlpha()
        slopemap = self.terrain.makeSlopeImage()
        for x in range(0, colormap.getXSize()):
            for y in range(0, colormap.getYSize()):
                # Else if statements used to make sure one channel is used per pixel
                # Also for some optimization
                # Snow. We do things funky here as alpha will be 1 already.
                if heightmap.getGrayVal(x, y) < 200:
                    colormap.setAlpha(x, y, 0)
                else:
                    colormap.setAlpha(x, y, 1)
                # Beach. Estimations from http://www.simtropolis.com/omnibus/index.cfm/Main.SimCity_4.Custom_Content.Custom_Terrains_and_Using_USGS_Data
                if heightmap.getGrayVal(x,y) < 62:
                    colormap.setBlue(x, y, 1)
                # Rock
                elif slopemap.getGrayVal(x, y) > 170:
                    colormap.setRed(x, y, 1)
                else:
                    colormap.setGreen(x, y, 1)
        self.colorTexture = Texture()
        self.colorTexture.load(colormap)
        self.colorTS = TextureStage('color')
        self.colorTS.setSort(0)
        self.colorTS.setPriority(1)
            
        self.setSurfaceTextures()
        self.generateWater(2)
        taskMgr.add(self.updateTerrain, "updateTerrain")
        print "Done with terrain generation"
        messenger.send("finishedTerrainGen", [[self.xsize, self.ysize]])
        self.terrain.getRoot().analyze()
        self.accept("h", self.switchWater)
    
    def regenerateWorld(self):
        '''Regenerates world, often upon city exit.'''
        self.terrain.generate()
        root = self.terrain.getRoot()
        root.reparentTo(render)
        self.terrain.setSz(100)
        messenger.send('makePickable', [root])   
        # Set multi texture
        # Source http://www.panda3d.org/phpbb2/viewtopic.php?t=4536
        #self.generateSurfaceTextures()
        self.generateWaterMap()
        
        self.setSurfaceTextures()
        self.generateWater(2)
        print "Done with terrain regeneration"
        messenger.send("finishedTerrainGen", [[self.xsize, self.ysize]])
    
    def generateWaterMap(self):
        ''' Iterate through every pix of color map. This will be very slow so until faster method is developed, use sparingly
        getXSize returns pixels length starting with 1, subtract 1 for obvious reasons
        We also slip in checking for the water card size, which should only change when the color map does
        '''
        print "GenerateWaterMap"
        self.waterXMin, self.waterXMax, self.waterYMin, self.waterYMax = -1,0,-1,0
        for x in range(0, self.heightmap.getXSize()-1):
            for y in range(0, self.heightmap.getYSize()-1):
                # Else if statements used to make sure one channel is used per pixel
                # Also for some optimization
                # Snow. We do things funky here as alpha will be 1 already.
                if self.heightmap.getGrayVal(x,y) < 62:
                    # Water card dimensions here
                    # Y axis flipped from texture space to world space
                    if self.waterXMin == -1 or x < self.waterXMin:
                        self.waterXMin = x
                    if not self.waterYMax:
                        self.waterYMax = y
                    if y < self.waterYMax:
                        self.waterYMax = y
                    if x > self.waterXMax:
                        self.waterXMax = x
                    if y > self.waterYMin:
                        self.waterYMin = y
        # Transform y coords
        self.waterYMin = self.size-64 - self.waterYMin
        self.waterYMax = self.size-64 - self.waterYMax
    
    def generateOwnerTexture(self, tiles, cities):
        '''Generates a simple colored texture to be applied to the city info region overlay.
        Due to different coordinate systems (terrain org bottom left, texture top left)
        some conversions are needed,
        
        Also creates and sends a citylabels dict for the region view
        '''
        self.citymap = PNMImage(self.xsize, self.ysize)
        citylabels = cities
        scratch = {}
        
        # Setup for city labels
        for ident in cities:
            scratch[ident] = []
        
        # conversion for y axis
        ycon = []
        s = self.ysize - 1
        for y in range(self.ysize):
            ycon.append(s)
            s -= 1
        for ident, city in cities.items():
            if ident not in self.citycolors:
                self.citycolors[ident] = VBase3D(random.random(), random.random(), random.random())
        for tile in tiles:
            self.citymap.setXel(tile.coords[0], ycon[tile.coords[1]], self.citycolors[tile.cityid])
            # Scratch for labeling
            if tile.cityid:
                scratch[tile.cityid].append((tile.coords[0], tile.coords[1]))
        for ident, values in scratch.items():
            xsum = 0
            ysum = 0
            n = 0
            for coords in values:
                xsum += coords[0]
                ysum += coords[1]
                n += 1
            xavg = xsum/n
            yavg = ysum/n
            print "Elevation:", self.terrain.getElevation(xavg, yavg)
            z = self.terrain.getElevation(xavg, yavg)*100
            citylabels[ident]["position"] = (xavg, yavg, z+15)
            print "Citylabels:", citylabels
        messenger.send("updateCityLabels", [citylabels, self.terrain])
    
    def generateSurfaceTextures(self):
        # Textureize
        self.grassTexture = loader.loadTexture("Textures/grass.png")
        self.grassTS = TextureStage('grass')
        self.grassTS.setSort(1)
        
        self.rockTexture = loader.loadTexture("Textures/rock.jpg")
        self.rockTS = TextureStage('rock')
        self.rockTS.setSort(2)
        self.rockTS.setCombineRgb(TextureStage.CMAdd, TextureStage.CSLastSavedResult, TextureStage.COSrcColor, TextureStage.CSTexture, TextureStage.COSrcColor)
        
        self.sandTexture = loader.loadTexture("Textures/sand.jpg")
        self.sandTS = TextureStage('sand')
        self.sandTS.setSort(3)
        self.sandTS.setPriority(5)
        
        self.snowTexture = loader.loadTexture("Textures/ice.png")
        self.snowTS = TextureStage('snow')
        self.snowTS.setSort(4)
        self.snowTS.setPriority(0)
        
        # Grid for city placement and guide and stuff
        self.gridTexture = loader.loadTexture("Textures/grid.png")
        self.gridTexture.setWrapU(Texture.WMRepeat)
        self.gridTexture.setWrapV(Texture.WMRepeat)
        self.gridTS = TextureStage('grid')
        self.gridTS.setSort(5)
        self.gridTS.setPriority(10)
    
    def enterCity(self, ident, city, position, tiles):
        '''Identifies which terrain blocks city belogs to and disables those that are not
        A lot of uneeded for loops in here. Will need to find a better way later.'''
        #root = self.terrain.getRoot()
        children = []
        for terrain in self.terrain.terrains:
            root = terrain.getRoot()
            children += root.getChildren()
        keepBlocks = []
        # Reset water dimentions
        self.waterXMin = 0
        self.waterXMax = 0
        self.waterYMin = 0
        self.waterYMax = 0
        
        for tile in tiles:
            blockCoords = self.terrain.getBlockFromPos(tile.coords[0], tile.coords[1])
            block = self.terrain.getBlockNodePath(blockCoords[0], blockCoords[1])
            if block not in keepBlocks:
                keepBlocks.append(block)
            if self.heightmap.getGrayVal(tile.coords[0], self.size-tile.coords[1]) < 62:
                # Water card dimensions here
                # Y axis flipped from texture space to world space
                if not self.waterXMin:
                    self.waterXMin = tile.coords[0]
                if not self.waterYMin:
                    self.waterYMin = tile.coords[1]
                if tile.coords[1] > self.waterYMax:
                    self.waterYMax = tile.coords[1]
                if tile.coords[0] > self.waterXMax:
                    self.waterXMax = tile.coords[0]
                if tile.coords[0] < self.waterXMin:
                    self.waterXMin = tile.coords[0]
                if tile.coords[1] < self.waterYMin:
                    self.waterYMin = tile.coords[1]
        for child in children:
            if child not in keepBlocks:
                child.detachNode()
        self.view = ident
        self.generateWater(2)
    
    def newTerrainOverlay(self, task):
        root = self.terrain.getRoot()
        position = picker.getMouseCell()
        if position:
            # Check to make sure we do not go out of bounds
            if position[0] < 32:
                position = (32, position[1])
            elif position[0] > self.xsize-32:
                position = (self.xsize-32, position[1])
            if position[1] < 32:
                position = (position[0], 32)
            elif position [1] > self.ysize-32:
                position = (position[0], self.size-32)                
            root.setTexOffset(self.tileTS, -(position[0]-32)/64, -(position[1]-32)/64)
        return task.cont
    
    def regionViewFound(self):
        '''Gui for founding a new city!'''
        self.setOwnerTextures()
        root = self.terrain.getRoot()
        task = taskMgr.add(self.newTerrainOverlay, "newTerrainOverlay")
        tileTexture = loader.loadTexture("Textures/tile.png")
        tileTexture.setWrapU(Texture.WMClamp)
        tileTexture.setWrapV(Texture.WMClamp)
        self.tileTS = TextureStage('tile')
        self.tileTS.setSort(6)
        self.tileTS.setMode(TextureStage.MDecal)
        #self.tileTS.setColor(Vec4(1,0,1,1))
        root.setTexture(self.tileTS, tileTexture)
        root.setTexScale(self.tileTS, self.terrain.xchunks, self.terrain.ychunks)
        self.acceptOnce("mouse1", self.regionViewFound2)
        self.acceptOnce("escape", self.cancelRegionViewFound)
    
    def regionViewFound2(self):
        '''Grabs cell location for founding.
        The texture coordinate is used as the mouse may enter an out of bounds area.
        '''
        root = self.terrain.getRoot()
        root_position = root.getTexOffset(self.tileTS)
        # We offset the position of the texture, so we will now put the origin of the new city not on mouse cursor but the "bottom left" of it. Just need to add 32 to get other edge
        position = [int(abs(root_position[0]*64)), int(abs(root_position[1]*64))]
        self.cancelRegionViewFound()
        messenger.send("found_city_name", [position])
    
    def cancelRegionViewFound(self):
        taskMgr.remove("newTerrainOverlay")
        root = self.terrain.getRoot()
        root.clearTexture(self.tileTS)
        # Restore original mouse function
        self.accept("mouse1", self.lclick)
        messenger.send("showRegionGUI")
    
    def setSurfaceTextures(self):
        self.ownerview = False
        root = self.terrain.getRoot()
        root.clearTexture()
        #self.terrain.setTextureMap()
        root.setTexture( self.colorTS, self.colorTexture )
        root.setTexture( self.grassTS, self.grassTexture )
        root.setTexScale(self.grassTS, self.size/8, self.size/8) 
        root.setTexture( self.rockTS, self.rockTexture ) 
        root.setTexScale(self.rockTS, self.size/8, self.size/8) 
        root.setTexture( self.sandTS, self.sandTexture) 
        root.setTexScale(self.sandTS, self.size/8, self.size/8) 
        root.setTexture( self.snowTS, self.snowTexture ) 
        root.setTexScale(self.snowTS, self.size/8, self.size/8) 
        root.setTexture( self.gridTS, self.gridTexture ) 
        root.setTexScale(self.gridTS, self.xsize, self.ysize)
        root.setShaderInput('size', self.xsize, self.ysize, self.size, self.size)
        root.setShader(loader.loadShader('Shaders/terraintexture.sha'))
    
    def setOwnerTextures(self):
        self.ownerview = True
        root = self.terrain.getRoot()
        root.clearShader()
        root.clearTexture()
        cityTexture = Texture()
        cityTexture.load(self.citymap)
        cityTS = TextureStage('citymap')
        cityTS.setSort(0)
        root.setTexture( self.gridTS, self.gridTexture ) 
        root.setTexScale(self.gridTS, self.terrain.xchunks, self.terrain.ychunks)
        root.setTexture(cityTS, cityTexture, 1)
    
    def updateRegion(self, heightmap, tiles, cities):
        self.generateOwnerTexture(tiles, cities)
        if self.ownerview:
            self.setOwnerTextures()
    
    def updateTerrain(self, task):
        '''Updates terrain and water'''
        self.terrain.update()
        # Water
        if self.waterType is 2:
            pos = base.camera.getPos()
            render.setShaderInput('time', task.time)
            mc = base.camera.getMat( )
            self.water.changeCameraPos(pos,mc)
            self.water.changeCameraPos(pos,mc)
        #print "Render diagnostics"
        #render.analyze()
        #base.cTrav.showCollisions(render)
        return task.cont 
    
    def generateWater(self, style):
        print "Generate Water:", self.waterXMin, self.waterXMax, self.waterYMin,  self.waterYMax
        '''Generates water
        style 0: blue card
        style 1: reflective card
        style 2: reflective card with shaders
        '''
        self.waterHeight = 22.0
        if self.water:
            self.water.removeNode()
        if style is 0:
            cm = CardMaker("water")
            #cm.setFrame(-1, 1, -1, 1)
            cm.setFrame(self.waterXMin, self.waterXMax, self.waterYMin,  self.waterYMax)
            cm.setColor(0, 0, 1, 0.9)
            self.water = render.attachNewNode(cm.generate())
            if self.waterYMax > self.waterXMax:
                size = self.waterYMax
            else:
                size = self.waterXMax
            self.water.lookAt(0, 0, -1)
            self.water.setZ(self.waterHeight)
            messenger.send('makePickable', [self.water])
        elif style is 1:
            # From Prosoft's super awesome terrain demo
            cm = CardMaker("water")
            #cm.setFrame(-1, 1, -1, 1)
            cm.setFrame(self.waterXMin, self.waterXMax, self.waterYMin,  self.waterYMax)
            self.water = render.attachNewNode(cm.generate())
            if self.waterYMax > self.waterXMax:
                size = self.waterYMax
            else:
                size = self.waterXMax
            #self.water.setScale(size)
            self.water.lookAt(0, 0, -1)
            self.water.setZ(self.waterHeight)
            self.water.setShaderOff(1)
            self.water.setLightOff(1)
            self.water.setAlphaScale(0.5)
            self.water.setTransparency(TransparencyAttrib.MAlpha)
            wbuffer = base.win.makeTextureBuffer("water", 512, 512)
            wbuffer.setClearColorActive(True)
            wbuffer.setClearColor(base.win.getClearColor())
            self.wcamera = base.makeCamera(wbuffer)
            self.wcamera.reparentTo(render)
            self.wcamera.node().setLens(base.camLens)
            self.wcamera.node().setCameraMask(BitMask32.bit(1))
            self.water.hide(BitMask32.bit(1))
            wtexture = wbuffer.getTexture()
            wtexture.setWrapU(Texture.WMClamp)
            wtexture.setWrapV(Texture.WMClamp)
            wtexture.setMinfilter(Texture.FTLinearMipmapLinear)
            self.wplane = Plane(Vec3(0, 0, 1), Point3(0, 0, self.water.getZ()))
            wplanenp = render.attachNewNode(PlaneNode("water", self.wplane))
            tmpnp = NodePath("StateInitializer")
            tmpnp.setClipPlane(wplanenp)
            tmpnp.setAttrib(CullFaceAttrib.makeReverse())
            self.wcamera.node().setInitialState(tmpnp.getState())
            self.water.projectTexture(TextureStage("reflection"), wtexture, self.wcamera)
            messenger.send('makePickable', [self.water])
        elif style is 2:
            # From Clcheung just as super awesome demomaster
            self.water_level = Vec4(0.0, 0.0, self.waterHeight, 1.0)
            self.water = water.WaterNode(self.waterXMin, self.waterYMin, self.waterXMax, self.waterYMax, self.water_level.getZ())
            self.water.setStandardControl()
            self.water.changeParams(None)
            wl=self.water_level
            wl.setZ(wl.getZ()-0.05)
            #root.setShaderInput('waterlevel', self.water_level)
            render.setShaderInput('time', 0)
            messenger.send('makePickable', [self.water.waterNP])
Exemple #13
0
    def generateNode(self, name, DB, parentNode):
        log.debug("Setting up " + name)
        bodyEntity = sandbox.createEntity()
        component = CelestialComponent()
        if DB['type'] == 'solid':
            body = Body(name)
        elif DB['type'] == 'moon':
            body = Body(name)
            body.kind = "moon"
        elif DB['type'] == 'star':
            body = Star(name)
            body.absoluteM = DB['absolute magnitude']
            body.spectral = DB['spectral']
        elif DB['type'] == 'barycenter':
            body = BaryCenter(name)

        component.kind = TYPES[DB['type']]

        if DB['type'] != "barycenter":
            component.mass = DB['mass']
            body.radius = DB['radius']
            body.rotation = DB['rotation']

        if 'orbit' in DB:
            component.orbit = DB['orbit']
            body.period = DB['period']
            #body.setPos(self.get2DBodyPosition(component, universals.day))
            component.truePos = self.get2DBodyPosition(component, universals.day)
            if name == "Earth":
                #universals.spawn = component.truePos + LPoint3d(0, 6671, 0)
                universals.spawn = component.truePos + LPoint3d(6671, 0, 0)

        if parentNode == universals.solarSystemRoot:
            universals.defaultSOIid = bodyEntity.id
            component.soi = 0
        elif DB['type'] != 'star' or DB['type'] != 'barycenter':
            component.soi = self.getSOI(component.mass, self.bodies[0].mass, component.orbit['a'])

        body.type = DB['type']
        body.reparentTo(parentNode)
        component.nodePath = body
        self.bodies.append(component)
        bodyEntity.addComponent(component)

        if universals.runClient and DB['type'] == 'star':
            component = graphicsComponents.RenderComponent()
            #component.mesh = NodePath(name)
            #self.sphere.copyTo(component.mesh)
            #component.mesh = shapeGenerator.Sphere(body.radius, 128, name)
            component.mesh = shapeGenerator.Sphere(body.radius, 64, name)
            #component.mesh.setScale(body.radius)
            component.mesh.reparentTo(sandbox.base.render)
            sandbox.send('makePickable', [component.mesh])
            #texture = sandbox.base.loader.loadTexture('planets/' + DB['texture'])
            #texture.setMinfilter(Texture.FTLinearMipmapLinear)
            #ts1 = TextureStage('textures1')
            #ts1.setMode(TextureStage.MGlow)
            #component.mesh.setTexture(ts1, texture)
            #component.mesh.setTexture(texture, 1)

            component.light = component.mesh.attachNewNode(PointLight("sunPointLight"))
            component.light.node().setColor(Vec4(1, 1, 1, 1))
            sandbox.base.render.setLight(component.light)
            bodyEntity.addComponent(component)

            #Shader test
            componentStar = graphicsComponents.StarRender()
            componentStar.noise_texture = Texture('noise')
            componentStar.noise_texture.setup2dTexture()
            img = PNMImage(1024, 1024)
            for y in range(1024):
                for x in range(1024):
                    img.setXel(x, y, componentStar.noise.noise(x, y))
                    #print componentStar.noise.noise(x, y)
            componentStar.noise_texture.load(img)
            #componentStar.noise_texture.write('test.png')
            #component.mesh.setTexture(componentStar.noise_texture, 1)

            texture = sandbox.base.loader.loadTexture('planets/' + DB['texture'])
            ts1 = TextureStage('textures1')
            ts1.setMode(TextureStage.MGlow)
            component.mesh.setTexture(ts1, componentStar.noise_texture)
            #component.mesh.setTexture(ts1, texture)

            component.mesh.setShaderInput('time', universals.get_day_in_seconds())
            shaders = Shader.load(Shader.SLGLSL, 'vortexVertex.glsl', 'starFrag.glsl')
            component.mesh.setShader(shaders)
            sandbox.send('makePickable', [component.mesh])


        if universals.runClient and (DB['type'] == 'solid' or DB['type'] == 'moon'):
            component = graphicsComponents.RenderComponent()
            #component.mesh = shapeGenerator.Sphere(body.radius, 128, name)
            #component.mesh = shapeGenerator.Sphere(body.radius, 64, name)
            component.mesh = surface_mesh.make_planet(name=name, scale=body.radius)
            #sandbox.send('makePickable', [component.mesh])
            sandbox.send('makePickable', [component.mesh.node_path])
            #component.mesh.setScale(body.radius)
            component.mesh.reparent_to(sandbox.base.render)
            # Doing world text
            text = TextNode('node name')
            text.setText(name)
            #textNodePath = component.mesh.attachNewNode(text)
            textNodePath = component.mesh.node_path.attachNewNode(text)
            textNodePath.setScale(0.07)

            component.mesh.set_textures(DB['texture'],
                night_path=DB['night'],
                gloss_path=DB['spec'])


            component.mesh.set_ambient(1, 1, 1, 1)
            component.mesh.set_diffuse(1, 1, 1, 1)
            component.mesh.set_specular(1, 1, 1, 1)
            component.mesh.set_shininess(100)

            '''if '#' in DB['texture']:
                component.mesh.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
                component.mesh.setTexProjector(TextureStage.getDefault(), sandbox.base.render, component.mesh)
                component.mesh.setTexScale(TextureStage.getDefault(), 1,  1, -1)
                component.mesh.setTexHpr(TextureStage.getDefault(), 90, -18, 90)
                #self.mesh.setHpr(0, 90, 0)
                texture = loader.loadCubeMap('planets/' + DB['texture'])
            else:
                texture = sandbox.base.loader.loadTexture('planets/' + DB['texture'])
            #texture.setMinfilter(Texture.FTLinearMipmapLinear)
            component.mesh.setTexture(texture, 1)'''
            '''if "atmosphere" in DB:
                component.atmosphere = shapeGenerator.Sphere(-1, 128)
                component.atmosphere.reparentTo(render)
                component.atmosphere.setScale(body.radius * 1.025)
                outerRadius = component.atmosphere.getScale().getX()
                scale = 1 / (outerRadius - component.body.getScale().getX())
                component.atmosphere.setShaderInput("fOuterRadius", outerRadius)
                component.atmosphere.setShaderInput("fInnerRadius", component.mesh.getScale().getX())
                component.atmosphere.setShaderInput("fOuterRadius2", outerRadius * outerRadius)
                component.atmosphere.setShaderInput("fInnerRadius2",
                    component.mesh.getScale().getX()
                    * component.mesh.getScale().getX())

                component.atmosphere.setShaderInput("fKr4PI",
                    0.000055 * 4 * 3.14159)
                component.atmosphere.setShaderInput("fKm4PI",
                    0.000015 * 4 * 3.14159)

                component.atmosphere.setShaderInput("fScale", scale)
                component.atmosphere.setShaderInput("fScaleDepth", 0.25)
                component.atmosphere.setShaderInput("fScaleOverScaleDepth", scale / 0.25)

                # Currently hard coded in shader
                component.atmosphere.setShaderInput("fSamples", 10.0)
                component.atmosphere.setShaderInput("nSamples", 10)
                # These do sunsets and sky colors
                # Brightness of sun
                ESun = 15
                # Reyleight Scattering (Main sky colors)
                component.atmosphere.setShaderInput("fKrESun", 0.000055 * ESun)
                # Mie Scattering -- Haze and sun halos
                component.atmosphere.setShaderInput("fKmESun", 0.000015 * ESun)
                # Color of sun
                component.atmosphere.setShaderInput("v3InvWavelength", 1.0 / math.pow(0.650, 4),
                                                  1.0 / math.pow(0.570, 4),
                                                  1.0 / math.pow(0.465, 4))
                #component.atmosphere.setShader(Shader.load("atmo.cg"))'''
            bodyEntity.addComponent(component)
        log.info(name + " set Up")
        if 'bodies' in DB:
            for bodyName, bodyDB in DB['bodies'].items():
                self.generateNode(bodyName, bodyDB, body)
Exemple #14
0
planet.reparentTo(sandbox.base.render)

planet.setPos(5, 20, 0)

mesh = shapeGenerator.Sphere(1, 64, 'star')
mesh.reparentTo(sandbox.base.render)

mesh.setPos(-5, 20, 0)

noise = PerlinNoise2(64, 64)
texture = Texture('noise')
texture.setup2dTexture()
img = PNMImage(1024, 1024)
for y in range(1024):
    for x in range(1024):
        img.setXel(x, y, noise.noise(x, y))
texture.load(img)
mesh.setTexture(texture, 1)

mesh.setShaderInput('time', 0)
#shaders = Shader.load(Shader.SLGLSL, 'vortexVertex.glsl', 'starFrag2.glsl')
shaders = Shader.load(Shader.SLGLSL, 'sphereVertex.glsl', 'starFrag2.glsl')
mesh.setShader(shaders)

light = mesh.attachNewNode(PointLight("sun"))
light.node().setColor(Vec4(1, 1, 1, 1))
sandbox.base.render.setLight(light)


def time_update(task):
    mesh.setShaderInput('time', task.time)

from panda3d.core import PNMImage, Vec3

lutSize = 32

image = PNMImage(lutSize * lutSize, lutSize, 3, 2**16 - 1)


for r in xrange(lutSize):
    for g in xrange(lutSize):
        for b in xrange(lutSize):
            image.setXel(r + b * lutSize, g, r / float(lutSize), g / float(lutSize), b / float(lutSize))

image.write("Default.png")
class ColorPicker(NodePath):
    def __init__(self,
                 parent,
                 minSat,
                 maxSat,
                 minVal,
                 maxVal,
                 callback,
                 pos=(0, 0, 0)):
        NodePath.__init__(self, 'colorPicker')
        self.reparentTo(parent)
        self.setPos(pos)

        self.minSat = minSat
        self.maxSat = maxSat
        self.minVal = minVal
        self.maxVal = maxVal
        self.callback = callback
        self.lastColor = None

        self.image = PNMImage(int((self.maxSat - self.minSat) * 100),
                              int((self.maxVal - self.minVal) * 100))
        self.slider = DirectSlider(self,
                                   relief=None,
                                   image='phase_3/maps/color_picker_hue.jpg',
                                   scale=0.3,
                                   pos=(0.2, 0, 0),
                                   image_scale=(0.1, 1.0, 1.0),
                                   pageSize=5,
                                   orientation=DGG.VERTICAL,
                                   command=self.__chooseHue)
        self.button = DirectButton(self,
                                   relief=None,
                                   image=None,
                                   scale=0.3,
                                   pos=(-0.2, 0, 0),
                                   frameColor=(1, 1, 1, 0.1),
                                   pressEffect=0)
        self.button.bind(DGG.B1PRESS, self.__startPick)
        self.button.bind(DGG.B1RELEASE, self.__stopPick)
        self.__chooseHue()

    def uniqueName(self, name):
        return 'ColorPicker-%s-%s' % (id(self), name)

    def removeNode(self):
        NodePath.removeNode(self)
        self.destroy()

    def destroy(self):
        if not self.slider:
            return

        self.__stopPick()
        self.slider.destroy()
        self.button.destroy()
        self.slider = None
        self.button = None
        self.image = None

    def __calcRelative(self, value, baseMin, baseMax, limitMin, limitMax):
        return ((limitMax - limitMin) * (value - baseMin) /
                (baseMax - baseMin)) + limitMin

    def __chooseHue(self):
        for x in xrange(self.image.getXSize()):
            for y in xrange(self.image.getYSize()):
                self.image.setXel(
                    x, y,
                    colorsys.hsv_to_rgb(self.slider['value'],
                                        (x / 100.0) + self.minSat,
                                        (y / 100.0) + self.minVal))

        texture = Texture()
        texture.load(self.image)
        self.button['image'] = texture

    def __pickColor(self, task):
        x = base.mouseWatcherNode.getMouseX()
        y = base.mouseWatcherNode.getMouseY()
        win_w, win_h = base.win.getSize()

        if win_w < win_h:
            y *= 1. * win_h / win_w
        else:
            x *= 1. * win_w / win_h

        x -= self.button.getX(aspect2d)
        y -= self.button.getZ(aspect2d)
        image_scale = self.button['image_scale']
        x = (.5 + x / (2. * self.button.getSx(aspect2d) * image_scale[0]))
        y = (.5 + y / -(2. * self.button.getSz(aspect2d) * image_scale[2]))

        if not (0.0 <= x <= 1.0 and 0.0 <= y <= 1.0):
            return task.cont

        x = self.__calcRelative(x, 0.0, 1.0, self.minSat, self.maxSat)
        y = self.__calcRelative(y, 0.0, 1.0, self.minVal, self.maxVal)
        rgb = colorsys.hsv_to_rgb(self.slider['value'], x, y) + (1, )
        rgb = tuple([float('%.2f' % x) for x in rgb])

        if self.lastColor != rgb:
            self.callback(rgb)
            self.lastColor = rgb

        return task.cont

    def __startPick(self, extra=None):
        self.__stopPick()
        taskMgr.add(self.__pickColor, self.uniqueName('colorDragTask'))

    def __stopPick(self, extra=None):
        taskMgr.remove(self.uniqueName('colorDragTask'))