def imgNoise2D(self, size = 512, autoOctave = False): myImage=PNMImage(1,1) myImage.makeGrayscale() myImage.setMaxval( (2<<16)-1 ) myImage.fill(0.5) octaves = self.numberOfOctaves if autoOctave == True: octaves = int(math.log(size,2)) self.pNoise = range(0,octaves) random.seed(self.seed) for i in range(1,octaves): self.pNoise[i] = PerlinNoise2( 1, 1, 256, random.randint(1,10000)) for o in range(1,octaves): freq = 2**o oldImage = myImage myImage = PNMImage(freq+1,freq+1) myImage.makeGrayscale() myImage.setMaxval( (2<<16)-1 ) myImage.gaussianFilterFrom(1.0, oldImage) for x in range(0,freq): for y in range(0,freq): newNoise = (self.pNoise[o].noise( x, y)*(self.persistance**o)) / 2 myImage.setGray(x,y, myImage.getGray(x,y) + newNoise)#*32) for i in range(0,freq+1): myImage.setGray(i,freq, myImage.getGray(i%freq,0)) myImage.setGray(freq,i, myImage.getGray(0,i%freq)) oldImage = myImage myImage = PNMImage(size,size) myImage.makeGrayscale() myImage.setMaxval( (2<<16)-1 ) myImage.gaussianFilterFrom(1.0, oldImage) return myImage
def run(self): size = 256 pb = Perlin.Perlin( persistance = 0.500, smooth = False, seed = random.random() ) myImage2 = pb.imgNoise2D(size,True) myImage=PNMImage(size,size) myImage.makeGrayscale() myImage.setMaxval( (2<<16)-1 ) myImage.fill(0.5) line = lineDrawer.LineDrawer(myImage,(42,180),(13,253),13) for x in range(size): for y in range(size): gray = myImage.getGray(x,y) - 0.5 gray = gray + (myImage2.getGray(x,y) - 0.5) myImage.setGray(x,y,gray + 0.5) self.myTexture.load(myImage)
class Heightfield(DirectObject):# threading.Thread): #def __init__(self): # threading.Thread.__init__(self)#, name="test") def __init__( self ): '''try: import psyco psyco.full() except ImportError: pass''' self.ts0 = TextureStage( 'dirtL0' ) self.ts1 = TextureStage( 'dirtL1' ) self.ts2 = TextureStage( 'dirtL3' ) self.tex0 = loader.loadTexture( 'mud-tile.png' ) self.mTerrainHeight = MAPSIZE*3 self.mHorizontalScale = MAPSIZE/TEXSIZE size = int(TEXSIZE) + 1 pb = Perlin.Perlin( persistance = 0.500, smooth = False, seed = random.random() ) myImage2 = pb.imgNoise2D(size,True) self.myImage=PNMImage(size,size) self.myImage.makeGrayscale() self.myImage.setMaxval( (2<<16)-1 ) line = lineDrawer.LineDrawer(self.myImage,(42,180),(13,240),30) for x in range(size): for y in range(size): if self.myImage.getGray(x,y) > myImage2.getGray(x,y): gray = self.myImage.getGray(x,y) - 0.5 else: gray = myImage2.getGray(x,y) - 0.5 self.myImage.setGray(x,y,gray + 0.5) #size = int(TEXSIZE) + 1 #randSeed = random.random() #p1 = Perlin.Perlin( persistance = 0.500, smooth = False, seed = randSeed ) #self.myImage = p1.imgNoise2D(size,True) self.terrain1 = GeoMipTerrain("myTerrain1") self.terrain2 = GeoMipTerrain("myTerrain2") self.setupHeightfield(self.terrain1) self.setupHeightfield(self.terrain2) self.terrain1.getRoot().reparentTo(render) self.terrain2.getRoot().reparentTo(render) self.accept( "g", self.flattenArea) self.accept( "u", self.updateWithNewImage) def setupHeightfield( self , terrain): terrain.setHeightfield(self.myImage) terrain.setBruteforce(True) terrain.setBlockSize(64) terrain.setNear(128) terrain.setFar(512) terrain.setFocalPoint(base.camera.getPos(render)) taskMgr.add(self.updateTask, "update") mHeightFieldNode = terrain.getRoot() mHeightFieldNode.setPos( -MAPSIZE/2, -MAPSIZE/2, - self.mTerrainHeight/2) mHeightFieldNode.setSx(self.mHorizontalScale) mHeightFieldNode.setSy(self.mHorizontalScale) mHeightFieldNode.setSz(self.mTerrainHeight) terrain.generate() scale = 1.0 mHeightFieldNode.setTexScale( self.ts0, scale, scale ) mHeightFieldNode.setTexture( self.ts0, self.tex0, 1 ) scale = 32.0 mHeightFieldNode.setTexScale( self.ts1, scale, scale ) mHeightFieldNode.setTexture( self.ts1, self.tex0, 1 ) scale = 128.0 mHeightFieldNode.setTexScale( self.ts2, scale, scale ) mHeightFieldNode.setTexture( self.ts2, self.tex0, 1 ) def flattenArea( self ): tilePos = (500,500) tileSize = (4000,4000) imgTilePos = self.world2MapPos(tilePos) imgTileSize = self.world2MapPos( (tilePos[0] + tileSize[0], tilePos[1] + tileSize[1]) ) imgTileSize = (imgTileSize[0] - imgTilePos[0], imgTileSize[1] - imgTilePos[1]) tileSquare = PNMImage(Filename("tile.png")) tileStamp = PNMImage(int(imgTileSize[0] * (5/3)),int(imgTileSize[1] * (5/3))) tileStamp.makeGrayscale() tileStamp.addAlpha() tileStamp.gaussianFilterFrom(1, tileSquare) count = 4 total = 0.0 selectXLow = int(imgTilePos[0] + imgTileSize[0] * 0.25) selectXHigh = int(imgTilePos[0] + imgTileSize[0] * 0.75) selectYLow = int(imgTilePos[1] + imgTileSize[1] * 0.25) selectYHigh = int(imgTilePos[1] + imgTileSize[1] * 0.75) total += self.myImage.getGray(selectXLow,selectYLow) total += self.myImage.getGray(selectXLow,selectYLow) total += self.myImage.getGray(selectXHigh,selectYHigh) total += self.myImage.getGray(selectXHigh,selectYHigh) average = total/count tileStamp.fill(average) edgeWidth = imgTilePos[0]*(1/3) self.myImage.blendSubImage(tileStamp, int( imgTilePos[0]-edgeWidth), int( imgTilePos[1]-edgeWidth), 0, 0, int(imgTileSize[0]*( 5/3 ) ), int(imgTileSize[1]*( 5/3 ) ), 1) def getCurrentTerrain(self): if self.terrain2.getRoot().isHidden(): return self.terrain1 else: return self.terrain2 def getHiddenTerrain(self): if self.terrain1.getRoot().isHidden(): return self.terrain1 else: return self.terrain2 def updateWithNewImage(self): posX = base.camera.getX() + MAPSIZE/2 posY = base.camera.getY() + MAPSIZE/2 if self.terrain2.getRoot().isHidden(): self.terrain2.setHeightfield(self.myImage) self.terrain2.setFocalPoint(posX, posY) if Thread.isThreadingSupported(): thread.start_new_thread(self.updateWithNewImageThread,(self.terrain2,1)) else: self.updateWithNewImageThread(self.terrain2) self.terrain1.getRoot().hide() self.terrain2.getRoot().show() print "done" else: self.terrain1.setHeightfield(self.myImage) self.terrain1.setFocalPoint(posX, posY) if Thread.isThreadingSupported(): thread.start_new_thread(self.updateWithNewImageThread,(self.terrain1,1)) else: self.updateWithNewImageThread(self.terrain1) self.terrain2.getRoot().hide() self.terrain1.getRoot().show() print "done2" def updateWithNewImageThread(self,terrain,blag=1): terrain.update() def updateTask(self,task): posX = base.camera.getX(render) + MAPSIZE/2 posY = base.camera.getY(render) + MAPSIZE/2 self.getCurrentTerrain().setFocalPoint(posX, posY) self.getCurrentTerrain().update() return task.cont def world2MapPos( self, in_pos ): result = (0,0) if abs(in_pos[0]) <= MAPSIZE/2.0 and abs(in_pos[1]) <= MAPSIZE/2.0: posX = (in_pos[0] + MAPSIZE/2.0) / self.mHorizontalScale posY = (in_pos[1] + MAPSIZE/2.0) / self.mHorizontalScale result = (posX,posY) return result def get_elevation( self, in_pos ): result = 0 if abs(in_pos[0]) <= MAPSIZE/2.0 and abs(in_pos[1]) <= MAPSIZE/2.0: posX = (in_pos[0] + MAPSIZE/2.0) / self.mHorizontalScale posY = (in_pos[1] + MAPSIZE/2.0) / self.mHorizontalScale result = (self.getCurrentTerrain().getElevation(posX ,posY ) * self.mTerrainHeight) - self.mTerrainHeight/2 return result
class PerlinTest(DirectObject): def __init__(self): self.size = 64 self.p = Perlin.Perlin(numberOfOctaves=10, persistance=0.75, smooth=False) self.myImage = PNMImage(self.size, self.size) self.myImage.makeGrayscale() self.myTexture = Texture() self.myImage.fill(0.5) self.myTexture.load(self.myImage) self.imageObject = OnscreenImage(image=self.myTexture, pos=(0, 0, 0)) self.myList = [None] * (self.size) for a in range(self.size): self.myList[a] = [0.5] * (self.size) taskMgr.add(self.noiseTaskVerySmart, "perlinNoiseTask") self.startTime = time() self.noiseTaskVerySmart() self.accept("arrow_up", self.run) self.i = [None] * (self.size + 1) for x in range(0, self.size + 1): self.i[x] = [None] * (self.size + 1) def run(self): for a in range(self.size): self.myList[a] = [0.5] * (self.size) self.startTime = time() taskMgr.add(self.noiseTaskVerySmart, "perlinNoiseTask") def noiseTask(self, Task=None): numLines = 8 if Task == None: y = 0 else: y = Task.frame * numLines for yNum in range(0, numLines): for x in range(0, self.size): i = self.p.noise2D(float(x) / self.size, float(y + yNum) / self.size) self.myImage.setGray(x, y + yNum, (i + 1.0) / 2) self.myTexture.load(self.myImage) if Task != None: if self.size >= y + numLines: return Task.cont else: self.myTexture.load(self.myImage) print time() - self.startTime return Task.done def noiseTaskSmart(self, Task=None): if Task == None: o = 0 else: o = Task.frame p = Perlin.Perlin(numberOfOctaves=1, smooth=False, seed=0) freq = 2 ** o for x in range(0, freq + 1): for y in range(0, freq + 1): self.i[x][y] = p.intNoise2D(x * freq, y * freq) for y in range(0, self.size): for x in range(0, self.size): intX = (x * freq) / self.size fraX = (float(x) * freq) / self.size - intX intY = (y * freq) / self.size i1 = p.linearInterpolate(self.i[intX][intY], self.i[intX + 1][intY], fraX) i2 = p.linearInterpolate(self.i[intX][intY + 1], self.i[intX + 1][intY + 1], fraX) interNoise = p.linearInterpolate(i1, i2, (float(y) * freq) / self.size - intY) self.myList[x][y] += interNoise * (0.75 ** o) / 2 self.myImage.setGray(x, y, self.myList[x][y]) self.myTexture.load(self.myImage) if Task != None: if freq < self.size: return Task.cont else: print time() - self.startTime return Task.done def noiseTaskVerySmart(self, Task=None): if Task == None: o = 0 else: o = Task.frame p = Perlin.Perlin(numberOfOctaves=1, smooth=False, seed=0) freq = 2 ** o self.oldImage = self.myImage self.myImage = PNMImage(freq + 1, freq + 1) self.myImage.makeGrayscale() self.myImage.gaussianFilterFrom(1.0, self.oldImage) for x in range(0, freq + 1): for y in range(0, freq + 1): self.myImage.setGray( x, y, self.myImage.getGray(x, y) + p.intNoise2D(x * freq, y * freq) * (0.75 ** o) / 2 ) self.myTexture.load(self.myImage) if Task != None: if freq < self.size: return Task.cont else: print time() - self.startTime return Task.done