Explorar el Código

IncludeMorethings

Diego Ovalle hace 5 días
padre
commit
2494d7c415

+ 21 - 0
Assets/Scripts/TerrainGen/Editor/MapGeneratorEditor.cs

@@ -0,0 +1,21 @@
+using UnityEngine;
+using System.Collections;
+using UnityEditor;
+
+[CustomEditor (typeof (MapGenerator))]
+public class MapGeneratorEditor : Editor {
+
+	public override void OnInspectorGUI() {
+		MapGenerator mapGen = (MapGenerator)target;
+
+		if (DrawDefaultInspector ()) {
+			if (mapGen.autoUpdate) {
+				mapGen.DrawMapInEditor ();
+			}
+		}
+
+		if (GUILayout.Button ("Generate")) {
+			mapGen.DrawMapInEditor ();
+		}
+	}
+}

+ 2 - 0
Assets/Scripts/TerrainGen/Editor/MapGeneratorEditor.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 4776ec344d65dca4f8a598df45fab6e4

+ 28 - 0
Assets/Scripts/TerrainGen/FalloffGenerator.cs

@@ -0,0 +1,28 @@
+using UnityEngine;
+using System.Collections;
+
+public static class FalloffGenerator {
+
+	public static float[,] GenerateFalloffMap(int size) {
+		float[,] map = new float[size,size];
+
+		for (int i = 0; i < size; i++) {
+			for (int j = 0; j < size; j++) {
+				float x = i / (float)size * 2 - 1;
+				float y = j / (float)size * 2 - 1;
+
+				float value = Mathf.Max (Mathf.Abs (x), Mathf.Abs (y));
+				map [i, j] = Evaluate(value);
+			}
+		}
+
+		return map;
+	}
+
+	static float Evaluate(float value) {
+		float a = 3;
+		float b = 2.2f;
+
+		return Mathf.Pow (value, a) / (Mathf.Pow (value, a) + Mathf.Pow (b - b * value, a));
+	}
+}

+ 2 - 0
Assets/Scripts/TerrainGen/FalloffGenerator.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 287da31736bdfa3479d8b406603ac44e

+ 65 - 0
Assets/Scripts/TerrainGen/MapDisplay.cs

@@ -0,0 +1,65 @@
+using UnityEngine;
+using System.Collections;
+
+public class MapDisplay : MonoBehaviour {
+
+	public Renderer textureRender;
+	public MeshFilter meshFilter;
+	public MeshRenderer meshRenderer;
+
+	public void DrawTexture(Texture2D texture) {
+		textureRender.sharedMaterial.mainTexture = texture;
+		textureRender.transform.localScale = new Vector3 (texture.width, 1, texture.height);
+	}
+
+	public void DrawMesh(MeshData meshData) {
+		meshFilter.sharedMesh = meshData.CreateMesh ();
+
+		meshFilter.transform.localScale = Vector3.one * FindFirstObjectByType<MapGenerator> ().terrainData.uniformScale;
+
+        ApplyVertexColors(meshFilter.sharedMesh);
+    }
+
+    void ApplyVertexColors(Mesh mesh)
+    {
+        Vector3[] vertices = mesh.vertices;
+        Color[] colors = new Color[vertices.Length];
+
+        float maxH = 25f;
+
+        for (int i = 0; i < vertices.Length; i++)
+        {
+            
+            float heightPercent = Mathf.InverseLerp(0, maxH, vertices[i].y);
+
+            // --- THE BIOME LAYERS ---
+            if (heightPercent < 0.05f)
+            {
+                colors[i] = new Color(0.1f, 0.3f, 0.6f); // Deep Water (Dark Blue)
+            }
+            else if (heightPercent < 0.12f)
+            {
+                colors[i] = new Color(0.9f, 0.8f, 0.6f); // Sand/Beach (Tan)
+            }
+            else if (heightPercent < 0.45f)
+            {
+                colors[i] = new Color(0.2f, 0.5f, 0.1f); // Grass (Rich Green)
+            }
+            else if (heightPercent < 0.65f)
+            {
+                colors[i] = new Color(0.4f, 0.35f, 0.3f); // Rock Color 1 (Brown-Grey)
+            }
+            else if (heightPercent < 0.85f)
+            {
+                colors[i] = new Color(0.3f, 0.3f, 0.3f); // Rock Color 2 (Dark Grey)
+            }
+            else
+            {
+                colors[i] = Color.white; // Snow (White)
+            }
+        }
+
+        mesh.colors = colors;
+    }
+
+}

+ 2 - 0
Assets/Scripts/TerrainGen/MapDisplay.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: a7ad81e5316662d4b8fa2a11a181272c

+ 239 - 0
Assets/Scripts/TerrainGen/MapGenerator.cs

@@ -0,0 +1,239 @@
+using UnityEngine;
+using System.Collections;
+using System;
+using System.Threading;
+using System.Collections.Generic;
+using UnityEditor.UI;
+
+public class MapGenerator : MonoBehaviour {
+
+	public enum DrawMode {NoiseMap, Mesh, FalloffMap};
+	public DrawMode drawMode;
+
+	public TerrainData terrainData;
+	public NoiseData noiseData;
+	public TextureData textureData;
+
+	public Material terrainMaterial;
+
+	[Range(0,6)]
+	public int editorPreviewLOD;
+
+	public bool autoUpdate;
+
+	float[,] falloffMap;
+
+	Queue<MapThreadInfo<MapData>> mapDataThreadInfoQueue = new Queue<MapThreadInfo<MapData>>();
+	Queue<MapThreadInfo<MeshData>> meshDataThreadInfoQueue = new Queue<MapThreadInfo<MeshData>>();
+
+
+	void OnValuesUpdated() {
+		if (!Application.isPlaying) {
+			DrawMapInEditor ();
+		}
+	}
+
+	//void OnTextureValuesUpdated() {
+	//	textureData.ApplyToMaterial (terrainMaterial);
+	//}
+
+    public int mapChunkSize {
+		get {
+
+
+			if (terrainData.useFlatShading) {
+				return 95;
+			} else {
+				return 239;
+			}
+		}
+	}
+
+	public void DrawMapInEditor() {
+		MapData mapData = GenerateMapData (Vector2.zero);
+
+		MapDisplay display = FindFirstObjectByType<MapDisplay> ();
+		if (drawMode == DrawMode.NoiseMap) {
+			display.DrawTexture (TextureGenerator.TextureFromHeightMap (mapData.heightMap));
+		} else if (drawMode == DrawMode.Mesh) {
+			display.DrawMesh (MeshGenerator.GenerateTerrainMesh (mapData.heightMap, terrainData.meshHeightMultiplier, terrainData.meshHeightCurve, editorPreviewLOD,terrainData.useFlatShading));
+		} else if (drawMode == DrawMode.FalloffMap) {
+			display.DrawTexture(TextureGenerator.TextureFromHeightMap(FalloffGenerator.GenerateFalloffMap(mapChunkSize)));
+		}
+	}
+
+	public void RequestMapData(Vector2 centre, Action<MapData> callback) {
+		ThreadStart threadStart = delegate {
+			MapDataThread (centre, callback);
+		};
+
+		new Thread (threadStart).Start ();
+	}
+
+	void MapDataThread(Vector2 centre, Action<MapData> callback) {
+		MapData mapData = GenerateMapData (centre);
+		lock (mapDataThreadInfoQueue) {
+			mapDataThreadInfoQueue.Enqueue (new MapThreadInfo<MapData> (callback, mapData));
+		}
+	}
+
+	public void RequestMeshData(MapData mapData, int lod, Action<MeshData> callback) {
+		ThreadStart threadStart = delegate {
+			MeshDataThread (mapData, lod, callback);
+		};
+
+		new Thread (threadStart).Start ();
+	}
+
+	void MeshDataThread(MapData mapData, int lod, Action<MeshData> callback) {
+		MeshData meshData = MeshGenerator.GenerateTerrainMesh (mapData.heightMap, terrainData.meshHeightMultiplier, terrainData.meshHeightCurve, lod,terrainData.useFlatShading);
+		lock (meshDataThreadInfoQueue) {
+			meshDataThreadInfoQueue.Enqueue (new MapThreadInfo<MeshData> (callback, meshData));
+		}
+	}
+
+    void Start()
+    {
+        //textureData.ApplyToMaterial(terrainMaterial);
+
+        noiseData.seed = UnityEngine.Random.Range(0, 100000);
+
+        DrawMapInEditor();
+
+        MeshFilter mf = GetComponent<MeshFilter>();
+
+        AddCollider();
+
+        Invoke("DelayedSpawn", 0.2f);
+
+    }
+
+    void AddCollider()
+    {
+        MeshFilter meshFilter = GetComponent<MeshFilter>();
+        if (meshFilter == null || meshFilter.sharedMesh == null) return;
+
+        MeshCollider meshCollider = GetComponent<MeshCollider>();
+        if (meshCollider == null)
+        {
+            meshCollider = gameObject.AddComponent<MeshCollider>();
+        }
+        meshCollider.sharedMesh = meshFilter.sharedMesh;
+    }
+
+    void DelayedSpawn()
+    {
+        Debug.Log("Attempting to spawn orbs now...");
+
+        // 1. Grab the mesh from the filter
+        MeshFilter mf = GetComponent<MeshFilter>();
+        if (mf == null || mf.sharedMesh == null)
+        {
+            Debug.LogError("No Mesh found! Spawner can't find the ground.");
+            return;
+        }
+
+        // 2. Force the collider to update to the NEW mesh shape
+        MeshCollider meshCollider = GetComponent<MeshCollider>();
+        if (meshCollider == null) meshCollider = gameObject.AddComponent<MeshCollider>();
+
+        meshCollider.sharedMesh = null; // Reset it
+        meshCollider.sharedMesh = mf.sharedMesh; // Assign new
+
+        // 3. Now trigger the spawner
+        TerrainObjectSpawner spawner = GetComponent<TerrainObjectSpawner>();
+        if (spawner != null)
+        {
+            spawner.SpawnOrbs();
+        }
+        else
+        {
+            Debug.LogError("TerrainObjectSpawner component missing on MapGenerator!");
+        }
+    }
+
+
+    void Update() {
+		if (mapDataThreadInfoQueue.Count > 0) {
+			for (int i = 0; i < mapDataThreadInfoQueue.Count; i++) {
+				MapThreadInfo<MapData> threadInfo = mapDataThreadInfoQueue.Dequeue ();
+				threadInfo.callback (threadInfo.parameter);
+			}
+		}
+
+		if (meshDataThreadInfoQueue.Count > 0) {
+			for (int i = 0; i < meshDataThreadInfoQueue.Count; i++) {
+				MapThreadInfo<MeshData> threadInfo = meshDataThreadInfoQueue.Dequeue ();
+				threadInfo.callback (threadInfo.parameter);
+			}
+		}
+	}
+
+	MapData GenerateMapData(Vector2 centre) {
+		float[,] noiseMap = Noise.GenerateNoiseMap (mapChunkSize + 2, mapChunkSize + 2, noiseData.seed, noiseData.noiseScale, noiseData.octaves, noiseData.persistance, noiseData.lacunarity, centre + noiseData.offset, noiseData.normalizeMode);
+
+		if (terrainData.useFalloff) {
+
+			if (falloffMap == null) {
+				falloffMap = FalloffGenerator.GenerateFalloffMap (mapChunkSize + 2);
+			}
+			 
+			for (int y = 0; y < mapChunkSize+2; y++) {
+				for (int x = 0; x < mapChunkSize+2; x++) {
+					if (terrainData.useFalloff) {
+						noiseMap [x, y] = Mathf.Clamp01 (noiseMap [x, y] - falloffMap [x, y]);
+					}
+				
+				}
+			}
+
+		}
+
+		//textureData.UpdateMeshHeights (terrainMaterial, terrainData.minHeight, terrainData.maxHeight);
+
+		return new MapData (noiseMap);
+	}
+
+	void OnValidate() {
+
+		if (terrainData != null) {
+			terrainData.OnValuesUpdated -= OnValuesUpdated;
+			terrainData.OnValuesUpdated += OnValuesUpdated;
+		}
+		if (noiseData != null) {
+			noiseData.OnValuesUpdated -= OnValuesUpdated;
+			noiseData.OnValuesUpdated += OnValuesUpdated;
+		}
+		//if (textureData != null) {
+		//	textureData.OnValuesUpdated -= OnTextureValuesUpdated;
+		//	textureData.OnValuesUpdated += OnTextureValuesUpdated;
+		//}
+
+	}
+
+	struct MapThreadInfo<T> {
+		public readonly Action<T> callback;
+		public readonly T parameter;
+
+		public MapThreadInfo (Action<T> callback, T parameter)
+		{
+			this.callback = callback;
+			this.parameter = parameter;
+		}
+
+	}
+
+}
+	
+
+public struct MapData {
+	public readonly float[,] heightMap;
+
+
+	public MapData (float[,] heightMap)
+	{
+		this.heightMap = heightMap;
+	}
+}
+
+

+ 2 - 0
Assets/Scripts/TerrainGen/MapGenerator.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 59efff4a5821f184da36cc56cb87758b

+ 211 - 0
Assets/Scripts/TerrainGen/MeshGenerator.cs

@@ -0,0 +1,211 @@
+using UnityEngine;
+using System.Collections;
+
+public static class MeshGenerator {
+
+	public static MeshData GenerateTerrainMesh(float[,] heightMap, float heightMultiplier, AnimationCurve _heightCurve, int levelOfDetail, bool useFlatShading) {
+		AnimationCurve heightCurve = new AnimationCurve (_heightCurve.keys);
+
+		int meshSimplificationIncrement = (levelOfDetail == 0)?1:levelOfDetail * 2;
+
+		int borderedSize = heightMap.GetLength (0);
+		int meshSize = borderedSize - 2*meshSimplificationIncrement;
+		int meshSizeUnsimplified = borderedSize - 2;
+
+		float topLeftX = (meshSizeUnsimplified - 1) / -2f;
+		float topLeftZ = (meshSizeUnsimplified - 1) / 2f;
+
+
+		int verticesPerLine = (meshSize - 1) / meshSimplificationIncrement + 1;
+
+		MeshData meshData = new MeshData (verticesPerLine,useFlatShading);
+
+		int[,] vertexIndicesMap = new int[borderedSize,borderedSize];
+		int meshVertexIndex = 0;
+		int borderVertexIndex = -1;
+
+		for (int y = 0; y < borderedSize; y += meshSimplificationIncrement) {
+			for (int x = 0; x < borderedSize; x += meshSimplificationIncrement) {
+				bool isBorderVertex = y == 0 || y == borderedSize - 1 || x == 0 || x == borderedSize - 1;
+
+				if (isBorderVertex) {
+					vertexIndicesMap [x, y] = borderVertexIndex;
+					borderVertexIndex--;
+				} else {
+					vertexIndicesMap [x, y] = meshVertexIndex;
+					meshVertexIndex++;
+				}
+			}
+		}
+
+		for (int y = 0; y < borderedSize; y += meshSimplificationIncrement) {
+			for (int x = 0; x < borderedSize; x += meshSimplificationIncrement) {
+				int vertexIndex = vertexIndicesMap [x, y];
+				Vector2 percent = new Vector2 ((x-meshSimplificationIncrement) / (float)meshSize, (y-meshSimplificationIncrement) / (float)meshSize);
+				float height = heightCurve.Evaluate (heightMap [x, y]) * heightMultiplier;
+				Vector3 vertexPosition = new Vector3 (topLeftX + percent.x * meshSizeUnsimplified, height, topLeftZ - percent.y * meshSizeUnsimplified);
+
+				meshData.AddVertex (vertexPosition, percent, vertexIndex);
+
+				if (x < borderedSize - 1 && y < borderedSize - 1) {
+					int a = vertexIndicesMap [x, y];
+					int b = vertexIndicesMap [x + meshSimplificationIncrement, y];
+					int c = vertexIndicesMap [x, y + meshSimplificationIncrement];
+					int d = vertexIndicesMap [x + meshSimplificationIncrement, y + meshSimplificationIncrement];
+					meshData.AddTriangle (a,d,c);
+					meshData.AddTriangle (d,a,b);
+				}
+
+				vertexIndex++;
+			}
+		}
+
+		meshData.ProcessMesh ();
+
+		return meshData;
+
+	}
+}
+
+public class MeshData {
+	Vector3[] vertices;
+	int[] triangles;
+	Vector2[] uvs;
+	Vector3[] bakedNormals;
+
+	Vector3[] borderVertices;
+	int[] borderTriangles;
+
+	int triangleIndex;
+	int borderTriangleIndex;
+
+	bool useFlatShading;
+
+	public MeshData(int verticesPerLine, bool useFlatShading) {
+		this.useFlatShading = useFlatShading;
+
+		vertices = new Vector3[verticesPerLine * verticesPerLine];
+		uvs = new Vector2[verticesPerLine * verticesPerLine];
+		triangles = new int[(verticesPerLine-1)*(verticesPerLine-1)*6];
+
+		borderVertices = new Vector3[verticesPerLine * 4 + 4];
+		borderTriangles = new int[24 * verticesPerLine];
+	}
+
+	public void AddVertex(Vector3 vertexPosition, Vector2 uv, int vertexIndex) {
+		if (vertexIndex < 0) {
+			borderVertices [-vertexIndex - 1] = vertexPosition;
+		} else {
+			vertices [vertexIndex] = vertexPosition;
+			uvs [vertexIndex] = uv;
+		}
+	}
+
+	public void AddTriangle(int a, int b, int c) {
+		if (a < 0 || b < 0 || c < 0) {
+			borderTriangles [borderTriangleIndex] = a;
+			borderTriangles [borderTriangleIndex + 1] = b;
+			borderTriangles [borderTriangleIndex + 2] = c;
+			borderTriangleIndex += 3;
+		} else {
+			triangles [triangleIndex] = a;
+			triangles [triangleIndex + 1] = b;
+			triangles [triangleIndex + 2] = c;
+			triangleIndex += 3;
+		}
+	}
+
+	Vector3[] CalculateNormals() {
+
+		Vector3[] vertexNormals = new Vector3[vertices.Length];
+		int triangleCount = triangles.Length / 3;
+		for (int i = 0; i < triangleCount; i++) {
+			int normalTriangleIndex = i * 3;
+			int vertexIndexA = triangles [normalTriangleIndex];
+			int vertexIndexB = triangles [normalTriangleIndex + 1];
+			int vertexIndexC = triangles [normalTriangleIndex + 2];
+
+			Vector3 triangleNormal = SurfaceNormalFromIndices (vertexIndexA, vertexIndexB, vertexIndexC);
+			vertexNormals [vertexIndexA] += triangleNormal;
+			vertexNormals [vertexIndexB] += triangleNormal;
+			vertexNormals [vertexIndexC] += triangleNormal;
+		}
+
+		int borderTriangleCount = borderTriangles.Length / 3;
+		for (int i = 0; i < borderTriangleCount; i++) {
+			int normalTriangleIndex = i * 3;
+			int vertexIndexA = borderTriangles [normalTriangleIndex];
+			int vertexIndexB = borderTriangles [normalTriangleIndex + 1];
+			int vertexIndexC = borderTriangles [normalTriangleIndex + 2];
+
+			Vector3 triangleNormal = SurfaceNormalFromIndices (vertexIndexA, vertexIndexB, vertexIndexC);
+			if (vertexIndexA >= 0) {
+				vertexNormals [vertexIndexA] += triangleNormal;
+			}
+			if (vertexIndexB >= 0) {
+				vertexNormals [vertexIndexB] += triangleNormal;
+			}
+			if (vertexIndexC >= 0) {
+				vertexNormals [vertexIndexC] += triangleNormal;
+			}
+		}
+
+
+		for (int i = 0; i < vertexNormals.Length; i++) {
+			vertexNormals [i].Normalize ();
+		}
+
+		return vertexNormals;
+
+	}
+
+	Vector3 SurfaceNormalFromIndices(int indexA, int indexB, int indexC) {
+		Vector3 pointA = (indexA < 0)?borderVertices[-indexA-1] : vertices [indexA];
+		Vector3 pointB = (indexB < 0)?borderVertices[-indexB-1] : vertices [indexB];
+		Vector3 pointC = (indexC < 0)?borderVertices[-indexC-1] : vertices [indexC];
+
+		Vector3 sideAB = pointB - pointA;
+		Vector3 sideAC = pointC - pointA;
+		return Vector3.Cross (sideAB, sideAC).normalized;
+	}
+
+	public void ProcessMesh() {
+		if (useFlatShading) {
+			FlatShading ();
+		} else {
+			BakeNormals ();
+		}
+	}
+
+	void BakeNormals() {
+		bakedNormals = CalculateNormals ();
+	}
+
+	void FlatShading() {
+		Vector3[] flatShadedVertices = new Vector3[triangles.Length];
+		Vector2[] flatShadedUvs = new Vector2[triangles.Length];
+
+		for (int i = 0; i < triangles.Length; i++) {
+			flatShadedVertices [i] = vertices [triangles [i]];
+			flatShadedUvs [i] = uvs [triangles [i]];
+			triangles [i] = i;
+		}
+
+		vertices = flatShadedVertices;
+		uvs = flatShadedUvs;
+	}
+
+	public Mesh CreateMesh() {
+		Mesh mesh = new Mesh ();
+		mesh.vertices = vertices;
+		mesh.triangles = triangles;
+		mesh.uv = uvs;
+		if (useFlatShading) {
+			mesh.RecalculateNormals ();
+		} else {
+			mesh.normals = bakedNormals;
+		}
+		return mesh;
+	}
+
+}

+ 2 - 0
Assets/Scripts/TerrainGen/MeshGenerator.cs.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 661b32635d5aa174da176502b6a101bb