parent
0837145782
commit
d7b12c7bd4
|
@ -130,6 +130,65 @@ public class BiomeDataOracleV7 extends MinetestBiomeDataOracle {
|
|||
return (height_base * hselect) + (height_alt * (1.0f - hselect));
|
||||
}
|
||||
|
||||
/**
|
||||
* A logarithmic-ish search for some ground with air directly above.
|
||||
* (If it's the top of a floating island or ground beneath an underhang then tough, but because we start
|
||||
* low, it should find what the player will consider the ground most of the time)
|
||||
* @param lastHeight - the height of the previously calculated adjacent coord. set to Short.MIN_VALUE if not known
|
||||
* @param mnt_h_n - the 2D perlin noise of noise_mount_height for the location
|
||||
* @param highestGround - highest known ground height
|
||||
* @param lowestAir - lowest known air height.
|
||||
* @return height of the first highest level of ground located with air directly above.
|
||||
*/
|
||||
int findMountainHeight(int lastHeight, float mnt_h_n, int highestGround, int x, int z) {
|
||||
|
||||
int lowestAir = Short.MAX_VALUE; // We don't know where the air starts
|
||||
int testHeight = highestGround + 4; // Seems like a good start point if we don't know anything else (most of the time this value is overwritten with lastAirHeight, so it's not too important).
|
||||
|
||||
if (lastHeight != Short.MIN_VALUE) {
|
||||
// Perhaps the height hasn't changed and we can save some tests with this information: We can check if
|
||||
// height is the same with only two tests (and only 1 will be needed if lastHeight was sea level).
|
||||
int lastAirHeight = lastHeight + 1;
|
||||
|
||||
float density_gradient = -((float)(lastAirHeight - mount_zero_level) / mnt_h_n);
|
||||
float mnt_n = Noise.NoisePerlin3D(noise_mountain.np, x, lastAirHeight, z, seed);
|
||||
boolean isAir = mnt_n + density_gradient < 0.0f;
|
||||
|
||||
if (isAir) {
|
||||
lowestAir = lastAirHeight;
|
||||
testHeight = lastHeight;
|
||||
} else {
|
||||
// Nope, height has changed, we will have to do a proper search
|
||||
highestGround = lastAirHeight;
|
||||
testHeight = lastAirHeight + 1; // perhaps the land has only raised by 1, we can live in hope
|
||||
}
|
||||
}
|
||||
|
||||
while (highestGround + 1 < lowestAir) {
|
||||
float density_gradient = -((float)(testHeight - mount_zero_level) / mnt_h_n);
|
||||
float mnt_n = Noise.NoisePerlin3D(noise_mountain.np, x, testHeight, z, seed);
|
||||
boolean isAir = mnt_n + density_gradient < 0.0f;
|
||||
|
||||
if (isAir) {
|
||||
lowestAir = testHeight;
|
||||
testHeight -= ((testHeight - highestGround) / 2);
|
||||
} else {
|
||||
int previousHighestGround = highestGround;
|
||||
highestGround = testHeight;
|
||||
if (lowestAir == Short.MAX_VALUE) {
|
||||
testHeight += 2 * (testHeight - previousHighestGround);
|
||||
} else {
|
||||
testHeight += (lowestAir - testHeight) / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (highestGround + 1 != lowestAir) {
|
||||
AmidstLogger.error("Ground search alg failed! highestGround: " + highestGround + ", lowestAir: " + lowestAir);
|
||||
}
|
||||
|
||||
return highestGround;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short populateArray(CoordinatesInWorld corner, short[][] result, boolean useQuarterResolution) {
|
||||
return isFloatlands ?
|
||||
|
@ -179,6 +238,8 @@ public class BiomeDataOracleV7 extends MinetestBiomeDataOracle {
|
|||
// and Amidst use right-handed coordinates.
|
||||
world_z = -world_z;
|
||||
|
||||
int lastMountainHeight = Short.MIN_VALUE; // minvalue will be the "not-known" value
|
||||
|
||||
for (int x = 0; x < width; x++, index2d++) {
|
||||
|
||||
biomeValue = 0;
|
||||
|
@ -201,33 +262,25 @@ public class BiomeDataOracleV7 extends MinetestBiomeDataOracle {
|
|||
float mnt_n1 = Noise.NoisePerlin3D(noise_mountain.np, world_x, surfaceOrSeaLevel, world_z, seed);
|
||||
|
||||
if (mnt_n1 + density_gradient >= 0.0) {
|
||||
// Mountains are here, but since we only have a 1-bit plane to represent them, lets
|
||||
// Mountains are here
|
||||
int mountainHeight = findMountainHeight(lastMountainHeight, mnt_h_n, surfaceOrSeaLevel, world_x, world_z);
|
||||
lastMountainHeight = mountainHeight;
|
||||
|
||||
// since we only have a 1-bit plane to represent them, lets
|
||||
// only draw ones that are quite high
|
||||
float mnt_n2 = Noise.NoisePerlin3D(noise_mountain.np, world_x, surfaceOrSeaLevel + cMimimumMountainHeight, world_z, seed);
|
||||
density_gradient = -((float)(surfaceOrSeaLevel + cMimimumMountainHeight - mount_zero_level) / mnt_h_n);
|
||||
if (mnt_n2 + density_gradient >= 0.0) {
|
||||
if (mountainHeight >= surfaceOrSeaLevel + cMimimumMountainHeight) {
|
||||
biomeValue |= BITPLANE_MOUNTAIN;
|
||||
surface_y = Math.max(surface_y, surfaceOrSeaLevel + cMimimumMountainHeight);
|
||||
}
|
||||
|
||||
if ((v7params.spflags & MapgenV7Params.FLAG_V7_MOUNTAINS) > 0) {
|
||||
surface_y = mountainHeight;
|
||||
// Remove ocean if mountains rise above sea level.
|
||||
// This makes the oceans more correct, but the biome here might be wrong since
|
||||
// we haven't worked out the real height.
|
||||
// TODO: Perhaps do a logarithmic search for the height like we do in v5 oracle
|
||||
if ((biomeValue & BITPLANE_OCEAN) > 0) {
|
||||
if ((biomeValue & BITPLANE_MOUNTAIN) > 0) {
|
||||
biomeValue -= BITPLANE_OCEAN;
|
||||
} else {
|
||||
mnt_n2 = Noise.NoisePerlin3D(noise_mountain.np, world_x, surfaceOrSeaLevel + 1, world_z, seed);
|
||||
density_gradient = -((float)(surfaceOrSeaLevel + 1 - mount_zero_level) / mnt_h_n);
|
||||
if (mnt_n2 + density_gradient >= 0.0) {
|
||||
biomeValue -= BITPLANE_OCEAN;
|
||||
surface_y = Math.max(surface_y, surfaceOrSeaLevel + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((biomeValue & BITPLANE_OCEAN) > 0 && mountainHeight > surfaceOrSeaLevel) {
|
||||
biomeValue -= BITPLANE_OCEAN;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lastMountainHeight = Short.MIN_VALUE; // minvalue will be the "not-known" value
|
||||
}
|
||||
|
||||
// add the river bitplane
|
||||
|
|
Loading…
Reference in New Issue