Minecraft的世界生成过程(三)噪声函数

本文深入探讨Minecraft的地形生成,重点解析噪声函数的作用,包括NoiseGeneratorImproved、NoiseGeneratorOctaves、NoiseGeneratorSimplex和NoiseGeneratorPerlin。噪声函数,尤其是Perlin和Simplex噪声,是生成逼真地形的关键,通过分形叠加创造多样化的地貌。
摘要由CSDN通过智能技术生成

接下来的地形生成代码会接触到噪声函数,所以本篇内容就先逆向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;
            
  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LibNoise分形噪声函数库的JAVA翻译版,个人开发,仅供参考。 包中包含: 异常模块: noise.Exception noise.ExceptionInvalidParam 无效的参数异常。 noise.ExceptionNoModule 无模块异常,无法检索到该源模块 noise.ExceptionOutOfMemory noise.ExceptionUnknown 模型模块: noise.model.Line 线 noise.model.Plane 平面 noise.model.Sphere 球体 noise.model.Cylinder 圆柱 发生器模块: noise.module.Perlin 培林噪声 noise.module.RidgedMulti 脊多重分形噪声 noise.module.Billow 巨浪 value = |perlin_value|*2-1.0; noise.module.Voronoi 细胞噪声,Voronoi图 noise.module.Const 常量 value = const; noise.module.Cylinders 圆柱 noise.module.Checkerboard 棋盘格 value = (floor(x) & 1 ^ floor(y) & 1 ^ floor(z) & 1) != 0 ? -1.0 : 1.0; noise.module.Spheres 球体 选择器模块: noise.module.Select 选择 noise.module.Blend 混合 value = ((1.0 - (modules[3].value+1)/2) * modules[0].value) + ((modules[3].value+1)/2 * modules[1].value); 修饰器模块: noise.module.Invert 倒置 value = -value; noise.module.Abs 绝对值 value = |value|; noise.module.Clamp 截取 value = (value < lowerBound ?lowerBound : value) or (value > upperBound ?upperBound : value);lowerBound:下截取值;upperBound:上截取值 noise.module.Curve 曲线 value = noise.module.Curve.ControlPoint 控制点 noise.module.ScaleBias 偏移缩放, value = value*scale+offset noise.module.Turbulence 湍流 value = modules[0].getValue(x+modules[1].value * power,y+modules[2].value * power,z+modules[3].value * power); noise.module.Exponent 指数 value = (pow(abs((value + 1.0) / 2.0), exponent) * 2.0 - 1.0); 组合模块: noise.module.Add 添加 value = modules[0].value+modules[1].value; noise.module.Max 最大值 value = max(value); noise.module.Min 最小值 value = min(value); noise.module.Multiply 乘法 value = modules[0].value * modules[1].value; noise.module.Power 权重 value = pow(modules[0].value , modules[1].value); 变压模块: noise.module.Displace 位移替换,扭曲 value = modules[0].getValue(x+modules[1].value,y+modules[2].value,z+modules[3].value); noise.module.RotatePoint 点旋转 noise.module.ScalePoint 点缩放,轴缩放 value = modules[0].getValue (x * xScale, y * yScale,z * zScale); noise.module.Terrace 露台,梯台 noise.module.TranslatePoint 位移变换 value = modules[0].getValue (x * xTranslation, y * yTranslation,z * zTranslation); 其他: noise.module.Cache 缓存 value = noise.module.Module 噪声模块基类 如果发现有要更改的地方,请发邮件给我,或者本人QQ:343179390,欢迎技术探讨
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值