void OnDrawGizmos() { if (isVisible && UnityEditor.Selection.activeGameObject == gameObject) { Gizmos.matrix = transform.localToWorldMatrix; Gizmos.color = Color.grey; Vector3 size = new Vector3(TerrainUtils.TERRAIN_TILE_SIZE, 2, TerrainUtils.TERRAIN_TILE_SIZE); Vector3 center = size / 2; Gizmos.DrawWireCube(center, size); Vector3 csize = new Vector3(TerrainUtils.GRASS_TILE_CELL_SIZE, 1.5f, TerrainUtils.GRASS_TILE_CELL_SIZE); for (int i = 0; i < TerrainUtils.GRASS_TILE_CELL_DIM; i++) { for (int j = 0; j < TerrainUtils.GRASS_TILE_CELL_DIM; j++) { GrassTileCell cell = cellMap[i, j]; if (cell != null) { Vector3 ccenter = new Vector3(i * TerrainUtils.GRASS_TILE_CELL_SIZE, 0, j * TerrainUtils.GRASS_TILE_CELL_SIZE) + csize / 2; Gizmos.DrawWireCube(ccenter, csize); } } } Gizmos.color = Color.clear; } }
public void OnUpdate(int updateFrame) { if (!isVisible) { return; } if (isDirty) { bool updateMesh = false; for (int i = 0; i < cellList.Count; i++) { GrassTileCell cell = cellList[i]; if (cell.isTurbulence || cell.turbulenceScale > 1) { updateMesh = true; float n = (!cell.isTurbulence) ? cell.turbulenceScale : cell.turbulenceScale * cell.turbulenceScaleFactor; cell.waveSpeed += cell.waveSpeedStep * ((n - 1) / 2 + 1); uv3[cell.vertStart + 0].x = n; uv3[cell.vertStart + 0].y = cell.waveSpeed - ((float)cell.waveSpeedStart + cell.waveSpeedStep * (float)updateFrame); uv3[cell.vertStart + 1].x = uv3[cell.vertStart + 0].x; uv3[cell.vertStart + 1].y = uv3[cell.vertStart + 0].y; if (cell.isTurbulence) { cell.turbulenceScaleFactor += 0.15f; if (cell.turbulenceScaleFactor > 1) { cell.turbulenceScaleFactor = 1; cell.isTurbulence = false; } } else { cell.turbulenceScale = n > 1 ? n * 0.95f : 1; cell.turbulenceScaleFactor *= 0.95f; } } } if (updateMesh) { meshFilter.sharedMesh.uv3 = uv3; } else { isDirty = false; } } }
public void AddTurbulence(Vector3 pos, float radius, float scale) { if (!gameObject.activeSelf) { return; } float posx = pos.x - basePos.x; float posz = pos.z - basePos.z; float x1 = posx - radius; float x2 = posx + radius; float z1 = posz - radius; float z2 = posz + radius; // out of bounds if (x1 > TerrainUtils.TERRAIN_TILE_SIZE || x2 < 0f || z1 > TerrainUtils.TERRAIN_TILE_SIZE || z2 < 0f) { return; } int cx1 = TerrainUtils.PosToGrid(x1, TerrainUtils.GRASS_TILE_CELL_SIZE, TerrainUtils.GRASS_TILE_CELL_DIM); int cx2 = TerrainUtils.PosToGrid(x2, TerrainUtils.GRASS_TILE_CELL_SIZE, TerrainUtils.GRASS_TILE_CELL_DIM); int cz1 = TerrainUtils.PosToGrid(z1, TerrainUtils.GRASS_TILE_CELL_SIZE, TerrainUtils.GRASS_TILE_CELL_DIM); int cz2 = TerrainUtils.PosToGrid(z2, TerrainUtils.GRASS_TILE_CELL_SIZE, TerrainUtils.GRASS_TILE_CELL_DIM); if (scale < 0) { scale = 0; } if (scale > 1f) { radius *= scale; } for (int i = cz1; i <= cz2; i++) { for (int j = cx1; j <= cx2; j++) { GrassTileCell cell = cellMap[j, i]; if (cell != null) { float cx = TerrainUtils.GridToPos(j, TerrainUtils.GRASS_TILE_CELL_SIZE) + TerrainUtils.GRASS_TILE_CELL_HALF_SIZE; float cz = TerrainUtils.GridToPos(i, TerrainUtils.GRASS_TILE_CELL_SIZE) + TerrainUtils.GRASS_TILE_CELL_HALF_SIZE; float dis = Mathf.Sqrt((cx - posx) * (cx - posx) + (cz - posz) * (cz - posz)); if (dis > radius) { continue; } float f = (1f - dis / radius) * 8f + 1f; f *= scale; if (cell.turbulenceScale < f) { cell.turbulenceScale = f; float ff = Mathf.Acos((cx - posx) / dis); if (cz < posz) { ff = 2 * Mathf.PI - ff; } cell.waveSpeed = 256 * ff / (2 * Mathf.PI); if (cell.turbulenceScaleFactor < 0.1f) { cell.turbulenceScaleFactor = 0.1f; } cell.isTurbulence = true; isDirty = true; } } } } }
private void BuildGrassTile(GrassTileData d) { if (d == null || d.textureIndeics == null) { return; } int grassCount = 0; int grassCounter = 0; int grassSkip = 2; for (int i = 0; i < d.textureIndeics.Length; i++) { for (int l = 0; l < TerrainUtils.GRASS_TILE_CELL_DIM; l++) { for (int m = 0; m < TerrainUtils.GRASS_TILE_CELL_DIM; m++) { int idx = l * TerrainUtils.GRASS_TILE_CELL_DIM + m; int texPos = d.texture[idx]; if (texPos != i || d.size[idx] <= 0) { continue; } if (grassCounter++ % grassSkip != 0) { continue; } grassCount++; } } } if (grassCount <= 0) { return; } grassCounter = 0; Random.seed = d.seed; Vector3 tilePos = new Vector3(); tilePos.x = (float)d.posX * TerrainUtils.TERRAIN_TILE_SIZE; tilePos.z = (float)d.posZ * TerrainUtils.TERRAIN_TILE_SIZE; tilePos.y = TerrainUtils.GetTerrainHeight(tilePos.x + TerrainUtils.TERRAIN_TILE_HALF_SIZE, tilePos.z + TerrainUtils.TERRAIN_TILE_HALF_SIZE); List <GrassTileCell> cellList = new List <GrassTileCell>(); GrassTileCell[,] cellMap = new GrassTileCell[TerrainUtils.GRASS_TILE_CELL_DIM, TerrainUtils.GRASS_TILE_CELL_DIM]; Vector3[] vertices = new Vector3[grassCount * 4]; Color32[] colors = new Color32[grassCount * 4]; Vector2[] uvs = new Vector2[grassCount * 4]; Vector2[] uv3 = new Vector2[grassCount * 4]; Vector3[] normals = new Vector3[grassCount * 4]; List <int> triangles = new List <int>(); int vertIndex = 0; for (int i = 0; i < d.textureIndeics.Length; i++) { int texIndex = d.textureIndeics[i]; Texture2D tex = null; Rect rect = default(Rect); float aspect = 1f; GetTexture(texIndex, ref tex, ref rect, ref aspect); for (int l = 0; l < TerrainUtils.GRASS_TILE_CELL_DIM; l++) { for (int m = 0; m < TerrainUtils.GRASS_TILE_CELL_DIM; m++) { int idx = l * TerrainUtils.GRASS_TILE_CELL_DIM + m; int texPos = d.texture[idx]; int size = d.size[idx]; if (texPos != i || d.size[idx] <= 0) { continue; } if (grassCounter++ % grassSkip != 0) { continue; } float gx = (float)m * TerrainUtils.GRASS_TILE_CELL_SIZE + Random.Range(0f, 0.26f); float gz = (float)l * TerrainUtils.GRASS_TILE_CELL_SIZE + Random.Range(0f, 0.26f); float gy = TerrainUtils.GetTerrainHeight(gx + tilePos.x, gz + tilePos.z) - tilePos.y; int rotation = Random.Range(0, 63); int waveSpeed = Random.Range(0, 255); float sx = gx; float sz = gz; float r = Mathf.Deg2Rad * ((float)rotation / 64f * -60f + -30f); float s = (float)size; float hw = aspect / 2f; float hwsinr = hw * Mathf.Sin(r); float hwcosr = hw * Mathf.Cos(r); vertices[vertIndex + 0].x = -hwcosr * s + sx; vertices[vertIndex + 0].y = 1 * s + gy; vertices[vertIndex + 0].z = -hwsinr * s + sz; vertices[vertIndex + 1].x = hwcosr * s + sx; vertices[vertIndex + 1].y = 1 * s + gy; vertices[vertIndex + 1].z = hwsinr * s + sz; vertices[vertIndex + 2].x = -hwcosr * s + sx; vertices[vertIndex + 2].y = 0 * s + gy; vertices[vertIndex + 2].z = -hwsinr * s + sz; vertices[vertIndex + 3].x = hwcosr * s + sx; vertices[vertIndex + 3].y = 0 * s + gy; vertices[vertIndex + 3].z = hwsinr * s + sz; r = Mathf.Deg2Rad * (Random.Range(0, 360f) * -60f + -30f); sx = gx + Random.Range(-1f, 1f) * hw * s; sz = gz + Random.Range(-1f, 1f) * hw * s; uvs[vertIndex + 0].x = rect.xMin; uvs[vertIndex + 0].y = rect.yMax - 0.01f; uvs[vertIndex + 1].x = rect.xMax; uvs[vertIndex + 1].y = rect.yMax - 0.01f; uvs[vertIndex + 2].x = rect.xMin; uvs[vertIndex + 2].y = rect.yMin; uvs[vertIndex + 3].x = rect.xMax; uvs[vertIndex + 3].y = rect.yMin; colors[vertIndex + 0] = useColors[texIndex]; colors[vertIndex + 1] = useColors[texIndex]; colors[vertIndex + 2] = useColors[texIndex]; colors[vertIndex + 3] = useColors[texIndex]; uv3[vertIndex + 0].x = 1; uv3[vertIndex + 0].y = waveSpeed; uv3[vertIndex + 1].x = 1; uv3[vertIndex + 1].y = waveSpeed; uv3[vertIndex + 2].x = 0f; uv3[vertIndex + 2].y = 0f; uv3[vertIndex + 3].x = 0f; uv3[vertIndex + 3].y = 0f; normals[vertIndex + 0].x = 0f; normals[vertIndex + 0].y = 1f; normals[vertIndex + 0].z = 0f; normals[vertIndex + 1].x = 0f; normals[vertIndex + 1].y = 1f; normals[vertIndex + 1].z = 0f; normals[vertIndex + 2].x = 0f; normals[vertIndex + 2].y = 1f; normals[vertIndex + 2].z = 0f; normals[vertIndex + 3].x = 0f; normals[vertIndex + 3].y = 1f; normals[vertIndex + 3].z = 0f; triangles.Add(vertIndex + 0); triangles.Add(vertIndex + 1); triangles.Add(vertIndex + 2); triangles.Add(vertIndex + 1); triangles.Add(vertIndex + 3); triangles.Add(vertIndex + 2); GrassTileCell cell = new GrassTileCell(); cell.vertStart = vertIndex; cell.waveSpeed = (float)waveSpeed; cell.waveSpeedStart = waveSpeed; cell.waveSpeedStep = 1 + Random.Range(0.0f, 1.0f); cell.turbulenceScale = 1; cell.turbulenceScaleFactor = 0.1f; cell.isTurbulence = true; cellList.Add(cell); cellMap[m, l] = cell; vertIndex += 4; } } } // create grass tile string tileName = string.Format("GrassTile({0},{1})", d.posX, d.posZ); GameObject gameObject = new GameObject(tileName); gameObject.transform.parent = transform; gameObject.transform.localPosition = Vector3.zero; gameObject.transform.localRotation = Quaternion.identity; gameObject.transform.localScale = Vector3.one; gameObject.hideFlags = HideFlags.DontSaveInEditor; gameObject.layer = LayerMask.NameToLayer("Terrain"); gameObject.transform.localPosition = tilePos; Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.uv = uvs; mesh.colors32 = colors; mesh.normals = normals; mesh.uv3 = uv3; mesh.triangles = triangles.ToArray(); MeshFilter meshFilter = gameObject.GetComponent <MeshFilter>(); if (meshFilter == null) { meshFilter = gameObject.AddComponent <MeshFilter>(); } meshFilter.sharedMesh = mesh; MeshRenderer meshRenderer = gameObject.GetComponent <MeshRenderer>(); if (meshRenderer == null) { meshRenderer = gameObject.AddComponent <MeshRenderer>(); } meshRenderer.sharedMaterial = packedMaterial; meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; mesh.MarkDynamic(); GrassTile tile = gameObject.GetComponent <GrassTile>(); if (tile == null) { tile = gameObject.AddComponent <GrassTile>(); } tile.basePos = tilePos; tile.cellList = cellList; tile.cellMap = cellMap; tile.meshRenderer = meshRenderer; tile.meshFilter = meshFilter; tile.uv3 = uv3; tile.Init(); tileList.Add(tile); }