Search Unity

[Solved] Dynamic Code Generated Voxel Terrain Help (C#)

Discussion in 'Scripting' started by Thecheatgamer1, Oct 30, 2014.

  1. Thecheatgamer1

    Thecheatgamer1

    Joined:
    Jul 9, 2013
    Posts:
    30
    Well the game i am planning to create will be mainly based on a dynamic voxel terrain what will interact with other meshes, for example, meteors crashing, this will create a crater what is dependent on the meteors physics (speed, temperature and more), i have tried multiple ways of doing this and have even tried this tutorial on voxels http://forum.unity3d.com/threads/tutorial-procedural-meshes-and-voxel-terrain-c.198651/ but it is very outdated and doesnt really explain things clearly enough.

    I have tried creating a large square mesh out of small squares that are on the same mesh, like this



    This mesh contains 40,000 vertices

    and the code

    Code (CSharp):
    1.     private List<Vector3> vertices = new List<Vector3>();
    2.     private List<int> triangles = new List<int>();
    3.     private List<Vector2> uvs = new List<Vector2>();
    4.  
    5.     private TerrainHandler terrain;
    6.  
    7.     private Mesh mesh;
    8.     private MeshCollider collider;
    9.     private MeshRenderer renderer;
    10.  
    11.     private float textureUnit = 0.25F;
    12.     private int faceCount = 0;
    13.  
    14.     private float tileSize = 0.5F;
    15.  
    16.     public bool update = false;
    17.  
    18.     void Start () {
    19.         terrain = GetComponent<TerrainHandler>();
    20.  
    21.         mesh = GetComponent<MeshFilter>().mesh;
    22.         collider = GetComponent<MeshCollider>();
    23.         renderer = GetComponent<MeshRenderer>();
    24.  
    25.         TerrainTop();
    26.         TerrainBomttom();
    27.         TerrainRight();
    28.         TerrainLeft();
    29.         TerrainFront();
    30.         TerrainBack();
    31.  
    32.         UpdateMesh();
    33.     }
    34.  
    35.     void Update () {
    36.         if (update) {
    37.             UpdateMesh();
    38.             update = false;
    39.         }
    40.     }
    41.  
    42.     public void TerrainTop() {
    43.         for (int x = 0; x < terrain.worldSize / tileSize; x++) {
    44.             for (int z = 0; z < terrain.worldSize / tileSize; z++) {
    45.                 vertices.Add(new Vector3(x * tileSize, terrain.worldHeight, z * tileSize));
    46.                 vertices.Add(new Vector3(x * tileSize, terrain.worldHeight, z * tileSize + tileSize));
    47.                 vertices.Add(new Vector3(x * tileSize + tileSize, terrain.worldHeight, z * tileSize + tileSize));
    48.                 vertices.Add(new Vector3(x * tileSize + tileSize, terrain.worldHeight, z * tileSize));
    49.                 Terrain(new Vector2(0, 0));
    50.             }
    51.         }
    52.     }
    53.  
    54.     public void TerrainBomttom() {
    55.         vertices.Add(new Vector3(0, 0, 0));
    56.         vertices.Add(new Vector3(0, 0, terrain.worldSize));
    57.         vertices.Add(new Vector3(terrain.worldSize, 0, terrain.worldSize));
    58.         vertices.Add(new Vector3(terrain.worldSize, 0, 0));
    59.         Terrain(new Vector2(0, 0));
    60.     }
    61.  
    62.     public void TerrainRight() {
    63.         vertices.Add(new Vector3(terrain.worldSize, 0, 0));
    64.         vertices.Add(new Vector3(terrain.worldSize, terrain.worldHeight, 0));
    65.         vertices.Add(new Vector3(terrain.worldSize, terrain.worldHeight, terrain.worldSize));
    66.         vertices.Add(new Vector3(terrain.worldSize, 0, terrain.worldSize));
    67.         Terrain(new Vector2(0, 0));
    68.     }
    69.  
    70.     public void TerrainLeft() {
    71.         vertices.Add(new Vector3(0, 0, 0));
    72.         vertices.Add(new Vector3(0, 0, terrain.worldSize));
    73.         vertices.Add(new Vector3(0, terrain.worldHeight, terrain.worldSize));
    74.         vertices.Add(new Vector3(0, terrain.worldHeight, 0));
    75.         Terrain(new Vector2(0, 0));
    76.     }
    77.  
    78.     public void TerrainFront() {
    79.         vertices.Add(new Vector3(0, 0, 0));
    80.         vertices.Add(new Vector3(0, terrain.worldHeight, 0));
    81.         vertices.Add(new Vector3(terrain.worldSize, terrain.worldHeight, 0));
    82.         vertices.Add(new Vector3(terrain.worldSize, 0, 0));
    83.         Terrain(new Vector2(0, 0));
    84.     }
    85.  
    86.     public void TerrainBack() {
    87.         vertices.Add(new Vector3(0, 0, terrain.worldSize));
    88.         vertices.Add(new Vector3(0, terrain.worldHeight, terrain.worldSize));
    89.         vertices.Add(new Vector3(terrain.worldSize, terrain.worldHeight, terrain.worldSize));
    90.         vertices.Add(new Vector3(terrain.worldSize, 0, terrain.worldSize));
    91.         Terrain(new Vector2(0, 0));
    92.     }
    93.  
    94.     public void Terrain(Vector2 texturePos) {
    95.         triangles.Add(faceCount * 4);
    96.         triangles.Add(faceCount * 4 + 1);
    97.         triangles.Add(faceCount * 4 + 2);
    98.         triangles.Add(faceCount * 4);
    99.         triangles.Add(faceCount * 4 + 2);
    100.         triangles.Add(faceCount * 4 + 3);
    101.  
    102.         uvs.Add(new Vector2(textureUnit * texturePos.x + textureUnit, textureUnit * texturePos.y));
    103.         uvs.Add(new Vector2(textureUnit * texturePos.x + textureUnit, textureUnit * texturePos.y + textureUnit));
    104.         uvs.Add(new Vector2(textureUnit * texturePos.x, textureUnit * texturePos.y + textureUnit));
    105.         uvs.Add(new Vector2(textureUnit * texturePos.x, textureUnit * texturePos.y));
    106.  
    107.         faceCount++;
    108.     }
    109.  
    110.     public void ModifyTerrain(int action, Vector3 eulerAngles, Vector3 verticeCoords, float speed) {
    111.  
    112.     }
    113.  
    114.     public void UpdateMesh() {
    115.         mesh.Clear();
    116.         mesh.vertices = vertices.ToArray();
    117.         mesh.uv = uvs.ToArray();
    118.         mesh.triangles = triangles.ToArray();
    119.         mesh.Optimize();
    120.         mesh.RecalculateBounds();
    121.         mesh.RecalculateNormals();
    122.  
    123.         collider.sharedMesh = null;
    124.         collider.sharedMesh = mesh;
    125.  
    126.         //vertices.Clear();
    127.         //uvs.Clear();
    128.         //triangles.Clear();
    129.  
    130.         faceCount = 0;
    131.     }
    Iv also tried creating cubes upon cubes but that seems to only make the fps drop dramatically and sometimes even crash unity on generation, i also want the player to be able to modify the terrain but im not entirely sure how to manipulate the mesh at will and have worried that if i change any of the vertices, the vertices beside them will not stay attached

    I am still new to Unity and semi-new to C# (Exerted Java Programmer and C# doesn't seem too different), i cant seem to find any answer to how to do a smooth voxel terrain that you can manipulate, i have seen fixed cube ones but that is far from what i am after and if it is possible, is there a way to not allow for things like chunk loading.

    For a idea, this is what i want my terrain to look something like


    If you have ever played CitiesXL 2012, you will know what im looking for, but a may more dynamic terrain and if you havent i recommend looking it up!

    The person who solves my problem will have the gratitude of having their name in the credits and helpers list on the games website when it is finished! with permissions of course.
     
  2. NeverConvex

    NeverConvex

    Joined:
    Jun 26, 2013
    Posts:
    88
    This question seems to come up a lot on the forums these days.

    My recommendation, as in past threads with the same basic line of questioning, is to download and dissect Scrawk's awesome Unity projects from his blog, and dissect the code in them for understanding:

    Scrawk's Marching Cubes Project

    Scrawk's Voxel Terrain Generator

    Scrawk's GPU-driven Voxel Marching Cubes Project

    The heart of each of them is the Marching Cubes (/ Tetrahedra) algorithm(s), for which Paul Bourke's long-standing guide is an excellent tutorial. In addition to studying Marching Cubes, you may also want to read up on Perlin noise (and various related families of noise, e.g. simplex noise).
     
  3. Thecheatgamer1

    Thecheatgamer1

    Joined:
    Jul 9, 2013
    Posts:
    30
    Thanks, i will look at this tomorrow!
     
  4. Thecheatgamer1

    Thecheatgamer1

    Joined:
    Jul 9, 2013
    Posts:
    30

    Thank you! this is just what i was looking for and now i can copy the code in my own syntax and modify it!

    If you would like your name in my games credits you will be allowed! but only with your permission
     
  5. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
    Dont forget to read through the whole after playing minecraft thread in the gossip section!
     
  6. Thecheatgamer1

    Thecheatgamer1

    Joined:
    Jul 9, 2013
    Posts:
    30
    I dont get what your trying to say?
     
  7. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
  8. Thecheatgamer1

    Thecheatgamer1

    Joined:
    Jul 9, 2013
    Posts:
    30
  9. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
    Where have you said that? Maybe you didn't read the forum thread well enough. Almost all the information that is in there applies to voxel engines in general, not only cubic style voxel worlds.

    Take a look at the terrain generation (noise etc) discussions, the lighting calculations, usage of chunks and optimizations. You are really overlooking those by just assuming that this is only for cubic worlds.

    Sure, if you dont want a cubic style, your iso surface extraction will be different. Be it marching cubes, dual contouring, surface nets or whatever. Still a lot of the data structure and processing is almost identical. Read through it if you want to understand what it all takes to build a fast and reliable voxel engine, regardless of the meshing style used in the end.

    EDIT: to clarify, if you dont want an infinite world and you want to constrain it to a certain limit, you probably still want to keep using chunks so you don't have to regenerate the WHOLE MAP everytime a single voxel changed. It's all about performance, and for large maps this could really kill your framerate if not done properly.
     
  10. Thecheatgamer1

    Thecheatgamer1

    Joined:
    Jul 9, 2013
    Posts:
    30
    I said it here

    I am using a better one than that explains and it has perfect results and i can have a non loadable world but at a right size, iv chosen to go with the chunk loading but the world will still be limited and it will only change values in chunk save files if needed
     
  11. NeverConvex

    NeverConvex

    Joined:
    Jun 26, 2013
    Posts:
    88
    I think it would probably be more appropriate for you to give credit to Scrawk (and P. Bourke) than to me. I'm just pointing you towards their work, really; appreciate the offer, though.