Search Unity

Chunk marching cubes

Discussion in 'Scripting' started by Arcratist, Jan 13, 2020.

  1. Arcratist

    Arcratist

    Joined:
    Sep 26, 2018
    Posts:
    5
    Hello, I'm currently having trouble getting chunking to work for marching cubes. I've based my project off of Scrawks (https://github.com/Scrawk/Marching-Cubes) Project.

    This is my problem



    The important part:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4.     public class Chunk : MonoBehaviour
    5.     {
    6.         public int width;
    7.         public int height;
    8.         public int length;
    9.         public Vector3Int coord;
    10.         public GameObject chunkObj;
    11.         public Material chunkMat;
    12.  
    13.         public ChunkVoxelProvider chunkVoxelProvider;
    14.  
    15.         private List<GameObject> meshes = new List<GameObject>();
    16.         public float[] voxels;
    17.      
    18.         public void Generate(List<Chunk> chunks)
    19.         {
    20.             List<Vector3> verts = new List<Vector3>();
    21.             List<int> indices = new List<int>();
    22.             //The voxel array.
    23.             voxels = new float[width * height * length];
    24.             //Cubes is faster and creates less verts, tetrahedrons is slower and creates more verts but better represents the mesh surface.
    25.             Marching marching = new MarchingCubes();
    26.             //Surface is the value that represents the surface of mesh
    27.             //For example the perlin noise has a range of -1 to 1 so the mid point is where we want the surface to cut through.
    28.             //The target value does not have to be the mid point it can be any value with in the range.
    29.             marching.Surface = chunkVoxelProvider.surface;
    30.             //Get generated values from chunk provider.
    31.             voxels = chunkVoxelProvider.Provide(width, height, length, coord.x, coord.y, coord.z);
    32.             //The mesh produced is not optimal. There is one vert for each index.
    33.             //Would need to weld vertices for better quality mesh.
    34.             marching.Generate(voxels, width, height, length, verts, indices);
    35.             //A mesh in unity can only be made up of 65000 verts.
    36.             //Need to split the verts between multiple meshes.
    37.             int maxVertsPerMesh = 30000; //must be divisible by 3, ie 3 verts == 1 triangle
    38.             int numMeshes = verts.Count / maxVertsPerMesh + 1;
    39.  
    40.             for (int i = 0; i < numMeshes; i++)
    41.             {
    42.  
    43.                 List<Vector3> splitVerts = new List<Vector3>();
    44.                 List<int> splitIndices = new List<int>();
    45.  
    46.                 for (int j = 0; j < maxVertsPerMesh; j++)
    47.                 {
    48.                     int idx = i * maxVertsPerMesh + j;
    49.  
    50.                     if (idx < verts.Count)
    51.                     {
    52.                         splitVerts.Add(verts[idx]);
    53.                         splitIndices.Add(j);
    54.                     }
    55.                 }
    56.  
    57.                 if (splitVerts.Count == 0) continue;
    58.  
    59.                 Mesh mesh = new Mesh();
    60.                 mesh.SetVertices(splitVerts);
    61.                 mesh.SetTriangles(splitIndices, 0);
    62.                 mesh.RecalculateBounds();
    63.                 mesh.RecalculateNormals();
    64.                 GameObject go = new GameObject("Mesh-" + i);
    65.                 go.transform.parent = transform;
    66.                 go.AddComponent<MeshFilter>();
    67.                 go.AddComponent<MeshRenderer>();
    68.                 go.GetComponent<Renderer>().material = chunkMat;
    69.                 go.GetComponent<MeshFilter>().mesh = mesh;
    70.                 go.transform.localPosition = new Vector3(-width / 2, -height / 2, -length / 2);
    71.  
    72.                 meshes.Add(go);
    73.             }
    74.  
    75.         }
    76. }
    77.  
    I have no idea how I'd pass the neighboring voxel data in.

    Any help is appreciated.
     
  2. Arcratist

    Arcratist

    Joined:
    Sep 26, 2018
    Posts:
    5
  3. Arcratist

    Arcratist

    Joined:
    Sep 26, 2018
    Posts:
    5
    Bump again. Is there is anything you think I could do or add to the post to get more reception?
     
  4. Orzel94

    Orzel94

    Joined:
    Feb 15, 2016
    Posts:
    1
  5. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    I had the same problem ('missing a cube between chunks') in my implementation. It actually makes sense when you think about it. In marching cubes, we generate the cube 'between coordinates'. This problem simply does not exist in a more minecraft-like blocky world. Here, for 0 to 1, we generate one cube, 1 to 2 another and so on. So for a 16 cube long chunk we generate 15 (!) such cubes. And that's the problem. We generate the last cube from 15 to 16, then we stop. The next chunk would start at 17 to 18 and continue from there. However, we never generated the 16 to 17 cube, which is the empty lines you can see in between the chunks.
    To fix this i simply included N+1 coordinates into the calculation for a N sized chunk, or more specifically, simply use 17x17x17 for a 16x16x16 sized chunk, since that's actually the amount of data we require to generate the 16 cubes in all directions.