Ex.
Spoiler:
I can't think of a way to smooth out the borders between blocks. Do any of you know of a better way to do this or a way to smooth out the borders?
Moderators: phlip, Moderators General, Prelates
All Shadow priest spells that deal Fire damage now appear green.
Big freaky cereal boxes of death.
Ended wrote:Hmm, what happens if you force the boundary values to agree? E.g. when generating a tile to the right of one which already exists, initialise the left-most column of values with the data from the right-most column of the pre-existing tile, and don't modify these boundary values during the algorithm.
gorcee wrote:Finite element methods do something very similar to this. In a finite element model, each element must inherit the boundary properties of its adjoining elements, generally up to a certain level of smoothness.
A more simplified example comes from cubic spline interpolation: If you want to interpolate a set of data using a series of cubics, then you need to enforce some conditions where those cubics meet. It is obviously not sufficient to just force equality at the boundary nodes: otherwise, you'll be non-differentiable at those nodes, and you'll have "corners" in your interpolated curve (which is typically undesirable). In cubic spline interpolation, it is sufficient (and in fact, I believe it is necessary for uniqueness) to force the first derivatives equal to one another. Then you can compute your spline coefficients.
In your case, what I would do is begin by specifying these conditions a priori at the boundary nodes. Specify a value and a gradient (without looking at your code, I assume you must have some gradient-type term in there, because you do not seem to generate based on random point processes). Then, generate the values on the interior nodes. This will ensure that your plateaus or valleys will seamlessly cross tile boundaries.
Code: Select all
from random import Random
import math
class Generator:
gRoughness = 0.0
gArea = 0.0
randgen = Random()
seed = None
def __init__(self, seed = None):
if seed is not None:
self.seed = seed
else:
self.seed = self.randgen.random()
def setSeed(self, seed):
self.seed = seed
def generate(self, width, height, roughness):
grid = {(x,y):0 for x in range(0, width) for y in range(0, height)}
self.randgen.seed(self.seed)
c1 = self.randgen.random()
c2 = self.randgen.random()
c3 = self.randgen.random()
c4 = self.randgen.random()
self.gRoughness = roughness
self.gArea = width + height
self.Divide(grid, 0, 0, width, height, c1, c2, c3, c4)
return grid
def Divide(self, grid, x, y, width, height, c1, c2, c3, c4):
e1, e2, e3, e4, middle = 0.0,0.0,0.0,0.0,0.0
newWidth = math.floor(width / 2)
newHeight = math.floor(height / 2)
if width > 1 or height > 1:
middle = self.FixNum(((c1 + c2 + c3 + c4) / 4) + self.Displace(newWidth + newHeight))
e1 = self.FixNum((c1 + c2) / 2)
e2 = self.FixNum((c2 + c3) / 2)
e3 = self.FixNum((c3 + c4) / 2)
e4 = self.FixNum((c4 + c1) / 2)
self.Divide(grid, x, y, newWidth, newHeight, c1, e1, middle, e4)
self.Divide(grid, x + newWidth, y, width - newWidth, newHeight, e1, c2, e2, middle)
self.Divide(grid, x + newWidth, y + newHeight, width - newWidth, height - newHeight, middle, e2, c3, e3);
self.Divide(grid, x, y + newHeight, newWidth, height - newHeight, e4, middle, e3, c4);
else:
c = (c1 + c2 + c3 + c4) / 4
grid[int(x), int(y)] = c
if width == 2 and height == 2: grid[int(x+1), int(y+1)] = c
if width == 2: grid[int(x+1), int(y)] = c
if height == 2: grid[int(x), int(y+1)] = c
def FixNum(self, input):
if input < 0: input = 0
elif input > 1: input = 1
return input
def Displace(self, size):
max = size / self.gArea * self.gRoughness
return (self.randgen.random() - 0.5) * max
WarDaft wrote:Why tile it? Just generate an infinite blotch procedurally and slice it up. Only compute the areas you need at a given time.
letterX wrote:You may also want to try looking at models like Perlin noise. One nice property of noise functions like these are that they continue infinitely in all directions, without directly repeating anywhere. Also, unlike enforcing boundary conditions on your chunk generators, you can do random-access to any point in your infinite world, so you don't have to generate chunks contiguously, and are free to throw away chunks and regenerate them later if you don't want to keep everything in memory.
Users browsing this forum: No registered users and 3 guests