/// <summary> /// Overrides the old heights of the temp vertices with the new heights of the temp vertices. /// Calls recalculateBuoyPosition() to update buoy position. /// </summary> private void setTempVertices() { Vector3[] tempVertices = terrain.tempVertices; int totalSize = DiamondSquareGenerator.getTotalSize(terrain.size); float[,] heights = new float[totalSize, totalSize]; if (tempVertices.Length > 0) { for (int index = 0, z = 0; z < totalSize; z++) { for (int x = 0; x < totalSize; x++) { tempVertices[index].y += terrain.tempDiffHeights[x, z]; heights[x, z] = tempVertices[index].y; index++; } } } terrain.tempVertices = tempVertices; terrain.tempDiffHeights = new float[totalSize, totalSize]; terrain.setColliderHeights(heights); terrain.recalculateBuoyPosition(); this.isEditMode = false; }
public float[,] GetCombinedMap(int power, int height, int seedCount) { var baseMap = new DiamondSquareGenerator().GenerateBaseMap(power, height); var voronoyMap = new VoronoyGenerator().GenerateMapWithVoronoyDiagrams(power, seedCount); var size = (1 << power) + 1; var resultMap = new float[size, size]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { resultMap[i, j] = (2 * baseMap[i, j] + voronoyMap[i, j]) / 3; } } return(resultMap); }
/// <summary> /// Sets the relevant heights of the collider. /// </summary> /// <param name="heights">The heights of the whole mesh</param> public void setColliderHeights(float[,] heights) { Vector3[] colliderVertices = this.colliderMesh.vertices; int totalSize = DiamondSquareGenerator.getTotalSize(this.size); int colliderTotalSize = totalSize / this.colliderScale; for (int index = 0, z = 0; z < colliderTotalSize; z++) { for (int x = 0; x < colliderTotalSize; x++) { colliderVertices[index].y = heights[x * this.colliderScale, z *this.colliderScale]; index++; } } this.colliderMesh.vertices = colliderVertices; this.updateCollider(); }
/// <summary> /// Sets the vertices heights of the mesh with heights calculated /// by the diamond square algorithm. /// Also sets a buoy on the deepest water point. /// </summary> public void generateMeshHeights() { int totalSize = DiamondSquareGenerator.getTotalSize(this.size); float[,] heights = DiamondSquareGenerator.diamondSquare(this.size, TerrainObject.rough, TerrainObject.seed); Vector3[] vertices = this.mesh.vertices; Vector3[] tempVertices = new Vector3[vertices.Length]; Color[] colors = new Color[vertices.Length]; int colliderTotalSize = totalSize / this.colliderScale; Vector3[] colliderVertices = this.colliderMesh.vertices; // Add diamond square calculated heights to the vertices for (int index = 0, z = 0; z < totalSize; z++) { for (int x = 0; x < totalSize; x++) { float height = heights[x, z]; vertices[index].y = height; tempVertices[index] = vertices[index]; colors[index] = this.getColorFromHeight(height); index++; } } this.setColliderHeights(heights); this.tempVertices = tempVertices; this.tempDiffHeights = new float[totalSize, totalSize]; this.updateMesh(vertices, colors); this.meshGameObject.SetActive(true); // Adds the buoy to the deepest water point (if there is water in the terrain) this.recalculateBuoyPosition(); }
/// <summary> /// Change the height of the given vertex and its neighbors with the gaussian bell algroithm /// </summary> /// <param name="vertexToChange">index of the vertex to change</param> /// <param name="heightFactor">factor to change the height</param> private void useGaussianBell(int indexOfVertexToChange, float heightFactor) { int totalSize = DiamondSquareGenerator.getTotalSize(terrain.size); float widthFactor = 0.02f; Vector3[] tempVertices = terrain.tempVertices; Vector3[] vertices = new Vector3[tempVertices.Length]; float[,] diffHeights = terrain.tempDiffHeights; Color[] colors = new Color[vertices.Length]; Vector3 vertexToChange = tempVertices[indexOfVertexToChange]; for (int index = 0, z = 0; z < totalSize; z++) { for (int x = 0; x < totalSize; x++) { Vector3 vertex = tempVertices[index]; Vector3 diff = vertex - vertexToChange; // calculates the distance in x and z direction to between the two vertices float dist = Mathf.Sqrt(Mathf.Pow(diff.x, 2) + Mathf.Pow(diff.z, 2)); // calculate the height for the current vertex with the gaussian bell algorithm float diffHeight = Mathf.Exp(-Mathf.Pow(widthFactor * dist, 2)) * heightFactor; diffHeights[x, z] += diffHeight; float height = vertex.y + diffHeights[x, z]; vertex.y = height; vertices[index] = vertex; colors[index] = terrain.getColorFromHeight(height); index++; } } terrain.tempDiffHeights = diffHeights; terrain.updateMesh(vertices, colors); }
void Start() { terrainData = GetComponent <Terrain>().terrainData; terrainGenerator = new DiamondSquareGenerator(resolution); }
private void _generateTerrain() { try { IGenerator generator = null; switch (_configurationManager.Algorithm) { case GeneratorAlgorithm.PerlinNoise: generator = new PerlinNoiseGenerator(GraphicsDevice, Graphics, _configurationManager.Parameters); break; case GeneratorAlgorithm.Hill: generator = new HillAlgorithmGenerator(GraphicsDevice, Graphics, _configurationManager.Parameters); break; case GeneratorAlgorithm.Random: generator = new RandomGenerator(GraphicsDevice, Graphics, _configurationManager.Parameters); break; case GeneratorAlgorithm.Rectangle: generator = new RectangleGenerator(GraphicsDevice, Graphics, _configurationManager.Parameters); break; case GeneratorAlgorithm.Voronoi: generator = new VoronoiGenerator(GraphicsDevice, Graphics, _configurationManager.Parameters); break; case GeneratorAlgorithm.SimplexNoise: generator = new SimplexNoise(GraphicsDevice, Graphics, _configurationManager.Parameters); break; case GeneratorAlgorithm.DiamondSquare: generator = new DiamondSquareGenerator(GraphicsDevice, Graphics, _configurationManager.Parameters); break; case GeneratorAlgorithm.RandomWalk: generator = new RandomWalkGenerator(GraphicsDevice, Graphics, _configurationManager.Parameters); break; case GeneratorAlgorithm.DrunkardWalk: generator = new DrunkardWalk(GraphicsDevice, Graphics, _configurationManager.Parameters); break; default: throw new NotImplementedException("Unknown algorithm"); } if (generator == null) { throw new NullReferenceException("Generator cannot be null"); } var timeStart = System.DateTime.Now; Scene.AddObjectToRender(generator.Generate()); Logger.Log.Info("Generated time = " + (DateTime.Now - timeStart).TotalMilliseconds + " ms for " + _configurationManager.Algorithm.ToString()); } catch (Exception e) { Logger.Log.Error(e); throw; } }
/// <summary> /// Creates a flat mesh /// </summary> private void createMesh() { int totalSize = DiamondSquareGenerator.getTotalSize(this.size); // Creates the mesh game object this.meshGameObject = new GameObject(); this.meshGameObject.SetActive(false); this.meshGameObject.transform.SetParent(gameObject.transform); this.meshGameObject.AddComponent <MeshRenderer>().material = GetComponent <MeshRenderer>().material; this.meshGameObject.name = "TerrainMesh"; this.meshGameObject.layer = 8; // Adds a mesh filter to the mesh MeshFilter meshFilter = this.meshGameObject.AddComponent <MeshFilter>(); this.mesh = new Mesh(); this.mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; meshFilter.sharedMesh = this.mesh; // Adds a mesh collider to the mesh int colliderTotalSize = totalSize / this.colliderScale; this.colliderMesh = new Mesh(); this.meshCollider = this.meshGameObject.AddComponent <MeshCollider>(); Vector3[] vertices = new Vector3[totalSize * totalSize]; Vector2[] uvs = new Vector2[vertices.Length]; int[] triangles = new int[6 * ((totalSize - 1) * (totalSize - 1))]; Vector3[] colliderVertices = new Vector3[colliderTotalSize * colliderTotalSize]; int[] colliderTriangles = new int[6 * ((colliderTotalSize - 1) * (colliderTotalSize - 1))]; // Fill vertices and uvs for (int index = 0, z = 0; z < totalSize; z++) { for (int x = 0; x < totalSize; x++) { vertices[index] = new Vector3(x, 0, z); uvs[index] = new Vector2(x, z); index++; } } // Fill collider vertices for (int index = 0, z = 0; z < colliderTotalSize; z++) { for (int x = 0; x < colliderTotalSize; x++) { colliderVertices[index] = new Vector3(x * this.colliderScale, 0, z * this.colliderScale); index++; } } // Fill triangles for (int triangleIndex = 0, index = 0, z = 0; z < totalSize - 1; z++) { for (int x = 0; x < totalSize - 1; x++) { triangles[triangleIndex++] = index; triangles[triangleIndex++] = index + totalSize; triangles[triangleIndex++] = index + 1; triangles[triangleIndex++] = index + 1; triangles[triangleIndex++] = index + totalSize; triangles[triangleIndex++] = index + totalSize + 1; index++; } index++; } // Fill collider triangles for (int triangleIndex = 0, index = 0, z = 0; z < colliderTotalSize - 1; z++) { for (int x = 0; x < colliderTotalSize - 1; x++) { colliderTriangles[triangleIndex++] = index; colliderTriangles[triangleIndex++] = index + colliderTotalSize; colliderTriangles[triangleIndex++] = index + 1; colliderTriangles[triangleIndex++] = index + 1; colliderTriangles[triangleIndex++] = index + colliderTotalSize; colliderTriangles[triangleIndex++] = index + colliderTotalSize + 1; index++; } index++; } // Add vertices, triangles and uvs to mesh this.mesh.vertices = vertices; this.mesh.triangles = triangles; this.mesh.uv = uvs; // Add vertices and triangles to collider mesh this.colliderMesh.vertices = colliderVertices; this.colliderMesh.triangles = colliderTriangles; // Instantiate buoy this.buoyPrefab.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); this.buoy = Instantiate(this.buoyPrefab, this.mesh.vertices[totalSize * totalSize / 4] * 0.05f, Quaternion.Euler(-90, 0, 0)); }