Update project to use Godot.NET.Sdk 4.3.0 and improve terrain generation performance
This commit is contained in:
@@ -48,12 +48,18 @@ public partial class Tile : Node2D
|
||||
|
||||
DebugType debugType = _world.DebugType;
|
||||
|
||||
// Run in thread
|
||||
// Use limited parallelism instead of unlimited Task.Run
|
||||
var parallelOptions = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = Math.Max(1, (int)(System.Environment.ProcessorCount * 0.5)),
|
||||
CancellationToken = CancellationToken
|
||||
};
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int x = 0; x < _size.X; x++)
|
||||
Parallel.For(0, _size.X, parallelOptions, x =>
|
||||
{
|
||||
if (CancellationToken.IsCancellationRequested) return;
|
||||
|
||||
@@ -88,7 +94,7 @@ public partial class Tile : Node2D
|
||||
|
||||
float neighborHeight = GetValueAtMapPosition(neighborCoords);
|
||||
|
||||
if (IsSeaAtMapPosition(neighborCoords, waterThreshold))
|
||||
if (IsSeaAtMapPosition(neighborCoords))
|
||||
{
|
||||
bordersSea = true;
|
||||
}
|
||||
@@ -109,14 +115,14 @@ public partial class Tile : Node2D
|
||||
// Grass (default)
|
||||
image.SetPixel(x, y, Color.FromString("#bed58a", Colors.Purple));
|
||||
|
||||
if (IsSeaAtMapPosition(pixelOffset, waterThreshold))
|
||||
if (IsSeaAtMapPosition(pixelOffset))
|
||||
{
|
||||
// Water
|
||||
image.SetPixel(x, y, Color.FromString("#4380b0", Colors.Purple));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (moistureValue < desertMoistureThreshold && heatValue > desertTemperatureThreshold)
|
||||
if (isDesertAtMapPosition(pixelOffset))
|
||||
{
|
||||
// Desert
|
||||
image.SetPixel(x, y, Color.FromString("#edc9af", Colors.Purple));
|
||||
@@ -129,7 +135,7 @@ public partial class Tile : Node2D
|
||||
continue;
|
||||
}
|
||||
|
||||
if (heightValue > snowHeightThreshold)
|
||||
if (heightValue > snowHeightThreshold && !isDesertAtMapPosition(pixelOffset))
|
||||
{
|
||||
// Snow
|
||||
image.SetPixel(x, y, Color.FromString("#f4f4f4", Colors.Purple));
|
||||
@@ -165,7 +171,7 @@ public partial class Tile : Node2D
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -186,13 +192,8 @@ public partial class Tile : Node2D
|
||||
}
|
||||
|
||||
// Terrain Query Methods
|
||||
private float GetValueAtMapPosition(Vector2I position)
|
||||
private Vector2I ToHeightMapCoordinates(Vector2I position)
|
||||
{
|
||||
|
||||
// Clamp position to map bounds
|
||||
position.X = Mathf.Clamp(position.X, 0, _world.ChunksPerAxis.X * _world.TileSize - 1);
|
||||
position.Y = Mathf.Clamp(position.Y, 0, _world.ChunksPerAxis.Y * _world.TileSize - 1);
|
||||
|
||||
Vector2I heightMapResolution = new Vector2I(
|
||||
_world.HeightMapImage.GetWidth(),
|
||||
_world.HeightMapImage.GetHeight()
|
||||
@@ -206,6 +207,19 @@ public partial class Tile : Node2D
|
||||
(int)(mapDelta.X * heightMapResolution.X),
|
||||
(int)(mapDelta.Y * heightMapResolution.Y)
|
||||
);
|
||||
|
||||
// Clamp to valid range
|
||||
heightMapCoords.X = Mathf.Clamp(heightMapCoords.X, 0, heightMapResolution.X - 1);
|
||||
heightMapCoords.Y = Mathf.Clamp(heightMapCoords.Y, 0, heightMapResolution.Y - 1);
|
||||
|
||||
return heightMapCoords;
|
||||
}
|
||||
|
||||
private float GetValueAtMapPosition(Vector2I position)
|
||||
{
|
||||
|
||||
|
||||
Vector2I heightMapCoords = ToHeightMapCoordinates(position);
|
||||
|
||||
Color hmColor = _world.HeightMapImage.GetPixel(heightMapCoords.X, heightMapCoords.Y);
|
||||
|
||||
@@ -218,10 +232,17 @@ public partial class Tile : Node2D
|
||||
return heightValue <= _world.WaterThreshold;
|
||||
}
|
||||
|
||||
private bool IsSeaAtMapPosition(Vector2I position, float waterThreshold)
|
||||
private bool isDesertAtMapPosition(Vector2I position)
|
||||
{
|
||||
float heatValue = GetHeatAtMapPosition(position);
|
||||
float moistureValue = GetMoistureAtMapPosition(position);
|
||||
return moistureValue < _world.DesertMoistureThreshold && heatValue > _world.DesertTemperatureThreshold;
|
||||
}
|
||||
|
||||
private bool IsSeaAtMapPosition(Vector2I position)
|
||||
{
|
||||
float heightValue = GetValueAtMapPosition(position);
|
||||
return heightValue <= waterThreshold;
|
||||
return heightValue <= _world.WaterThreshold;
|
||||
}
|
||||
|
||||
private FastNoiseLite _heatNoise = null;
|
||||
@@ -233,21 +254,21 @@ public partial class Tile : Node2D
|
||||
_heatNoise = new FastNoiseLite();
|
||||
_heatNoise.SetNoiseType(FastNoiseLite.NoiseTypeEnum.Perlin);
|
||||
_heatNoise.SetFrequency(1/_world.TemperatureNoiseFrequency);
|
||||
_heatNoise.SetFractalType(FastNoiseLite.FractalTypeEnum.Fbm);
|
||||
_heatNoise.SetFractalOctaves(12);
|
||||
_heatNoise.SetSeed(1738);
|
||||
}
|
||||
|
||||
float heat = _heatNoise.GetNoise2D(position.X, position.Y);
|
||||
heat *= 0.2f;
|
||||
|
||||
Vector2I heightMapCoords = ToHeightMapCoordinates(position);
|
||||
|
||||
float heat = _heatNoise.GetNoise2D(heightMapCoords.X, heightMapCoords.Y);
|
||||
heat *= _world.TemperatureNoiseAmplitude;
|
||||
|
||||
// Fall off towards the poles. Use sine function for a globe effect.
|
||||
float mapResolutionY = _world.ChunksPerAxis.Y * _world.TileSize;
|
||||
float latitudeFactor = Mathf.Sin(Mathf.Pi * position.Y / mapResolutionY);
|
||||
float mapResolutionY = _world.HeightMapImage.GetHeight();
|
||||
float latitudeFactor = Mathf.Sin(Mathf.Pi * heightMapCoords.Y / mapResolutionY);
|
||||
heat = latitudeFactor + heat;
|
||||
heat = Mathf.Clamp(
|
||||
heat,
|
||||
0.0f,
|
||||
1.0f
|
||||
);
|
||||
|
||||
|
||||
return heat;
|
||||
}
|
||||
@@ -261,21 +282,20 @@ public partial class Tile : Node2D
|
||||
_moistureNoise = new FastNoiseLite();
|
||||
_moistureNoise.SetNoiseType(FastNoiseLite.NoiseTypeEnum.Perlin);
|
||||
_moistureNoise.SetFrequency(1/_world.MoistureNoiseFrequency);
|
||||
_moistureNoise.SetFractalType(FastNoiseLite.FractalTypeEnum.Fbm);
|
||||
_moistureNoise.SetFractalOctaves(12);
|
||||
_moistureNoise.SetSeed(1337);
|
||||
}
|
||||
|
||||
Vector2I heightMapCoords = ToHeightMapCoordinates(position);
|
||||
|
||||
float moisture = _moistureNoise.GetNoise2D(position.X, position.Y);
|
||||
moisture *= 0.2f;
|
||||
float moisture = _moistureNoise.GetNoise2D(heightMapCoords.X, heightMapCoords.Y);
|
||||
moisture *= _world.MoistureNoiseAmplitude;
|
||||
|
||||
// Fall off towards the poles. Use sine function for a globe effect.
|
||||
float mapResolutionY = _world.ChunksPerAxis.Y * _world.TileSize;
|
||||
float latitudeFactor = Mathf.Sin(Mathf.Pi * position.Y / mapResolutionY);
|
||||
float mapResolutionY = _world.HeightMapImage.GetHeight();
|
||||
float latitudeFactor = Mathf.Sin(Mathf.Pi * heightMapCoords.Y / mapResolutionY);
|
||||
moisture = latitudeFactor + moisture;
|
||||
moisture = Mathf.Clamp(
|
||||
moisture,
|
||||
0.0f,
|
||||
1.0f
|
||||
);
|
||||
|
||||
|
||||
return moisture;
|
||||
|
||||
Reference in New Issue
Block a user