Hi guys,
Having an issue with seams in regards to turning on borderstitch with GeoMipTerrain.
When I turn on borderstitch, I get some horrible merged vertices:
The two images are actually just mirrors of the same image. Additionally, the pixels around the edge are copied to match. So this SHOULD resolve any issues with the images themselves.
When border stitch is off, it looks pretty good, but still sort of obvious where the terrains come together:
The seam is less noticeable if you bump down the block size, but that just increases the vertice count…
Any ideas? Anybody used this before successfully? Or is this a bug?
Heres the code/assests to generate two terrains and try to stitch them together.
from pandac.PandaModules import loadPrcFileData
loadPrcFileData('', 'threading-model /Draw')
loadPrcFileData('', 'sync-video 0');
import direct.directbase.DirectStart
from pandac.PandaModules import *
from pandac.PandaModules import GeoMipTerrain
from direct.task import Task
class Terrain:
def __init__(self, heightfield, scale, pos, name, minlevel):
self.heightfield = heightfield
self.scale = scale
self.pos = pos
self.name = name
self.tile = ''
self.minlevel = minlevel
# Our heightmap
self.tex = loader.loadTexture(heightfield)
# Our colour texture
self.ctex = loader.loadTexture(heightfield)
# Stops edge bleeding on colour texture
self.ctex.setWrapU(Texture.WMClamp)
self.ctex.setWrapV(Texture.WMClamp)
# Doesn't really help for the heightmap though...
#self.tex.setWrapU(Texture.WMClamp)
#self.tex.setWrapV(Texture.WMClamp)
# Would setting these filters fix stitching?
#self.tex.setMagfilter(Texture.FTNearest)
#self.tex.setMinfilter(Texture.FTNearest)
class TiledTerrain:
def __init__(self):
# An array of all our Terrain objects
self.TerrainPieces = []
# Whats the size of each tile? Heightfield - 1
self.terrainSize = 256
self.updateTime = 0
# Lets add a whole bunch of tiles
# Heightmap / ZScale / Position / Name / Minlevel
self.TerrainPieces.append(Terrain('1.png', 50, Vec3(0,0,0), '1', 1))
self.TerrainPieces.append(Terrain('2.png', 50, Vec3(0,self.terrainSize,0), '2', 1))
#self.TerrainPieces.append(Terrain('3.jpg', 50, Vec3(0,self.terrainSize*2,0), '3'))
#self.TerrainPieces.append(Terrain('4.jpg', 50, Vec3(self.terrainSize,0,0), '4'))
#self.TerrainPieces.append(Terrain('5.jpg', 50, Vec3(self.terrainSize,self.terrainSize,0), '5'))
#self.TerrainPieces.append(Terrain('6.jpg', 50, Vec3(self.terrainSize,self.terrainSize*2,0), '6'))
#self.TerrainPieces.append(Terrain('7.jpg', 50, Vec3(self.terrainSize*2,0,0), '7'))
#self.TerrainPieces.append(Terrain('8.jpg', 50, Vec3(self.terrainSize*2,self.terrainSize,0), '8'))
#self.TerrainPieces.append(Terrain('9.jpg', 50, Vec3(self.terrainSize*2,self.terrainSize*2,0), '9'))
for terrain in self.TerrainPieces:
t = GeoMipTerrain(terrain.name)
t.setHeightfield(Filename(terrain.heightfield))
# Try to stitch together borders - broken?
# If your heightmaps have a few copied data around the edge, you get a sort of seamless appearance
t.setBorderStitching(True)
t.clearColorMap()
t.getRoot().setTexture(terrain.ctex)
t.getRoot().setSz(terrain.scale)
# Only really needed if we were to call update
#t.setFocalPoint(base.camera)
t.setBlockSize(64)
t.setMinLevel(terrain.minlevel)
t.setBruteforce(1)
# Move and rotate to get correctly positioned
t.getRoot().setPos(terrain.pos)
t.getRoot().setH(90)
# Lets show and generate the terrain
t.getRoot().reparentTo(render)
t.generate()
# Lets set two sided, so we can see whats going on
t.getRoot().setTwoSided(True)
# Save a reference back into our array
terrain.tile = t
#Perform an update every second
#Even at high min level and framerate, there is a noticeable jolt when the update is run
#myTask = taskMgr.doMethodLater(1, self.update, 'tickTask')
def update(self, task):
for terrain in self.TerrainPieces:
# Setting autoflatten seems to reset things shaders, textures, scaling etc
# So if we want autoflatten, we need to reapply all those settings
#terrain.tile.setAutoFlatten(GeoMipTerrain.AFMMedium)
#terrain.tile.getRoot().setSz(terrain.scale)
#terrain.tile.getRoot().setH(90)
#terrain.tile.getRoot().setPos(terrain.pos)
#terrain.tile.clearColorMap()
#terrain.tile.getRoot().setTexture(terrain.tex)
#terrain.tile.setBlockSize(128)
#Need to reset the focal point
terrain.tile.setFocalPoint(base.camera)
terrain.tile.update()
return task.again
class World:
def __init__(self):
base.camLens.setNear(16)
base.camLens.setFar(10000)
base.setFrameRateMeter(True)
#render.setRenderModeWireframe()
# Create some basic lighting so we can see some shading
dlight = DirectionalLight('dlight')
dlight.setColor(VBase4(0.8, 0.8, 0.6, 1))
dlnp = render.attachNewNode(dlight)
dlnp.setHpr(0, -60, 0)
render.setLight(dlnp)
alight = AmbientLight('alight')
alight.setColor(VBase4(0.1, 0.1, 0.2, 1))
alnp = render.attachNewNode(alight)
render.setLight(alnp)
# Create out terrain
# Todo - pass a variable to turn on and off update calls or bruteforce
terrain = TiledTerrain()
if __name__ == '__main__':
myworld = World()
run()