Search Unity

Question Marching cubes with a 2d heightmap from perlin noise not working

Discussion in 'Scripting' started by Connodore64, Sep 16, 2020.

  1. Connodore64

    Connodore64

    Joined:
    Feb 12, 2020
    Posts:
    10
    I can't seem to get my marching cubes algorithm to work with 2D perlin noise, which is all the more frustrating considering I have it working with 3D perlin noise. That makes me think that my logic for using the 2D perlin noise is just completely wrong. I'm not sure what to do.
    upload_2020-9-16_16-1-24.png
    (this is what it's generating with the 2D perlin noise. You can kinda make out the terrain and can see what it's trying to do, but it's not working properly, obviously)

    Here's where I set what corners are above or below the perlin noise function, which I then plug into my marching cubes algorithm:

    Code (CSharp):
    1. for (int x = 0; x < worldPieceSize.x; x++) {
    2.             for (int z = 0; z < worldPieceSize.z; z++) {
    3.                 for (int y = 0; y < worldPieceSize.y; y++) {
    4.                     float[] perlinStuff = PerlinNoiseGen.marchingPerlin2D(x + position.x, z + position.z, perlin2DScalar, false);
    5.                     for (int i = 0; i < perlinStuff.Length; i++) {
    6.                         perlinStuff[i] *= perlinMultiplier;
    7.                         //perlinStuff[i] += heightBuffer;
    8.                     }
    9.                     if (y > perlinStuff[0] && y + 1 > perlinStuff[0] &&
    10.                         y > perlinStuff[1] && y + 1 > perlinStuff[1] &&
    11.                         y > perlinStuff[2] && y + 1 > perlinStuff[2] &&
    12.                         y > perlinStuff[3] && y + 1 > perlinStuff[3]) {
    13.                         swp.data[x, z, y] = new MarchingBlock(LandType.Air, new Vector3(x + position.x, y, z + position.z));
    14.                     } else {
    15.                         List<int> corners = new List<int>();
    16.                         if (y >= perlinStuff[0]) {
    17.                             corners.Add(0);
    18.                         }
    19.                         if (y + 1 >= perlinStuff[0]) {
    20.                             corners.Add(1);
    21.                         }
    22.                         if (y >= perlinStuff[1]) {
    23.                             corners.Add(2);
    24.                         }
    25.                         if (y + 1 >= perlinStuff[1]) {
    26.                             corners.Add(3);
    27.                         }
    28.                         if (y >= perlinStuff[2]) {
    29.                             corners.Add(6);
    30.                         }
    31.                         if (y + 1 >= perlinStuff[2]) {
    32.                             corners.Add(7);
    33.                         }
    34.                         if (y >= perlinStuff[3]) {
    35.                             corners.Add(4);
    36.                         }
    37.                         if (y + 1 >= perlinStuff[3]) {
    38.                             corners.Add(5);
    39.                         }
    40.                         if (corners.Count == 8 || corners.Count == 0) {
    41.                             swp.data[x, z, y] = new MarchingBlock(LandType.Dirt, new Vector3(x + position.x, y, z + position.z));
    42.                         } else {
    43.                             swp.data[x, z, y] = new MarchingBlock(LandType.Dirt, new Vector3(x + position.x, y, z + position.z), corners);
    44.                         }
    45.                     }
    And here's my 2D perlin noise function:

    Code (CSharp):
    1. public static float[] marchingPerlin2D(float x, float z, float scalar, bool multiply) {
    2.         float _x = x * scalar;
    3.         float _z = z * scalar;
    4.  
    5.         float XZ = Mathf.PerlinNoise(_x, _z);
    6.         float XZ2 = Mathf.PerlinNoise(_x + 1, _z);
    7.         float XZ3 = Mathf.PerlinNoise(_x, _z + 1);
    8.         float XZ4 = Mathf.PerlinNoise(_x + 1, _z + 1);
    9.  
    10.         if (multiply) {
    11.             float ZX = Mathf.PerlinNoise(_z, _x);
    12.             float ZX2 = Mathf.PerlinNoise(_z + 1, _x);
    13.             float ZX3 = Mathf.PerlinNoise(_z, _x + 1);
    14.             float ZX4 = Mathf.PerlinNoise(_z + 1, _x + 1);
    15.  
    16.             return new float[] { XZ * ZX, XZ2 * ZX2, XZ3 * ZX3, XZ4 * ZX4 };
    17.         } else {
    18.             return new float[] { XZ, XZ2, XZ3, XZ4 };
    19.         }
    20.     }
    Any ideas of what I should do?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    The triangles where the quads should be make me think you're winding half your triangles the wrong way.

    What does it look like if you go underneath it? Are some of the faces pointed down? Viewed from directly below you shouldn't see anything... do you?
     
  3. Connodore64

    Connodore64

    Joined:
    Feb 12, 2020
    Posts:
    10
    No, I don't see anything upload_2020-9-16_17-6-40.png
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Might want to just simplify it down as small as you can, maybe 9 verts and 4 quads... then study what data is going into what. It certainly seems like every other tri is degenerate in some way.
     
  5. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Marching cubes is not really the approach you want to use for creating terrain from a heightmap (generated from perlin)

    Marching cubes is inherantly about creating a volume of 'inside' or 'outside', or in your terms 'dirt' and 'air', this allows you (in games) to create holes, caves, overhangs, etc.
    When creating a terrain from 2D perlin, you dont want there to be holes, there should never be a result that gives 'air' in your surface
     
  6. Connodore64

    Connodore64

    Joined:
    Feb 12, 2020
    Posts:
    10
    Thank you, I should've done this from the beginning. I noticed that the perlin noise values weren't the same at each corner when the x or z value incremented, so I decided to just directly compare the y value to the Mathf.PerlinNoise() function and that worked!
    upload_2020-9-16_18-34-0.png
    Edit: It looks like I was incrementing the value of the x and z inputs into my perlin noise function AFTER multiplying it by the scalar... oops
     
    Kurt-Dekker likes this.
  7. Connodore64

    Connodore64

    Joined:
    Feb 12, 2020
    Posts:
    10
    I've been able to use 3D perlin noise with marching cubes, and my plan was to use that to cut caves and overhangs out of the terrain. If I can't get it to work well at all, then I'll have to rethink my approach.
     
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Sweet! Now all you need is a jetpack script to leap from the low parts to the high parts!!! :)