i'm using a noise function inspired by libnoiseforjava to try and generate roads. (See below)
public class VoronoiNoise {
private static final double SQRT_2 = 1.4142135623730950488;
private static final double SQRT_3 = 1.7320508075688772935;
private long seed;
private short distanceMethod;
private final double frequency;
public VoronoiNoise(long seed, double frequency, short distanceMethod) {
this.seed = seed;
this.distanceMethod = distanceMethod;
this.frequency = frequency;
}
private double getDistance(double xDist, double zDist) {
switch(distanceMethod) {
case 0: //EUCLIDIAN - Length
return Math.sqrt(xDist * xDist + zDist * zDist) / SQRT_2;
case 1: //???
return xDist + zDist;
case 2: //???
return Math.pow(Math.E, Math.sqrt(xDist * xDist + zDist * zDist) / SQRT_2)/Math.E;
case 3: //MANHATTAN
return Math.abs(xDist) + Math.abs(zDist);
case 4: //CHEBYCHEV
return Math.max(Math.abs(xDist), Math.abs(zDist));
case 5: //MINKOVSKI
return Math.pow(Math.pow(Math.abs(xDist), Math.PI) + Math.pow(Math.abs(zDist), Math.PI), (1 / Math.PI));
case 6: //MINKOVSKI4
return Math.pow(xDist*xDist*xDist*xDist+zDist*zDist*zDist*zDist,0.25);
default:
return 1.0;
}
}
private double getDistance(double xDist, double yDist, double zDist) {
switch(distanceMethod) {
case 0:
return Math.sqrt(xDist * xDist + yDist * yDist + zDist * zDist) / SQRT_3;
case 1:
return xDist + yDist + zDist;
default:
return 1.0;
}
}
public short getDistanceMethod() {
return distanceMethod;
}
public long getSeed() {
return seed;
}
public double noise(double x, double z) {
x *= frequency;
z *= frequency;
int xInt = (x > .0? (int)x: (int)x - 1);
int zInt = (z > .0? (int)z: (int)z - 1);
double minDist = 32000000.0;
double xCandidate = 0;
double zCandidate = 0;
double xCandidate2 = 0;
double zCandidate2 = 0;
Random random = new Random(seed);
long xSeed = random.nextLong();
long zSeed = random.nextLong();
for(int zCur = zInt - 2; zCur <= zInt + 2; zCur++) {
for(int xCur = xInt - 2; xCur <= xInt + 2; xCur++) {
double xPos = xCur + valueNoise2D(xCur, zCur, xSeed);
double zPos = zCur + valueNoise2D(xCur, zCur, zSeed);
double xDist = xPos - x;
double zDist = zPos - z;
double dist = xDist * xDist + zDist * zDist;
if(dist < minDist) {
xCandidate2 = xCandidate;
zCandidate2 = zCandidate;
xCandidate = xPos;
zCandidate = zPos;
minDist = dist;
}
}
}
double xDist = xCandidate - x;
double zDist = zCandidate - z;
//return getDistance(xDist, zDist);
return getDistance(xCandidate2 - x, zCandidate2 - z) - getDistance(xCandidate - x, zCandidate - z);
}
public double noise(double x, double y, double z) {
x *= frequency;
y *= frequency;
z *= frequency;
int xInt = (x > .0? (int)x: (int)x - 1);
int yInt = (y > .0? (int)y: (int)y - 1);
int zInt = (z > .0? (int)z: (int)z - 1);
double minDist = 32000000.0;
double xCandidate = 0;
double yCandidate = 0;
double zCandidate = 0;
Random rand = new Random(seed);
for(int zCur = zInt - 2; zCur <= zInt + 2; zCur++) {
for(int yCur = yInt - 2; yCur <= yInt + 2; yCur++) {
for(int xCur = xInt - 2; xCur <= xInt + 2; xCur++) {
double xPos = xCur + valueNoise3D (xCur, yCur, zCur, seed);
double yPos = yCur + valueNoise3D (xCur, yCur, zCur, rand.nextLong());
double zPos = zCur + valueNoise3D (xCur, yCur, zCur, rand.nextLong());
double xDist = xPos - x;
double yDist = yPos - y;
double zDist = zPos - z;
double dist = xDist * xDist + yDist * yDist + zDist * zDist;
if(dist < minDist) {
minDist = dist;
xCandidate = xPos;
yCandidate = yPos;
zCandidate = zPos;
}
}
}
}
double xDist = xCandidate - x;
double yDist = yCandidate - y;
double zDist = zCandidate - z;
return getDistance(xDist, yDist, zDist);
}
public void setDistanceMethod(short distanceMethod) {
this.distanceMethod = distanceMethod;
}
public void setSeed(long seed) {
this.seed = seed;
}
public static double valueNoise2D (int x, int z, long seed) {
long n = (1619 * x + 6971 * z + 1013 * seed) & 0x7fffffff;
n = (n >> 13) ^ n;
return 1.0 - ((double)((n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff) / 1073741824.0);
}
public static double valueNoise3D (int x, int y, int z, long seed) {
long n = (1619 * x + 31337 * y + 6971 * z + 1013 * seed) & 0x7fffffff;
n = (n >> 13) ^ n;
return 1.0 - ((double)((n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff) / 1073741824.0);
}
}
As you can see i've been calculating the Distance21 - the distance of the 1st minus the 2nd closest point. I've been using this along with Euclidian distance calculation to generate a noise map. Here is what I get: I've then been checking whether the noise is below a certain value (black colours) and using that to place roads. One problem is that some of the cells are black, some blacker than the roads causing a mass of roads. Also, the roads are more than 1 unit in width which is unacceptable for my purposes.
Here is a chart of the different types of voronoi noise.
I was wondering if there is an algorithm for procedurally generating noise like this
Except that given a seed, a frequency and a point (x,y) it would return true or false whether or not the vertices pass through that point or not. Creating lines
As a last resort I will use a repeating, static, image.
Aucun commentaire:
Enregistrer un commentaire