Пример #1
0
    public void RequestMapData(System.Action <ChunkColumn.MapDataInfo> callback, ColumnCoord colCoord)
    {
        ThreadMapObject threadTask = new ThreadMapObject(callback, colCoord);

        ThreadPool.QueueUserWorkItem(new WaitCallback(MapDataThread), threadTask);
        amountOfWorkerThreads++;
    }
Пример #2
0
 private void OrderList(ColumnCoord playerCoord)
 {
     columnsToBuild.Sort(delegate(ColumnCoord colCoord, ColumnCoord colCoord2)
     {
         return(colCoord.GetSqrDistance(playerCoord).CompareTo(colCoord2.GetSqrDistance(playerCoord)));
     });
 }
Пример #3
0
    public static void SetBlock(int x, int y, int z, byte blockID)
    {
        ColumnCoord colCoord = GetColumnCoord(x, z);

        try
        {
            ChunkColumn chunkCol = null;
            if (columns.TryGetValue(colCoord, out chunkCol))
            {
                if (chunkCol.hasMapData)
                {
                    chunkCol.SetBlock(x - colCoord.x * ChunkColumn.chunkSize, y, z - colCoord.z * ChunkColumn.chunkSize, blockID);
                }
                else
                {
                    Debug.LogError("Block set on chunk without data");
                }
            }
            else
            {
                Debug.LogError("Block set on non existing chunk");
            }
        }
        catch (Exception e)
        {
            Debug.Log("Set Block chunk error " + e);
        }
    }
Пример #4
0
 /// <summary>
 /// Translate the noisevalue into a blockId at a position
 /// </summary>
 /// <param name="x">Local x position</param>
 /// <param name="y">Local y position</param>
 /// <param name="z">Local z position</param>
 /// <param name="noiseVal">Sampled value</param>
 /// <param name="colCoord">Column coordinate</param>
 /// <returns>The blockId</returns>
 private byte GetBlockIdFromNoise(int x, int y, int z, float noiseVal, ColumnCoord colCoord)
 {
     // Treshold needed
     if (noiseVal > SOLID_TRESHOLD)
     {
         // Spawn block
         if (y < waterHeight + 5)
         {
             if (y < waterHeight + 1 || y < waterHeight + 3 + (Mathf.PerlinNoise((x + colCoord.x * ChunkColumn.chunkSize) / 13f, (z + colCoord.z * ChunkColumn.chunkSize) / 17f) * 2 - 1) * 2)
             {
                 // Sand
                 return(6);
             }
         }
         // Stone
         return(2);
     }
     else if (y < waterHeight)
     {
         // Water
         return(1);
     }
     else
     {
         // Air
         return(0);
     }
 }
Пример #5
0
    public static ChunkColumn GetColumn(ColumnCoord colCoord)
    {
        if (columns.ContainsKey(colCoord))
        {
            // Chunk exists
            return(columns[colCoord]);
        }

        return(null);
    }
Пример #6
0
    public static bool ColumnHasMapdata(ColumnCoord colCoord)
    {
        ChunkColumn chunkCol = GetColumn(colCoord);

        if (chunkCol != null)
        {
            return(chunkCol.hasMapData);
        }

        return(false);
    }
Пример #7
0
    public void BuildNextColumn()
    {
        ColumnCoord currentViewedColumnCoord = columnsToBuild[0];

        columnsToBuild.RemoveAt(0);
        GameObject newColumn = Instantiate(columnPrefab, new Vector3(currentViewedColumnCoord.x * ChunkColumn.chunkSize * ChunkColumn.blockSize, 0, currentViewedColumnCoord.z * ChunkColumn.chunkSize * ChunkColumn.blockSize), Quaternion.identity);

        newColumn.transform.parent = transform;
        newColumn.name             = "aChunkColumn " + currentViewedColumnCoord.x + " " + currentViewedColumnCoord.z;
        ChunkColumn chunkColScript = newColumn.GetComponent <ChunkColumn>();

        columns.Add(currentViewedColumnCoord, chunkColScript);
        chunkColScript.Init(currentViewedColumnCoord);
        chunkColScript.StartGenerating();
    }
Пример #8
0
    private void UpdateVisibleChunks()
    {
        int         currentChunkCoordX = Mathf.RoundToInt(viewer.transform.position.x / (ChunkColumn.chunkSize * ChunkColumn.blockSize));
        int         currentChunkCoordZ = Mathf.RoundToInt(viewer.transform.position.z / (ChunkColumn.chunkSize * ChunkColumn.blockSize));
        ColumnCoord playerCoord        = new ColumnCoord(currentChunkCoordX, currentChunkCoordZ);

        for (int i = chunksVisibleLastUpdate.Count - 1; i >= 0; i--)
        {
            if (chunksVisibleLastUpdate[i].colCoord.GetSqrDistance(playerCoord) > sqrViewTreshold)
            {
                // Chunk is out of view distance
                chunksVisibleLastUpdate[i].SetInVisible();
            }
        }
        //chunksVisibleLastUpdate.Clear();

        columnsToBuild.Clear();

        for (int zOffset = -viewDistance; zOffset <= viewDistance; zOffset++)
        {
            for (int xOffset = -viewDistance; xOffset <= viewDistance; xOffset++)
            {
                ColumnCoord currentViewedColumnCoord = new ColumnCoord(currentChunkCoordX + xOffset, currentChunkCoordZ + zOffset);

                if (currentViewedColumnCoord.GetSqrDistance(playerCoord) < sqrViewTreshold)
                {
                    ChunkColumn currentColumn;
                    if (columns.TryGetValue(currentViewedColumnCoord, out currentColumn))
                    {
                        currentColumn.SetVisible();
                    }
                    else
                    {
                        GenerateColumn(currentViewedColumnCoord);
                    }
                }
            }
        }

        OrderList(playerCoord);
    }
Пример #9
0
    public static byte GetBlock(int x, int y, int z)
    {
        ColumnCoord colCoord = GetColumnCoord(x, z);

        try
        {
            ChunkColumn chunkCol = null;
            if (columns.TryGetValue(colCoord, out chunkCol))
            {
                if (chunkCol.hasMapData)
                {
                    return(chunkCol.GetBlock(x - colCoord.x * ChunkColumn.chunkSize, y, z - colCoord.z * ChunkColumn.chunkSize));
                }
            }
        }
        catch (Exception e)
        {
            Debug.Log("Chunk error!! " + e);
        }

        return(0);
    }
Пример #10
0
    /// <summary>
    /// Samples all points in a chunk column using perlin noise
    /// </summary>
    /// <param name="colCoord">The coordinate of the chunk</param>
    /// <returns>The filled noisemap</returns>
    private float[,,] SamplePoints(ColumnCoord colCoord)
    {
        int   size = ChunkColumn.chunkSize;
        int   amountOfVerticalChunks = ChunkColumn.worldHeight;
        float halfSize = size * 0.5f;

        float[,,] sampleNoiseMap = new float[size / horizontalNoiseScale + 1, size *amountOfVerticalChunks / verticalNoiseScale + 1, size / horizontalNoiseScale + 1];

        float sampleX, sampleY, sampleZ, adjustmentVal;

        // Sampling points
        for (int x = 0; x < sampleNoiseMap.GetLength(0); x++)
        {
            for (int y = 0; y < sampleNoiseMap.GetLength(1); y++)
            {
                for (int z = 0; z < sampleNoiseMap.GetLength(2); z++)
                {
                    Vector3 chunkOffset = new Vector3(colCoord.x, 0, colCoord.z) * size;

                    sampleX = ((float)x * horizontalNoiseScale - halfSize + chunkOffset.x) * ChunkColumn.blockSize / zoomScale;
                    sampleY = ((float)y * verticalNoiseScale + chunkOffset.y) * ChunkColumn.blockSize / zoomScale;
                    sampleZ = ((float)z * horizontalNoiseScale - halfSize + chunkOffset.z) * ChunkColumn.blockSize / zoomScale;

                    sampleNoiseMap[x, y, z] = CustomPerlinNoise.PerlinNoise(sampleX, sampleY, sampleZ);

                    adjustmentVal = (1 - Mathf.InverseLerp(solidHeight, airHeight, y * verticalNoiseScale) * (1 - Mathf.PerlinNoise(sampleX, sampleZ) * 0.2f)) * 2 - 1;

                    adjustmentVal *= adjustScalar;

                    sampleNoiseMap[x, y, z] += adjustmentVal;
                }
            }
        }

        return(sampleNoiseMap);
    }
Пример #11
0
 public void Init(ColumnCoord colCoord)
 {
     this.colCoord = colCoord;
 }
Пример #12
0
    /// <summary>
    /// Interpolate points within a sampling block and translate them to blockId's to fill the array with
    /// </summary>
    /// <param name="sampleNoiseMap">Noise map to interpolate from</param>
    /// <param name="blockMap">BlockId array to fill</param>
    /// <param name="x">Local x coordinate</param>
    /// <param name="y">Local y coordinate</param>
    /// <param name="z">Local z coordinate</param>
    /// <param name="colCoord">Column coordinate</param>
    private void InterpolatePoints(ref float[,,] sampleNoiseMap, ref byte[,,] blockMap, int x, int y, int z, ColumnCoord colCoord)
    {
        float xStep1, xStep2, xStep3, xStep4, xLerped1, xLerped2, xLerped3, xLerped4, yPercentage, zPercentage, interpolatedY1, interpolatedY2;
        int   blockX, blockY, blockZ;

        // Accurate interpolation
        xStep1 = (sampleNoiseMap[x + 1, y, z] - sampleNoiseMap[x, y, z]) / horizontalNoiseScale;
        xStep2 = (sampleNoiseMap[x + 1, y + 1, z] - sampleNoiseMap[x, y + 1, z]) / horizontalNoiseScale;
        xStep3 = (sampleNoiseMap[x + 1, y, z + 1] - sampleNoiseMap[x, y, z + 1]) / horizontalNoiseScale;
        xStep4 = (sampleNoiseMap[x + 1, y + 1, z + 1] - sampleNoiseMap[x, y + 1, z + 1]) / horizontalNoiseScale;

        for (int k = 0; k < horizontalNoiseScale; k++)
        {
            xLerped1 = sampleNoiseMap[x, y, z] + xStep1 * k;
            xLerped2 = sampleNoiseMap[x, y + 1, z] + xStep2 * k;
            xLerped3 = sampleNoiseMap[x, y, z + 1] + xStep3 * k;
            xLerped4 = sampleNoiseMap[x, y + 1, z + 1] + xStep4 * k;

            for (int j = 0; j < verticalNoiseScale; j++)
            {
                yPercentage = (float)j / verticalNoiseScale;

                interpolatedY1 = Mathf.Lerp(xLerped1, xLerped2, yPercentage);
                interpolatedY2 = Mathf.Lerp(xLerped3, xLerped4, yPercentage);

                for (int i = 0; i < horizontalNoiseScale; i++)
                {
                    zPercentage = (float)i / horizontalNoiseScale;
                    blockX      = x * horizontalNoiseScale + k;
                    blockY      = y * verticalNoiseScale + j;
                    blockZ      = z * horizontalNoiseScale + i;

                    byte blockId = GetBlockIdFromNoise(blockX, blockY, blockZ, Mathf.Lerp(interpolatedY1, interpolatedY2, zPercentage), colCoord);
                    blockMap[blockX, blockY, blockZ] = blockId;

                    // Change top layer to grass
                    if (y == 0)
                    {
                        continue;
                    }

                    if (blockId == 0 && blockMap[blockX, blockY - 1, blockZ] == 2)
                    {
                        // Spawn grass
                        blockMap[blockX, blockY - 1, blockZ] = 3;
                    }
                }
            }
        }
    }
Пример #13
0
    /// <summary>
    /// Generate chunk map data based on perlin noise and interpolation
    /// </summary>
    /// <param name="colCoord">Column coordinate to sample</param>
    /// <returns>Chunk block data</returns>
    public ChunkColumn.MapDataInfo GenerateNoiseMap(ColumnCoord colCoord)
    {
        int size = ChunkColumn.chunkSize;
        int amountOfVerticalChunks = ChunkColumn.worldHeight;

        ChunkColumn.MapDataInfo mapData = new ChunkColumn.MapDataInfo();
        mapData.SetAllEmpty();
        byte[,,] chunkBlockData = new byte[size, size *amountOfVerticalChunks, size];

        // Sampling all points using perlin noise within chunk
        float[,,] sampleNoiseMap = SamplePoints(colCoord);

        // 0 = differences, 1 = all non-solid, 2 = all solid
        int allSolidIndex;

        for (int x = 0; x < sampleNoiseMap.GetLength(0) - 1; x++)
        {
            for (int y = 0; y < sampleNoiseMap.GetLength(1) - 1; y++)
            {
                for (int z = 0; z < sampleNoiseMap.GetLength(2) - 1; z++)
                {
                    allSolidIndex = GetAllSolidIndex(ref sampleNoiseMap, x, y, z);

                    if (allSolidIndex == 0)
                    {
                        InterpolatePoints(ref sampleNoiseMap, ref chunkBlockData, x, y, z, colCoord);
                        // Any interpolation means the is atleast 1 solid block
                        mapData.isEmpty[(y * verticalNoiseScale + verticalNoiseScale / 2) / ChunkColumn.chunkSize] = false;
                    }
                    else
                    {
                        float noiseVal;
                        int   blockX, blockY, blockZ;

                        if (allSolidIndex == 2)
                        {
                            mapData.isEmpty[(y * verticalNoiseScale + verticalNoiseScale / 2) / ChunkColumn.chunkSize] = false;
                        }

                        // All points the same, skip interpolation
                        for (int k = 0; k < horizontalNoiseScale; k++)
                        {
                            for (int j = 0; j < verticalNoiseScale; j++)
                            {
                                for (int i = 0; i < horizontalNoiseScale; i++)
                                {
                                    blockX = x * horizontalNoiseScale + k;
                                    blockY = y * verticalNoiseScale + j;
                                    blockZ = z * horizontalNoiseScale + i;

                                    noiseVal = allSolidIndex == 1 ? 0 : 1;

                                    byte blockId = GetBlockIdFromNoise(blockX, blockY, blockZ, noiseVal, colCoord);
                                    chunkBlockData[blockX, blockY, blockZ] = blockId;

                                    // Add grass to the top layer
                                    if (y == 0)
                                    {
                                        continue;
                                    }

                                    if (blockId == 0 && chunkBlockData[blockX, blockY - 1, blockZ] == 2)
                                    {
                                        // Spawn grass
                                        chunkBlockData[blockX, blockY - 1, blockZ] = 3;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        mapData.voxelData = chunkBlockData;
        return(mapData);
    }
Пример #14
0
 public float GetSqrDistance(ColumnCoord colCoord)
 {
     return((x - colCoord.x) * (x - colCoord.x) + (z - colCoord.z) * (z - colCoord.z));
 }
Пример #15
0
    public static ColumnCoord GetColumnCoord(int x, int z)
    {
        ColumnCoord colCoord = new ColumnCoord(Mathf.FloorToInt((float)x / ChunkColumn.chunkSize), Mathf.FloorToInt((float)z / ChunkColumn.chunkSize));

        return(colCoord);
    }
Пример #16
0
 public ThreadMapObject(System.Action <ChunkColumn.MapDataInfo> callback, ColumnCoord colCoord)
 {
     this.callback = callback;
     this.colCoord = colCoord;
 }
Пример #17
0
 public void GenerateColumn(ColumnCoord colCoord)
 {
     columnsToBuild.Add(colCoord);
 }