示例#1
0
    protected void ClampPosition()
    {
        Vector3 pos = transform.position;

        pos.x = LC_Math.Clamp(pos.x, MinPosition.x, MaxPosition.x);
        pos.y = LC_Math.Clamp(pos.y, MinPosition.y, MaxPosition.y);
        pos.z = LC_Math.Clamp(pos.z, MinPosition.z, MaxPosition.z);

        transform.position = pos;
    }
示例#2
0
    protected override void SplitAndMergeMesh(LC_Chunk <WorldCell> chunk)
    {
        List <LC_Math.QuadTreeSector> sectors = LC_Math.SplitAndMerge(
            (x, z) => { return(chunk.Cells[x, z].RealHeight); },
            (x, y) => { return(x == y); },
            ChunkSize, true);

        foreach (LC_Math.QuadTreeSector sector in sectors)
        {
            CreateElementMesh(sector.Initial, sector.Final, chunk);
        }
    }
示例#3
0
 /// <summary>
 /// Compute the heights map using LC_Math.PerlinNoiseMap.
 /// </summary>
 /// <param name="chunkPos">Position of the chunk</param>
 /// <returns></returns>
 protected virtual float[,] CreateChunkHeightsMap(Vector2Int chunkPos)
 {
     return(LC_Math.PerlinNoiseMap(
                new Vector2Int(ChunkSize + 3, ChunkSize + 3),        // +1 for top-right edges and +2 for normals computation
                Seed,
                Octaves, Persistance, Lacunarity,
                new Vector2(0, MaxHeight),
                HeightsDivisor,
                (chunkPos.x - 1) * ChunkSize,          // -1 for normals computation (get neighbour chunk edge heights)
                (chunkPos.y - 1) * ChunkSize,          // -1 for normals computation (get neighbour chunk edge heights)
                true));
 }
    /// <summary>
    /// <para>Generates a new terrain around the reference with square shape.</para>
    /// <para>If DynamicChunkLoading is enabled the square shape is substituted using the ChunkRenderDistance.</para>
    /// <para>If ParallelChunkLoading is enabled the chunks around the reference need to be build at Update method.</para>
    /// </summary>
    protected virtual void IniTerrain()
    {
        // Always load the current reference chunk
        LoadChunk(ReferenceChunkPos, true);

        // Load the other chunks
        foreach (Vector2Int chunkPos in LC_Math.AroundPositions(ReferenceChunkPos, ChunkRenderDistance))
        {
            LoadChunk(chunkPos);
        }

        IsGenerated = true;
    }
    public virtual Cell GetCell(Vector2Int terrainPos, bool isForMap = false)
    {
        Cell cell = null;

        Chunk chunk = GetChunk(terrainPos);

        // Check ChunksForMap
        if (chunk == null && isForMap)
        {
            Vector2Int chunkPos = TerrainPosToChunk(terrainPos);
            ChunksForMap.TryGetValue(chunkPos, out chunk);
        }

        // Get cell from the chunk if it exists
        if (chunk != null)
        {
            Vector2Int posInChunk = new Vector2Int(LC_Math.Mod(terrainPos.x, ChunkSize),
                                                   LC_Math.Mod(terrainPos.y, ChunkSize));

            cell = chunk.Cells[posInChunk.x, posInChunk.y];
        }

        return(cell);
    }
示例#6
0
    /// <summary>
    /// <para>Calculates a pseudo-random direction based on lastDirection and a random value.</para>
    /// <para>If the random value is greater than sameDirectionProbability it will compute a diferent direction.</para>
    /// <para>For that, it will test alternate directions trying to minimize the turn from the lastDirection.</para>
    /// <para>If no direction is possible, returns Vector2Int.zero.</para>
    /// </summary>
    /// <param name="origin">Original position.</param>
    /// <param name="lastDirection">Last direction. Must be a normalized vector.</param>
    /// <param name="randGenerator">Random generator for the direction.</param>
    /// <param name="sameDirectionProbability">Probability of conserve the lastDirection.</param>
    /// <param name="isPositionAccessible">>Method to check if a position is accessible.</param>
    /// <returns>The new direction or, if no one is possible, Vector2Int.zero.</returns>
    public static Vector2Int PseudorandomDirection(Vector2Int origin, Vector2Int lastDirection, System.Random randGenerator, float sameDirectionProbability, IsPositionAccessible isPositionAccessible)
    {
        Vector2Int nextDirection = Vector2Int.zero;

        lastDirection = lastDirection.TransformToDirection();

        float sameDirectionProb = Mathf.Clamp(sameDirectionProbability, 0, 100);
        bool  useSameDirection  = RandomDouble(randGenerator, 0, 100) <= sameDirectionProb;

        // If is possible continue in the same direction ( not 0,0 )
        if (useSameDirection && !lastDirection.Equals(Vector2Int.zero) && IsPossibleDirection(origin, lastDirection, isPositionAccessible))
        {
            nextDirection = lastDirection;
        }
        // Search a new random direction different of last
        else
        {
            int lastDirectionIdx = EightDirections2D.IndexOf(lastDirection);
            // If any previous direction is possible, assign one random
            if (lastDirectionIdx == -1)
            {
                lastDirectionIdx = randGenerator.Next(0, EightDirections2D.Count);
            }

            // Check the possible directions incrementing the offset relative to lastDirection
            int        idx;
            bool       turnRight;
            Vector2Int possibleDirection;
            for (int offset = 1; offset < EightDirections2D.Count / 2 && nextDirection == Vector2Int.zero; offset++)
            {
                turnRight = randGenerator.Next(0, 2) == 0;

                idx = LC_Math.Mod(lastDirectionIdx + (turnRight ? offset : -offset), EightDirections2D.Count);
                possibleDirection = EightDirections2D[idx];
                if (IsPossibleDirection(origin, possibleDirection, isPositionAccessible))
                {
                    nextDirection = possibleDirection;
                }
                else
                {
                    idx = LC_Math.Mod(lastDirectionIdx + (!turnRight ? offset : -offset), EightDirections2D.Count);
                    possibleDirection = EightDirections2D[idx];
                    if (IsPossibleDirection(origin, possibleDirection, isPositionAccessible))
                    {
                        nextDirection = possibleDirection;
                    }
                }
            }

            // If any other direction isn't possible, check the opposite of last direction
            if (nextDirection == Vector2Int.zero)
            {
                possibleDirection = lastDirection * -1;
                if (IsPossibleDirection(origin, possibleDirection, isPositionAccessible))
                {
                    nextDirection = possibleDirection;
                }
            }
        }

        return(nextDirection);
    }
示例#7
0
    /// <summary>
    /// <para>Compute the normals for each vertex of the mesh, checking the edges cells of other chunks.</para>
    /// <para>This process is needed to avoid illumination differences between contiguous cells of different chunks (seams).</para>
    /// </summary>
    /// <param name="chunk"></param>
    protected virtual void ComputeNormals(Chunk chunk)
    {
        chunk.Normals = new Vector3[(ChunkSize + 1) * (ChunkSize + 1)];
        int        i, triangleIdx, x, z;
        Vector2Int vertexTerrainPos;
        Vector3    a, b, c, normal;

        // Normal for each vertex
        for (i = 0; i < chunk.Vertices.Count; i++)
        {
            LC_Math.IndexToCoords(i, ChunkSize + 1, out x, out z);

            // If isn't edge
            if (x < ChunkSize && z < ChunkSize)
            {
                triangleIdx = LC_Math.CoordsToIndex(x, z, ChunkSize) * 6;
                CalculateTrianglesNormals(triangleIdx, chunk);
                CalculateTrianglesNormals(triangleIdx + 3, chunk);
            }
            // If is edge
            if (x == 0 || z == 0 || x >= ChunkSize || z >= ChunkSize)
            {
                vertexTerrainPos = chunk.ChunkPosToTerrain(new Vector2Int(x, z));
                a = chunk.Vertices[i];

                if (x == 0 || z == 0)
                {
                    b                 = TerrainPosToReal(vertexTerrainPos.x - 1, chunk.HeightsMap[x, z + 1], vertexTerrainPos.y);       // x - 1, z
                    c                 = TerrainPosToReal(vertexTerrainPos.x - 1, chunk.HeightsMap[x, z], vertexTerrainPos.y - 1);       // x - 1, z - 1
                    normal            = -Vector3.Cross(b - a, c - a);
                    chunk.Normals[i] += normal;
                    if (x != 0)
                    {
                        chunk.Normals[i - (ChunkSize + 1)] += normal;
                    }

                    b                 = c;                                                                                        // x - 1, z - 1
                    c                 = TerrainPosToReal(vertexTerrainPos.x, chunk.HeightsMap[x + 1, z], vertexTerrainPos.y - 1); // x, z - 1
                    normal            = -Vector3.Cross(b - a, c - a);
                    chunk.Normals[i] += normal;
                    if (z != 0)
                    {
                        chunk.Normals[i - 1] += normal;
                    }
                }
                if (x == ChunkSize || z == ChunkSize)
                {
                    b                 = TerrainPosToReal(vertexTerrainPos.x + 1, chunk.HeightsMap[x + 2, z + 1], vertexTerrainPos.y);       // x + 1, z
                    c                 = TerrainPosToReal(vertexTerrainPos.x + 1, chunk.HeightsMap[x + 2, z + 2], vertexTerrainPos.y + 1);   // x + 1, z + 1
                    normal            = -Vector3.Cross(b - a, c - a);
                    chunk.Normals[i] += normal;
                    if (x < ChunkSize)
                    {
                        chunk.Normals[i + (ChunkSize + 1)] += normal;
                    }

                    b                 = c;                                                                                            // x + 1, z + 1
                    c                 = TerrainPosToReal(vertexTerrainPos.x, chunk.HeightsMap[x + 1, z + 2], vertexTerrainPos.y + 1); // x, z + 1
                    normal            = -Vector3.Cross(b - a, c - a);
                    chunk.Normals[i] += normal;
                    if (z < ChunkSize)
                    {
                        chunk.Normals[i + 1] += normal;
                    }
                }
            }
        }

        for (i = 0; i < chunk.Normals.Length; i++)
        {
            chunk.Normals[i].Normalize();
        }
    }