Ejemplo n.º 1
0
    /** <summary>
     * Creates a new biome at the specified biome-space coordinates with the specified type
     * <para />
     * If biome is set to null then it picks a random biome except Premade
     */
    public BiomeController CreateBiome(Vector3Int pos, BiomeType?type = null, bool generate = true)
    {
        BiomeController b = Instantiate <BiomeController>(BiomePrefab, transform);

        b.name = String.Format("{0}-{1}-{2}", pos.x, pos.y, pos.z);

        b.Manager = this;
        Vector3 worldPos = Biome.BlockSize * (new Vector3(Biome.XSize, Biome.YSize, Biome.ZSize) + Biome.BiomeSpacing * Vector3.one);

        worldPos.Scale(pos);
        b.transform.localPosition = worldPos;

        Biome instance = null;

        if (type != null)
        {
            Biomes.TryGetValue(type.Value, out instance);
        }
        else
        {
            List <BiomeType> biomes = new List <BiomeType>(Biomes.Keys);
            type = biomes[UnityEngine.Random.Range(2, biomes.Count - 1)];
            Biomes.TryGetValue(type.Value, out instance);
        }
        b.Type          = type.Value;
        b.BiomeInstance = instance;
        if (generate)
        {
            instance.Generate(b);
        }

        return(b);
    }
Ejemplo n.º 2
0
    // Start is called before the first frame update
    void Start()
    {
        mesh      = new Mesh();
        mesh.name = "Procedural Terrain";

        //Generate vertices
        int vertexCount = (vertexCountRadius * 2 + 1) * (vertexCountRadius * 2 + 1);

        Vector3[] vertices = new Vector3[vertexCount];
        for (int x = -vertexCountRadius, i = 0; x <= vertexCountRadius; x++)
        {
            for (int z = -vertexCountRadius; z <= vertexCountRadius; z++)
            {
                //Get nearest biome(s) and crossfade values
                float u         = (float)(x + vertexCountRadius) / (2 * vertexCountRadius);
                float v         = (float)(z + vertexCountRadius) / (2 * vertexCountRadius);
                var   biomeData = GetBiomeInterpolationValues(u, v);

                //Crossfade values
                float regionDetailScale  = Mathf.Lerp(biomeData.lerpBiomes[0].biomeDetailScale, biomeData.lerpBiomes[1].biomeDetailScale, biomeData.lerpPosition);
                float regionHeightScale  = Mathf.Lerp(biomeData.lerpBiomes[0].biomeHeightScale, biomeData.lerpBiomes[1].biomeHeightScale, biomeData.lerpPosition) * heightScale;
                float regionHeightOffset = Mathf.Lerp(biomeData.lerpBiomes[0].biomeHeightOffset, biomeData.lerpBiomes[1].biomeHeightOffset, biomeData.lerpPosition);

                //Generate vertex
                vertices[i]   = new Vector3();
                vertices[i].x = (float)x / vertexCountRadius;
                vertices[i].z = (float)z / vertexCountRadius;

                //Generate height from noise
                float height = Mathf.PerlinNoise(
                    (vertices[i].x + transform.position.x) * regionDetailScale,
                    (vertices[i].z + transform.position.z) * regionDetailScale);

                //Evaluate against height curves
                height = regionHeightOffset + regionHeightScale *
                         Mathf.Lerp(biomeData.lerpBiomes[0].heightCurve.Evaluate(height),
                                    biomeData.lerpBiomes[1].heightCurve.Evaluate(height),
                                    biomeData.lerpPosition);

                //Set vertex height
                vertices[i].y = height;

                //Debug.Log("" + vertices[i].x + ", " + vertices[i].y + ", " + vertices[i].z);
                i++;
            }
        }

        //Generate triangles (quads)
        int verticesPerRow = vertexCountRadius * 2 + 1;
        int quadCount      = (verticesPerRow - 1) * (verticesPerRow - 1);

        int[] triangles = new int[quadCount * 6];
        for (int ti = 0, vi = 0, x = -vertexCountRadius; x < vertexCountRadius; x++, vi++)
        {
            for (int z = -vertexCountRadius; z < vertexCountRadius; z++, ti += 6, vi++)
            {
                triangles[ti]     = vi;
                triangles[ti + 1] = vi + 1;
                triangles[ti + 2] = vi + verticesPerRow;
                triangles[ti + 3] = vi + verticesPerRow + 1;
                triangles[ti + 4] = vi + verticesPerRow;
                triangles[ti + 5] = vi + 1;
                //Debug.Log("" + x + ", " + z + ": " + vertices[triangles[ti]] + ", " + vertices[triangles[ti + 1]] + ", " + vertices[triangles[ti + 2]]);
                //Debug.Log("" + x + ", " + z + ": " + vertices[triangles[ti + 3]] + ", " + vertices[triangles[ti + 4]] + ", " + vertices[triangles[ti + 5]]);
            }
        }

        //Generate u,v (texture) coordinates
        Vector2[] uvs = new Vector2[vertices.Length];
        for (int x = 0, i = 0; x < verticesPerRow; x++)
        {
            for (int z = 0; z < verticesPerRow; z++)
            {
                uvs[i] = new Vector2((float)x / verticesPerRow, (float)z / verticesPerRow);
                i++;
            }
        }

        //Update mesh
        mesh.vertices  = vertices;
        mesh.triangles = triangles;
        mesh.uv        = uvs;

        mesh.RecalculateBounds();
        mesh.RecalculateNormals();
        mesh.RecalculateTangents();

        GetComponent <MeshFilter>().mesh = mesh;

        //Update mesh collider
        GetComponent <MeshCollider>().sharedMesh = mesh;

        //Set initial cube to the position
        GameObject referenceHuman = GameObject.Find("Reference Human");
        Vector3    cubePos        = referenceHuman.transform.position;

        referenceHuman.transform.position = new Vector3(cubePos.x, GetMinimumHeightNear(cubePos.x, cubePos.z, Mathf.Sqrt(2)) + referenceHuman.transform.localScale.y / 2, cubePos.z);

        //Set house position
        float      approximateHeightAtZero = GetHeightAtPoint(0f, 0f);
        GameObject smallHouse = GameObject.Find("Small House");
        GameObject largeHouse = GameObject.Find("Large House");

        smallHouse.transform.position = new Vector3(smallHouse.transform.position.x, smallHouse.transform.position.y + approximateHeightAtZero, smallHouse.transform.position.z);
        largeHouse.transform.position = new Vector3(largeHouse.transform.position.x, largeHouse.transform.position.y + approximateHeightAtZero, largeHouse.transform.position.z);

        //Reset preview scale
        transform.localScale = new Vector3(transform.localScale.x, 1.0f, transform.localScale.z);

        //Enable water
        //GameObject.Find("Water").SetActive(true);

        //Hide reference human
        GameObject.Find("Reference Human").SetActive(false);

        //Generate biome
        for (float x = -transform.localScale.x; x <= transform.localScale.x; x += Constants.BLOCK_SIZE_METERS)
        {
            for (float z = -transform.localScale.z; z <= transform.localScale.z; z += Constants.BLOCK_SIZE_METERS)
            {
                //Get nearest biome and calculate biome strength
                float u                      = (x + transform.localScale.x) / (2f * transform.localScale.x);
                float v                      = (z + transform.localScale.z) / (2f * transform.localScale.z);
                var   biomeData              = GetBiomeInterpolationValues(u, v);
                Biome primaryBiome           = biomeData.lerpPosition >= 0.5f ? biomeData.lerpBiomes[1] : biomeData.lerpBiomes[0];
                Biome secondaryBiome         = biomeData.lerpPosition < 0.5f ? biomeData.lerpBiomes[1] : biomeData.lerpBiomes[0];
                float primaryBiomeStrength   = 1.0f - biomeData.lerpPosition;
                float secondaryBiomeStrength = biomeData.lerpPosition;

                //Calculate block positions
                Vector2 blockLowerLeft  = new Vector2(x, z);
                Vector2 blockUpperRight = new Vector2(x + Constants.BLOCK_SIZE_METERS, z + Constants.BLOCK_SIZE_METERS);

                //Generate biome
                if (primaryBiomeStrength > Constants.BIOME_GENERATION_STRENGTH_THRESHOLD)
                {
                    primaryBiome.Generate(this, blockLowerLeft, blockUpperRight, primaryBiomeStrength);
                }
                if (secondaryBiomeStrength > Constants.BIOME_GENERATION_STRENGTH_THRESHOLD)
                {
                    secondaryBiome.Generate(this, blockLowerLeft, blockUpperRight, secondaryBiomeStrength);
                }
            }
        }
    }