Created
April 12, 2013 03:01
-
-
Save Deamon5550/5368984 to your computer and use it in GitHub Desktop.
terrain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.thevoxelbox.generator; | |
import java.util.Arrays; | |
import java.util.Random; | |
public class TerrainGenerator { | |
Random rand; | |
int w, h; | |
public int size; | |
int[] heightMap; | |
public TerrainGenerator(Random random, int w, int h) { | |
rand = random; | |
//rand.setSeed(31415926535897932l); | |
this.w = w; | |
this.h = h; | |
size = w/32; | |
heightMap = new int[(w+1) * (h+1)]; | |
Arrays.fill(heightMap, (short) 0); | |
short[] seedMap = new short[Gen.seedMapSize*Gen.seedMapSize]; | |
Arrays.fill(seedMap, (short) 0); | |
for(int i = 0; i < Gen.seedbaseNum+rand.nextInt(Gen.seedRandNum); i++) { | |
int x = rand.nextInt(Gen.seedRange)+(Gen.seedMapSize - Gen.seedRange)/2; | |
int y = rand.nextInt(Gen.seedRange)+(Gen.seedMapSize - Gen.seedRange)/2; | |
seedMap[x + y * 64] = Gen.seedStrength; | |
int steps = rand.nextInt(10) + 12; | |
int dx = (x < 32? 1 : -1); | |
int dy = (y < 32? 1 : -1); | |
int aoe = 1; | |
int str = Gen.seedStrength + rand.nextInt(70); | |
for(int s = 0; s < steps ;s++) { | |
dx = (x < 10? 1 : (x > 54? -1: dx)); | |
dy = (y < 10? 1 : (y > 54? -1: dy)); | |
if(dx == 0 && dy == 0) continue; | |
x+= dx * rand.nextInt(3); | |
y+= dy * rand.nextInt(3); | |
str += rand.nextInt(5); | |
aoe += (rand.nextInt(3)-1); | |
aoe = clamp(aoe, 4, 1); | |
for(int x1 = x - aoe; x1 < x + aoe; x1++) { | |
for(int y1 = y - aoe; y1 < y + aoe; y1++) { | |
int ds = (x1-x)*(x1-x) + (y1-y)*(y1-y); | |
if(ds < aoe*aoe) { | |
float mult = (1/(ds+1) + 0.5F); | |
mult = clamp(mult, 1, 0); | |
if(x1 > 3 && x1 < 61 && y1 > 3 && y1 < 61) seedMap[x1 + y1*65] = (short) (str*mult); | |
} | |
} | |
} | |
} | |
} | |
for(int x = 0; x < 65; x++) { | |
for(int y = 0; y < 65; y++) { | |
heightMap[(x*64) + (y*64)*4097] = seedMap[x + y * 65]; | |
} | |
} | |
} | |
public int[] generate() { | |
int slope = Gen.slope; | |
while(size >= 1) { | |
//System.out.println(size); | |
for(int xn = 0; xn < ((w/2)/size); xn++) { | |
for(int yn = 0; yn < ((w/2)/size); yn++) { | |
int heightWeightOffset = rand.nextInt(20) - 10; | |
int y = size + (2 * size) * yn; | |
int x = size + (2 * size) * xn; | |
//System.out.println(slope); | |
int rOffs = rand.nextInt(slope) - (slope / 2); | |
int avg = (avgSquareVals(x, y, size, heightMap)); | |
if(avg > 128) rOffs *= Gen.highAltitudeRandomMultiplier; | |
short height = (short) (avg + rOffs); | |
if(height > Gen.heightWeightFloor + heightWeightOffset) { | |
height *= Gen.heightWeightMult; | |
} else { | |
height *= 1/Gen.heightWeightMult; | |
} | |
height = clamp(height, 255, 0); | |
heightMap[x + y * w] = height; | |
} | |
} | |
for(int xn = 0; xn < ((w/2)/size); xn++) { | |
for(int yn = 0; yn < ((w/2)/size); yn++) { | |
int heightWeightOffset = rand.nextInt(20) - 10; | |
int y = size + (2 * size) * yn; | |
int x = size + (2 * size) * xn; | |
if(heightMap[x-size + y * w] == 0) { | |
int rOffs = rand.nextInt(slope) - (slope / 2); | |
int avg = (avgSquareVals(x, y, size, heightMap)); | |
if(avg > 128) rOffs *= Gen.highAltitudeRandomMultiplier; | |
short height = (short) (avg + rOffs); | |
if(height > Gen.heightWeightFloor + heightWeightOffset) { | |
height *= Gen.heightWeightMult; | |
} else { | |
height *= 1/Gen.heightWeightMult; | |
} | |
height = clamp(height, 255, 0); | |
heightMap[x-size + y * w] = height; | |
} | |
if(heightMap[x+size + y * w] == 0) { | |
int rOffs = rand.nextInt(slope) - (slope / 2); | |
int avg = (avgSquareVals(x, y, size, heightMap)); | |
if(avg > 128) rOffs *= Gen.highAltitudeRandomMultiplier; | |
short height = (short) (avg + rOffs); | |
if(height > Gen.heightWeightFloor + heightWeightOffset) { | |
height *= Gen.heightWeightMult; | |
} else { | |
height *= 1/Gen.heightWeightMult; | |
} | |
height = clamp(height, 255, 0); | |
heightMap[x+size + y * w] = height; | |
} | |
if(heightMap[x + (y-size) * w] == 0) { | |
int rOffs = rand.nextInt(slope) - (slope / 2); | |
int avg = (avgSquareVals(x, y, size, heightMap)); | |
if(avg > 128) rOffs *= Gen.highAltitudeRandomMultiplier; | |
short height = (short) (avg + rOffs); | |
if(height > Gen.heightWeightFloor + heightWeightOffset) { | |
height *= Gen.heightWeightMult; | |
} else { | |
height *= 1/Gen.heightWeightMult; | |
} | |
height = clamp(height, 255, 0); | |
heightMap[x + (y-size) * w] = height; | |
} | |
if(heightMap[x + (y+size) * w] == 0) { | |
int rOffs = rand.nextInt(slope) - (slope / 2); | |
int avg = (avgSquareVals(x, y, size, heightMap)); | |
if(avg > 128) rOffs *= Gen.highAltitudeRandomMultiplier; | |
short height = (short) (avg + rOffs); | |
if(height > Gen.heightWeightFloor + heightWeightOffset) { | |
height *= Gen.heightWeightMult; | |
} else { | |
height *= 1/Gen.heightWeightMult; | |
} | |
height = clamp(height, 255, 0); | |
heightMap[x + (y+size) * w] = height; | |
} | |
} | |
} | |
slope *= Gen.slopeDegrader; | |
slope = clamp(slope, 256, 1); | |
size /= 2; | |
} | |
smooth(heightMap, 4098, 4098, 8); | |
for(int i = 0; i < heightMap.length; i++) heightMap[i] = (0xFF) << 24 | (heightMap[i]&0xFF) << 16 | (heightMap[i]&0xFF) << 8 | (heightMap[i]&0xFF); | |
return heightMap; | |
} | |
public int avgDiamondVals(int x, int y, int size, int[] fa) { | |
int x0 = x, y0 = y; | |
int h1; | |
x0 = x-size; | |
if(x0 < 0) { | |
h1 = 0; | |
} else { | |
h1 = fa[x0 + y0 * w]; | |
} | |
int h2; | |
x0 = x+size; | |
if(x0 > w) { | |
h2 = 0; | |
} else { | |
h2 = fa[x0 + y0 * w]; | |
} | |
x0 = x; | |
int h3; | |
y0 = y-size; | |
if(y0 < 0) { | |
h3 = 0; | |
} else { | |
h3 = fa[x0 + y0 * w]; | |
} | |
int h4; | |
y0 = y+size; | |
if(y0 > h) { | |
h4 = 0; | |
} else { | |
h4 = fa[x0 + y0 * w]; | |
} | |
short ha = (short) ((h1 + h2 + h3 + h4)/4); | |
//System.out.println("Diamond " + x + " " + y + " " + size + " " + ha); | |
return ha; | |
} | |
public int avgSquareVals(int x, int y,int size, int[] fa) { | |
x = clamp(x, size); | |
y = clamp(y, size); | |
int h1 = fa[(x-size) + (y-size) * w]; | |
int h2 = fa[(x-size) + (y+size) * w]; | |
int h3 = fa[(x+size) + (y-size) * w]; | |
int h4 = fa[(x+size) + (y+size) * w]; | |
short ha = (short) ((h1 + h2 + h3 + h4)/4); | |
//System.out.println("Square " + x + " " + y + " " + size + " " + ha); | |
return ha; | |
} | |
public void smooth(int[] heightMap, int w, int h, int passes) | |
{ | |
int[] tmp = new int[heightMap.length]; | |
while(passes > 0) { | |
passes--; | |
for(int x = 0; x < w; x++) { | |
for(int y = 0; y < h; y++) { | |
int adj = 0; | |
int tot = 0; | |
if ((x - 1) > 0) // Check to left | |
{ | |
tot += heightMap[(x-1)+ y * w]; | |
adj++; | |
if ((y - 1) > 0) // Check up and to the left | |
{ | |
tot += heightMap[(x-1)+ (y-1) * w]; | |
adj++; | |
} | |
if ((y + 1) < h) // Check down and to the left | |
{ | |
tot += heightMap[(x-1)+ (y+1) * w]; | |
adj++; | |
} | |
} | |
if ((x + 1) < w) // Check to right | |
{ | |
tot += heightMap[(x+1)+ (y) * w]; | |
adj++; | |
if ((y - 1) > 0) // Check up and to the right | |
{ | |
tot += heightMap[(x+1)+ (y-1) * w]; | |
adj++; | |
} | |
if ((y + 1) < h) // Check down and to the right | |
{ | |
tot += heightMap[(x+1)+ (y+1) * w]; | |
adj++; | |
} | |
} | |
if ((y - 1) > 0) // Check above | |
{ | |
tot += heightMap[(x)+ (y-1) * w]; | |
adj++; | |
} | |
if ((y + 1) < h) // Check below | |
{ | |
tot += heightMap[(x)+ (y+1) * w]; | |
adj++; | |
} | |
if((x - 2) > 0) { | |
if ((y + 1) < h) // Check above | |
{ | |
tot += heightMap[(x-2)+ (y+1) * w]; | |
adj++; | |
} | |
tot += heightMap[(x-2)+ (y) * w]; | |
adj++; | |
if ((y - 1) > 0) // Check above | |
{ | |
tot += heightMap[(x-2)+ (y-1) * w]; | |
adj++; | |
} | |
if ((y - 2) > 0) // Check up and to the right | |
{ | |
tot += heightMap[(x-2)+ (y-2) * w]; | |
adj++; | |
} | |
if ((y + 2) < h) // Check down and to the right | |
{ | |
tot += heightMap[(x-2)+ (y+2) * w]; | |
adj++; | |
} | |
} | |
if((x + 2) < w) { | |
if ((y + 1) < h) // Check above | |
{ | |
tot += heightMap[(x+2)+ (y+1) * w]; | |
adj++; | |
} | |
tot += heightMap[(x+2)+ (y) * w]; | |
adj++; | |
if ((y - 1) > 0) // Check above | |
{ | |
tot += heightMap[(x+2)+ (y-1) * w]; | |
adj++; | |
} | |
if ((y - 2) > 0) // Check up and to the right | |
{ | |
tot += heightMap[(x+2)+ (y-2) * w]; | |
adj++; | |
} | |
if ((y + 2) < h) // Check down and to the right | |
{ | |
tot += heightMap[(x+2)+ (y+2) * w]; | |
adj++; | |
} | |
} | |
if((y + 2) < h) { | |
if ((x - 1) > 0) // Check above | |
{ | |
tot += heightMap[(x-1)+ (y+2) * w]; | |
adj++; | |
} | |
tot += heightMap[(x)+ (y+2) * w]; | |
adj++; | |
if ((x + 1) < w) // Check above | |
{ | |
tot += heightMap[(x+1)+ (y+2) * w]; | |
adj++; | |
} | |
} | |
if((y - 2) > 0) { | |
if ((x - 1) > 0) // Check above | |
{ | |
tot += heightMap[(x-1)+ (y-2) * w]; | |
adj++; | |
} | |
tot += heightMap[(x)+ (y-2) * w]; | |
adj++; | |
if ((x + 1) < w) // Check above | |
{ | |
tot += heightMap[(x+1)+ (y-2) * w]; | |
adj++; | |
} | |
} | |
tmp[x + y * w] = (int) ((heightMap[x + y * w] + (tot/adj))*0.5f); | |
} | |
} | |
for(int x = 0; x < w; x++) { | |
for(int y = 0; y < h; y++) { | |
heightMap[x + y * w] = tmp[x + y * w]; | |
} | |
} | |
} | |
} | |
public short clamp(short i, int max, int min) { | |
return (short) (i < min? min : (i > max? max : i)); | |
} | |
public float clamp(float i, float max, float min) { | |
return (i < min? min : (i > max? max : i)); | |
} | |
public int clamp(int i, int max, int min) { | |
return (i < min? min : (i > max? max : i)); | |
} | |
public int clamp(int i, int min) { | |
return (short) (i < min? min : i); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment