/** <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); }
// 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); } } } }