接下来的地形生成代码会接触到噪声函数,所以本篇内容就先逆向MC的噪声函数吧
噪声函数就是比较好看的随机数,如果用纯随机数(白噪声)不适合生成地形,但是噪声函数就很适合
具体的噪声介绍可以参考这篇文章,建议先阅读一下,否则后面的算法可能看不懂…
各种NoiseGenerator
在包net.minecraft.world.gen
里可以看到几个噪声生成器,它们的命名比较乱所以不要看类名来推断算法(本来柏林噪声的命名就经常被混淆),其实MC里只有Perlin噪声和Simplex噪声
NoiseGeneratorImproved
用来生成一个柏林噪声
public class NoiseGeneratorImproved extends NoiseGenerator
{
// 0~255的随机排列
private int[] permutations;
// 坐标偏移量
public double xCoord;
public double yCoord;
public double zCoord;
// 三维梯度向量,去掉y维度后和二维的一样
private static final double[] field_152381_e = new double[] {
1.0D, -1.0D, 1.0D, -1.0D, 1.0D, -1.0D, 1.0D, -1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, -1.0D, 0.0D};
private static final double[] field_152382_f = new double[] {
1.0D, 1.0D, -1.0D, -1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, -1.0D, 1.0D, -1.0D, 1.0D, -1.0D, 1.0D, -1.0D};
private static final double[] field_152383_g = new double[] {
0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 1.0D, -1.0D, -1.0D, 1.0D, 1.0D, -1.0D, -1.0D, 0.0D, 1.0D, 0.0D, -1.0D};
// 二维梯度向量
private static final double[] field_152384_h = new double[] {
1.0D, -1.0D, 1.0D, -1.0D, 1.0D, -1.0D, 1.0D, -1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, -1.0D, 0.0D};
private static final double[] field_152385_i = new double[] {
0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 1.0D, -1.0D, -1.0D, 1.0D, 1.0D, -1.0D, -1.0D, 0.0D, 1.0D, 0.0D, -1.0D};
public NoiseGeneratorImproved()
{
this(new Random());
}
public NoiseGeneratorImproved(Random rand)
{
this.permutations = new int[512];
this.xCoord = rand.nextDouble() * 256.0D;
this.yCoord = rand.nextDouble() * 256.0D;
this.zCoord = rand.nextDouble() * 256.0D;
// 生成0~255的随机排列
for (int i = 0; i < 256; ++i)
{
this.permutations[i] = i;
}
for (int i = 0; i < 256; ++i)
{
// 从i~255中选j
int j = rand.nextInt(256 - i) + i;
// 把i和j交换
int t = this.permutations[i];
this.permutations[i] = this.permutations[j];
this.permutations[j] = t;
// 形成一个周期
this.permutations[i + 256] = this.permutations[i];
}
}
// 在a与b间线性插值
public final double lerp(double t, double a, double b)
{
return a + t * (b - a);
}
// 返回与二维梯度向量点乘的结果,参数:梯度向量索引, 向量(其实就是权重)
public final double func_76309_a(int index, double xWeight, double zWeight)
{
int i = index % 16;
return field_152384_h[i] * xWeight
+ field_152385_i[i] * zWeight;
}
// 返回与三维梯度向量点乘的结果,参数:梯度向量索引, 向量(其实就是权重)
public final double grad(int index, double xWeight, double yWeight, double zWeight)
{
int i = index % 16;
return field_152381_e[i] * xWeight
+ field_152382_f[i] * yWeight
+ field_152383_g[i] * zWeight;
}
/**
* pars: noiseArray , xOffset , yOffset , zOffset , xSize , ySize , zSize , xScale, yScale , zScale , noiseScale.
* noiseArray should be xSize*ySize*zSize in size
*/
// 这个noiseScale和振幅成反比...
public void populateNoiseArray(double[] result, double xOffset, double yOffset, double zOffset, int xSize, int ySize, int zSize, double xScale, double yScale, double zScale, double noiseScale)
{
if (ySize == 1) // 二维
{
int resultIndex = 0;