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; }