Пример #1
0
    def fillTextureStages(self, nodePath):
        """ Prepares all materials of a given nodepath to have at least the 4 
        default textures in the correct order: [diffuse, normal, specular, roughness] """
        
        emptyDiffuseTex = loader.loadTexture("Data/Textures/EmptyDiffuseTexture.png")
        emptyNormalTex = loader.loadTexture("Data/Textures/EmptyNormalTexture.png")
        emptySpecularTex = loader.loadTexture("Data/Textures/EmptySpecularTexture.png")
        emptyRoughnessTex = loader.loadTexture("Data/Textures/EmptyRoughnessTexture.png")

        textureOrder = [emptyDiffuseTex, emptyNormalTex, emptySpecularTex, emptyRoughnessTex]
        textureSorts = [0, 10, 20, 30]

        # Prepare the textures
        for tex in textureOrder:
            tex.setMinfilter(SamplerState.FTLinear)
            tex.setMagfilter(SamplerState.FTLinear)
            tex.setFormat(Texture.FRgba)

        # Iterate over all geom nodes
        for np in nodePath.findAllMatches("**/+GeomNode"):

            # Check how many texture stages the nodepath already has
            stages = np.findAllTextureStages()
            numStages = len(stages)

            # Fill the texture stages up
            for i in xrange(numStages, 4):
                stage = TextureStage("DefaultTexStage" + str(i))
                stage.setSort(textureSorts[i])
                stage.setMode(TextureStage.CMModulate)
                stage.setColor(Vec4(0, 0, 0, 1))
                np.setTexture(stage, textureOrder[i])
    def fillTextureStages(self, nodePath):
        """ Prepares all materials of a given nodepath to have at least the 4 
        default textures in the correct order: [diffuse, normal, specular, roughness] """
        
        emptyDiffuseTex = loader.loadTexture("Data/Textures/EmptyDiffuseTexture.png")
        emptyNormalTex = loader.loadTexture("Data/Textures/EmptyNormalTexture.png")
        emptySpecularTex = loader.loadTexture("Data/Textures/EmptySpecularTexture.png")
        emptyRoughnessTex = loader.loadTexture("Data/Textures/EmptyRoughnessTexture.png")

        textureOrder = [emptyDiffuseTex, emptyNormalTex, emptySpecularTex, emptyRoughnessTex]
        textureSorts = [0, 10, 20, 30]

        # Prepare the textures
        for tex in textureOrder:
            tex.setMinfilter(SamplerState.FTLinear)
            tex.setMagfilter(SamplerState.FTLinear)
            tex.setFormat(Texture.FRgba)

        # Iterate over all geom nodes
        for np in nodePath.findAllMatches("**/+GeomNode"):

            # Check how many texture stages the nodepath already has
            stages = np.findAllTextureStages()
            numStages = len(stages)

            # Fill the texture stages up
            for i in xrange(numStages, 4):
                stage = TextureStage("DefaultTexStage" + str(i))
                stage.setSort(textureSorts[i])
                stage.setMode(TextureStage.CMModulate)
                stage.setColor(Vec4(0, 0, 0, 1))
                np.setTexture(stage, textureOrder[i])
Пример #3
0
 def makeTextureMap(self):
     '''Citymania function that generates and sets the 4 channel texture map'''
     self.colorTextures = []
     for terrain in self.terrains:
         terrain.getRoot().clearTexture()
         heightmap = terrain.heightfield()
         colormap = PNMImage(heightmap.getXSize()-1, heightmap.getYSize()-1)
         colormap.addAlpha()
         slopemap = 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)
         colorTexture = Texture()
         colorTexture.load(colormap)
         colorTS = TextureStage('color')
         colorTS.setSort(0)
         colorTS.setPriority(1)
         self.colorTextures.append((colorTexture, colorTS))
Пример #4
0
 def makeTextureMap(self):
     '''Citymania function that generates and sets the 4 channel texture map'''
     self.colorTextures = []
     for terrain in self.terrains:
         terrain.getRoot().clearTexture()
         heightmap = terrain.heightfield()
         colormap = PNMImage(heightmap.getXSize() - 1,
                             heightmap.getYSize() - 1)
         colormap.addAlpha()
         slopemap = 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)
         colorTexture = Texture()
         colorTexture.load(colormap)
         colorTS = TextureStage('color')
         colorTS.setSort(0)
         colorTS.setPriority(1)
         self.colorTextures.append((colorTexture, colorTS))
Пример #5
0
 def __apply_Textures(self, recipe, tex_dict):
     for i, ter_dict in enumerate(recipe['terrains']):
         tex_img = PNMImage()
         tex_img.read(Filename("{}/tex/{}".format(recipe['planet_path'], ter_dict['texture'])))
         tex = Texture()
         tex.load(tex_img)
         tex.setMinfilter(Texture.FTLinear)
         ts = TextureStage(str(i))
         ts.setSort(i)
         self.NP.setTexture(ts, tex, i*10)
Пример #6
0
 def __apply_Textures(self, recipe, tex_dict):
     for i, ter_dict in enumerate(recipe['terrains']):
         tex_img = PNMImage()
         tex_img.read(Filename("{}/tex/{}".format(recipe['planet_path'], ter_dict['texture'])))
         tex = Texture()
         tex.load(tex_img)
         tex.setMinfilter(Texture.FTLinear)
         ts = TextureStage(str(i))
         ts.setSort(i)
         self.NP.setTexture(ts, tex, i*10)
Пример #7
0
def addTexture(stage,path):
    tex=loader.loadTexture(path)
    tex.setWrapU(Texture.WMRepeat)
    tex.setWrapV(Texture.WMRepeat)
    s=str(stage)
    TS=model.findTextureStage(s)
    if not TS:
       TS=TextureStage(s)
       TS.setMode(TSmode[stage-2])
       TS.setSort(stage-1)
    model.setTexture(TS,tex)
Пример #8
0
 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)
Пример #9
0
 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)
Пример #10
0
def splatting(node, first, second, stencil, scale=None, offset=None):
    """Apply a texture splatting to the provided NodePath.
    """
    # Apply the first texture.
    ts1 = TextureStage("stage-first")
    ts1.setSort(0)
    ts1.setMode(TextureStage.MReplace)
    ts1.setSavedResult(True)
    node.setTexture(ts1, first)
    # Apply the second texture.
    ts2 = TextureStage("stage-second")
    ts2.setSort(1)
    ts2.setMode(TextureStage.MReplace)
    node.setTexture(ts2, second)
    # Apply the stencil.
    ts3 = TextureStage("stage-stencil")
    ts3.setSort(2)
    ts3.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSPrevious,
                      TextureStage.COSrcColor, TextureStage.CSLastSavedResult,
                      TextureStage.COSrcColor, TextureStage.CSTexture,
                      TextureStage.COSrcColor)
    node.setTexture(ts3, stencil)
    if scale: node.setTexScale(ts3, scale, scale)
    if offset is not None:
        node.setTexOffset(ts1, *offset)
        node.setTexOffset(ts2, *offset)
        node.setTexOffset(ts3, *offset)
Пример #11
0
    def apply_splatted_textures(self, tile: NodePath, first_tex, second_tex,
                                stencil_tex):
        # first = self.load("textures/sand_tex_1.png")
        # second = self.load("textures/grass_tex_1.png")
        # third = self.load("textures/water_tex_1.png")
        # stencil = self.load("textures/stencil_tex_1.png")
        # stencil_2 = self.load("textures/stencil_tex_2.png")
        # # normal = self.load("textures/sea-normal.jpg")
        # normal = self.loader.load_texture("textures/layingrock-n.jpg")

        # Apply the first texture.
        ts1 = TextureStage("stage-first")
        ts1.setSort(0)
        ts1.setMode(TextureStage.MReplace)
        ts1.setSavedResult(True)
        tile.setTexture(ts1, first_tex)
        # Apply the second texture.
        ts2 = TextureStage("stage-second")
        ts2.setSort(1)
        ts2.setMode(TextureStage.MReplace)
        tile.setTexture(ts2, second_tex)
        ts3 = TextureStage("stage-stencil")
        ts3.setSort(2)
        ts3.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSPrevious,
                          TextureStage.COSrcColor,
                          TextureStage.CSLastSavedResult,
                          TextureStage.COSrcColor, TextureStage.CSTexture,
                          TextureStage.COSrcColor)
        ts3.setSavedResult(True)
        tile.setTexture(ts3, stencil_tex)
Пример #12
0
    def __create_terrain(self):
        terrain = GeoMipTerrain("Terrain")
        terrain.setHeightfield(self.__texture_path(self.__scene.get("scene", "heightmap")))
        terrain.getRoot().reparentTo(self.render)
        terrain.generate()
        terrain.getRoot().setSx(1000.0 / 512)
        terrain.getRoot().setSy(1000.0 / 512)
        terrain.getRoot().setSz(74)
        terrain.getRoot().setPos(-500, -500, 0)

        black = self.loader.loadTexture(self.__texture_path(self.__scene.get("terrain", "black")))
        black.setMinfilter(Texture.FTLinearMipmapNearest)
        ts = TextureStage("stage-first")
        ts.setSort(0)
        ts.setMode(TextureStage.MReplace)
        ts.setSavedResult(True)
        terrain.getRoot().setTexture(ts, black)
        terrain.getRoot().setTexScale(ts, 250, 250)

        white = self.loader.loadTexture(self.__texture_path(self.__scene.get("terrain", "white")))
        white.setMinfilter(Texture.FTLinearMipmapNearest)
        ts = TextureStage("stage-second")
        ts.setSort(1)
        ts.setMode(TextureStage.MReplace)
        terrain.getRoot().setTexture(ts, white)
        terrain.getRoot().setTexScale(ts, 250, 250)

        stencil = self.loader.loadTexture(self.__texture_path(self.__scene.get("scene", "stencil")))
        ts = TextureStage("stage-stencil")
        ts.setSort(2)
        ts.setCombineRgb(TextureStage.CMInterpolate,
                         TextureStage.CSPrevious, TextureStage.COSrcColor,
                         TextureStage.CSLastSavedResult, TextureStage.COSrcColor,
                         TextureStage.CSTexture, TextureStage.COSrcColor)

        terrain.getRoot().setTexture(ts, stencil)

        ts = TextureStage("stage-vertexcolour")
        ts.setSort(3)
        ts.setCombineRgb(TextureStage.CMModulate, TextureStage.CSPrevious, TextureStage.COSrcColor,
                         TextureStage.CSPrimaryColor, TextureStage.COSrcColor)

        terrain.getRoot().setTexture(ts, "final")
Пример #13
0
    def __create_terrain(self):
        terrain = GeoMipTerrain("Terrain")
        terrain.setHeightfield(self.__texture_path(self.__scene.get("scene", "heightmap")))
        terrain.getRoot().reparentTo(self.render)
        terrain.generate()
        terrain.getRoot().setSx(1000.0 / 512)
        terrain.getRoot().setSy(1000.0 / 512)
        terrain.getRoot().setSz(74)
        terrain.getRoot().setPos(-500, -500, 0)

        black = self.loader.loadTexture(self.__texture_path(self.__scene.get("terrain", "black")))
        black.setMinfilter(Texture.FTLinearMipmapNearest)
        ts = TextureStage("stage-first")
        ts.setSort(0)
        ts.setMode(TextureStage.MReplace)
        ts.setSavedResult(True)
        terrain.getRoot().setTexture(ts, black)
        terrain.getRoot().setTexScale(ts, 250, 250)

        white = self.loader.loadTexture(self.__texture_path(self.__scene.get("terrain", "white")))
        white.setMinfilter(Texture.FTLinearMipmapNearest)
        ts = TextureStage("stage-second")
        ts.setSort(1)
        ts.setMode(TextureStage.MReplace)
        terrain.getRoot().setTexture(ts, white)
        terrain.getRoot().setTexScale(ts, 250, 250)

        stencil = self.loader.loadTexture(self.__texture_path(self.__scene.get("scene", "stencil")))
        ts = TextureStage("stage-stencil")
        ts.setSort(2)
        ts.setCombineRgb(TextureStage.CMInterpolate,
                         TextureStage.CSPrevious, TextureStage.COSrcColor,
                         TextureStage.CSLastSavedResult, TextureStage.COSrcColor,
                         TextureStage.CSTexture, TextureStage.COSrcColor)

        terrain.getRoot().setTexture(ts, stencil)

        ts = TextureStage("stage-vertexcolour")
        ts.setSort(3)
        ts.setCombineRgb(TextureStage.CMModulate, TextureStage.CSPrevious, TextureStage.COSrcColor,
                         TextureStage.CSPrimaryColor, TextureStage.COSrcColor)

        terrain.getRoot().setTexture(ts, "final")
Пример #14
0
class ShadowCaster(DirectObject):
    def __init__(self):
        DirectObject.__init__(self)
        self.shadowCamArm = None
        self.casterState = None
        self.shadowBuffer = None
        self.shadowColor = 0.5
        self.shadowColorIndex = 0
        self.shadowsEnabled = 0
        self.clearColor = VBase4(1, 1, 1, 1)
        self.setupTask = None
        self.shadowsHidden = False

    def enable(self):
        camNode = Camera('shadowCam')
        camNode.setCameraMask(CIGlobals.ShadowCameraBitmask)
        self.shadowLens = OrthographicLens()
        self.shadowLens.setFilmSize(60 * 4, 60 * 4)
        camNode.setLens(self.shadowLens)
        self.shadowCamArm = camera.attachNewNode('shadowCamArm')
        self.shadowCam = self.shadowCamArm.attachNewNode(camNode)
        self.shadowCamArm.setPos(0, 40, 0)
        self.shadowCam.setPos(0, -40, 0)
        self.shadowTex = Texture('shadow')
        self.shadowTex.setBorderColor(self.clearColor)
        self.shadowTex.setWrapU(Texture.WMBorderColor)
        self.shadowTex.setWrapV(Texture.WMBorderColor)
        self.casterState = NodePath('temp')
        self.casterState.setColorScaleOff(10)
        self.casterState.setColor(self.shadowColor, self.shadowColor,
                                  self.shadowColor, 1, 10)
        self.casterState.setTextureOff(10)
        self.casterState.setLightOff(10)
        self.casterState.setFogOff(10)
        camNode.setInitialState(self.casterState.getState())
        render.hide(CIGlobals.ShadowCameraBitmask)
        self.shadowStage = TextureStage('shadow')
        self.shadowStage.setSort(1000)
        self.turnOnShadows()

    def disable(self):
        if not self.shadowsEnabled:
            return None

        self.shadowsEnabled = 0
        self.shadowCamArm.removeNode()
        self.shadowCam.removeNode()
        base.camNode.clearTagState('caster')
        self.turnOffShadows()
        self.shadowTex = None
        self.shadowStage = None

    def turnOnShadows(self):
        render.setTexProjector(self.shadowStage, NodePath(), self.shadowCam)

    def turnOffShadows(self):
        render.clearTexProjector(self.shadowStage)
        self.destroyBuffer()

    def createBuffer(self):
        if not base.win.getGsg():
            return None

        self.shadowBuffer = base.win.makeTextureBuffer('shadow',
                                                       1024 * 4,
                                                       1024 * 4,
                                                       tex=self.shadowTex)
        self.shadowBuffer.setSort(30)
        self.shadowBuffer.setClearColor(self.clearColor)
        dr = self.shadowBuffer.makeDisplayRegion()
        dr.setCamera(self.shadowCam)

        self.setupCamera()

    def setupCamera(self):
        groundState = NodePath('temp')
        groundState.setTexture(self.shadowStage, self.shadowTex)
        groundState.setTexGen(self.shadowStage, TexGenAttrib.MWorldPosition)
        base.camNode.setTagStateKey('cam')
        base.camNode.setTagState('shground', groundState.getState())

    def destroyBuffer(self):
        if self.shadowBuffer:
            base.graphicsEngine.removeWindow(self.shadowBuffer)
            self.shadowBuffer = None
Пример #15
0
class Terrain:
    folder = os.path.dirname(os.path.abspath(__file__))
    subfolder = "/Maps/"
    file = "simple.jpg"
    filepath = folder + subfolder + file

    def __init__(self):
        fn = Filename.fromOsSpecific(self.filepath)
        self.terrain = GeoMipTerrain("mySimpleTerrain")
        self.terrain.setHeightfield("Entities/Maps/heightmap.png")
        self.terrain.getRoot().setSz(40)
        #terrain.setBruteforce(True)
        self.terrain.getRoot().reparentTo(render)

        # Set terrain properties
        self.terrain.setBlockSize(16)
        self.terrain.setNear(500)
        self.terrain.setFar(100)
        self.terrain.setFocalPoint(base.camera)

        # Store the root NodePath for convenience
        root = self.terrain.getRoot()
        root.reparentTo(render)

        # some tinkering
        """
        # tell renderer to repeat texture when reading over the edge.
        texGrass.setWrapU(Texture.WM_repeat)
        texGrass.setWrapV(Texture.WM_repeat)
        # apply mipmapping: tell renderer how to handle multiple texture pixels being rendered t a single screen pixel (makes textures 30% larger in GPU mem.)
        texGrass.setMinfilter(SamplerState.FT_linear_mipmap_linear)
        """
        self.terrain.generate()
        """
        new attempt to include blend mapping:
        """
        # determine terrain size
        self.heightmap = self.terrain.heightfield()
        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()

        # load a blend texture from file:
        self.blendTexture = loader.loadTexture("Entities/Maps/blendMap.png")

        self.blendTS = TextureStage('blend')
        self.blendTS.setSort(0)
        self.blendTS.setPriority(1)
        # apply textures to the terrain and connect custom shader for blend mapping:
        self.setSurfaceTextures()

        # Add a task to keep updating the terrain (for changing terrain, or synamic resolution)
        def updateTask(task):
            self.terrain.update()
            return task.cont

        taskMgr.add(updateTask, "update")

        # this is where we load the textures to be assigned to the terrain
    def generateSurfaceTextures(self):
        # Textureize
        self.grassTexture = loader.loadTexture("Entities/Maps/grassy2.png")
        self.grassTexture.setWrapU(Texture.WMRepeat)
        self.grassTexture.setWrapV(Texture.WMRepeat)
        self.grassTexture.setMinfilter(SamplerState.FT_linear_mipmap_linear)
        self.grassTexture.setAnisotropicDegree(8)
        self.grassTS = TextureStage('grass')
        self.grassTS.setSort(
            1)  # sorting order is relevent for assigning textures to the four

        self.rockTexture = loader.loadTexture("Entities/Maps/simple.jpg")
        self.rockTexture.setWrapU(Texture.WMRepeat)
        self.rockTexture.setWrapV(Texture.WMRepeat)
        self.rockTexture.setMinfilter(SamplerState.FT_linear_mipmap_linear)
        #self.grassTexture.setAnisotropicDegree(8)
        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("Entities/Maps/stars.png")
        self.sandTexture.setWrapU(Texture.WMRepeat)
        self.sandTexture.setWrapV(Texture.WMRepeat)
        self.sandTexture.setMinfilter(SamplerState.FT_linear_mipmap_linear)
        #self.sandTexture.setAnisotropicDegree(8)
        self.sandTS = TextureStage('sand')
        self.sandTS.setSort(3)
        self.sandTS.setPriority(5)  # TODO: figure out what this is for...

        self.snowTexture = loader.loadTexture("Entities/Maps/grass.png")
        self.snowTexture.setWrapU(Texture.WMRepeat)
        self.snowTexture.setWrapV(Texture.WMRepeat)
        self.snowTexture.setMinfilter(SamplerState.FT_linear_mipmap_linear)
        #self.snowTexture.setAnisotropicDegree(8)
        self.snowTS = TextureStage('snow')
        self.snowTS.setSort(4)
        self.snowTS.setPriority(0)

        # a background (or rather freground?) texture that will be present independently from the blend map (consider removal)
        self.overlayTexture = loader.loadTexture("Entities/Maps/heightmap.png")
        self.overlayTexture.setWrapU(Texture.WMRepeat)
        self.overlayTexture.setWrapV(Texture.WMRepeat)
        self.overlayTexture.setMinfilter(SamplerState.FT_linear_mipmap_linear)
        #self.overlayTexture.setAnisotropicDegree(8)
        self.overlayTS = TextureStage('overlay')
        self.overlayTS.setSort(5)
        self.overlayTS.setPriority(10)

    # this is where we assign loaded textures to be blended in the shader.
    def setSurfaceTextures(self):
        self.ownerview = False
        root = self.terrain.getRoot()
        root.clearTexture()
        #self.terrain.setTextureMap()
        root.setTexture(
            self.blendTS, self.snowTexture
        )  # this texture determines where the other textures are visible

        root.setTexture(self.grassTS, self.snowTexture)
        #root.setTexScale(self.grassTS, self.size*5, self.size*5) # I try to make the texture 20 times smaller then the blend map...

        root.setTexture(self.rockTS, self.snowTexture)  #rockTexture
        #root.setTexScale(self.rockTS, self.size*5, self.size*5)

        root.setTexture(self.sandTS, self.snowTexture)  #sandTexture
        #root.setTexScale(self.sandTS, self.size*5, self.size*5)

        root.setTexture(self.snowTS, self.snowTexture)  #snowTexture
        #root.setTexScale(self.snowTS, self.size*5, self.size*5)

        #(consider removal)
        root.setTexture(self.overlayTS, self.overlayTexture)  #overlayTexture
        #root.setTexScale(self.overlayTS, self.xsize, self.ysize)

        root.setShaderInput('size', self.xsize, self.ysize, self.size,
                            self.size)
        root.setShader(loader.loadShader('Entities/Maps/terrainblender.sha'))
    def __init__(self, path, heightScale, shader=None, skipTextures=False):
        self.shader = shader
        meshManager.MeshFactory.__init__(self)

        self.dataIndex = {}

        self.heightScale = heightScale

        d = parseFile(path + "/texList.txt")

        self.mapTexStages = {}
        self.specialMaps = {}
        for m in d["Special"]:
            s = m.split("\t")
            self.specialMaps[s[1]] = s[0]

        # List of non map texture stages, and their sizes
        # (TexStage,Size)
        self.texList = []

        if not skipTextures:

            if "Tex2D" in d:
                sort = 0
                for m in d["Tex2D"]:
                    sort += 1
                    s = m.split()
                    name = s[0]
                    texStage = TextureStage(name + "stage" + str(sort))
                    texStage.setSort(sort)
                    source = s[1]

                    #                 def setTexModes(modeText):
                    #                     combineMode=[]
                    #                     for t in modeText:
                    #                         if t[:1]=='M':
                    #                             texStage.setMode(getRenderMapType(t))
                    #                         elif t[:1]=='C':
                    #                             combineMode.append(getCombineMode(t))
                    #                         elif t=='Save':
                    #                             texStage.setSavedResult(True)
                    #                         else:
                    #                             print "Illegal mode info for "+name
                    #                     if len(combineMode)>0:
                    #                         texStage.setCombineRgb(*combineMode)
                    #                     if len(modeText)==0:
                    #                         texStage.setMode(TextureStage.MModulate)

                    if source == "file":

                        #                     setTexModes(s[3:])
                        tex = loadTex(path + "/textures/" + name)
                        #                     self.terrainNode.setTexture(texStage,tex)
                        #                     self.terrainNode.setShaderInput('tex2D_'+name,tex)
                        self.texList.append((texStage, float(s[2]), tex, name))

                    elif source == "map":
                        #                     setTexModes(s[2:])
                        self.mapTexStages[s[0]] = texStage
        #
        #                 else:
        #                     print 'Invalid source for '+name+' int Tex2D'

        self.LOD = meshManager.LOD(float("inf"), 0)
Пример #17
0
class GUnit(GEntity):
   
   def __init__(self,conf):
      GEntity.__init__(self,conf)
      self.p3dobject.reparentTo(self.gmap.units_node)
      self.p3dobject.setTransparency(TransparencyAttrib.MAlpha)
      #to be put under condition for non pickable units (bonuses npc for instance)
      self.p3dobject.setTag('GUnit-pickable','1')
      self.p3dobject.setPos(self.gmap.root.find('**/tile_'+str(conf['tileid'])),0,0,0)
      #supposedly already a float, but will screw up if not, so just making sure.
      self.move_speed=float(conf['move_speed'])
      self.path=[]
      self.popout_when_move_over=False
      self.pid=conf['pid']
      #highlight
      self.ts_highlighted=TextureStage('ts_highlighted')
      self.ts_highlighted.setMode(TextureStage.MDecal)
      self.ts_highlighted.setSort(2)
      #highlight
      self.ts_selected=TextureStage('ts_selected')
      self.ts_selected.setMode(TextureStage.MDecal)
      self.ts_selected.setSort(3)
               
   @staticmethod
   def load_resources():
      GUnit.textures={   'highlighted':loader.loadTexture('data/models/highlighted.tex.png'),
                        'selected':loader.loadTexture('data/models/selected.tex.png'),
                     }
      
   def dispose(self):
      '''del method'''
      GEntity.dispose(self)
      self.popout_sequence.finish()
      del self.popout_sequence

   def add_path(self,data):
      '''
      adds tile to pass by.
      '''
      #check for data completeness
      if not 'path' in data:
         out('WARNING in GUnit.add_path: incomplete data:\n'+str(data))
         return
      elif not isinstance(data['path'],list):
         out('WARNING in GUnit.add_path: invalid data:\n'+str(data))
         return
      #data considered valid
      self.path.extend([self.instances[eid] for eid in data['path']])
      if not self.update_move in update_list: 
         update_list.append(self.update_move)
      #out('GUnit.add_path:'+str(data))
   
   def finish_move_to(self,data):
      '''triggered by server side unit, to indicate the need to popout at end of move.'''
      out('GUnit.finish_move_to()'+str(data))
      if self.update_move in update_list:
         self.popout_when_move_over=True
      else:
         self.popout()
         
   def popout(self):
      '''sets up the popout animation at end of unit's mission'''
      scale=self.p3dobject.scaleInterval(.5,(.1,.1,.1))
      finish=Func(lambda:dispose_list.append(self))
      self.popout_sequence=Sequence(scale,finish)
      self.popout_sequence.start()
      
   def set_highlighted(self):
      self.p3dobject.setTexture(self.ts_highlighted,self.textures['highlighted'])
      
   def unset_highlighted(self):
      self.p3dobject.clearTexture(self.ts_highlighted)
      
   def set_selected(self):
      self.p3dobject.setTexture(self.ts_selected,self.textures['selected'])
      
   def unset_selected(self):
      self.p3dobject.clearTexture(self.ts_selected)
      
   def update_move(self):
      '''called every frame during while a move.'''
      if len(self.path)==0:
         out('WARNING in GUnit.update_move: path is empty, but method still called. removing it.')
         update_list.remove(self.update_move)
         return
      if not hasattr(self,'move_interval'):
         #start moving
         #first 3 args=model,duration,pos, the duration=1/... is relative to server side tile side size
         self.move_interval=LerpPosInterval(self.p3dobject,
                                    (1/(self.move_speed*ConfigVariableDouble('clock-frame-rate').getValue())),
                                    self.path[0].p3dobject.getPos(),
                                    name='interval_unit_move_'+str(self.eid)
                                    )
         self.p3dobject.lookAt(self.path[0].p3dobject.getPos())
         self.p3dobject.loop('run')
         self.move_interval.start()
      else:
         #is move ~over ?
         #t=self.move_interval.getT()
         #d=self.move_interval.getDuration()
         #d=d-t
         d=dist3(self.p3dobject,self.path[0].p3dobject)
         #out('client '+str(t*100./d)+'%')
         #arrived
         if d<self.move_speed:
            #out('client '+str(self.path[0].eid)+'@'+str(self.frame_no))
            self.p3dobject.setPos(self.path[0].p3dobject,0,0,0)
            self.path.pop(0)
            if len(self.path)==0:
               self.p3dobject.stop()
               self.move_interval.finish()
               del self.move_interval
               update_list.remove(self.update_move)
               if self.popout_when_move_over:
                  self.popout()
            else:
               #first 3 args=model,duration,pos
               self.move_interval.finish()
               self.move_interval=LerpPosInterval(self.p3dobject,
                                          (1/(self.move_speed*ConfigVariableDouble('clock-frame-rate').getValue())),
                                          self.path[0].p3dobject.getPos(),
                                          name='interval_unit_move_'+str(self.eid)
                                          )
               self.p3dobject.lookAt(self.path[0].p3dobject.getPos())
               self.move_interval.start()
Пример #18
0
class Water(AssetBase):
    def __init__(self, name, size=10000, resolution=1024):
        """Arguments:
        size -- Edge length of the water square.
        resolution -- Texture size of the rendered reflection buffer.
        """
        # Uncomment to see the output of the refclection buffer.
        base.bufferViewer.toggleEnable()

        AssetBase.__init__(self)
        self.name = name

        self.cm = CardMaker("water surface")
        self.cm.setFrame(-0.5 * size, 0.5 * size, -0.5 * size, 0.5 * size)
        self.cm.setHasUvs(True)
        self.node = NodePath(self.cm.generate())

        self.node.setP(self.node, -90)
        self.node.flattenLight()
        self.node.hide(BitMask32.bit(1))
        #self.node.setTwoSided(True)
        self.node.setShaderOff()

        # size of one texture tile in meters
        self.tex_size = 100.0

        diffuse = TexturePool.loadTexture("textures/water.diffuse.png")
        diffuse.setWrapU(Texture.WMRepeat)
        diffuse.setWrapV(Texture.WMRepeat)
        diffuse.setMinfilter(Texture.FTLinearMipmapLinear)
        diffuse.setMagfilter(Texture.FTLinearMipmapLinear)
        self.diffuse_stage = TextureStage("diffuse")
        self.diffuse_stage.setSort(2)
        self.node.setTexture(self.diffuse_stage, diffuse)
        self.node.setTexScale(self.diffuse_stage, size / self.tex_size,
                              size / self.tex_size)

        # Reflection camera renders to 'buffer' which is projected onto the
        # water surface.
        buffer = base.win.makeTextureBuffer("water reflection", resolution,
                                            resolution)
        buffer.setClearColor(Vec4(0, 0, 0, 1))

        self.refl_cam = base.makeCamera(buffer)
        self.refl_cam.reparentTo(self.node)
        self.refl_cam.node().setCameraMask(BitMask32.bit(1))
        self.refl_cam.node().getLens().setFov(base.camLens.getFov())
        self.refl_cam.node().getLens().setNearFar(1, 100000)

        plane = PlaneNode("water culling plane",
                          Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
        cfa = CullFaceAttrib.makeReverse()
        cpa = ClipPlaneAttrib.make(PlaneNode.CEVisible, plane)
        rs = RenderState.make(cfa, cpa)
        self.refl_cam.node().setInitialState(rs)

        reflection = buffer.getTexture()
        reflection.setMinfilter(Texture.FTLinear)
        reflection.setMagfilter(Texture.FTLinear)
        self.refl_stage = TextureStage("reflection")
        self.refl_stage.setSort(1)
        self.node.projectTexture(self.refl_stage, reflection, base.cam)
        self.node.setTexture(self.refl_stage, reflection)

        # Blend between diffuse and reflection.
        self.diffuse_stage.setColor(VBase4(1, 1, 1, 0.2))  # opacity of 20%
        self.diffuse_stage.setCombineRgb(
            TextureStage.CMInterpolate, TextureStage.CSTexture,
            TextureStage.COSrcColor, TextureStage.CSPrevious,
            TextureStage.COSrcColor, TextureStage.CSConstant,
            TextureStage.COSrcAlpha)

        self.addTask(self.update,
                     name="water update",
                     sort=1,
                     taskChain="world")

    def update(self, task):
        """Updates position of the reflection camera and the water plane."""
        mc = base.cam.getMat(render)
        #mf = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)).getReflectionMat()
        mf = Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)
        self.refl_cam.setMat(mc * mf)

        self.node.setX(camera.getX(render))
        self.node.setY(camera.getY(render))
        self.node.setTexOffset(self.diffuse_stage,
                               self.node.getX() / self.tex_size,
                               self.node.getY() / self.tex_size)

        return task.cont

    def destroy(self):
        self.removeAllTasks()
        self.node.removeNode()
        self.refl_cam.removeNode()
Пример #19
0
class GTile(GEntity):
   def __init__(self,conf):
      self.p3dobject=self.gmap.tile_matrix_node.attachNewNode('tile_'+str(conf['eid']))
      self.p3dobject.setTransparency(TransparencyAttrib.MAlpha)
      #self.test_sphere=loader.loadModel('data/models/test_sphere.egg')
      #self.test_sphere.reparentTo(self.p3dobject)
      GEntity.__init__(self,conf)
      self.x,self.y=x,y=conf['x'],conf['y']
      self.p3dobject.setTag('x',str(x))
      self.p3dobject.setTag('y',str(y))
      self.p3dobject.setPythonTag('ref',self)
      #half of a tile side
      t=self.gmap.tile_matrix_node.getScale()[0]/2.
      self.p3dobject.setPos(self.gmap.tile_matrix_node,(-self.gmap.resx/2.+x+t)*2.,(y-self.gmap.resy/2.+t)*2.,0)
      #preload texture holder quad
      self.quad=GTile.resources['quad']()
      self.quad.setTransparency(TransparencyAttrib.MAlpha)
      #self.quad.reparentTo(self.p3dobject)
      self.quad.reparentTo(self.gmap.tiles_quads_node)
      self.quad.setPos(self.p3dobject.getPos())
      self.quad.hide()
      
      #pid of the player that owns the tile
      self.pawner=None
      self.ts_pawn=TextureStage('ts_pawn')
      self.ts_pawn.setMode(TextureStage.MReplace)
      self.ts_pawn.setSort(2)
      
      #selection
      self.is_selected=False
      self.ts_selected=TextureStage('ts_selected')
      self.ts_selected.setMode(TextureStage.MReplace)
      self.ts_selected.setSort(3)
      
      #highlight
      self.is_highlighted=False
      self.ts_highlighted=TextureStage('ts_highlighted')
      self.ts_highlighted.setMode(TextureStage.MDecal)
      self.ts_highlighted.setSort(4)
      
   def __repr__(self):
      return 'GTile{eid:'+str(self.eid)+'\n\
x/y:'+str(self.x)+'/'+str(self.y)+'\n\
pawner:'+str(self.pawner)+'\n\
selected:'+str(self.is_selected)+'\n\
highlighted:'+str(self.is_highlighted)+'\n\
}'
   
   def __str__(self):
      return self.__repr__()
   
   @staticmethod
   def load_resources():
      #dict of texture
      GTile.resources={   'quad':lambda:loader.loadModel('data/models/tiles/tile.egg'),
                        }
      GTile.textures={   'highlighted':loader.loadTexture('data/models/tiles/tile.highlighted.tex.png'),
                        'selected':loader.loadTexture('data/models/tiles/tile.selected.tex.png'),
                        'pawn-0':loader.loadTexture('data/models/tiles/tile.pawned.black.tex.png'),
                        'pawn-1':loader.loadTexture('data/models/tiles/tile.pawned.white.tex.png'),
                         }

   @property
   def left_tile(self):
      '''property getter'''
      if self.x>0:return self.gmap.tile_matrix[self.x-1][self.y]
      return None

   @property
   def lower_tile(self):
      '''property getter'''
      if self.y>0:return self.gmap.tile_matrix[self.x][self.y-1]
      return None

   @property
   def right_tile(self):
      '''property getter'''
      if self.x<self.gmap.resx-1:return self.gmap.tile_matrix[self.x+1][self.y]
      return None

   @property
   def upper_tile(self):
      '''property getter'''
      if self.y<self.gmap.resy-1:return self.gmap.tile_matrix[self.x][self.y+1]
      return None

   @property
   def neighbors(self):
      '''property getter'''
      return filter(lambda t:t!=None,[self.left_tile,self.lower_tile,self.right_tile,self.upper_tile])

   @property
   def wall(self):
      '''
      returns a list of all tiles that form a wall connected to this tile.
      a tile with no pawner doesn't belong to any wall.
      '''
      if self.pawner==None:
         return []
      wall=[]
      fringe=[self]
      visited={}
      while len(fringe):
         t=fringe.pop(0)
         if t.pawner==self.pawner:
            wall.append(t)
            visited[t]=1
         fringe.extend([n for n in t.neighbors if n.pawner==self.pawner and n not in visited])

   def change_pawner(self,data):
      #out('tile '+str(self.eid)+' set to '+str(data['owner']))
      if self.pawner!=data['pawner']:
         self.pawner=data['pawner']
         if self.pawner==None:
            self.quad.clearTexture(self.ts_pawn)
            if not (self.is_selected or self.is_highlighted):
               self.quad.hide()
         else: 
            self.quad.setTexture(self.ts_pawn,self.textures['pawn-'+str(self.pawner)])
            self.quad.show()
   
   def set_highlighted(self):
      #out('tile.eid='+str(self.eid))
      self.is_highlighted=True
      self.quad.show()
      self.quad.setTexture(self.ts_highlighted,self.textures['highlighted'])
   
   def unset_highlighted(self):
      self.is_highlighted=False
      self.quad.clearTexture(self.ts_highlighted)
      if not (self.is_selected or self.pawner!=None):
         self.quad.hide()
   
   def set_selected(self):
      self.is_selected=True
      self.quad.show()
      self.quad.setTexture(self.ts_selected,self.textures['selected'])
   
   def unset_selected(self):
      self.is_selected=False
      self.quad.clearTexture(self.ts_selected)
      if not (self.is_highlighted or self.pawner!=None):
         self.quad.hide()

   @property
   def center_pos(self):
      return self.p3dobject.getPos()


      
Пример #20
0
 
"""base.camLens.setNearFar(1.0, 50.0)
base.camLens.setFov(45.0)"""
 
camera.setPos(0.0, -20.0, 10.0)
camera.lookAt(0.0, 0.0, 0.0)
 
root = render.attachNewNode("Root")
root.setPos(0.0, 0.0, 0.0)
 
textureArrow = loader.loadTexture("arrow.png")
textureArrow.setWrapU(Texture.WMClamp)
textureArrow.setWrapV(Texture.WMClamp)
 
stageArrow = TextureStage("Arrow")
stageArrow.setSort(1)
 
textureCircle = loader.loadTexture("circle.png")
textureCircle.setWrapU(Texture.WMClamp)
textureCircle.setWrapV(Texture.WMClamp)
 
stageCircle = TextureStage("Circle")
stageCircle.setSort(2)
 
modelCube = loader.loadModel("cube.egg")
 
cubes = []
for x in [-3.0, 0.0, 3.0]:
    cube = modelCube.copyTo(root)
    cube.setPos(x, 0.0, 0.0)
    cubes += [ cube ]
Пример #21
0
	def setupHeightmap(self, name):
		
		# Automatically generate a heightmap mesh from a monochrome image.
		self.hmHeight = 120
		hmPath = "../maps/map" + name + "/map" + name + "-h.png"
		imPath = "../maps/map" + name + "/map" + name + "-i.png"
		smPath = "../maps/map" + name + "/map" + name + "-s.png"
		scmPath = "../maps/map" + name + "/map" + name + "-sc.png"
		print(hmPath)
		print(imPath)
		print(smPath)
		print(scmPath)
		hmImg = PNMImage(Filename(hmPath))
		hmShape = BulletHeightfieldShape(hmImg, self.hmHeight, ZUp)
		hmNode = BulletRigidBodyNode('Terrain')
		hmNode.addShape(hmShape)
		hmNode.setMass(0)
		self.hmNP = render.attachNewNode(hmNode)
		self.worldBullet.attachRigidBody(hmNode)
		self.hmOffset = hmImg.getXSize() / 2.0 - 0.5
		self.hmTerrain = GeoMipTerrain('gmTerrain')
		self.hmTerrain.setHeightfield(hmImg)
		
		# Optimizations and fixes
		self.hmTerrain.setBruteforce(True) # I don't think this is actually needed. 
		self.hmTerrain.setMinLevel(3) # THIS is what triangulates the terrain.
		self.hmTerrain.setBlockSize(128)  # This does a pretty good job of raising FPS.
		# Level-of-detail (not yet working)
		# self.hmTerrain.setNear(40)
		# self.hmTerrain.setFar(200)
		
		self.hmTerrain.generate()
		
		self.hmTerrainNP = self.hmTerrain.getRoot()
		self.hmTerrainNP.setSz(self.hmHeight)
		self.hmTerrainNP.setPos(-self.hmOffset, -self.hmOffset, -self.hmHeight / 2.0)
		self.hmTerrainNP.flattenStrong() # This only reduces the number of nodes; nothing to do with polys.
		self.hmTerrainNP.analyze()

		# Here begins the scenery mapping
		treeModel = loader.loadModel("../res/models/tree_1.egg")
		rockModel = loader.loadModel("../res/models/rock_1.egg")
		rock2Model = loader.loadModel("../res/models/rock_2.egg")
		rock3Model = loader.loadModel("../res/models/rock_3.egg")
		# caveModel = loader.loadModel("../res/models/cave_new.egg")
		# planeFrontModel = loader.loadModel("../res/models/plane_front.egg")
		# planeWingModel = loader.loadModel("../res/models/plane_wing.egg")
		texpk = loader.loadTexture(scmPath).peek()
		
		# GameObject nodepath for flattening
		self.objNP = render.attachNewNode("gameObjects")
		self.treeNP = self.objNP.attachNewNode("goTrees")
		self.rockNP = self.objNP.attachNewNode("goRocks")
		self.rock2NP = self.objNP.attachNewNode("goRocks2")
		self.rock3NP = self.objNP.attachNewNode("goRocks3")
		# self.caveNP = self.objNP.attachNewNode("goCave")
		# self.planeFrontNP = self.objNP.attachNewNode("goPlaneFront")
		# self.planeWingNP = self.objNP.attachNewNode("goPlaneWing")
		
		for i in range(0, texpk.getXSize()):
			for j in range(0, texpk.getYSize()):
				color = VBase4(0, 0, 0, 0)
				texpk.lookup(color, float(i) / texpk.getXSize(), float(j) / texpk.getYSize())
				if(int(color.getX() * 255.0) == 255.0):
					newTree = self.treeNP.attachNewNode("treeNode")
					treeModel.instanceTo(newTree)
					newTree.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					# newTree.setScale(randint(0,4))
					newTree.setScale(2)
					
				if(int(color.getX() * 255.0) == 128):
					newRock = self.rockNP.attachNewNode("newRock")
					newRock.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					rockModel.instanceTo(newRock)
					
				if(int(color.getX() * 255.0) == 77):
					newRock2 = self.rock2NP.attachNewNode("newRock2")
					newRock2.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					rock2Model.instanceTo(newRock2)
					
				if(int(color.getX() * 255.0) == 102):
					newRock3 = self.rock3NP.attachNewNode("newRock3")
					newRock3.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					rock3Model.instanceTo(newRock3)
					
				# if(int(color.getX() * 255.0) == 64):
					# newCave = self.caveNP.attachNewNode("newCave")
					# newCave.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					# newCave.setScale(5)
					# newCave.setP(180)
					# caveModel.instanceTo(newCave)
				
				# if(int(color.getX() * 255.0) == 191):
					# newPlaneFront = self.planeFrontNP.attachNewNode("newPlaneFront")
					# newPlaneFront.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					# newPlaneFront.setScale(6)
					# planeFrontModel.instanceTo(newPlaneFront)
					
				# if(int(color.getX() * 255.0) == 179):
					# newPlaneWing = self.planeWingNP.attachNewNode("newPlaneWing")
					# newPlaneWing.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					# newPlaneWing.setScale(6)
					# newPlaneWing.setH(250)
					# newPlaneWing.setR(180)
					# newPlaneWing.setP(135)
					# planeWingModel.instanceTo(newPlaneWing)

		self.snowflakes = []
		
		for i in xrange(0, self.snowflakeCount):
			print("Call " + str(i))
			sf = SMCollect(self.worldBullet, self.worldObj, self.snowflakePositions[i])
			self.snowflakes.append(sf)
					
		# render.flattenStrong()
		self.hmTerrainNP.reparentTo(render)
		
		# Here begins the attribute mapping
		ts = TextureStage("stage-alpha")
		ts.setSort(0)
		ts.setPriority(1)
		ts.setMode(TextureStage.MReplace)
		ts.setSavedResult(True)
		self.hmTerrainNP.setTexture(ts, loader.loadTexture(imPath, smPath))

		ts = TextureStage("stage-stone")
		ts.setSort(1)
		ts.setPriority(1)
		ts.setMode(TextureStage.MReplace)
		self.hmTerrainNP.setTexture(ts, loader.loadTexture("../res/textures/stone_tex.png"))
		self.hmTerrainNP.setTexScale(ts, 32, 32)

		ts = TextureStage("stage-ice")
		ts.setSort(2)
		ts.setPriority(1)
		ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSTexture, TextureStage.COSrcColor,
						 TextureStage.CSPrevious, TextureStage.COSrcColor,
						 TextureStage.CSLastSavedResult, TextureStage.COSrcColor)
		self.hmTerrainNP.setTexture(ts, loader.loadTexture("../res/textures/ice_tex.png"))
		self.hmTerrainNP.setTexScale(ts, 32, 32)

		ts = TextureStage("stage-snow")
		ts.setSort(3)
		ts.setPriority(0)
		ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSTexture, TextureStage.COSrcColor,
						 TextureStage.CSPrevious, TextureStage.COSrcColor,
						 TextureStage.CSLastSavedResult, TextureStage.COSrcAlpha)
		self.hmTerrainNP.setTexture(ts, loader.loadTexture("../res/textures/snow_tex_1.png"))
		self.hmTerrainNP.setTexScale(ts, 32, 32)

		# print(self.snowflakes)
		
		return hmNode
Пример #22
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])
Пример #23
0
base.disableMouse()
"""base.camLens.setNearFar(1.0, 50.0)
base.camLens.setFov(45.0)"""

camera.setPos(0.0, -20.0, 10.0)
camera.lookAt(0.0, 0.0, 0.0)

root = render.attachNewNode("Root")
root.setPos(0.0, 0.0, 0.0)

textureArrow = loader.loadTexture("arrow.png")
textureArrow.setWrapU(Texture.WMClamp)
textureArrow.setWrapV(Texture.WMClamp)

stageArrow = TextureStage("Arrow")
stageArrow.setSort(1)

textureCircle = loader.loadTexture("circle.png")
textureCircle.setWrapU(Texture.WMClamp)
textureCircle.setWrapV(Texture.WMClamp)

stageCircle = TextureStage("Circle")
stageCircle.setSort(2)

modelCube = loader.loadModel("cube.egg")

cubes = []
for x in [-3.0, 0.0, 3.0]:
    cube = modelCube.copyTo(root)
    cube.setPos(x, 0.0, 0.0)
    cubes += [cube]
Пример #24
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])
Пример #25
0
class PlayerBase(DirectObject):
    def __init__(self):
        # Player Model setup
        self.player = Actor("Player",
                            {"Run":"Player-Run",
                            "Sidestep":"Player-Sidestep",
                            "Idle":"Player-Idle"})
        self.player.setBlend(frameBlend = True)
        self.player.setPos(0, 0, 0)
        self.player.pose("Idle", 0)
        self.player.reparentTo(render)
        self.player.hide()

        self.footstep = base.audio3d.loadSfx('footstep.ogg')
        self.footstep.setLoop(True)
        base.audio3d.attachSoundToObject(self.footstep, self.player)

        # Create a brush to paint on the texture
        splat = PNMImage("../data/Splat.png")
        self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1)

        CamMask = BitMask32.bit(0)
        AvBufMask = BitMask32.bit(1)
        self.avbuf = None
        if base.win:
            self.avbufTex = Texture('avbuf')
            self.avbuf = base.win.makeTextureBuffer('avbuf', 256, 256, self.avbufTex, True)
            cam = Camera('avbuf')
            cam.setLens(base.camNode.getLens())
            self.avbufCam = base.cam.attachNewNode(cam)
            dr = self.avbuf.makeDisplayRegion()
            dr.setCamera(self.avbufCam)
            self.avbuf.setActive(False)
            self.avbuf.setClearColor((1, 0, 0, 1))
            cam.setCameraMask(AvBufMask)
            base.camNode.setCameraMask(CamMask)

            # avbuf renders everything it sees with the gradient texture.
            tex = loader.loadTexture('gradient.png')
            np = NodePath('np')
            np.setTexture(tex, 100)
            np.setColor((1, 1, 1, 1), 100)
            np.setColorScaleOff(100)
            np.setTransparency(TransparencyAttrib.MNone, 100)
            np.setLightOff(100)
            cam.setInitialState(np.getState())
            #render.hide(AvBufMask)

        # Setup a texture stage to paint on the player
        self.paintTs = TextureStage('paintTs')
        self.paintTs.setMode(TextureStage.MDecal)
        self.paintTs.setSort(10)
        self.paintTs.setPriority(10)

        self.tex = Texture('paint_av_%s'%id(self))

        # Setup a PNMImage that will hold the paintable texture of the player
        self.imageSizeX = 64
        self.imageSizeY = 64
        self.p = PNMImage(self.imageSizeX, self.imageSizeY, 4)
        self.p.fill(1)
        self.p.alphaFill(0)
        self.tex.load(self.p)
        self.tex.setWrapU(self.tex.WMClamp)
        self.tex.setWrapV(self.tex.WMClamp)

        # Apply the paintable texture to the avatar
        self.player.setTexture(self.paintTs, self.tex)

        # team
        self.playerTeam = ""
        # A lable that will display the players team
        self.lblTeam = DirectLabel(
            scale = 1,
            pos = (0, 0, 3),
            frameColor = (0, 0, 0, 0),
            text = "TEAM",
            text_align = TextNode.ACenter,
            text_fg = (0,0,0,1))
        self.lblTeam.reparentTo(self.player)
        self.lblTeam.setBillboardPointEye()

        # basic player values
        self.maxHits = 3
        self.currentHits = 0
        self.isOut = False

        self.TorsorControl = self.player.controlJoint(None,"modelRoot","Torsor")

        # setup the collision detection
        # wall and object collision
        self.playerSphere = CollisionSphere(0, 0, 1, 1)
        self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision%d"%id(self)))
        self.playerCollision.node().addSolid(self.playerSphere)
        base.pusher.addCollider(self.playerCollision, self.player)
        base.cTrav.addCollider(self.playerCollision, base.pusher)
        # foot (walk) collision
        self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision%d"%id(self)))
        self.playerFootRay.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -1))
        self.playerFootRay.node().setIntoCollideMask(0)
        self.lifter = CollisionHandlerFloor()
        self.lifter.addCollider(self.playerFootRay, self.player)
        base.cTrav.addCollider(self.playerFootRay, self.lifter)

        # Player weapon setup
        self.gunAttach = self.player.exposeJoint(None, "modelRoot", "WeaponSlot_R")
        self.color = LPoint3f(1, 1, 1)
        self.gun = Gun(id(self))
        self.gun.reparentTo(self.gunAttach)
        self.gun.hide()
        self.gun.setColor(self.color)

        self.hud = None

        # Player controls setup
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0}
        # screen sizes
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2
        self.mouseSpeedX = 0.1
        self.mouseSpeedY = 0.1
        # AI controllable variables
        self.AIP = 0.0
        self.AIH = 0.0

        self.movespeed = 5.0

        self.userControlled = False

        self.accept("Bulet-hit-playerCollision%d" % id(self), self.hit)
        self.accept("window-event", self.recalcAspectRatio)

    def runBase(self):
        self.player.show()
        self.gun.show()
        taskMgr.add(self.move, "moveTask%d"%id(self), priority=-4)

    def stopBase(self):
        taskMgr.remove("moveTask%d"%id(self))
        self.ignoreAll()
        self.gun.remove()
        self.footstep.stop()
        base.audio3d.detachSound(self.footstep)
        self.player.delete()

    def setKey(self, key, value):
        self.keyMap[key] = value

    def setPos(self, pos):
        self.player.setPos(pos)

    def setColor(self, color=LPoint3f(0,0,0)):
        self.color = color
        self.gun.setColor(color)
        c = (color[0], color[1], color[2], 1.0)
        self.lblTeam["text_fg"] = c

    def setTeam(self, team):
        self.playerTeam = team
        self.lblTeam["text"] = team


    def shoot(self, shotVec=None):
        self.gun.shoot(shotVec)
        if self.hud != None:
            self.hud.updateAmmo(self.gun.maxAmmunition, self.gun.ammunition)

    def reload(self):
        self.gun.reload()
        if self.hud != None:
            self.hud.updateAmmo(self.gun.maxAmmunition, self.gun.ammunition)

    def recalcAspectRatio(self, window):
        self.winXhalf = window.getXSize() / 2
        self.winYhalf = window.getYSize() / 2

    def hit(self, entry, color):
        self.currentHits += 1

        # Create a brush to paint on the texture
        splat = PNMImage("../data/Splat.png")
        splat = splat * LColorf(color[0], color[1], color[2], 1.0)
        self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1)

        self.paintAvatar(entry)

        if self.currentHits >= self.maxHits:
            base.messenger.send("GameOver-player%d" % id(self))
            self.isOut = True

    def __paint(self, s, t):
        """ Paints a point on the avatar at texture coordinates (s, t). """
        x = (s * self.p.getXSize())
        y = ((1.0 - t) * self.p.getYSize())

        # Draw in color directly on the avatar
        p1 = PNMPainter(self.p)
        p1.setPen(self.colorBrush)
        p1.drawPoint(x, y)

        self.tex.load(self.p)
        self.tex.setWrapU(self.tex.WMClamp)
        self.tex.setWrapV(self.tex.WMClamp)

        self.paintDirty = True

    def paintAvatar(self, entry):
        """ Paints onto an avatar.  Returns true on success, false on
        failure (because there are no avatar pixels under the mouse,
        for instance). """

        # First, we have to render the avatar in its false-color
        # image, to determine which part of its texture is under the
        # mouse.
        if not self.avbuf:
            return False

        #mpos = base.mouseWatcherNode.getMouse()
        mpos = entry.getSurfacePoint(self.player)
        ppos = entry.getSurfacePoint(render)

        self.player.showThrough(BitMask32.bit(1))
        self.avbuf.setActive(True)
        base.graphicsEngine.renderFrame()
        self.player.show(BitMask32.bit(1))
        self.avbuf.setActive(False)

        # Now we have the rendered image in self.avbufTex.
        if not self.avbufTex.hasRamImage():
            print "Weird, no image in avbufTex."
            return False
        p = PNMImage()
        self.avbufTex.store(p)
        ix = int((1 + mpos.getX()) * p.getXSize() * 0.5)
        iy = int((1 - mpos.getY()) * p.getYSize() * 0.5)
        x = 1
        if ix >= 0 and ix < p.getXSize() and iy >= 0 and iy < p.getYSize():
            s = p.getBlue(ix, iy)
            t = p.getGreen(ix, iy)
            x = p.getRed(ix, iy)
        if x > 0.5:
            # Off the avatar.
            return False

        # At point (s, t) on the avatar's map.

        self.__paint(s, t)
        return True

    def move(self, task):
        if self is None: return task.done
        if self.userControlled:
            if not base.mouseWatcherNode.hasMouse(): return task.cont
            self.pointer = base.win.getPointer(0)
            mouseX = self.pointer.getX()
            mouseY = self.pointer.getY()

            if base.win.movePointer(0, self.winXhalf, self.winYhalf):
                p = self.TorsorControl.getP() + (mouseY - self.winYhalf) * self.mouseSpeedY
                if p <-80:
                    p = -80
                elif p > 90:
                    p = 90
                self.TorsorControl.setP(p)

                h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX
                if h <-360:
                    h = 360
                elif h > 360:
                    h = -360
                self.player.setH(h)
        else:
            self.TorsorControl.setP(self.AIP)
            self.player.setH(self.AIH)

        forward =  self.keyMap["forward"] != 0
        backward = self.keyMap["backward"] != 0

        if self.keyMap["left"] != 0:
            if self.player.getCurrentAnim() != "Sidestep" and not (forward or backward):
                self.player.loop("Sidestep")
                self.player.setPlayRate(5, "Sidestep")
            self.player.setX(self.player, self.movespeed * globalClock.getDt())
        elif self.keyMap["right"] != 0:
            if self.player.getCurrentAnim() != "Sidestep" and not (forward or backward):
                self.player.loop("Sidestep")
                self.player.setPlayRate(5, "Sidestep")
            self.player.setX(self.player, -self.movespeed * globalClock.getDt())
        else:
            self.player.stop("Sidestep")
        if forward:
            if self.player.getCurrentAnim() != "Run":
                self.player.loop("Run")
                self.player.setPlayRate(5, "Run")
            self.player.setY(self.player, -self.movespeed * globalClock.getDt())
        elif backward:
            if self.player.getCurrentAnim() != "Run":
                self.player.loop("Run")
                self.player.setPlayRate(-5, "Run")
            self.player.setY(self.player, self.movespeed * globalClock.getDt())
        else:
            self.player.stop("Run")

        if not (self.keyMap["left"] or self.keyMap["right"] or
                self.keyMap["forward"] or self.keyMap["backward"] or
                self.player.getCurrentAnim() == "Idle"):
            self.player.loop("Idle")
            self.footstep.stop()
        else:
            self.footstep.play()

        return task.cont
class Water(AssetBase):
    def __init__(self, name, size=10000, resolution=1024):
        """Arguments:
        size -- Edge length of the water square.
        resolution -- Texture size of the rendered reflection buffer.
        """
        # Uncomment to see the output of the refclection buffer.
        base.bufferViewer.toggleEnable()

        AssetBase.__init__(self)
        self.name = name

        self.cm = CardMaker("water surface")
        self.cm.setFrame(-0.5 * size, 0.5 * size, -0.5 * size, 0.5 * size)
        self.cm.setHasUvs(True)
        self.node = NodePath(self.cm.generate())

        self.node.setP(self.node, -90)
        self.node.flattenLight()
        self.node.hide(BitMask32.bit(1))
        # self.node.setTwoSided(True)
        self.node.setShaderOff()

        # size of one texture tile in meters
        self.tex_size = 100.0

        diffuse = TexturePool.loadTexture("textures/water.diffuse.png")
        diffuse.setWrapU(Texture.WMRepeat)
        diffuse.setWrapV(Texture.WMRepeat)
        diffuse.setMinfilter(Texture.FTLinearMipmapLinear)
        diffuse.setMagfilter(Texture.FTLinearMipmapLinear)
        self.diffuse_stage = TextureStage("diffuse")
        self.diffuse_stage.setSort(2)
        self.node.setTexture(self.diffuse_stage, diffuse)
        self.node.setTexScale(self.diffuse_stage, size / self.tex_size, size / self.tex_size)

        # Reflection camera renders to 'buffer' which is projected onto the
        # water surface.
        buffer = base.win.makeTextureBuffer("water reflection", resolution, resolution)
        buffer.setClearColor(Vec4(0, 0, 0, 1))

        self.refl_cam = base.makeCamera(buffer)
        self.refl_cam.reparentTo(self.node)
        self.refl_cam.node().setCameraMask(BitMask32.bit(1))
        self.refl_cam.node().getLens().setFov(base.camLens.getFov())
        self.refl_cam.node().getLens().setNearFar(1, 100000)

        plane = PlaneNode("water culling plane", Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
        cfa = CullFaceAttrib.makeReverse()
        cpa = ClipPlaneAttrib.make(PlaneNode.CEVisible, plane)
        rs = RenderState.make(cfa, cpa)
        self.refl_cam.node().setInitialState(rs)

        reflection = buffer.getTexture()
        reflection.setMinfilter(Texture.FTLinear)
        reflection.setMagfilter(Texture.FTLinear)
        self.refl_stage = TextureStage("reflection")
        self.refl_stage.setSort(1)
        self.node.projectTexture(self.refl_stage, reflection, base.cam)
        self.node.setTexture(self.refl_stage, reflection)

        # Blend between diffuse and reflection.
        self.diffuse_stage.setColor(VBase4(1, 1, 1, 0.2))  # opacity of 20%
        self.diffuse_stage.setCombineRgb(
            TextureStage.CMInterpolate,
            TextureStage.CSTexture,
            TextureStage.COSrcColor,
            TextureStage.CSPrevious,
            TextureStage.COSrcColor,
            TextureStage.CSConstant,
            TextureStage.COSrcAlpha,
        )

        self.addTask(self.update, name="water update", sort=1, taskChain="world")

    def update(self, task):
        """Updates position of the reflection camera and the water plane."""
        mc = base.cam.getMat(render)
        # mf = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)).getReflectionMat()
        mf = Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)
        self.refl_cam.setMat(mc * mf)

        self.node.setX(camera.getX(render))
        self.node.setY(camera.getY(render))
        self.node.setTexOffset(self.diffuse_stage, self.node.getX() / self.tex_size, self.node.getY() / self.tex_size)

        return task.cont

    def destroy(self):
        self.removeAllTasks()
        self.node.removeNode()
        self.refl_cam.removeNode()
Пример #27
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # Load the environment model.
        self.setup_environment()
        #self.scene = self.loader.loadModel("models/environment")
        # Reparent the model to render.
        #self.scene.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        #self.scene.setScale(0.25, 0.25, 0.25)
        #self.scene.setPos(-8, 42, 0)

        # Needed for camera image
        self.dr = self.camNode.getDisplayRegion(0)

        # Needed for camera depth image
        winprops = WindowProperties.size(self.win.getXSize(),
                                         self.win.getYSize())
        fbprops = FrameBufferProperties()
        fbprops.setDepthBits(1)
        self.depthBuffer = self.graphicsEngine.makeOutput(
            self.pipe, "depth buffer", -2, fbprops, winprops,
            GraphicsPipe.BFRefuseWindow, self.win.getGsg(), self.win)
        self.depthTex = Texture()
        self.depthTex.setFormat(Texture.FDepthComponent)
        self.depthBuffer.addRenderTexture(self.depthTex,
                                          GraphicsOutput.RTMCopyRam,
                                          GraphicsOutput.RTPDepth)
        lens = self.cam.node().getLens()
        lens.setFov(90.0, 90.0)
        # the near and far clipping distances can be changed if desired
        # lens.setNear(5.0)
        # lens.setFar(500.0)
        self.depthCam = self.makeCamera(self.depthBuffer,
                                        lens=lens,
                                        scene=self.render)
        self.depthCam.reparentTo(self.cam)

        # TODO: Scene is rendered twice: once for rgb and once for depth image.
        # How can both images be obtained in one rendering pass?
        self.render.setAntialias(AntialiasAttrib.MAuto)

    def setup_environment(self):
        # encapsulate some stuff

        # set up ambient lighting
        self.alight = AmbientLight('alight')
        self.alight.setColor(VBase4(0.1, 0.1, 0.1, 1))
        self.alnp = self.render.attachNewNode(self.alight)
        self.render.setLight(self.alnp)

        # set up a point light
        self.plight = PointLight('plight')
        self.plight.setColor(VBase4(0.8, 0.8, 0.8, 1))
        self.plnp = self.render.attachNewNode(self.plight)
        self.plnp.setPos(0, 0, 100)
        self.render.setLight(self.plnp)

        # set up terrain model
        self.terr_material = Material()
        self.terr_material.setShininess(1.0)
        self.terr_material.setAmbient(VBase4(0, 0, 0, 0))
        self.terr_material.setDiffuse(VBase4(1, 1, 1, 1))
        self.terr_material.setEmission(VBase4(0, 0, 0, 0))
        self.terr_material.setSpecular(VBase4(0, 0, 0, 0))

        # general scaling
        self.trrHorzSc = 4.0
        self.trrVertSc = 4.0  # was 4.0

        # Create sky
        #terrctr = self.trrHorzSc*65.0
        #self.setup_skybox(terrctr,800.0,2.0,0.3)

        self.skysphere = self.loader.loadModel("sky-forest/SkySphere.bam")
        self.skysphere.setBin('background', 1)
        self.skysphere.setDepthWrite(0)
        self.skysphere.reparentTo(self.render)

        # Load some textures
        self.grsTxtSc = 5
        self.numTreeTexts = 7

        # ground texture
        self.txtGrass = self.loader.loadTexture('tex/ground005.png')
        self.txtGrass.setWrapU(Texture.WM_mirror)
        self.txtGrass.setWrapV(Texture.WM_mirror)
        self.txtGrass.setMagfilter(Texture.FTLinear)
        self.txtGrass.setMinfilter(Texture.FTLinearMipmapLinear)

        # set up terrain texture stages
        self.TS1 = TextureStage('terrtext')
        self.TS1.setSort(0)
        self.TS1.setMode(TextureStage.MReplace)

        # Set up the GeoMipTerrain
        self.terrain = GeoMipTerrain("myDynamicTerrain")
        img = PNMImage(Filename('tex/bowl_height_map.png'))
        self.terrain.setHeightfield(img)
        self.terrain.setBruteforce(0)
        self.terrain.setAutoFlatten(GeoMipTerrain.AFMMedium)

        # Set terrain properties
        self.terrain.setBlockSize(32)
        self.terrain.setNear(50)
        self.terrain.setFar(500)
        self.terrain.setFocalPoint(self.camera)

        # Store the root NodePath for convenience
        self.root = self.terrain.getRoot()
        self.root.clearTexture()
        self.root.setTwoSided(0)
        self.root.setCollideMask(BitMask32.bit(0))
        self.root.setSz(self.trrVertSc)
        self.root.setSx(self.trrHorzSc)
        self.root.setSy(self.trrHorzSc)
        self.root.setMaterial(self.terr_material)
        self.root.setTexture(self.TS1, self.txtGrass)
        self.root.setTexScale(self.TS1, self.grsTxtSc, self.grsTxtSc)
        offset = 0.5 * img.getXSize() * self.trrHorzSc - 0.5
        self.root.setPos(-offset, -offset, 0)

        self.terrain.generate()
        self.root.reparentTo(self.render)

        # load tree billboards
        self.txtTreeBillBoards = []
        for a in range(self.numTreeTexts):
            fstr = 'trees/tree' + '%03d' % (a + 991)
            self.txtTreeBillBoards.append( \
                self.loader.loadTexture(fstr + '-color.png', fstr + '-opacity.png'))
            self.txtTreeBillBoards[a].setMinfilter(
                Texture.FTLinearMipmapLinear)

        #self.placePlantOnTerrain('trees',300,0,20,20,self.trrHorzSc,self.trrVertSc, \
        #    self.numTreeTexts,self.txtTreeBillBoards,'scene-def/trees.txt')
        self.setup_house()
        self.setup_vehicle()

        self.taskMgr.add(self.skysphereTask, "SkySphere Task")

    def setup_house(self):
        # place farmhouse on terrain
        self.house = ModelNode('house1')
        self.loadModelOntoTerrain(self.render, self.terrain, self.house, 43.0,
                                  0.275, 0.0, 0.0, self.trrHorzSc,
                                  self.trrVertSc, 'models/FarmHouse',
                                  Vec3(0, 0, 0),
                                  Point3(-12.0567, -29.1724, 0.0837742),
                                  Point3(12.2229, 21.1915, 21.3668))

    def setup_vehicle(self):
        # place HMMWV on terrain
        self.hmmwv = ModelNode('hmmwv1')
        self.loadModelOntoTerrain(self.render, self.terrain, self.hmmwv, 33.0,
                                  1.0, 20.0, 24.0, self.trrHorzSc,
                                  self.trrVertSc, 'models/hmmwv',
                                  Vec3(0, -90, 0),
                                  Point3(-1.21273, -2.49153, -1.10753),
                                  Point3(1.21273, 2.49153, 1.10753))

    def setup_skybox(self,
                     terrctr=645.0,
                     boxsz=1000.0,
                     aspect=1.0,
                     uplift=0.0):
        vsz = boxsz / aspect
        self.bckgtx = []
        self.bckgtx.append(self.loader.loadTexture('sky/Back2.png'))
        self.bckgtx.append(self.loader.loadTexture('sky/Right2.png'))
        self.bckgtx.append(self.loader.loadTexture('sky/Front2.png'))
        self.bckgtx.append(self.loader.loadTexture('sky/Left2.png'))
        self.bckgtx.append(self.loader.loadTexture('sky/Up.png'))
        for a in range(4):
            self.bckg = CardMaker('bkcard')
            lr = Point3(0.5 * boxsz, 0.5 * boxsz, -0.5 * vsz)
            ur = Point3(0.5 * boxsz, 0.5 * boxsz, 0.5 * vsz)
            ul = Point3(-0.5 * boxsz, 0.5 * boxsz, 0.5 * vsz)
            ll = Point3(-0.5 * boxsz, 0.5 * boxsz, -0.5 * vsz)
            self.bckg.setFrame(ll, lr, ur, ul)
            self.bckg.setHasNormals(0)
            self.bckg.setHasUvs(1)
            #self.bckg.setUvRange(self.bckgtx[a])
            bkcrd = self.render.attachNewNode(self.bckg.generate())
            bkcrd.setTexture(self.bckgtx[a])
            self.bckgtx[a].setWrapU(Texture.WMClamp)
            self.bckgtx[a].setWrapV(Texture.WMClamp)
            bkcrd.setLightOff()
            bkcrd.setFogOff()
            bkcrd.setHpr(90.0 * a, 0, 0)
            cz = 0.5 * boxsz * uplift
            #print 'set card at:', terrctr,terrctr,cz, ' with points: ', lr,ur,ul,ll
            bkcrd.setPos(terrctr, terrctr, cz)
            self.top = CardMaker('bkcard')
            lr = Point3(0.5 * boxsz, -0.5 * boxsz, 0)
            ur = Point3(0.5 * boxsz, 0.5 * boxsz, 0)
            ul = Point3(-0.5 * boxsz, 0.5 * boxsz, 0)
            ll = Point3(-0.5 * boxsz, -0.5 * boxsz, 0)
            self.top.setFrame(ll, lr, ur, ul)
            self.top.setHasNormals(0)
            self.top.setHasUvs(1)
            #self.top.setUvRange(self.bckgtx[4])
            bkcrd = self.render.attachNewNode(self.bckg.generate())
            bkcrd.setTexture(self.bckgtx[4])
            self.bckgtx[4].setWrapU(Texture.WMClamp)
            self.bckgtx[4].setWrapV(Texture.WMClamp)
            bkcrd.setLightOff()
            bkcrd.setFogOff()
            bkcrd.setHpr(0, 90, 90)
            bkcrd.setPos(terrctr, terrctr, 0.5 * vsz + 0.5 * boxsz * uplift)

    def placePlantOnTerrain(self, itemStr, itemCnt, Mode, typItemWidth,
                            typItemHeight, trrHorzSc, trrVertSc, numTxtTypes,
                            txtList, planFileName):
        # Billboarding plants
        crd = CardMaker('mycard')
        crd.setColor(0.5, 0.5, 0.5, 1)
        ll = Point3(-0.5 * typItemWidth, 0, 0)
        lr = Point3(0.5 * typItemWidth, 0, 0)
        ur = Point3(0.5 * typItemWidth, 0, typItemHeight)
        ul = Point3(-0.5 * typItemWidth, 0, typItemHeight)
        crd.setFrame(ll, lr, ur, ul)
        crd.setHasNormals(False)
        crd.setHasUvs(True)
        # generate/save/load locations
        try:
            plan_data_fp = open(planFileName, 'r')
            item_list = []
            for line in plan_data_fp:
                toks = line.split(',')
                px = float(toks[0].strip(' '))
                py = float(toks[1].strip(' '))
                ang = float(toks[2].strip(' '))
                dht = float(toks[3].strip(' '))
                scl = float(toks[4].strip(' '))
                idx = int(toks[5].strip(' '))
                item_list.append((px, py, ang, dht, scl, idx))
            plan_data_fp.close()
            print 'loaded ', itemStr, ' data file of size:', len(item_list)
        except IOError:
            # generate list and try to save
            item_list = []
            for a in range(itemCnt):
                px = random.randrange(-self.trrHorzSc * 64,
                                      self.trrHorzSc * 64)
                py = random.randrange(-self.trrHorzSc * 64,
                                      self.trrHorzSc * 64)
                ang = 180 * random.random()
                dht = 0.0
                scl = 0.75 + 0.25 * (random.random() + random.random())
                idx = random.randrange(0, numTxtTypes)
                item_list.append([px, py, ang, dht, scl, idx])
            try:
                plan_data_fp = open(planFileName, 'w')
                for c in item_list:
                    print >> plan_data_fp, c[0], ',', c[1], ',', c[2], ',', c[
                        3], ',', c[4], ',', c[5]
                plan_data_fp.close()
                print 'saved ', itemStr, ' data of size: ', len(item_list)
            except IOError:
                print 'unable to store ', itemStr, ' data of size: ', len(
                    item_list)
        # define each plant
        for c in item_list:
            px = c[0]
            py = c[1]
            ang = c[2]
            dht = c[3]
            scl = c[4]
            idx = c[5]
            if idx >= numTxtTypes:
                idx = 0
            if Mode > 0:
                for b in range(Mode):
                    crdNP = self.render.attachNewNode(crd.generate())
                    crdNP.setTexture(txtList[idx])
                    crdNP.setScale(scl)
                    crdNP.setTwoSided(True)
                    ht = self.terrain.getElevation(px / trrHorzSc,
                                                   py / trrHorzSc)
                    crdNP.setPos(px, py, ht * trrVertSc + dht)
                    crdNP.setHpr(ang + (180 / Mode) * b, 0, 0)
                    crdNP.setTransparency(TransparencyAttrib.MAlpha)
                    crdNP.setLightOff()
            else:
                # set up item as defined
                crd.setUvRange(txtList[idx])
                crdNP = self.render.attachNewNode(crd.generate())
                crdNP.setBillboardAxis()
                crdNP.setTexture(txtList[idx])
                crdNP.setScale(scl)
                ht = self.terrain.getElevation(px / trrHorzSc, py / trrHorzSc)
                crdNP.setPos(px, py, ht * trrVertSc)
                crdNP.setTransparency(TransparencyAttrib.MAlpha)
                crdNP.setLightOff()

    def loadModelOntoTerrain(self, render_node, terr_obj, model_obj, hdg, scl,
                             xctr, yctr, terr_horz_sc, terr_vert_sc,
                             model_path, rotA, minP, maxP):
        # load model onto terrain
        hdg_rads = hdg * math.pi / 180.0
        model_obj = self.loader.loadModel(model_path)
        rotAll = rotA
        rotAll.setX(rotAll.getX() + hdg)
        model_obj.setHpr(rotA)
        model_obj.setLightOff()
        # if model changes, these will have to be recomputed
        # minP = Point3(0,0,0)
        # maxP = Point3(0,0,0)
        # model_obj.calcTightBounds(minP,maxP)
        print minP
        print maxP
        htl = []
        maxzofs = -1000.0
        for xi in [minP[0], maxP[0]]:
            for yi in [minP[1], maxP[1]]:
                tx = xctr + scl * xi * math.cos(hdg_rads)
                ty = yctr + scl * yi * math.sin(hdg_rads)
                tht = self.terrain.getElevation(tx / terr_horz_sc,
                                                ty / terr_horz_sc)
                print 'tx=', tx, ', ty=', ty, ', tht=', tht
                htl.append(tht * terr_vert_sc - minP.getZ())
        for hi in htl:
            if hi > maxzofs:
                maxzofs = hi
        print maxzofs
        model_obj.setPos(xctr, yctr, maxzofs)
        model_obj.setHpr(rotAll)
        model_obj.setScale(scl)
        model_obj.reparentTo(render_node)
        return maxzofs, minP, maxP

    def get_camera_image(self, requested_format=None):
        """
        Returns the camera's image, which is of type uint8 and has values
        between 0 and 255.
        The 'requested_format' argument should specify in which order the
        components of the image must be. For example, valid format strings are
        "RGBA" and "BGRA". By default, Panda's internal format "BGRA" is used,
        in which case no data is copied over.
        """
        tex = self.dr.getScreenshot()
        if requested_format is None:
            data = tex.getRamImage()
        else:
            data = tex.getRamImageAs(requested_format)
        image = np.frombuffer(
            data.get_data(),
            np.uint8)  # use data.get_data() instead of data in python 2
        image.shape = (tex.getYSize(), tex.getXSize(), tex.getNumComponents())
        image = np.flipud(image)
        return image

    def get_camera_depth_image(self):
        """
        Returns the camera's depth image, which is of type float32 and has
        values between 0.0 and 1.0.
        """
        data = self.depthTex.getRamImage()
        depth_image = np.frombuffer(data.get_data(), np.float32)
        depth_image.shape = (self.depthTex.getYSize(),
                             self.depthTex.getXSize(),
                             self.depthTex.getNumComponents())
        depth_image = np.flipud(depth_image)
        '''
        
        Surface position can be inferred by calculating backward from the
        depth buffer. Each pixel on the screen represents a ray from the
        camera into the scene, and the depth value in the pixel indicates a
        distance along the ray. Because of this, it is not actually necessary
        to store surface position explicitly - it is only necessary to store
        depth values. Of course, OpenGL does that for free.

        So the framebuffer now needs to store surface normal, diffuse color,
        and depth value (to infer surface position). In practice, most
        ordinary framebuffers can only store color and depth - they don't have
        any place to store a third value. So we need to use a special
        offscreen buffer with an "auxiliary" bitplane. The auxiliary bitplane
        stores the surface normal.

        So then, there's the final postprocessing pass. This involves
        combining the diffuse color texture, the surface normal texture, the
        depth texture, and the light parameters into a final rendered output.
        The light parameters are passed into the postprocessing shader as
        constants, not as textures.

        If there are a lot of lights, things get interesting. You use one
        postprocessing pass per light. Each pass only needs to scan those
        framebuffer pixels that are actually in range of the light in
        question. To traverse only the pixels that are affected by the light,
        just render the illuminated area's convex bounding volume.

        The shader to store the diffuse color and surface normal is trivial.
        But the final postprocessing shader is a little complicated. What
        makes it tricky is that it needs to regenerate the original surface
        position from the screen position and depth value. The math for that
        deserves some explanation.

        We need to take a clip-space coordinate and depth-buffer value
        (ClipX,ClipY,ClipZ,ClipW) and unproject it back to a view-space
        (ViewX,ViewY,ViewZ) coordinate. Lighting is then done in view-space.

        Okay, so here's the math. Panda uses the projection matrix to
        transform view-space into clip-space. But in practice, the projection
        matrix for a perspective camera always contains four nonzero
        constants, and they're always in the same place:
            
        -- here are the non-zero elements of the projection matrix --
        
        A	0	0	0
        0	0	B	1
        0	C	0	0
        0	0	D	0
        
        -- precompute these from above projection matrix --
        '''
        proj = self.cam.node().getLens().getProjectionMat()
        proj_x = 0.5 * proj.getCell(3, 2) / proj.getCell(0, 0)
        proj_y = 0.5 * proj.getCell(3, 2)
        proj_z = 0.5 * proj.getCell(3, 2) / proj.getCell(2, 1)
        proj_w = -0.5 - 0.5 * proj.getCell(1, 2)
        '''
        -- now for each pixel compute viewpoint coordinates --
        
        viewx = (screenx * projx) / (depth + projw)
        viewy = (1 * projy) / (depth + projw)
        viewz = (screeny * projz) / (depth + projw)
        '''
        grid = np.mgrid[0:depth_image.shape[0], 0:depth_image.shape[1]]
        ygrid = np.float32(np.squeeze(
            grid[0, :, :])) / float(depth_image.shape[0] - 1)
        ygrid -= 0.5
        xgrid = np.float32(np.squeeze(
            grid[1, :, :])) / float(depth_image.shape[1] - 1)
        xgrid -= 0.5
        xview = 2.0 * xgrid * proj_x
        zview = 2.0 * ygrid * proj_z
        denom = np.squeeze(depth_image) + proj_w
        xview = xview / denom
        yview = proj_y / denom
        zview = zview / denom
        sqrng = xview**2 + yview**2 + zview**2
        range_image = np.sqrt(sqrng)
        range_image_1 = np.expand_dims(range_image, axis=2)

        return depth_image, range_image_1

    def compute_sample_pattern(self, limg_shape, res_factor):
        # assume velocity is XYZ and we are looking +X up and towards -Z
        pattern = []
        lens = self.cam.node().getLens()
        sx = self.win.getXSize()
        sy = self.win.getYSize()
        ifov_vert = 2.0 * math.tan(
            0.5 * math.radians(lens.getVfov())) / float(sy - 1)
        ifov_horz = 2.0 * math.tan(
            0.5 * math.radians(lens.getHfov())) / float(sx - 1)
        #ifov_vert = lens.getVfov() / float(sy-1)
        #ifov_horz = lens.getHfov() / float(sy-1)
        for ldr_row in range(limg_shape[0]):
            theta = -10.0 - 41.33 * (
                float(ldr_row) / float(limg_shape[0] - 1) - 0.5)
            for ldr_col in range(limg_shape[1]):
                psi = 60.0 * (float(ldr_col) / float(limg_shape[1] - 1) - 0.5)
                cpsi = math.cos(math.radians(psi))
                vert_ang = theta / cpsi
                img_row_flt = (0.5 * float(sy - 1) -
                               (math.tan(math.radians(vert_ang)) / ifov_vert))
                #img_row_flt = 0.5*(sy-1) - (vert_ang / ifov_vert)
                if img_row_flt < 0:
                    print('img_row_flt=%f' % img_row_flt)
                    img_row_flt = 0.0
                if img_row_flt >= sy:
                    print('img_row_flt=%f' % img_row_flt)
                    img_row_flt = float(sy - 1)
                img_col_flt = (0.5 * float(sx - 1) +
                               (math.tan(math.radians(psi)) / ifov_horz))
                #img_col_flt = 0.5*(sx-1) + (psi / ifov_horz)
                if img_col_flt < 0:
                    print('img_col_flt=%f' % img_col_flt)
                    img_col_flt = 0.0
                if img_col_flt >= sx:
                    print('img_col_flt=%f' % img_col_flt)
                    img_col_flt = float(sx - 1)
                pattern.append((ldr_row, ldr_col, img_row_flt, img_col_flt))
        return pattern

    def find_sorted_ladar_returns(self, rangearr, intensarr, ks_m):
        my_range = rangearr.copy()
        my_inten = intensarr.copy()
        '''
        pixels data is organized by:
           [0] starting range of this return
           [1] ending range of this return
           [2] peak range of this return
           [3] total intensity of this return
        '''
        int_mult = len(my_inten)
        pixels = map(
            list,
            zip(my_range.tolist(), my_range.tolist(), my_range.tolist(),
                my_inten.tolist()))
        spix = sorted(pixels, key=lambda x: x[0])
        done = False
        while not done:
            mxpi = len(spix)
            if mxpi > 2:
                mindel = 1e20
                mnidx = None
                for pidx in range(mxpi - 1):
                    rdel = spix[pidx + 1][0] - spix[pidx][1]
                    # must be within ks_m meters in range to merge
                    if (rdel < ks_m) and (rdel < mindel):
                        mindel = rdel
                        mnidx = pidx
                # merge best two returns
                if mnidx is not None:
                    # new range span for testing against neighbors
                    spix[mnidx][1] = spix[mnidx + 1][1]
                    # new peak range is range of max contributor
                    if spix[mnidx + 1][3] > spix[mnidx][3]:
                        spix[mnidx][2] = spix[mnidx + 1][2]
                    # intensity of return is sum of contributors
                    spix[mnidx][3] += spix[mnidx + 1][3]
                    # remove one of the two merged
                    del spix[mnidx + 1]
                else:
                    done = True
            else:
                done = True
        # now eliminate all but max and last returns
        max_idx = None
        max_val = 0.0
        for ci, pix in enumerate(spix):
            if pix[3] > max_val:
                max_val = pix[3] / int_mult
                max_idx = ci
        # if they are the same, return only one
        if spix[-1][3] >= spix[max_idx][3]:
            return [spix[-1]]
        else:
            return [spix[max_idx], spix[-1]]

    def sample_range_image(self, rng_img, int_img, limg_shape, vel_cam, pps,
                           ldr_err, pattern):
        # depth image is set up as 512 x 512 and is 62.5 degrees vertical FOV
        # the center row is vertical, but we want to sample from the
        # region corresponding to HDL-32 FOV: from +10 to -30 degrees
        detailed_sensor_model = False
        fwd_vel = vel_cam[1]
        beam_div = 0.002
        lens = self.cam.node().getLens()
        #sx = self.win.getXSize()
        sy = self.win.getYSize()
        ifov_vert = 2.0 * math.tan(
            0.5 * math.radians(lens.getVfov())) / float(sy - 1)
        #ifov_horz = 2.0*math.tan(0.5*math.radians(lens.getHfov()))/float(sx-1)
        #ifov = math.radians(self.cam.node().getLens().getVfov() / self.win.getYSize())
        sigma = beam_div / ifov_vert
        hs = int(2.0 * sigma + 1.0)
        gprof = gauss_kern(sigma, hs, normalize=False)
        rimg = np.zeros(limg_shape, dtype=np.float32)
        iimg = np.zeros(limg_shape, dtype=np.float32)
        margin = 10.0

        for pidx, relation in enumerate(pattern):

            # get the usual scan pattern sample
            ldr_row, ldr_col, img_row_flt, img_col_flt = relation

            if ((img_row_flt > -margin) and (img_col_flt > -margin)
                    and (img_row_flt < rng_img.shape[0] + margin)
                    and (img_col_flt < rng_img.shape[1] + margin)):

                # within reasonable distance from image limits
                img_row = int(round(img_row_flt))
                img_col = int(round(img_col_flt))

                # motion compensation
                trng = np.float32(rng_img[img_row, img_col])
                if trng > 0.0:
                    # TODO: change this back to False
                    done = True
                    ic = 0
                    while not done:
                        old_trng = trng
                        del_row = pidx * fwd_vel / (ifov_vert * trng * pps)
                        if (abs(del_row) > 1e-1) and (ic < 10):
                            img_row_f = img_row_flt + del_row
                            img_row = int(round(img_row_f))
                            trng = np.float32(rng_img[img_row, img_col])
                            ic += 1
                            if abs(trng - old_trng) < 0.5:
                                done = True
                        else:
                            done = True

                    # simple sensor processing: just sample from large images
                    rimg[ldr_row, ldr_col] = np.float32(rng_img[img_row,
                                                                img_col])
                    iimg[ldr_row, ldr_col] = np.float32(int_img[img_row,
                                                                img_col])

                    if detailed_sensor_model:
                        # detailed model subsamples whole beam width
                        gpatch = copy_patch_centered((img_row, img_col), hs,
                                                     int_img, 0.0)
                        gpatch = np.float32(gpatch)
                        gpatch *= gprof
                        rpatch = copy_patch_centered((img_row, img_col), hs,
                                                     rng_img, 0.0)
                        rpatch = np.squeeze(rpatch)
                        valid = rpatch > 1e-3
                        if np.count_nonzero(valid) > 0:
                            rpatch_ts = rpatch[valid]
                            gpatch_ts = gpatch[valid]
                            returns = self.find_sorted_ladar_returns(
                                rpatch_ts, gpatch_ts, 2.5)
                            # for now we just take first return
                            rimg[ldr_row, ldr_col] = returns[0][2]
                            iimg[ldr_row, ldr_col] = returns[0][3]
                else:
                    rimg[ldr_row, ldr_col] = 0.0
                    iimg[ldr_row, ldr_col] = np.float32(int_img[img_row,
                                                                img_col])

        rimg += ldr_err * np.random.standard_normal(rimg.shape)
        return rimg, iimg

    def skysphereTask(self, task):
        if self.base is not None:
            self.skysphere.setPos(self.base.camera, 0, 0, 0)
            self.terrain.generate()
        return task.cont
    def setupHeightmap(self, name):

        # Automatically generate a heightmap mesh from a monochrome image.
        self.hmHeight = 120
        hmPath = "../maps/map" + name + "/map" + name + "-h.png"
        imPath = "../maps/map" + name + "/map" + name + "-i.png"
        smPath = "../maps/map" + name + "/map" + name + "-s.png"
        scmPath = "../maps/map" + name + "/map" + name + "-sc.png"
        print(hmPath)
        print(imPath)
        print(smPath)
        print(scmPath)
        hmImg = PNMImage(Filename(hmPath))
        hmShape = BulletHeightfieldShape(hmImg, self.hmHeight, ZUp)
        hmNode = BulletRigidBodyNode('Terrain')
        hmNode.addShape(hmShape)
        hmNode.setMass(0)
        self.hmNP = render.attachNewNode(hmNode)
        self.worldBullet.attachRigidBody(hmNode)
        self.hmOffset = hmImg.getXSize() / 2.0 - 0.5
        self.hmTerrain = GeoMipTerrain('gmTerrain')
        self.hmTerrain.setHeightfield(hmImg)

        # Optimizations and fixes
        self.hmTerrain.setBruteforce(
            True)  # I don't think this is actually needed.
        self.hmTerrain.setMinLevel(3)  # THIS is what triangulates the terrain.
        self.hmTerrain.setBlockSize(
            128)  # This does a pretty good job of raising FPS.
        # Level-of-detail (not yet working)
        # self.hmTerrain.setNear(40)
        # self.hmTerrain.setFar(200)

        self.hmTerrain.generate()

        self.hmTerrainNP = self.hmTerrain.getRoot()
        self.hmTerrainNP.setSz(self.hmHeight)
        self.hmTerrainNP.setPos(-self.hmOffset, -self.hmOffset,
                                -self.hmHeight / 2.0)
        self.hmTerrainNP.flattenStrong(
        )  # This only reduces the number of nodes; nothing to do with polys.
        self.hmTerrainNP.analyze()

        # Here begins the scenery mapping
        treeModel = loader.loadModel("../res/models/tree_1.egg")
        rockModel = loader.loadModel("../res/models/rock_1.egg")
        rock2Model = loader.loadModel("../res/models/rock_2.egg")
        rock3Model = loader.loadModel("../res/models/rock_3.egg")
        # caveModel = loader.loadModel("../res/models/cave_new.egg")
        # planeFrontModel = loader.loadModel("../res/models/plane_front.egg")
        # planeWingModel = loader.loadModel("../res/models/plane_wing.egg")
        texpk = loader.loadTexture(scmPath).peek()

        # GameObject nodepath for flattening
        self.objNP = render.attachNewNode("gameObjects")
        self.treeNP = self.objNP.attachNewNode("goTrees")
        self.rockNP = self.objNP.attachNewNode("goRocks")
        self.rock2NP = self.objNP.attachNewNode("goRocks2")
        self.rock3NP = self.objNP.attachNewNode("goRocks3")
        # self.caveNP = self.objNP.attachNewNode("goCave")
        # self.planeFrontNP = self.objNP.attachNewNode("goPlaneFront")
        # self.planeWingNP = self.objNP.attachNewNode("goPlaneWing")

        for i in range(0, texpk.getXSize()):
            for j in range(0, texpk.getYSize()):
                color = VBase4(0, 0, 0, 0)
                texpk.lookup(color,
                             float(i) / texpk.getXSize(),
                             float(j) / texpk.getYSize())
                if (int(color.getX() * 255.0) == 255.0):
                    newTree = self.treeNP.attachNewNode("treeNode")
                    treeModel.instanceTo(newTree)
                    newTree.setPos(
                        i - texpk.getXSize() / 2, j - texpk.getYSize() / 2,
                        self.hmTerrain.get_elevation(i, j) * self.hmHeight -
                        self.hmHeight / 2)
                    # newTree.setScale(randint(0,4))
                    newTree.setScale(2)

                if (int(color.getX() * 255.0) == 128):
                    newRock = self.rockNP.attachNewNode("newRock")
                    newRock.setPos(
                        i - texpk.getXSize() / 2, j - texpk.getYSize() / 2,
                        self.hmTerrain.get_elevation(i, j) * self.hmHeight -
                        self.hmHeight / 2)
                    rockModel.instanceTo(newRock)

                if (int(color.getX() * 255.0) == 77):
                    newRock2 = self.rock2NP.attachNewNode("newRock2")
                    newRock2.setPos(
                        i - texpk.getXSize() / 2, j - texpk.getYSize() / 2,
                        self.hmTerrain.get_elevation(i, j) * self.hmHeight -
                        self.hmHeight / 2)
                    rock2Model.instanceTo(newRock2)

                if (int(color.getX() * 255.0) == 102):
                    newRock3 = self.rock3NP.attachNewNode("newRock3")
                    newRock3.setPos(
                        i - texpk.getXSize() / 2, j - texpk.getYSize() / 2,
                        self.hmTerrain.get_elevation(i, j) * self.hmHeight -
                        self.hmHeight / 2)
                    rock3Model.instanceTo(newRock3)

                # if(int(color.getX() * 255.0) == 64):
                # newCave = self.caveNP.attachNewNode("newCave")
                # newCave.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
                # newCave.setScale(5)
                # newCave.setP(180)
                # caveModel.instanceTo(newCave)

                # if(int(color.getX() * 255.0) == 191):
                # newPlaneFront = self.planeFrontNP.attachNewNode("newPlaneFront")
                # newPlaneFront.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
                # newPlaneFront.setScale(6)
                # planeFrontModel.instanceTo(newPlaneFront)

                # if(int(color.getX() * 255.0) == 179):
                # newPlaneWing = self.planeWingNP.attachNewNode("newPlaneWing")
                # newPlaneWing.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
                # newPlaneWing.setScale(6)
                # newPlaneWing.setH(250)
                # newPlaneWing.setR(180)
                # newPlaneWing.setP(135)
                # planeWingModel.instanceTo(newPlaneWing)

        self.snowflakes = []

        for i in xrange(0, self.snowflakeCount):
            print("Call " + str(i))
            sf = SMCollect(self.worldBullet, self.worldObj,
                           self.snowflakePositions[i])
            self.snowflakes.append(sf)

        # render.flattenStrong()
        self.hmTerrainNP.reparentTo(render)

        # Here begins the attribute mapping
        ts = TextureStage("stage-alpha")
        ts.setSort(0)
        ts.setPriority(1)
        ts.setMode(TextureStage.MReplace)
        ts.setSavedResult(True)
        self.hmTerrainNP.setTexture(ts, loader.loadTexture(imPath, smPath))

        ts = TextureStage("stage-stone")
        ts.setSort(1)
        ts.setPriority(1)
        ts.setMode(TextureStage.MReplace)
        self.hmTerrainNP.setTexture(
            ts, loader.loadTexture("../res/textures/stone_tex.png"))
        self.hmTerrainNP.setTexScale(ts, 32, 32)

        ts = TextureStage("stage-ice")
        ts.setSort(2)
        ts.setPriority(1)
        ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSTexture,
                         TextureStage.COSrcColor, TextureStage.CSPrevious,
                         TextureStage.COSrcColor,
                         TextureStage.CSLastSavedResult,
                         TextureStage.COSrcColor)
        self.hmTerrainNP.setTexture(
            ts, loader.loadTexture("../res/textures/ice_tex.png"))
        self.hmTerrainNP.setTexScale(ts, 32, 32)

        ts = TextureStage("stage-snow")
        ts.setSort(3)
        ts.setPriority(0)
        ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSTexture,
                         TextureStage.COSrcColor, TextureStage.CSPrevious,
                         TextureStage.COSrcColor,
                         TextureStage.CSLastSavedResult,
                         TextureStage.COSrcAlpha)
        self.hmTerrainNP.setTexture(
            ts, loader.loadTexture("../res/textures/snow_tex_1.png"))
        self.hmTerrainNP.setTexScale(ts, 32, 32)

        # print(self.snowflakes)

        return hmNode
Пример #29
0
 def __init__(self,path,heightScale,shader=None,skipTextures=False):
     self.shader=shader
     meshManager.MeshFactory.__init__(self)
 
     self.dataIndex={}
     
     
     
     self.heightScale=heightScale
     
     d=parseFile(path+'/texList.txt')
         
     self.mapTexStages={}
     self.specialMaps={}
     for m in d['Special']:
         s=m.split('\t')
         self.specialMaps[s[1]]=s[0]
     
     # List of non map texture stages, and their sizes
     # (TexStage,Size)
     self.texList=[]
     
     if not skipTextures:
         
         
         
         
         
         
         if "Tex2D" in d:
             sort=0;
             for m in d["Tex2D"]:
                 sort+=1
                 s=m.split()
                 name=s[0]
                 texStage=TextureStage(name+'stage'+str(sort))
                 texStage.setSort(sort)
                 source=s[1]
                 
 #                 def setTexModes(modeText):
 #                     combineMode=[]
 #                     for t in modeText:
 #                         if t[:1]=='M':
 #                             texStage.setMode(getRenderMapType(t))
 #                         elif t[:1]=='C':
 #                             combineMode.append(getCombineMode(t))
 #                         elif t=='Save':
 #                             texStage.setSavedResult(True)
 #                         else:
 #                             print "Illegal mode info for "+name
 #                     if len(combineMode)>0:
 #                         texStage.setCombineRgb(*combineMode)
 #                     if len(modeText)==0:
 #                         texStage.setMode(TextureStage.MModulate)
                 
                 if source=='file':
                     
 #                     setTexModes(s[3:])
                     tex=loadTex(path+"/textures/"+name)
 #                     self.terrainNode.setTexture(texStage,tex)
 #                     self.terrainNode.setShaderInput('tex2D_'+name,tex)
                     self.texList.append((texStage,float(s[2]),tex,name))
                     
                 elif source=='map':
 #                     setTexModes(s[2:])
                     self.mapTexStages[s[0]]=texStage
 # 
 #                 else:
 #                     print 'Invalid source for '+name+' int Tex2D'
         
     
     self.LOD=meshManager.LOD(float('inf'),0)