我有一个Perlin噪音生成器,我试图用它来创建滚动地形。
我有一个中心地形,围绕它的同一侧的八个地形(这些工作正常)和第二个三倍大的地形环。对于这些,我需要我的噪声发生器输出三倍“密度”的噪声,这样我可以在较小的地形上放置一个更大的地形,除了三倍大的瓷砖(和地图大小),它们匹配
我不想只生成更大的地图;这会很快变得令人望而却步。
我不知道该怎么办;显而易见的解决方案都以某种方式失败了。
/// <summary>
/// Generates a new perlin map.
/// </summary>
/// <param name="xStart">The left coordinate (using 0, 0 as top-left and +, + as down and to the right).</param>
/// <param name="yStart">The top coordinate (using 0, 0 as top-left and +, + as down and to the right).</param>
/// <param name="width">The width of the map.</param>
/// <param name="length">The length of the map.</param>
/// <param name="persistance">If set, values lower than 1 make the map less noisey; values greater than 1 make the map more noisy.</param>
/// <param name="fromShift">Low values here provide for a broader "base".</param>
/// <param name="toShift">High values here provide for more speckled "highlights".</param>
/// <param name="interpolate">If set to false, the algorithm will not smooth values.</param>
public double[,] Generate(
int xStart, int yStart,
int width, int length,
double? persistance,
uint fromShift, uint toShift,
bool interpolate = true,
)
{
_noiseMap = new double[width, length];
_workingMap = new double[width + 6, length + 6];
_smoothedNoise = new double[width + 6, length + 6];
int ifromShift = -(int)(toShift),
itoShift = -(int)(fromShift);
int idiv = 1 + (itoShift - ifromShift);
double ddiv = 0;
double amplitude = 0.0;
if (persistance.HasValue)
for (int i = ifromShift; i <= itoShift; ++i)
ddiv += Math.Pow(persistance.Value, i);
for (int i = ifromShift; i <= itoShift; ++i)
{
_frequency = Math.Pow(2, i);
if (persistance.HasValue) amplitude = Math.Pow(persistance.Value, i);
int useWidth = (int)(width * _frequency) + 1,
useLength = (int)(length * _frequency) + 1;
int useXStart = (int)(xStart * _frequency),
useYStart = (int)(yStart * _frequency);
double frequencyXStart = xStart * _frequency - useXStart,
frequencyYStart = yStart * _frequency - useYStart;
for (int y = 0; y < useLength + 5; ++y)
for (int x = 0; x < useWidth + 5; ++x)
{
int genX = ((int)(useXStart) + (int)((x) + 0.5));
int genY = ((int)(useYStart) + (int)((y) + 0.5));
_workingMap[x, y] = GenerateNoise(genX, genY);
}
if (interpolate)
{
for (int y = 1; y < length + 4; ++y)
for (int x = 1; x < width + 4; ++x)
{
_smoothedNoise[x, y] = SmoothedNoise(x, y);
}
if (persistance.HasValue)
for (int y = 0; y < length; ++y)
for (int x = 0; x < width; ++x)
{
_noiseMap[x, y] += InterpolatedNoise((x * _frequency) + 2 + frequencyXStart, (y * _frequency) + 2 + frequencyYStart) * amplitude;
// _noiseMap[x, y] += _workingMap[x, y] * amplitude;
}
else
for (int y = 0; y < length; ++y)
for (int x = 0; x < width; ++x)
{
_noiseMap[x, y] += InterpolatedNoise((x * _frequency) + 2 + frequencyXStart, (y * _frequency) + 2 + frequencyYStart) / idiv;
// _noiseMap[x, y] += _workingMap[x, y] / idiv;
}
}
else
if (persistance.HasValue)
for (int y = 0; y < length; ++y)
for (int x = 0; x < width; ++x)
{
_noiseMap[x, y] +=
_workingMap[(int)((x * _frequency) + 2 + frequencyXStart), (int)((y * _frequency) + 2 + frequencyYStart)] * amplitude;
}
else
for (int y = 0; y < length; ++y)
for (int x = 0; x < width; ++x)
{
_noiseMap[x, y] +=
_workingMap[(int)((x * _frequency) + 2 + frequencyXStart), (int)((y * _frequency) + 2 + frequencyYStart)] / idiv;
}
}
if (persistance.HasValue)
for (int y = 0; y < length; ++y)
for (int x = 0; x < width; ++x)
{
_noiseMap[x, y] = _noiseMap[x, y] / ddiv;
}
return _noiseMap;
}
感谢。
答案 0 :(得分:0)
只是要清楚(检查我对你的问题的理解)。
生成大小为X的地图A. 这张地图周围有九个地图B1 ... B9,每个地图的边长为X. 现在你想要地图C1 ... C2,它将从外面围绕地图B1 ... B9。这些地图中的每一个都有一个大小为3X的边,但只有X ^ 2个数据点(每个数据点的大小为3x3)。
右?
您是否尝试过使用最近邻算法插入数据?当任何代码从坐标X请求数据时,只需将坐标四舍五入为三的倍数并使用它。我认为这应该有效。
另一种选择是使用midpoint displacement algorithm,除非您将每个递归步骤中的切片分成三个部分而不是两个部分。这将允许您提前停止一轮,这将显示您正在寻找的结果:仅在3x3网格的交叉点上生成数据点的高度图。无需触及其余的点。
答案 1 :(得分:0)
Perlin噪音比你的样本更加密集,因此一个algorythm的形状对于所有网格都是密集的。如果你想要额外的细节,你必须添加一个八度音或第二次噪音,在这种情况下,网格不能正确覆盖。所以选择一个形状并用不同的网格密度对其进行采样是个问题。