public Vector2[] CreateUV(PreMesh pmesh)
    {
        Vector2[] UV          = new Vector2[pmesh.Verticies.Length];
        float     scaleFactor = .4f;

        for (int index = 0; index < pmesh.Triangles.Length; index += 3)
        {
            // Get the three vertices bounding this triangle.
            Vector3 v1 = pmesh.Verticies[pmesh.Triangles[index]];
            Vector3 v2 = pmesh.Verticies[pmesh.Triangles[index + 1]];
            Vector3 v3 = pmesh.Verticies[pmesh.Triangles[index + 2]];

            // Compute a vector perpendicular to the face.
            Vector3 normal = Vector3.Cross(v3 - v1, v2 - v1);

            // Form a rotation that points the z+ axis in this perpendicular direction.
            // Multiplying by the inverse will flatten the triangle into an xy plane.
            Quaternion rotation = Quaternion.Inverse(Quaternion.LookRotation(normal));

            // Assign the uvs, applying a scale factor to control the texture tiling.
            UV[pmesh.Triangles[index]]     = (Vector2)(rotation * v1) * scaleFactor;
            UV[pmesh.Triangles[index + 1]] = (Vector2)(rotation * v2) * scaleFactor;
            UV[pmesh.Triangles[index + 2]] = (Vector2)(rotation * v3) * scaleFactor;
        }
        return(UV);
    }
    public PreLoadedChunk(Vec2i cPos, PreMesh terrain, ChunkData cDat)
    {
        Position = cPos;

        TerrainMesh = terrain;
        VoxelMesh   = new Dictionary <Voxel, PreMesh>();
        ChunkData   = cDat;
    }
Beispiel #3
0
    void GenerateSurface()
    {
        List <PreMesh> preMeshes = new List <PreMesh>();

        for (int x = 0; x < Width; x++)
        {
            for (int y = 0; y < Height; y++)
            {
                preMeshes.Add(CreateTopPanel(x, y, Global.GetTexture(this[x, y].Material)));
            }
        }
        Mesh.mesh = PreMesh.ToMesh(preMeshes);
    }
    public static Mesh CreateMesh(PreMesh pmesh)
    {
        Mesh mesh = new Mesh();

        mesh.vertices  = pmesh.Verticies;
        mesh.triangles = pmesh.Triangles;
        if (pmesh.Colours != null)
        {
            mesh.colors = pmesh.Colours;
        }
        if (pmesh.UV != null)
        {
            mesh.uv = pmesh.UV;
        }
        if (pmesh.Normals != null)
        {
            mesh.normals = pmesh.Normals;
        }



        return(mesh);
    }
Beispiel #5
0
    private PreMesh GenerateSmoothTerrain(ChunkData chunk, int LOD = 1)
    {
        int size = World.ChunkSize / LOD;

        Color[,] colourMap = new Color[size + 1, size + 1];
        ClearBuffers();
        ChunkData[] neighbors = GetNeighbors(new Vec2i(chunk.X, chunk.Z));

        for (int x = 0; x <= size; x++)
        {
            for (int z = 0; z <= size; z++)
            {
                float height = 0;



                if (x == size && z == size)
                {
                    if (neighbors != null && neighbors[1] != null)
                    {
                        height = neighbors[1].BaseHeight;
                        if (neighbors[1].Heights != null)
                        {
                            height = neighbors[1].Heights[0, 0];
                        }
                        colourMap[x, z] = neighbors[1].GetTile(0, 0).GetColor();
                    }

                    else
                    {
                        //height = chunk.Heights != null ? chunk.Heights[x - 1, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile((x - 1) * LOD, (z - 1) * LOD).GetColor();
                    }
                }
                else if (x == size)
                {
                    if (neighbors != null && neighbors[2] != null)
                    {
                        height = neighbors[2].BaseHeight;
                        if (neighbors[2].Heights != null)
                        {
                            height = neighbors[2].Heights[0, z *LOD];
                        }

                        colourMap[x, z] = neighbors[2].GetTile(0, z * LOD).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[(x - 1) * LOD, z *LOD] : height;
                        colourMap[x, z] = chunk.GetTile((x - 1) * LOD, z * LOD).GetColor();
                    }
                }
                else if (z == size)
                {
                    if (neighbors != null && neighbors[0] != null)
                    {
                        height = neighbors[0].BaseHeight;
                        if (neighbors[0].Heights != null)
                        {
                            height = neighbors[0].Heights[x * LOD, 0];
                        }

                        colourMap[x, z] = neighbors[0].GetTile(x * LOD, 0).GetColor();
                    }
                    else
                    {
                        // height = chunk.Heights != null ? chunk.Heights[x, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x * LOD, (z - 1) * LOD).GetColor();
                    }
                }
                else
                {
                    if (chunk.Heights != null)
                    {
                        height = chunk.Heights[x * LOD, z *LOD];
                    }
                    colourMap[x, z] = chunk.GetTile(x * LOD, z * LOD).GetColor();
                }
                CurrentColours.Add(colourMap[x, z]);
                CurrentVerticies.Add(new Vector3(x * LOD, height, z * LOD));

                /*
                 * for (int y = 0; y < height + 1; y++)
                 * {
                 *  int idx = x + y * (World.ChunkSize + 1) + z * (World.ChunkHeight + 1) * (World.ChunkSize + 1);
                 *
                 *  //cube[idx] = -2;
                 * }*/
            }
        }


        int vert = 0;
        int tris = 0;

        for (int z = 0; z < size; z++)
        {
            for (int x = 0; x < size; x++)
            {
                CurrentTriangles.Add(vert + 1);
                CurrentTriangles.Add(vert + size + 1);
                CurrentTriangles.Add(vert + 0);


                CurrentTriangles.Add(vert + size + 2);
                CurrentTriangles.Add(vert + size + 1);
                CurrentTriangles.Add(vert + 1);


                vert++;
                tris += 6;
            }
            vert++;
        }

        //We iterate each triangle

        /* for (int i = 0; i < CurrentTriangles.Count; i += 3)
         * {
         *   int tri1 = CurrentTriangles[i];
         *   int tri2 = CurrentTriangles[i + 1];
         *   int tri3 = CurrentTriangles[i + 2];
         *   /*Vector3 vec1 = CurrentVerticies[i];
         *   Vector3 vec2 = CurrentVerticies[i+1];
         *   Vector3 vec3 = CurrentVerticies[i+2];
         *
         *   //We find the average/mid point of this triangle
         *    Vector3 mid = (CurrentVerticies[tri1] + CurrentVerticies[tri2] + CurrentVerticies[tri3]) / 3;
         *   //Vector3 mid = (vec1 + vec2 + vec3) / 3;
         *   Vec2i tMid = Vec2i.FromVector3(mid);
         *   Color c = colourMap[tMid.x, tMid.z];
         *
         *   CurrentColours.Add(c);
         *   CurrentColours.Add(c);
         *   CurrentColours.Add(c);
         * }
         * Debug.Log("Colours: " + CurrentColours.Count + " vert: " + CurrentVerticies.Count);*/

        PreMesh pmesh = new PreMesh();

        pmesh.Verticies = CurrentVerticies.ToArray();
        pmesh.Triangles = CurrentTriangles.ToArray();
        pmesh.Colours   = CurrentColours.ToArray();
        return(pmesh);
    }
Beispiel #6
0
    /// <summary>
    /// Creates a pre loaded chunk from chunk data.
    /// This entire function is run in a thread
    /// </summary>
    /// <param name="cData"></param>
    /// <returns></returns>
    private PreLoadedChunk GeneratePreLoadedChunk(ChunkData chunk, int lod = 1)
    {
        //We create a thread safe mesh for the terrain
        // PreMesh terrainMesh = GenerateMarchingCubesTerrain(chunk);

        PreMesh terrainMesh = GenerateSmoothTerrain(chunk);

        Debug.Log("[ChunkLoader] Terrain mesh for " + chunk + " created - " + CurrentVerticies.Count + " verticies", Debug.CHUNK_LOADING);
        //Create the base pre-loaded chunk
        PreLoadedChunk preChunk = new PreLoadedChunk(new Vec2i(chunk.X, chunk.Z), terrainMesh, chunk);

        //if we have no voxel data, return just the terrain map
        if (chunk.VoxelData == null)
        {
            return(preChunk);
        }



        foreach (Voxel v in MiscUtils.GetValues <Voxel>())
        {
            if (v == Voxel.none)
            {
                continue;
            }
            //If the chunk has this type of voxel in it
            if (chunk.VoxelData.VoxelTypeBounds.TryGetValue(v, out VoxelBounds vb))
            {
                //Clear all lists to prepair
                CurrentVerticies.Clear();
                CurrentTriangles.Clear();
                CurrentColours.Clear();
                CurrentUVs.Clear();
                //Generate the voxel mesh
                //MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize+1, World.ChunkHeight+1, World.ChunkSize+1, CurrentVerticies, CurrentTriangles);
                //MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);



                MarchingCubes.Generate(chunk.VoxelData.AllVoxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);
                PreMesh voxelMesh = new PreMesh();
                voxelMesh.Verticies = CurrentVerticies.ToArray();
                voxelMesh.Triangles = CurrentTriangles.ToArray();
                voxelMesh.UV        = CreateUV(voxelMesh);
                //Add it the the pre loaded chunk
                preChunk.VoxelMesh.Add(v, voxelMesh);
            }
        }
        if (chunk.WorldObjects != null)
        {
            /*lock (ObjectsToLoadLock)
             * {
             *  Debug.Log("[ChunkLoader] Chunk " + chunk.X + "," + chunk.Z + " has " + chunk.WorldObjects.Count + " objects to load", Debug.CHUNK_LOADING);
             *
             *  ObjectsToLoad.AddRange(chunk.WorldObjects);
             * }*/
        }



        return(preChunk);
    }
Beispiel #7
0
 public Vector2[] CreateUV(PreMesh pmesh)
 {
     return(CreateUV(pmesh, Vector2.zero, 0.5f));
 }
    private PreLoadedChunk GeneratePreLoadedChunk(ChunkData chunk)
    {
        //Null till we integrate fully
        //ChunkData2[] neighbors = null;

        ChunkData[] neighbors = GetNeighbors(new Vec2i(chunk.X, chunk.Z));


        float[] cube = new float[(World.ChunkSize + 1) * (World.ChunkSize + 1) * (World.ChunkHeight + 1)];
        Color[,] colourMap = new Color[World.ChunkSize + 1, World.ChunkSize + 1];

        //We iterate through the whole chunk, and create a cub map and colour map based on the
        //height map and tile map
        for (int x = 0; x < World.ChunkSize + 1; x++)
        {
            for (int z = 0; z < World.ChunkSize + 1; z++)
            {
                float height = chunk.BaseHeight;
                if (x == World.ChunkSize && z == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[1] != null)
                    {
                        height = neighbors[1].BaseHeight;
                        if (neighbors[1].Heights != null)
                        {
                            height = neighbors[1].Heights[0, 0];
                        }
                        colourMap[x, z] = neighbors[1].GetTile(0, 0).GetColor();
                    }

                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x - 1, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x - 1, z - 1).GetColor();
                    }
                }
                else if (x == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[2] != null)
                    {
                        height = neighbors[2].BaseHeight;
                        if (neighbors[2].Heights != null)
                        {
                            height = neighbors[2].Heights[0, z];
                        }

                        colourMap[x, z] = neighbors[2].GetTile(0, z).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x - 1, z] : height;
                        colourMap[x, z] = chunk.GetTile(x - 1, z).GetColor();
                    }
                }
                else if (z == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[0] != null)
                    {
                        height = neighbors[0].BaseHeight;
                        if (neighbors[0].Heights != null)
                        {
                            height = neighbors[0].Heights[x, 0];
                        }

                        colourMap[x, z] = neighbors[0].GetTile(x, 0).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x, z - 1).GetColor();
                    }
                }
                else
                {
                    if (chunk.Heights != null)
                    {
                        height = chunk.Heights[x, z];
                    }
                    colourMap[x, z] = chunk.GetTile(x, z).GetColor();
                }
                for (int y = 0; y < height + 1; y++)
                {
                    int idx = x + y * (World.ChunkSize + 1) + z * (World.ChunkHeight + 1) * (World.ChunkSize + 1);

                    cube[idx] = -2;
                }
            }
        }

        CurrentVerticies.Clear();
        CurrentTriangles.Clear();
        CurrentColours.Clear();
        //March the terrain map
        MarchingCubes.Generate(cube, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);

        /*for (int i = 0; i < CurrentTriangles.Count; i += 3)
         * {
         *  int tri1 = CurrentTriangles[i];
         *  int tri2 = CurrentTriangles[i + 1];
         *  int tri3 = CurrentTriangles[i + 2];
         *
         *  //We find the average/mid point of this triangle
         *  Vector3 mid = (CurrentVerticies[tri1] + CurrentVerticies[tri2] + CurrentVerticies[tri3]) / 3;
         *  Vec2i tMid = Vec2i.FromVector3(mid);
         *  Color c = colourMap[tMid.x, tMid.z];
         *
         *  CurrentColours.Add(c);
         *  CurrentColours.Add(c);
         *  CurrentColours.Add(c);
         * }*/

        for (int i = 0; i < CurrentVerticies.Count; i++)
        {
            int x = (int)CurrentVerticies[i].x;
            int z = (int)CurrentVerticies[i].z;
            CurrentColours.Add(colourMap[x, z]);
        }

        //We create a thread safe mesh for the terrain
        PreMesh terrainMesh = new PreMesh();

        terrainMesh.Verticies = CurrentVerticies.ToArray();
        terrainMesh.Triangles = CurrentTriangles.ToArray();
        terrainMesh.Colours   = CurrentColours.ToArray();
        terrainMesh.UV        = CreateUV(terrainMesh);
        //Debug.Log("[ChunkLoader] Terrain mesh for " + chunk + " created - " + CurrentVerticies.Count + " verticies");
        //Create the base pre-loaded chunk
        PreLoadedChunk preChunk = new PreLoadedChunk(new Vec2i(chunk.X, chunk.Z), terrainMesh, chunk);

        Debug.Log("Pre loaded chunk started, now for voxels");

        //if we have no voxel data, return just the terrain map
        if (chunk.VoxelData == null)
        {
            Debug.Log("Chunk has no voxels");
            return(preChunk);
        }



        foreach (Voxel v in MiscUtils.GetValues <Voxel>())
        {
            if (v == Voxel.none)
            {
                continue;
            }

            if (!chunk.VoxelData.HasVoxel(v))
            {
                // Debug.Log("Chunk " + chunk + " does not have the voxel " + v);
                continue;
            }

            CurrentVerticies.Clear();
            CurrentTriangles.Clear();
            CurrentColours.Clear();
            CurrentUVs.Clear();
            // Debug.Log("starting march");

            //Generate the voxel mesh
            MarchingCubes.Generate(chunk.VoxelData.Voxels, null, v, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);
            PreMesh voxelMesh = new PreMesh();
            voxelMesh.Verticies = CurrentVerticies.ToArray();
            voxelMesh.Triangles = CurrentTriangles.ToArray();
            voxelMesh.UV        = CreateUV(voxelMesh);
            //Add it the the pre loaded chunk
            preChunk.VoxelMesh.Add(v, voxelMesh);

            /*
             * //If the chunk has this type of voxel in it
             * if (chunk.VoxelData.VoxelTypeBounds.TryGetValue(v, out VoxelBounds vb))
             * {
             *  //Clear all lists to prepair
             *  CurrentVerticies.Clear();
             *  CurrentTriangles.Clear();
             *  CurrentColours.Clear();
             *  CurrentUVs.Clear();
             *  Debug.Log("starting march");
             *
             *  //Generate the voxel mesh
             *  MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize+1, World.ChunkHeight+1, World.ChunkSize+1, CurrentVerticies, CurrentTriangles);
             *  PreMesh voxelMesh = new PreMesh();
             *  voxelMesh.Verticies = CurrentVerticies.ToArray();
             *  voxelMesh.Triangles = CurrentTriangles.ToArray();
             *  voxelMesh.UV = CreateUV(voxelMesh);
             *  //Add it the the pre loaded chunk
             *  preChunk.VoxelMesh.Add(v, voxelMesh);
             * }*/
        }



        return(preChunk);
    }
Beispiel #9
0
    /// <summary>
    /// Creates a pre loaded chunk from chunk data.
    /// This entire function is run in a thread
    /// </summary>
    /// <param name="cData"></param>
    /// <returns></returns>
    private PreLoadedChunk GeneratePreLoadedChunk(ChunkData chunk, int lod = 1)
    {
        //We create a thread safe mesh for the terrain
        // PreMesh terrainMesh = GenerateMarchingCubesTerrain(chunk);
        ChunkData[] neighbors = ChunkRegionManager.GetNeighbors(new Vec2i(chunk.X, chunk.Z));

        PreMesh terrainMesh = GenerateSmoothTerrain(chunk, neighbors, lod);

        terrainMesh.RecalculateNormals();
        Debug.Log("[ChunkLoader] Terrain mesh for " + chunk + " created - " + CurrentVerticies.Count + " verticies", Debug.CHUNK_LOADING);
        //Create the base pre-loaded chunk
        PreLoadedChunk preChunk = new PreLoadedChunk(new Vec2i(chunk.X, chunk.Z), terrainMesh, chunk);

        //if we have no voxel data, return just the terrain map
        if (chunk.VoxelData == null)
        {
            return(preChunk);
        }


        int maxHeight = 0;

        if (neighbors != null)
        {
            foreach (ChunkData cd in neighbors)
            {
                if (cd != null && cd.VoxelData != null)
                {
                    if (maxHeight < cd.VoxelData.TotalHeight())
                    {
                        maxHeight = cd.VoxelData.TotalHeight();
                    }
                }
            }
        }



        //If the chunk hasn't had its boundry points defined, we do it now
        if (!chunk.VoxelData.HasBoundryVoxels)
        {
            for (int y = 0; y < maxHeight; y++)
            {
                for (int i = 0; i < World.ChunkSize; i++)
                {
                    if (neighbors[0] != null && neighbors[0].VoxelData != null)
                    {
                        VoxelNode node = neighbors[0].VoxelData.GetVoxelNode(i, y, 0);
                        if (node.IsNode)
                        {
                            chunk.VoxelData.SetVoxelNode(i, y, World.ChunkSize, node);
                        }
                    }
                    if (neighbors[2] != null && neighbors[2].VoxelData != null)
                    {
                        VoxelNode node = neighbors[2].VoxelData.GetVoxelNode(0, y, i);
                        if (node.IsNode)
                        {
                            chunk.VoxelData.SetVoxelNode(World.ChunkSize, y, i, node);
                        }
                    }
                }
                if (neighbors[1] != null && neighbors[1].VoxelData != null)
                {
                    VoxelNode node = neighbors[1].VoxelData.GetVoxelNode(0, y, 0);
                    if (node.IsNode)
                    {
                        chunk.VoxelData.SetVoxelNode(World.ChunkSize, y, World.ChunkSize, node);
                    }
                }
            }
            chunk.VoxelData.HasBoundryVoxels = true;
        }

        //Next we generate all relevent voxel meshes
        foreach (Voxel v in MiscUtils.GetValues <Voxel>())
        {
            if (v == Voxel.none)
            {
                continue;
            }
            //If the chunk has this type of voxel in it
            if (chunk.VoxelData.VoxelTypeBounds.TryGetValue(v, out VoxelBounds vb))
            {
                //Clear all lists to prepair
                CurrentVerticies.Clear();
                CurrentTriangles.Clear();
                CurrentColours.Clear();
                CurrentUVs.Clear();
                //Generate the voxel mesh
                //MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize+1, World.ChunkHeight+1, World.ChunkSize+1, CurrentVerticies, CurrentTriangles);
                //MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);
                //MarchingCubes.Generate(chunk.VoxelData.AllVoxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);

                MarchingCubes.Generate(chunk.VoxelData.AllVoxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);


                PreMesh voxelMesh = new PreMesh();
                voxelMesh.Verticies = CurrentVerticies.ToArray();
                voxelMesh.Triangles = CurrentTriangles.ToArray();
                voxelMesh.UV        = CreateUV(voxelMesh);
                voxelMesh.RecalculateNormals();
                //Add it the the pre loaded chunk
                preChunk.VoxelMesh.Add(v, voxelMesh);
            }
        }

        /*
         * if(chunk.WorldObjects != null)
         * {
         *
         *  lock (ObjectsToLoadLock)
         *  {
         *      Debug.Log("[ChunkLoader] Chunk " + chunk.X + "," + chunk.Z + " has " + chunk.WorldObjects.Count + " objects to load", Debug.CHUNK_LOADING);
         *      ObjectsToLoad.AddRange(chunk.WorldObjects);
         *  }
         *
         * }*/



        return(preChunk);
    }
Beispiel #10
0
    private PreMesh GenerateMarchingCubesTerrain(ChunkData chunk)
    {
        ChunkData[] neighbors = ChunkRegionManager.GetNeighbors(new Vec2i(chunk.X, chunk.Z));


        float[] cube = new float[(World.ChunkSize + 1) * (World.ChunkSize + 1) * (World.ChunkHeight + 1)];
        Color[,] colourMap = new Color[World.ChunkSize + 1, World.ChunkSize + 1];

        //We iterate through the whole chunk, and create a cub map and colour map based on the
        //height map and tile map
        for (int x = 0; x < World.ChunkSize + 1; x++)
        {
            for (int z = 0; z < World.ChunkSize + 1; z++)
            {
                float height = chunk.BaseHeight;
                if (x == World.ChunkSize && z == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[1] != null)
                    {
                        height = neighbors[1].BaseHeight;
                        if (neighbors[1].Heights != null)
                        {
                            height = neighbors[1].Heights[0, 0];
                        }
                        colourMap[x, z] = neighbors[1].GetTile(0, 0).GetColor();
                    }

                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x - 1, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x - 1, z - 1).GetColor();
                    }
                }
                else if (x == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[2] != null)
                    {
                        height = neighbors[2].BaseHeight;
                        if (neighbors[2].Heights != null)
                        {
                            height = neighbors[2].Heights[0, z];
                        }

                        colourMap[x, z] = neighbors[2].GetTile(0, z).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x - 1, z] : height;
                        colourMap[x, z] = chunk.GetTile(x - 1, z).GetColor();
                    }
                }
                else if (z == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[0] != null)
                    {
                        height = neighbors[0].BaseHeight;
                        if (neighbors[0].Heights != null)
                        {
                            height = neighbors[0].Heights[x, 0];
                        }

                        colourMap[x, z] = neighbors[0].GetTile(x, 0).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x, z - 1).GetColor();
                    }
                }
                else
                {
                    if (chunk.Heights != null)
                    {
                        height = chunk.Heights[x, z];
                    }
                    colourMap[x, z] = chunk.GetTile(x, z).GetColor();
                }
                for (int y = 0; y < height + 1; y++)
                {
                    int idx = x + y * (World.ChunkSize + 1) + z * (World.ChunkHeight + 1) * (World.ChunkSize + 1);

                    cube[idx] = -2;
                }
            }
        }

        CurrentVerticies.Clear();
        CurrentTriangles.Clear();
        CurrentColours.Clear();
        //March the terrain map
        MarchingCubes.Generate(cube, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);

        //We iterate each triangle
        for (int i = 0; i < CurrentTriangles.Count; i += 3)
        {
            int tri1 = CurrentTriangles[i];
            int tri2 = CurrentTriangles[i + 1];
            int tri3 = CurrentTriangles[i + 2];

            //We find the average/mid point of this triangle
            Vector3 mid  = (CurrentVerticies[tri1] + CurrentVerticies[tri2] + CurrentVerticies[tri3]) / 3;
            Vec2i   tMid = Vec2i.FromVector3(mid);
            Color   c    = colourMap[tMid.x, tMid.z];

            CurrentColours.Add(c);
            CurrentColours.Add(c);
            CurrentColours.Add(c);
        }

        /*
         * for (int i = 0; i < CurrentVerticies.Count; i++)
         * {
         *  int x = (int)CurrentVerticies[i].x;
         *  int z = (int)CurrentVerticies[i].z;
         *  CurrentColours.Add(colourMap[x, z]);
         *
         * }*/

        //We create a thread safe mesh for the terrain
        PreMesh terrainMesh = new PreMesh();

        terrainMesh.Verticies = CurrentVerticies.ToArray();
        terrainMesh.Triangles = CurrentTriangles.ToArray();
        terrainMesh.Colours   = CurrentColours.ToArray();

        return(terrainMesh);
    }