/// <summary> /// Returns the initial corners for the Diamond Square Algorithm. /// </summary> /// <param name="vmap"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="width"></param> /// <param name="depth"></param> /// <returns></returns> public float[] InitializeCorners(VertexMap vmap, int x, int y, int width, int depth) { float[] corners = new float[4]; //corner lower left int vx = x - (width - 1) / 2; //vertex x int vy = y - (width - 1) / 2; //vertex y if (!float.IsNaN(corners[1] = vmap.GetHeight(vx, vy))) { corners[0] = 0f; } //corner lower right vx = x + (width - 1) / 2; //vertex x vy = y - (width - 1) / 2; //vertex y if (!float.IsNaN(corners[1] = vmap.GetHeight(vx, vy))) { corners[1] = 0f; } //corner upper right vx = x + (width - 1) / 2; //vertex x vy = y + (width - 1) / 2; //vertex y if (!float.IsNaN(corners[1] = vmap.GetHeight(vx, vy))) { corners[2] = 0f; } //corner upper left vx = x - (width - 1) / 2; //vertex x vy = y + (width - 1) / 2; //vertex y if (!float.IsNaN(corners[1] = vmap.GetHeight(vx, vy))) { corners[3] = 0f; } return(corners); }
void CalculateBlend2() { float max = 0f; VertexMap map = DynamicTerrain.Instance.VertexMap; Vertex l = map.VertexAt(_x - 1, _y); if (l != null && l._loaded) { float diff = Mathf.Abs(l._height - _height); if (diff > max) { max = diff; } } Vertex r = map.VertexAt(_x + 1, _y); if (r != null && r._loaded) { float diff = Mathf.Abs(r._height - _height); if (diff > max) { max = diff; } } Vertex u = map.VertexAt(_x, _y + 1); if (u != null && u._loaded) { float diff = Mathf.Abs(u._height - _height); if (diff > max) { max = diff; } } Vertex d = map.VertexAt(_x, _y - 1); if (d != null && d._loaded) { float diff = Mathf.Abs(d._height - _height); if (diff > max) { max = diff; } } _color.a = Mathf.Clamp01(max / 50f); }
void Start() { int chunkLoadRadius = WorldManager.Instance.ChunkLoadRadius; int chunkRes = WorldManager.Instance.ChunkResolution; // Init verts int verts = 2 * chunkLoadRadius * (chunkRes - 1); _loadOpsToDo = verts * verts; // Init vertex map _vertexMap = new VertexMap(); // Init chunk map _chunkMap = new Map <Chunk>(chunkLoadRadius * 2); // Init frequency data vars int freqSampleSize = WorldManager.Instance.FrequencySampleSize; _data = new float[freqSampleSize]; }
/// <summary> /// Resets necessary variables after de-pooling a chunk. /// </summary> public void Reuse(int x, int y) { DynamicTerrain terrain = DynamicTerrain.Instance; VertexMap vmap = terrain.VertexMap; float chunkSize = WorldManager.Instance.ChunkSize; // Update vars _x = x; _y = y; // Move chunk to appropriate position transform.position = new Vector3(x * chunkSize - chunkSize / 2f, 0f, y * chunkSize - chunkSize / 2f); // Update chunk name gameObject.name = "Chunk (" + x + "," + y + ") Position:" + transform.position.ToString(); _priority = 0f; // Clear decoration list _decorations.Clear(); // Register all vertices with vertex map // Move vertices, generate normals/colors for (int i = 0; i < _numVerts; i++) { // Get VMap coords IntVector2 coord = IntToV2(i); _coords[i] = coord; // Get corresponding vertex _mapVerts[i] = vmap.VertexAt(coord, true); // Get height from vertex UpdateVertex(i, _mapVerts[i].Height); } _hasCheckedForRoad = false; UpdateCollider(); }
public void SmoothHeight(float h, float factor, float range) { SetHeight(h); Vector2 v = new Vector2((float)_x, (float)_y); VertexMap map = DynamicTerrain.Instance.VertexMap; for (int ix = map.XMin; ix <= map.XMax; ix++) { if ((float)Mathf.Abs(ix - _x) > range) { continue; } for (int iy = map.YMin; iy <= map.YMax; iy++) { if ((float)Mathf.Abs(iy - _y) > range) { continue; } Vector2 n = new Vector2((float)ix, (float)iy); float dist = Vector2.Distance(n, v); if (dist > range) { continue; } if (ix == _x && iy == _y) { continue; } Vertex vert = map.VertexAt(ix, iy); if (vert != null && !vert._locked) { vert.Smooth(h, factor * (range - dist) / range); } } } }
void CalculateBlend() { bool debug = (UnityEngine.Random.Range(0, 10000) == 1); if (debug) { Debug.Log(ToString()); } int numNeighbors = 0; float delta = 0f; VertexMap map = DynamicTerrain.Instance.VertexMap; Vertex l = map.VertexAt(_x - 1, _y); if (l != null && l._loaded) { numNeighbors++; float diff = Mathf.Abs(_height - l._height); if (debug) { Debug.Log("Left: " + l.ToString() + " " + diff); } delta += diff; } Vertex r = map.VertexAt(_x + 1, _y); if (r != null && r._loaded) { numNeighbors++; float diff = Mathf.Abs(_height - r._height); if (debug) { Debug.Log("Right: " + r.ToString() + " " + diff); } delta += diff; } Vertex u = map.VertexAt(_x, _y + 1); if (u != null && u._loaded) { numNeighbors++; float diff = Mathf.Abs(_height - u._height); if (debug) { Debug.Log("Up: " + u.ToString() + " " + diff); } delta += diff; } Vertex d = map.VertexAt(_x, _y - 1); if (d != null && d._loaded) { numNeighbors++; float diff = Mathf.Abs(_height - d._height); if (debug) { Debug.Log("Down: " + d.ToString() + " " + diff); } delta += diff; } _color.a = delta / (float)numNeighbors / 100f; if (debug) { Debug.Log("final blend: " + _color.a); } }
public void SmoothHeight(float h, float factor) { SetHeight(h); VertexMap map = DynamicTerrain.Instance.VertexMap; Vertex l = map.LeftNeighbor(this); if (l != null && !l._locked && !l.NearRoad) { l.Smooth(h, factor); } Vertex r = map.RightNeighbor(this); if (r != null && !r._locked && r.NearRoad) { r.Smooth(h, factor); } Vertex d = map.DownNeighbor(this); if (d != null && !d._locked && d.NearRoad) { d.Smooth(h, factor); } Vertex u = map.UpNeighbor(this); if (u != null && !u._locked && u.NearRoad) { u.Smooth(h, factor); } float factor_squared = factor * factor; if (u != null) { Vertex ul = map.LeftNeighbor(u); if (ul != null && !ul._locked && ul.NearRoad) { ul.Smooth(h, factor_squared); } Vertex ur = map.RightNeighbor(u); if (ur != null && !ur._locked && ur.NearRoad) { ur.Smooth(h, factor_squared); } } if (d != null) { Vertex dl = map.LeftNeighbor(d); if (dl != null && !dl._locked && dl.NearRoad) { dl.Smooth(h, factor_squared); } Vertex dr = map.RightNeighbor(d); if (dr != null && !dr._locked && dr.NearRoad) { dr.Smooth(h, factor_squared); } } }
/// <summary> /// Coroutine to update the vertices of a chunk. /// </summary> /// <returns>The verts.</returns> private IEnumerator UpdateVerts() { if (!GameManager.Instance.IsLoaded) { yield break; } _isUpdatingVerts = true; float margin = WorldManager.Instance.ChunkSize / 2; float startTime = Time.realtimeSinceStartup; Vector3 playerPos = PlayerMovement.Instance.transform.position; Vector3 chunkPos = transform.position; DynamicTerrain terrain = DynamicTerrain.Instance; VertexMap vmap = terrain.VertexMap; int v = 0; for (; v < _numVerts; v++) { // Get VMap coordinates IntVector2 coord = _coords[v]; // Get coresponding vertex Vertex vert = _mapVerts[v]; // Update vertex height UpdateVertex(v, vert.Height); if (terrain.FreqData == null) { yield break; } // If vertex is not locked and there is frequency data to use if (!vert.Locked) { // Distance between player and vertex Vector3 vertPos = chunkPos + _verts[v]; float distance = Vector3.Distance(vertPos, playerPos); // If vertex is close enough if (CheckDist(distance, WorldManager.Instance.VertexUpdateDistance, margin)) { // Calculate new height Vector3 angleVector = vertPos - playerPos; float angle = Vector3.Angle(Vector3.right, angleVector); float linIntInput = angle / 360f; float newY = terrain.FreqData.GetDataPoint(linIntInput) * WorldManager.Instance.HeightScale; // If new height, set it //if (newY != vmap.VertexAt(coord, false).height) vmap.SetHeight (coord, newY); if (newY != 0f) { vmap.AddHeight(coord, newY); } } } if (v == _numVerts - 1) { _isUpdatingVerts = false; yield break; } else if (Time.realtimeSinceStartup - startTime > GameManager.TargetDeltaTime) { yield return(null); startTime = Time.realtimeSinceStartup; } } }
/// <summary> /// Initializes a brand new chunk at x and y. /// </summary> public void Initialize(int x, int y) { DynamicTerrain terrain = DynamicTerrain.Instance; // Init vars _x = x; _y = y; VertexMap vmap = terrain.VertexMap; int chunkRes = WorldManager.Instance.ChunkResolution; float chunkSize = WorldManager.Instance.ChunkSize; // Generate vertices _verts = CreateUniformVertexArray(chunkRes); _numVerts = _verts.Length; // Generate triangles _triangles = CreateSquareArrayTriangles(chunkRes); // Init normals _normals = new Vector3[_numVerts]; // Generate UVs _uvs = CreateUniformUVArray(chunkRes); // Init colors _colors = new Color[_numVerts]; // Init coords and mapVerts _coords = new IntVector2[_numVerts]; _mapVerts = new Vertex[_numVerts]; // Build initial chunk mesh _mesh = CreateChunkMesh(); // Assign mesh GetComponent <MeshFilter>().mesh = _mesh; // Move GameObject to appropriate position transform.position = new Vector3(x * chunkSize - chunkSize / 2f, 0f, y * chunkSize - chunkSize / 2f); // Initialize name gameObject.name = "Chunk (" + x + "," + y + ") Position:" + transform.position.ToString(); // Init decorations list _decorations = new List <GameObject>(); // Register all vertices with vertex map // Move vertices, generate normals/colors for (int i = 0; i < _numVerts; i++) { // Init normal/color _normals[i] = Vector3.up; _colors[i] = Color.white; // Get VMap coords IntVector2 coord = IntToV2(i); _coords[i] = coord; // Get corresponding vertex _mapVerts[i] = vmap.VertexAt(coord, true); // If vertex exists, get height UpdateVertex(i, _mapVerts[i].Height); UpdateColor(i, _mapVerts[i].Color); } // Assign material MeshRenderer renderer = GetComponent <MeshRenderer>(); renderer.sharedMaterial = WorldManager.Instance.TerrainMaterial; renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; renderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off; // Assign collision mesh MeshCollider collider = GetComponent <MeshCollider>(); collider.sharedMesh = _mesh; collider.convex = false; // Init rigidbody Rigidbody rigidbody = GetComponent <Rigidbody>(); rigidbody.freezeRotation = true; rigidbody.isKinematic = true; rigidbody.useGravity = false; rigidbody.constraints = RigidbodyConstraints.FreezeAll; // Add grass system _grassEmitter = GameObject.Instantiate(WorldManager.Instance.GrassEmitterPrefab); _grassEmitter.transform.parent = transform; _grassEmitter.transform.localPosition = Vector3.zero; // Randomize grass density ParticleSystem sys = _grassEmitter.GetComponent <ParticleSystem>(); sys.maxParticles = UnityEngine.Random.Range(0, WorldManager.Instance.GrassPerChunk); sys.playOnAwake = true; // Assign particle system emission shape ParticleSystem.ShapeModule shape = sys.shape; shape.mesh = _mesh; // Assign particle system emission rate ParticleSystem.EmissionModule emit = sys.emission; emit.rate = new ParticleSystem.MinMaxCurve(WorldManager.Instance.DecorationsPerStep); UpdateCollider(); }