将 PerlinNoise 映射到网格
Mapping PerlinNoise to a Grid
我正在尝试在我的地图上生成一个网格并根据 perlin 噪声值添加节点。根据从某个位置的 perlin 噪声获得的值,我将添加一个新节点,该节点将属于某种类型,例如山,水等代表terrian。在这里,我试图做到这一点,如果该值 > 0.5,这意味着它只有山脉,所以黑色立方体应该围绕着山区,但是,我的黑色立方体与 perlin 噪声中的山区不匹配,我似乎无法弄清楚为什么我会出错。如果能深入了解我如何实现这一目标,我将不胜感激。
private void LocateWalkableCells()
{
for(int z = 0; z < Height; z++)
{
for(int x = 0; x < Width; x++)
{
noise = GetNoiseValue(x, z);
if(noise > 0.5) {
grid[x,z] = new Node(new Vector3(x, 0, z), TerrainType.Mountain, 1);
}
else {
grid[x,z] = new Node(new Vector3(x, 0, z), TerrainType.Grass, 1);
}
}
}
}
private float GetNoiseValue(int x, int z)
{
int pos = (x * Width) + z;
return Mathf.Round(terrainGenerator.noiseArray[pos] * 10) / 10;
}
// Draw gizmos to visualize colour
void OnDrawGizmos()
{
Gizmos.DrawWireCube(transform.position, new Vector3(Width, 1, Height));
if(grid != null)
{
foreach(Node n in grid)
{
if(n.TerrainType == TerrainType.Grass)
{
Gizmos.color = Color.green;
}
else if(n.TerrainType == TerrainType.Mountain)
{
Gizmos.color = Color.black;
}
Gizmos.DrawCube(n.Position, Vector3.one * (nodeDiameter - .1f));
}
}
}
noiseArray
用于地形的顶点,代码如下:
vertices = new Vector3[(Width + 1) * (Depth + 1)];
noiseArray = PerlinNoise();
int i = 0;
for(int z = 0; z <= Depth; z++)
{
for(int x = 0; x <= Width; x++)
{
var currentHeight = noiseArray[i];
if(currentHeight > HeightThreshold)
{
currentHeight *= HeightMultiplier;
}
vertices[i] = new Vector3(x, currentHeight, z);
i++;
}
}
输出
建议答案的结果
似乎还是遗漏了一些山区,用绿色代替黑色。
认为问题出在
var pos = (x * Width) + z;
因为 x
你索引的是你可能更想要的网格宽度
var pos = z * Width + x;
换句话说你想要
- 跳过
z
行
- 每行有
Width
个元素
- 然后从那里取出第
x
个元素
假设您的地形已布置 row-wise。
或者如果它被布局 column-wise(这很不寻常但可能)
var pos = x * Height + z;
或者换句话说
- 跳过
x
列
- 每列有
Height
个元素
- 然后从那里取出第
z
个元素
另见 Converting index of one dimensional array into two dimensional array i. e. row and column
更新
现在您已经展示了地形生成代码,它需要
var pos = z * (Width + 1) + x;
因为地形数组实际上每行有 Width + 1
个元素。
我正在尝试在我的地图上生成一个网格并根据 perlin 噪声值添加节点。根据从某个位置的 perlin 噪声获得的值,我将添加一个新节点,该节点将属于某种类型,例如山,水等代表terrian。在这里,我试图做到这一点,如果该值 > 0.5,这意味着它只有山脉,所以黑色立方体应该围绕着山区,但是,我的黑色立方体与 perlin 噪声中的山区不匹配,我似乎无法弄清楚为什么我会出错。如果能深入了解我如何实现这一目标,我将不胜感激。
private void LocateWalkableCells()
{
for(int z = 0; z < Height; z++)
{
for(int x = 0; x < Width; x++)
{
noise = GetNoiseValue(x, z);
if(noise > 0.5) {
grid[x,z] = new Node(new Vector3(x, 0, z), TerrainType.Mountain, 1);
}
else {
grid[x,z] = new Node(new Vector3(x, 0, z), TerrainType.Grass, 1);
}
}
}
}
private float GetNoiseValue(int x, int z)
{
int pos = (x * Width) + z;
return Mathf.Round(terrainGenerator.noiseArray[pos] * 10) / 10;
}
// Draw gizmos to visualize colour
void OnDrawGizmos()
{
Gizmos.DrawWireCube(transform.position, new Vector3(Width, 1, Height));
if(grid != null)
{
foreach(Node n in grid)
{
if(n.TerrainType == TerrainType.Grass)
{
Gizmos.color = Color.green;
}
else if(n.TerrainType == TerrainType.Mountain)
{
Gizmos.color = Color.black;
}
Gizmos.DrawCube(n.Position, Vector3.one * (nodeDiameter - .1f));
}
}
}
noiseArray
用于地形的顶点,代码如下:
vertices = new Vector3[(Width + 1) * (Depth + 1)];
noiseArray = PerlinNoise();
int i = 0;
for(int z = 0; z <= Depth; z++)
{
for(int x = 0; x <= Width; x++)
{
var currentHeight = noiseArray[i];
if(currentHeight > HeightThreshold)
{
currentHeight *= HeightMultiplier;
}
vertices[i] = new Vector3(x, currentHeight, z);
i++;
}
}
输出
建议答案的结果
似乎还是遗漏了一些山区,用绿色代替黑色。
认为问题出在
var pos = (x * Width) + z;
因为 x
你索引的是你可能更想要的网格宽度
var pos = z * Width + x;
换句话说你想要
- 跳过
z
行 - 每行有
Width
个元素 - 然后从那里取出第
x
个元素
假设您的地形已布置 row-wise。
或者如果它被布局 column-wise(这很不寻常但可能)
var pos = x * Height + z;
或者换句话说
- 跳过
x
列 - 每列有
Height
个元素 - 然后从那里取出第
z
个元素
另见 Converting index of one dimensional array into two dimensional array i. e. row and column
更新
现在您已经展示了地形生成代码,它需要
var pos = z * (Width + 1) + x;
因为地形数组实际上每行有 Width + 1
个元素。