Saturday, January 11, 2020

procedural generation - Working with 3D Noise


I am using a simplex 2D noise to generate my worlds so far. This however was never the plan and has the downside that I basically can only generate a heightmap. Instead I want to aim for floating islands scattered in the sky, but I fail to see how I can utilize 3D noise properly for this.


Based on a simplex 3D noise function I am currently generating noise like this:


float

sc_perlin_noise3_ex(const sc_perlin_t *perlin, float x, float y,
float z, int octaves, float persistence,
float base_frequency, float base_amp,
float lacunarity)
{
int i;
float freq = base_frequency;
float amp = base_amp;
float max = 1.0f;
float total = 1.0f;


for (i = 0; i < octaves; i++) {
total += sc_perlin_noise3(perlin, x * freq, y * freq, z * freq) * amp;
max += amp;
freq *= lacunarity;
amp *= persistence;
}
return total / max;
}


Problems start there: first of all I think I got octaves wrong, at least the outcome is very unpredictable. Persistence would be a value smaller 1 that removes the effect of the higher octaves.


Secondly however I have a general problem understanding how 3D noise works. From my understanding a value < -1 could mean air, a value > 1 would be solid and 0 is the thin line between them (the surface). First of all however I get a lot more values below zero than above zero, so I had to flip those two around. That seems odd, do I have the math wrong?


The actual problem however is that I cannot locate "islands" properly. Say I have a container of 256^3 in size and I want to have one large island in there with maybe up to three smaller islands in there I have to ensure that:



  1. no island is cut off at the edges

  2. that I only get two even sized islands in my block

  3. I have some better control of the actual appearance of my island. For instance it would be nice if it had an actual flat-ish surface where I can put a heighmap on top of that for mountains etc.


Based on that I have the feeling I am on the completely wrong track here. Can anyone give me some pointers on where to head now?


Generally speaking I would like to have something that looks like this: floating island




Answer



I went with 3D noise again because it produces much nicer things than I could accomplish with 2D noise. I'm currently using a falloff factor for the general form of my island but unfortunately it still sometimes happens that the island will just be too small.


Generally though it works:


static int
block_is_solid(const sc_worldgen_t *worldgen, float x, float y, float z)
{
float noise, density, center_falloff, plateau_falloff;

/* caves */
if (powf(sc_perlin_noise3_ex(worldgen->perlin, x * 5.0f, y * 5.0f,

z * 5.0f, 3), 3.0f) < -0.5f)
return 0;

/* falloff from the top */
if (y > 0.9f)
return SC_BLOCK_AIR;
else if (y > 0.8f)
plateau_falloff = 1.0f - (y - 0.8f) * 10.0f;
else
plateau_falloff = 1.0f;


/* falloff from center */
center_falloff = 0.1f / (
powf((x - 0.5f) * 1.5f, 2.0f) +
powf((y - 1.0f) * 0.8f, 2.0f) +
powf((z - 0.5f) * 1.5f, 2.0f)
);

/* noise combined density */
noise = sc_perlin_noise3_ex(worldgen->perlin, x, y * 0.5, z, 7);

density = noise * center_falloff * plateau_falloff;
return density > 0.2f ? SC_BLOCK_STONE : SC_BLOCK_AIR;
}

Technique from pyalot.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...