Tworzę silnik podobny do Minecrafta w XNA. Chcę stworzyć pływające wyspy podobne do pokazanych na tym filmie:
http://www.youtube.com/watch?v=gqHVOEPQK5g&feature=related
Jak mam to powtórzyć za pomocą generatora świata? Czy musiałbym użyć algorytmu szumu Perlina? Nie wiem, jak to pomogłoby mi stworzyć takie masy lądowe.
Oto kod generatora hałasu Perlin, którego używam:
private double[,] noiseValues;
private float amplitude = 1; // Max amplitude of the function
private int frequency = 1; // Frequency of the function
/// <summary>
/// Constructor
/// </summary>
///
public PerlinNoise(int freq, float _amp)
{
Random rand = new Random(System.Environment.TickCount);
noiseValues = new double[freq, freq];
amplitude = _amp;
frequency = freq;
// Generate our noise values
for (int i = 0; i < freq; i++)
{
for (int k = 0; k < freq; k++)
{
noiseValues[i, k] = rand.NextDouble();
}
}
}
/// <summary>
/// Get the interpolated point from the noise graph using cosine interpolation
/// </summary>
/// <returns></returns>
public double getInterpolatedPoint(int _xa, int _xb, int _ya, int _yb, double x, double y)
{
double i1 = interpolate(
noiseValues[_xa % Frequency, _ya % frequency],
noiseValues[_xb % Frequency, _ya % frequency]
, x);
double i2 = interpolate(
noiseValues[_xa % Frequency, _yb % frequency],
noiseValues[_xb % Frequency, _yb % frequency]
, x);
return interpolate(i1, i2, y);
}
public static double[,] SumNoiseFunctions(int width, int height, List<PerlinNoise> noiseFunctions)
{
double[,] summedValues = new double[width, height];
// Sum each of the noise functions
for (int i = 0; i < noiseFunctions.Count; i++)
{
double x_step = (float)width / (float)noiseFunctions[i].Frequency;
double y_step = (float)height / (float)noiseFunctions[i].Frequency;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int a = (int)(x / x_step);
int b = a + 1;
int c = (int)(y / y_step);
int d = c + 1;
double intpl_val = noiseFunctions[i].getInterpolatedPoint(a, b, c, d, (x / x_step) - a, (y / y_step) - c);
summedValues[x, y] += intpl_val * noiseFunctions[i].Amplitude;
}
}
}
return summedValues;
}
/// <summary>
/// Get the interpolated point from the noise graph using cosine interpolation
/// </summary>
/// <returns></returns>
private double interpolate(double a, double b, double x)
{
double ft = x * Math.PI;
double f = (1 - Math.Cos(ft)) * .5;
// Returns a Y value between 0 and 1
return a * (1 - f) + b * f;
}
public float Amplitude { get { return amplitude; } }
public int Frequency { get { return frequency; } }
Ale rzecz w tym, że autor kodu wykorzystuje następujące czynniki do generowania szumu, a ja nie rozumiem tego w najmniejszym stopniu.
private Block[, ,] GenerateLandmass()
{
Block[, ,] blocks = new Block[300, 400, 300];
List<PerlinNoise> perlins = new List<PerlinNoise>();
perlins.Add(new PerlinNoise(36, 29));
perlins.Add(new PerlinNoise(4, 33));
double[,] noisemap = PerlinNoise.SumNoiseFunctions(300, 300, perlins);
int centrey = 400 / 2;
for (short x = 0; x < blocks.GetLength(0); x++)
{
for (short y = 0; y < blocks.GetLength(1); y++)
{
for (short z = 0; z < blocks.GetLength(2); z++)
{
blocks[x, y, z] = new Block(BlockType.none);
}
}
}
for (short x = 0; x < blocks.GetLength(0); x++)
{
for (short z = 0; z < blocks.GetLength(2); z++)
{
blocks[x, centrey - (int)noisemap[x, z], z].BlockType = BlockType.stone;
}
}
//blocks = GrowLandmass(blocks);
return blocks;
}
I oto strona, której używam: http://lotsacode.wordpress.com/2010/02/24/perlin-noise-in-c/ .
I staram się realizować hałas perlin w sposób określony przez Martina Sojkę.
Ok, więc oto co mam do tej pory:
Czy coś takiego wystarczyłoby?
Jeśli tak, sprawdź ten artykuł . Cytując najważniejsze części:
źródło
Pseudokod dla kroku 2:
Po zakończeniu generowania wysp możesz opcjonalnie przesunąć je w górę i w dół w przestrzeni, aby mieć je na różnych wysokościach.
źródło