示例#1
0
        private void GenerateDensityMap(float[,,] densityMap, int xOffset, int yOffset, int zOffset, GeneratorSettings settings)
        {
            _depthNoise.Noise(
                _depthMap,
                new Vector3(xOffset + 0.1f, 0.0f, zOffset + 0.1f),
                new Vector3(settings.DepthNoiseScaleX, 1.0f, settings.DepthNoiseScaleZ));

            float coordinateScale = settings.CoordinateScale;
            float heightScale     = settings.HeightScale;

            // 生成3个5*5*33的噪声
            _mainNoise.Noise(
                _mainNoiseMap,
                new Vector3(xOffset, yOffset, zOffset),
                new Vector3(
                    coordinateScale / settings.MainNoiseScaleX,
                    heightScale / settings.MainNoiseScaleY,
                    coordinateScale / settings.MainNoiseScaleZ));

            _minNoise.Noise(
                _minLimitMap,
                new Vector3(xOffset, yOffset, zOffset),
                new Vector3(
                    coordinateScale,
                    heightScale,
                    coordinateScale));

            _maxNoise.Noise(
                _maxLimitMap,
                new Vector3(xOffset, yOffset, zOffset),
                new Vector3(
                    coordinateScale,
                    heightScale,
                    coordinateScale));

            // chunk遍历
            for (int x1 = 0; x1 < 5; ++x1)
            {
                for (int z1 = 0; z1 < 5; ++z1)
                {
                    float scale         = 0.0F;
                    float groundYOffset = 0.0F;
                    float totalWeight   = 0.0F;

                    // 中心点生物群系
                    Biome centerBiome = _biomesForGeneration[z1 + 2, x1 + 2];

                    // 求scale和groundYOffset的加权平均值
                    for (int x2 = 0; x2 < 5; ++x2)
                    {
                        for (int z2 = 0; z2 < 5; ++z2)
                        {
                            Biome biome            = _biomesForGeneration[z1 + z2, x1 + x2];
                            float curGroundYOffset = settings.BiomeDepthOffSet + biome.GetBaseHeight() * settings.BiomeDepthWeight;      // biomeDepthOffSet=0
                            float curScale         = settings.BiomeScaleOffset + biome.GetHeightVariation() * settings.BiomeScaleWeight; // biomeScaleOffset=0

                            // parabolicField为 10 / √(该点到中心点的距离^2 + 0.2)
                            float weight = _biomeWeights[z2, x2] / (curGroundYOffset + 2.0F);

                            if (biome.GetBaseHeight() > centerBiome.GetBaseHeight())
                            {
                                weight /= 2.0F;
                            }

                            scale         += curScale * weight;
                            groundYOffset += curGroundYOffset * weight;
                            totalWeight   += weight;
                        }
                    }

                    scale         = scale / totalWeight;
                    groundYOffset = groundYOffset / totalWeight;
                    scale         = scale * 0.9F + 0.1F;
                    groundYOffset = (groundYOffset * 4.0F - 1.0F) / 8.0F;

                    // 取一个-0.36~0.125的随机数,这个随机数决定了起伏的地表
                    float random = (_depthMap[x1, 0, z1] - 0.5F) * 2 / 8000.0F;
                    if (random < 0.0F)
                    {
                        random = -random * 0.3F;
                    }

                    random = random * 3.0F - 2.0F;

                    if (random < 0.0)
                    {
                        random = random / 2.0F;
                        if (random < -1.0)
                        {
                            random = -1.0F;
                        }

                        random = random / 1.4F;
                        random = random / 2.0F;
                    }
                    else
                    {
                        if (random > 1.0F)
                        {
                            random = 1.0F;
                        }

                        random = random / 8.0F;
                    }

                    float groundYOffset1 = groundYOffset;
                    float scale1         = scale;

                    // groundYOffset有-0.072~0.025的变动量
                    groundYOffset1 = groundYOffset1 + random * 0.2F;
                    groundYOffset1 = groundYOffset1 * settings.BaseSize / 8.0F;

                    // 这个是大概的地面y坐标
                    float groundY = settings.BaseSize + groundYOffset1 * 4.0F; // baseSize=8.5,应该代表了平均地表高度68

                    // 注意这个y*8才是最终的y坐标
                    for (int y = 0; y < 33; ++y)
                    {
                        // result偏移量,这个是负数则趋向固体,是正数则趋向液体和空气
                        float offset = (y - groundY) * settings.StretchY * 128.0F / 256.0F / scale1; // scale大概在0.1~0.2这样...

                        if (offset < 0.0F)
                        {
                            offset *= 4.0F;
                        }

                        // 并不保证lowerLimit < upperLimit,不过没有影响
                        float lowerLimit = (_minLimitMap[x1, y, z1] - 0.5F) * 160000 / settings.LowerLimitScale; // lowerLimitScale=512
                        float upperLimit = (_maxLimitMap[x1, y, z1] - 0.5F) * 160000 / settings.UpperLimitScale; // upperLimitScale=512
                        float t          = ((_mainNoiseMap[x1, y, z1] - 0.5F) * 160000 / 10.0F + 1.0F) / 2.0F;

                        // 这个函数t < 0则取lowerLimit,t > 1则取upperLimit,否则以t为参数在上下限间线性插值
                        float result = MathHelper.DenormalizeClamp(lowerLimit, upperLimit, t) - offset;

                        // y = 30~32
                        if (y > 29)
                        {
                            // 在原result和-10之间线性插值,这样y > 240的方块就会越来越少,最后全变成空气
                            float t2 = (float)(y - 29) / 3.0F;
                            result = result * (1.0F - t2) + -10.0F * t2;
                        }

                        _densityMap[x1, y, z1] = (float)result;
                    }
                }
            }

            densityMap = _densityMap;
        }