private static void ApplyTexturesToNewTerrain(TerrainData terrainData, TextureData data) { if (data.ControlTextureResolution != terrainData.alphamapResolution) { data.AdjustSplatMapResolution(terrainData.alphamapResolution); } terrainData.SetAlphamaps(0, 0, data.SplatMaps); }
/// <summary> /// Creates terrain data from heights. /// </summary> /// <param name="heightPercents">Terrain height percentages ranging from 0 to 1.</param> /// <param name="maxHeight">The maximum height of the terrain, corresponding to a height percentage of 1.</param> /// <param name="heightSampleDistance">The horizontal/vertical distance between height samples.</param> /// <param name="splatPrototypes">The textures used by the terrain.</param> /// <param name="alphaMap">Texture blending information.</param> /// <returns>A TerrainData instance.</returns> public static TerrainData CreateTerrainData(float[,] heightPercents, float maxHeight, float heightSampleDistance, SplatPrototype[] splatPrototypes, float[,,] alphaMap) { Debug.Assert((heightPercents.GetLength(0) == heightPercents.GetLength(1)) && (maxHeight >= 0) && (heightSampleDistance >= 0)); // Create the TerrainData. var terrainData = new TerrainData(); terrainData.heightmapResolution = heightPercents.GetLength(0); var terrainWidth = (terrainData.heightmapResolution - 1) * heightSampleDistance; // If maxHeight is 0, leave all the heights in terrainData at 0 and make the vertical size of the terrain 1 to ensure valid AABBs. if(!Mathf.Approximately(maxHeight, 0)) { terrainData.size = new Vector3(terrainWidth, maxHeight, terrainWidth); terrainData.SetHeights(0, 0, heightPercents); } else { terrainData.size = new Vector3(terrainWidth, 1, terrainWidth); } // Texture the terrain. if((splatPrototypes != null) && (alphaMap != null)) { Debug.Assert(alphaMap.GetLength(0) == alphaMap.GetLength(1)); terrainData.alphamapResolution = alphaMap.GetLength(0); terrainData.splatPrototypes = splatPrototypes; terrainData.SetAlphamaps(0, 0, alphaMap); } return terrainData; }
void Start() { terr = Terrain.activeTerrain.terrainData; splatData = new float[terr.alphamapWidth, terr.alphamapHeight, terr.alphamapLayers]; for(int x = 0; x < terr.alphamapWidth; x++) { for(int y = 0; y < terr.alphamapHeight; y++) { splatData[x, y, 0] = 1; splatData[x, y, 1] = 0; } } terr.SetAlphamaps(0, 0, splatData); }
internal static void RemoveSplatTexture(TerrainData terrainData, int index) { Undo.RegisterCompleteObjectUndo((Object) terrainData, "Remove texture"); int alphamapWidth = terrainData.alphamapWidth; int alphamapHeight = terrainData.alphamapHeight; float[,,] alphamaps = terrainData.GetAlphamaps(0, 0, alphamapWidth, alphamapHeight); int length1 = alphamaps.GetLength(2); int length2 = length1 - 1; float[,,] map = new float[alphamapHeight, alphamapWidth, length2]; for (int index1 = 0; index1 < alphamapHeight; ++index1) { for (int index2 = 0; index2 < alphamapWidth; ++index2) { for (int index3 = 0; index3 < index; ++index3) map[index1, index2, index3] = alphamaps[index1, index2, index3]; for (int index3 = index + 1; index3 < length1; ++index3) map[index1, index2, index3 - 1] = alphamaps[index1, index2, index3]; } } for (int index1 = 0; index1 < alphamapHeight; ++index1) { for (int index2 = 0; index2 < alphamapWidth; ++index2) { float num1 = 0.0f; for (int index3 = 0; index3 < length2; ++index3) num1 += map[index1, index2, index3]; if ((double) num1 >= 0.01) { float num2 = 1f / num1; for (int index3 = 0; index3 < length2; ++index3) map[index1, index2, index3] *= num2; } else { for (int index3 = 0; index3 < length2; ++index3) map[index1, index2, index3] = index3 != 0 ? 0.0f : 1f; } } } SplatPrototype[] splatPrototypes = terrainData.splatPrototypes; SplatPrototype[] splatPrototypeArray = new SplatPrototype[splatPrototypes.Length - 1]; for (int index1 = 0; index1 < index; ++index1) splatPrototypeArray[index1] = splatPrototypes[index1]; for (int index1 = index + 1; index1 < length1; ++index1) splatPrototypeArray[index1 - 1] = splatPrototypes[index1]; terrainData.splatPrototypes = splatPrototypeArray; terrainData.SetAlphamaps(0, 0, map); }
public override void OnInspectorGUI() { DrawDefaultInspector(); if (GUILayout.Button("Generuj")) { var terrainData = new TerrainData { heightmapResolution = 65, size = new Vector3(50f, 20f, 50f) }; int xSize = terrainData.heightmapHeight; int zSize = terrainData.heightmapWidth; const float noiseScale = 1.5f; var heights = terrainData.GetHeights(0, 0, xSize, zSize); float[][] noise = PerlinTools.GeneratePerlinNoise(xSize, zSize, 8); for (var x = 0; x < terrainData.heightmapHeight; x++) { for (var z = 0; z < terrainData.heightmapWidth; z++) { heights[x, z] = noise[x][z] * noiseScale; } } terrainData.SetHeights(0, 0, heights); var tekstura = Resources.Load<Texture2D>( "prototype_textures/Textures/proto_blue"); if (tekstura != null) { var sp = new SplatPrototype[1]; sp[0] = new SplatPrototype{texture = tekstura}; terrainData.splatPrototypes = sp; var alphamaps = new float[xSize, zSize, sp.Length]; for(int ax = 0; ax < xSize; ++ax) for(int az = 0; az < zSize; ++az) for (int tex = 0; tex < sp.Length; ++tex) alphamaps[ax, az, tex] = Math.Abs(Mathf.Sin(ax*1.2f + az*1.3f)); terrainData.SetAlphamaps(0, 0, alphamaps); } GameObject terrain = Terrain.CreateTerrainGameObject(terrainData); } /* _Terrain.terr = Terrain.activeTerrain; hmWidth = terr.terrainData.heightmapWidth; hmHeight = terr.terrainData.heightmapHeight; Terrain.activeTerrain.heightmapMaximumLOD = 0; // get the heights of the terrain under this game object float[,] heights = terr.terrainData.GetHeights(0, 0, hmWidth, hmHeight); // we set each sample of the terrain in the size to the desired height //for (int i=0; i<hmWidth; i++) //for (int j=0; j<hmHeight; j++){ //heights[i,j] = (Mathf.Sin(i/10f)/100f + Mathf.Cos((i+j)/10f) / 100f) + 0.5f; float[][] mapa = PerlinTools.GeneratePerlinNoise(hmWidth, hmHeight, 4); for (int x = 0; x < hmWidth; ++x) for (int z = 0; z < hmHeight; ++z) { heights[x, z] = mapa[x][z] / 1000f; } //print(heights[i,j]); //} // set the new height terr.terrainData.SetHeights(0, 0, heights); */ }
/// <summary> /// Read the data into the specified value. /// </summary> /// <param name="value">Value.</param> /// <param name="reader">Reader.</param> public override void ReadInto(object value, ISaveGameReader reader) { UnityEngine.TerrainData terrainData = (UnityEngine.TerrainData)value; foreach (string property in reader.Properties) { switch (property) { case "alphamaps": terrainData.SetAlphamaps(0, 0, reader.ReadProperty <float [, , ]> ()); break; case "heights": terrainData.SetHeights(0, 0, reader.ReadProperty <float [, ]> ()); break; case "heightmapResolution": terrainData.heightmapResolution = reader.ReadProperty <System.Int32> (); break; case "size": terrainData.size = reader.ReadProperty <UnityEngine.Vector3> (); break; case "thickness": terrainData.thickness = reader.ReadProperty <System.Single> (); break; case "wavingGrassStrength": terrainData.wavingGrassStrength = reader.ReadProperty <System.Single> (); break; case "wavingGrassAmount": terrainData.wavingGrassAmount = reader.ReadProperty <System.Single> (); break; case "wavingGrassSpeed": terrainData.wavingGrassSpeed = reader.ReadProperty <System.Single> (); break; case "wavingGrassTint": terrainData.wavingGrassTint = reader.ReadProperty <UnityEngine.Color> (); break; case "detailPrototypes": terrainData.detailPrototypes = reader.ReadProperty <UnityEngine.DetailPrototype []> (); break; case "treeInstances": terrainData.treeInstances = reader.ReadProperty <UnityEngine.TreeInstance []> (); break; case "treePrototypes": terrainData.treePrototypes = reader.ReadProperty <UnityEngine.TreePrototype []> (); break; case "alphamapResolution": terrainData.alphamapResolution = reader.ReadProperty <System.Int32> (); break; case "baseMapResolution": terrainData.baseMapResolution = reader.ReadProperty <System.Int32> (); break; case "splatPrototypes": terrainData.splatPrototypes = reader.ReadProperty <UnityEngine.SplatPrototype []> (); break; case "name": terrainData.name = reader.ReadProperty <System.String> (); break; case "hideFlags": terrainData.hideFlags = reader.ReadProperty <UnityEngine.HideFlags> (); break; } } }
static public void AddSplatmaps (TerrainData data, Matrix[] matrices, int[] channels, float[] opacity, float[,,] array=null, float brushFallof=0.5f) { int numChannels = data.alphamapLayers; bool[] usedChannels = new bool[numChannels]; for (int i=0; i<channels.Length; i++) usedChannels[channels[i]] = true; float[] slice = new float[numChannels]; Coord dataSize = new Coord(data.alphamapResolution, data.alphamapResolution); CoordRect dataRect = new CoordRect(new Coord(0,0), dataSize); CoordRect intersection = CoordRect.Intersect(dataRect, matrices[0].rect); if (array==null) array = data.GetAlphamaps(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z); Coord min = intersection.Min; Coord max = intersection.Max; for (int x=min.x; x<max.x; x++) for (int z=min.z; z<max.z; z++) { //calculating fallof and opacity float fallofFactor = matrices[0].Fallof(x,z,brushFallof); if (Mathf.Approximately(fallofFactor,0)) continue; //reading slice for (int c=0; c<numChannels; c++) slice[c] = array[z-min.z, x-min.x, c]; //converting matrices to additive for (int i=0; i<matrices.Length; i++) matrices[i][x,z] = Mathf.Max(0, matrices[i][x,z] - slice[channels[i]]); //apply fallof for (int i=0; i<matrices.Length; i++) matrices[i][x,z] *= fallofFactor * opacity[i]; //calculating sum of adding values float addedSum = 0; //the sum of adding channels for (int i=0; i<matrices.Length; i++) addedSum += matrices[i][x,z]; //if (addedSum < 0.00001f) continue; //no need to do anything //if addedsum exceeds 1 - equalizing matrices if (addedSum > 1f) { for (int i=0; i<matrices.Length; i++) matrices[i][x,z] /= addedSum; addedSum=1; } //multiplying all values on a remaining amount float multiplier = 1-addedSum; for (int c=0; c<numChannels; c++) slice[c] *= multiplier; //adding matrices for (int i=0; i<matrices.Length; i++) slice[channels[i]] += matrices[i][x,z]; //saving slice for (int c=0; c<numChannels; c++) array[z-min.z, x-min.x, c] = slice[c]; } data.SetAlphamaps(intersection.offset.x, intersection.offset.z, array); }
void finalizeHeightmap(RenderedHeightmap rh) { TerrainData tData = new TerrainData(); tData.heightmapResolution = chunkResolution; tData.alphamapResolution = chunkResolution; tData.SetDetailResolution(chunkResolution*2, 1); tData.size = new Vector3(chunkWidth, terrainHeight, chunkWidth); tData.splatPrototypes = splats; tData.detailPrototypes = grassProto; tData.treePrototypes = treeProto; tData.RefreshPrototypes(); // tree placement tData.treeInstances = rh.treeInstances.ToArray(); /* Create and position the terrain */ GameObject terrain = Terrain.CreateTerrainGameObject(tData); terrain.transform.position = new Vector3 ( chunkWidth * rh.coord.x, 0.0f, chunkWidth * rh.coord.z); /* Set the heightmap data from the background thread. */ tData.SetHeights(0, 0, rh.heightmap); stitchTerrain(tData, rh.coord); chunks[rh.coord] = tData; // texturing tData.SetAlphamaps(0, 0, rh.splatmap); // grass placement /*if (texturesToAffect.Length != 0) { var detailedLayer = grassPlacement (tData.detailResolution, tData.GetAlphamaps (0, 0, tData.alphamapWidth, tData.alphamapHeight)); tData.SetDetailLayer (0, 0, grassType, detailedLayer); }*/ }
public void generer(float lx, float lz) { this.lx = lx; this.lz = lz; data = terrain.terrainData; float[, ,] alphas = data.GetAlphamaps(0, 0, data.alphamapWidth, data.alphamapHeight); Debug.Log ("alpha width : " + data.alphamapWidth); Debug.Log ("alpha he : " + data.alphamapWidth); Debug.Log ("world size : " + data.size); Debug.Log ("distance between patch X : " + data.size[0] / data.alphamapWidth); Debug.Log ("distance between patch Y : " + data.size[1] / data.alphamapHeight); dx = data.size [0] / data.alphamapWidth; dz = data.size [2] / data.alphamapHeight; for (int i = 0; i < data.alphamapWidth; i++) { for (int j = 0; j < data.alphamapHeight; j++) { foreach (Terrains t in Enum.GetValues(typeof(Terrains))) { alphas[j, i, (int) t] = 0; } alphas[j, i, (int) Terrains.BANQUISE] = 100; } } data.SetAlphamaps(0, 0, alphas); changeHexagoneTexture (0, 0, Terrains.BANQUISE); }
public void Perform(TerrainData data) { data.SetHeights(heightsOffsetX,heightsOffsetZ,heights); if (splats!=null) data.SetAlphamaps(splatsOffsetX,splatsOffsetZ,splats); }
//конец блока нормализации //Применяем полученый SplatMap на терейн дату private void LoadSplats(string xvalue, string yvalue, ref TerrainData tdata) { if (_splats.Count > 0) { float[, ,] splatarray = new float[(int)_heightmapsize.x, (int)_heightmapsize.y, _splats.Count]; SplatPrototype[] prototypes = new SplatPrototype[_splats.Count]; for (int k = 0; k < _splats.Count; k++) { LoadSplat(_splats[k], _normals[k], k, xvalue, yvalue, ref prototypes, ref splatarray); // Прогресс бар (тормазим работу :) //EditorUtility.DisplayProgressBar("Importing Splat", ((k + 1)).ToString() + " Splat Files", 1); } if (_optionSplatMix) //Если стоит галочка нормализовать { NORMALIZ(ref splatarray); } tdata.splatPrototypes = prototypes; tdata.SetAlphamaps(0, 0, splatarray); prototypes = null; splatarray = null; System.GC.Collect(0); } }
/// <summary> /// Preprocess the terrain to clamp down on the number of splat maps which have weights on each control point. First pass /// limits the number of weights to the specified amount per control point. Since each rendered pixel is a blend of 4 possible /// control points, this still means a given pixel may need up to 4 weights even if the control point is clamped to 1 weight. /// In the second pass, we check all of the neighoring pixels to see if they have different weights- if they do, we clamp /// down to one less weight on this control point. The idea here is to create some extra headroom for the blend, but since /// you can still need 4 blend weights in some cases, there is no perfect solution to this issue when running with less than /// 4 blend weights. It does, however, greatly help when running under those constraints. /// /// </summary> /// <param name="bt">Bt.</param> /// <param name="maxWeights">Max weights.</param> /// <param name="secondPass">If set to <c>true</c> second pass.</param> public static void WeightLimitTerrain(MicroSplatTerrain bt, int maxWeights, bool secondPass = false) { Terrain t = bt.GetComponent <Terrain>(); if (t == null) { return; } UnityEngine.TerrainData td = t.terrainData; if (td == null) { return; } int w = td.alphamapWidth; int h = td.alphamapHeight; int l = td.alphamapLayers; Undo.RegisterCompleteObjectUndo(t, "Weight Limit Terrain"); var splats = td.GetAlphamaps(0, 0, w, h); float[] data = new float[16]; List <WeightPair> sorted = new List <WeightPair>(); List <int> validIndexes = new List <int>(); for (int x = 0; x < w; ++x) { for (int y = 0; y < h; ++y) { // gather all weights for (int i = 0; i < l; ++i) { data[i] = splats[x, y, i]; } sorted.Clear(); for (int i = 0; i < 16; ++i) { var wp = new WeightPair(); wp.index = i; wp.weight = data[i]; sorted.Add(wp); } sorted.Sort((w0, w1) => w1.weight.CompareTo(w0.weight)); // remove lower weights int allowedWeights = maxWeights; while (sorted.Count > allowedWeights) { sorted.RemoveAt(sorted.Count - 1); } // generate valid index list validIndexes.Clear(); for (int i = 0; i < sorted.Count; ++i) { if (sorted[i].weight > 0) { validIndexes.Add(sorted[i].index); } } // figure out if our neighbors have weights which we don't have- if so, clamp down harder to make room for blending.. // if not, allow us to blend fully. We do this in a second pass so that small weights are reduced before we make // this decision.. if (secondPass) { for (int xm = -1; xm < 2; ++xm) { for (int ym = -1; ym < 2; ++ym) { int nx = x + xm; int ny = y + ym; if (nx >= 0 && ny >= 0 && nx < w && ny < y) { for (int layer = 0; layer < l; ++layer) { float weight = splats[nx, ny, layer]; if (weight > 0 && !validIndexes.Contains(layer)) { allowedWeights = maxWeights - 1; } } } } } while (sorted.Count > allowedWeights) { sorted.RemoveAt(sorted.Count - 1); } // generate valid index list validIndexes.Clear(); for (int i = 0; i < sorted.Count; ++i) { if (sorted[i].weight > 0) { validIndexes.Add(sorted[i].index); } } } // clear non-valid indexes for (int j = 0; j < 16; ++j) { if (!validIndexes.Contains(j)) { data[j] = 0; } } // now normalize weights so that they total one on each pixel float total = 0; for (int j = 0; j < 16; ++j) { total += data[j]; } float scale = 1.0f / total; for (int j = 0; j < 16; ++j) { data[j] *= scale; } // now map back to splat data array for (int i = 0; i < l; ++i) { splats[x, y, i] = data[i]; } } } td.SetAlphamaps(0, 0, splats); }
private void ApplyTextures(TerrainData data) { var flatSplat = new SplatPrototype(); var steepSplat = new SplatPrototype(); flatSplat.texture = Settings.FlatTexture; steepSplat.texture = Settings.SteepTexture; data.splatPrototypes = new [] { flatSplat, steepSplat }; data.RefreshPrototypes(); var splatMap = new float[data.alphamapResolution, data.alphamapResolution, 2]; for (var z = 0; z < data.alphamapHeight; z++) { for (var x = 0; x < data.alphamapWidth; x++) { var normalizedX = (float)x / (data.alphamapWidth - 1); var normalizedZ = (float)z / (data.alphamapHeight - 1); var steepness = data.GetSteepness(normalizedX, normalizedZ) * Settings.SteepnessTextureMultiplier; var steepnessNormalized = Mathf.Clamp(steepness, 0, 1f); splatMap[z, x, 0] = 1f - steepnessNormalized; splatMap[z, x, 1] = steepnessNormalized; } } data.SetAlphamaps(0, 0, splatMap); }
public void Perform(TerrainData data) { data.SetHeights(x,z,heights); if (splats!=null) data.SetAlphamaps(x,z,splats); }
internal static void RemoveSplatTexture(TerrainData terrainData, int index) { Undo.RegisterCompleteObjectUndo(terrainData, "Remove texture"); int alphamapWidth = terrainData.alphamapWidth; int alphamapHeight = terrainData.alphamapHeight; float[,,] numArray = terrainData.GetAlphamaps(0, 0, alphamapWidth, alphamapHeight); int length = numArray.GetLength(2); int num4 = length - 1; float[,,] map = new float[alphamapHeight, alphamapWidth, num4]; for (int i = 0; i < alphamapHeight; i++) { for (int n = 0; n < alphamapWidth; n++) { for (int num7 = 0; num7 < index; num7++) { map[i, n, num7] = numArray[i, n, num7]; } for (int num8 = index + 1; num8 < length; num8++) { map[i, n, num8 - 1] = numArray[i, n, num8]; } } } for (int j = 0; j < alphamapHeight; j++) { for (int num10 = 0; num10 < alphamapWidth; num10++) { float num11 = 0f; for (int num12 = 0; num12 < num4; num12++) { num11 += map[j, num10, num12]; } if (num11 >= 0.01) { float num13 = 1f / num11; for (int num14 = 0; num14 < num4; num14++) { float single1 = map[j, num10, num14]; single1[0] *= num13; } } else { for (int num15 = 0; num15 < num4; num15++) { map[j, num10, num15] = (num15 != 0) ? 0f : 1f; } } } } SplatPrototype[] splatPrototypes = terrainData.splatPrototypes; SplatPrototype[] prototypeArray2 = new SplatPrototype[splatPrototypes.Length - 1]; for (int k = 0; k < index; k++) { prototypeArray2[k] = splatPrototypes[k]; } for (int m = index + 1; m < length; m++) { prototypeArray2[m - 1] = splatPrototypes[m]; } terrainData.splatPrototypes = prototypeArray2; terrainData.SetAlphamaps(0, 0, map); }
void UpdateTerrainTexture( TerrainData terrainData ) { if(disableProceduralTerrain) return; float[, ,] alphas = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight); float alphaToHeightMapCoordsW = terrainData.heightmapWidth/terrainData.alphamapWidth; float alphaToHeightMapCoordsH = terrainData.heightmapHeight/terrainData.alphamapHeight; for (int i = 0; i < terrainData.alphamapWidth; i++) { for (int j = 0; j < terrainData.alphamapHeight; j++) { int hi = (int)(i*alphaToHeightMapCoordsW); int hj = (int)(j*alphaToHeightMapCoordsH); float terrainInterp = Mathf.Clamp((_heightMap[hi,hj] / snowHeight),0f,1f); alphas[i, j, 0] = 1f - terrainInterp; alphas[i, j, 1] = terrainInterp; } } terrainData.SetAlphamaps(0, 0, alphas); }
void texturizeTerrain(TerrainData terrainData, float max_altura) { float[, ,] map = new float[tamAlpha, tamAlpha, terrainData.alphamapLayers]; Random.seed = 0; for (int x = 0; x < tamAlpha; x++) { for (int z = 0; z < tamAlpha; z++) { //** texturizado float normX = x * 1.0f / (tamAlpha - 1); float normZ = z * 1.0f / (tamAlpha - 1); float height = terrainData.GetHeight(Mathf.RoundToInt(normX * terrainData.heightmapHeight), Mathf.RoundToInt(normZ * terrainData.heightmapWidth)); float[] splatWeights = new float[terrainData.alphamapLayers]; float peso = 0; if (height <= max_altura * AlphaCorte1) { peso = height / (max_altura * AlphaCorte1); splatWeights[0] = 1 - peso; splatWeights[1] = peso; } if ((height > max_altura * AlphaCorte1) && (height <= max_altura * AlphaCorte2)) { float altura2 = height - (max_altura * AlphaCorte1); float maximo2 = (max_altura * AlphaCorte2) - (max_altura * AlphaCorte1); peso = altura2 / maximo2; splatWeights[1] = 1 - peso; splatWeights[2] = peso; } if ((height > max_altura * AlphaCorte2) && (height <= max_altura)) { float altura2 = height - (max_altura * AlphaCorte2); float maximo2 = max_altura - (max_altura * AlphaCorte2); peso = altura2 / maximo2; splatWeights[2] = 1 - peso; splatWeights[3] = peso; } float suma = splatWeights.Sum(); //Recorremos las texturas y las pintamos. for (int i = 0; i < terrainData.alphamapLayers; i++) { splatWeights[i] /= suma; map[z, x, i] = splatWeights[i]; } } } terrainData.alphamapResolution = tamAlpha; terrainData.SetAlphamaps(0, 0, map); }
void finalizeHeightmap(RenderedHeightmap rh) { TerrainData tData = new TerrainData(); tData.heightmapResolution = chunkResolution; tData.alphamapResolution = chunkResolution; tData.size = new Vector3(chunkWidth, terrainHeight, chunkWidth); tData.splatPrototypes = splats; tData.RefreshPrototypes(); /* Create and position the terrain */ GameObject terrain = Terrain.CreateTerrainGameObject(tData); terrain.transform.position = new Vector3( chunkWidth * rh.coord.x, 0.0f, chunkWidth * rh.coord.z); /* Set the heightmap data from the background thread. */ tData.SetHeights(0, 0, rh.heightmap); stitchTerrain(tData, rh.coord); chunks[rh.coord] = tData; // texturing tData.SetAlphamaps(0, 0, rh.splatmap); }
void FillAlphaMapByBiomes (TerrainData terrainData) { float[,,] map = new float[m_alphaMapSize, m_alphaMapSize, 15]; Random.seed = 0; for(int x = 0; x < m_alphaMapSize; x++) { for (int z = 0; z < m_alphaMapSize; z++) { float ratio = (float)(m_heightMapSize-1)/m_alphaMapSize; Center.BiomeTypes biome = getCenter[(int)(x*ratio),(int)(z*ratio)].biome; for (int i=0; i< 15;i++) map[z,x,i]= 0; map[z,x,(int)biome]=1; } } terrainData.SetAlphamaps(0, 0, map); //pridruzi alfa mapu terenu }
/// <summary> /// Remove splatprototype /// </summary> /// <param name="td"></param> /// <param name="index"></param> public static void RemoveSplatTexture(TerrainData td, int index) { Point size = new Point(td.alphamapWidth, td.alphamapHeight); float[,,] alphamaps = td.GetAlphamaps(0, 0, size.x, size.y); float[,,] newAlphaMaps = new float[alphamaps.GetLength(0), alphamaps.GetLength(1), alphamaps.GetLength(2) - 1]; // Duplicate except the removed for (int i = 0; i < size.y; i++) { for (int j = 0; j < size.x; j++) { for (int k = 0; k < index; k++) { newAlphaMaps[i, j, k] = alphamaps[i, j, k]; } for (int l = index + 1; l < alphamaps.GetLength(2); l++) { newAlphaMaps[i, j, l - 1] = alphamaps[i, j, l]; } } } for (int i = 0; i < size.y; i++) { for (int j = 0; j < size.x; j++) { float alpha = 0f; for (int k = 0; k < alphamaps.GetLength(2) - 1; k++) { alpha += newAlphaMaps[i, j, k]; } if (alpha >= 0.01f) { for (int k = 0; k < alphamaps.GetLength(2) - 1; k++) { newAlphaMaps[i, j, k] *= (1.0f / alpha); } } else { for (int k = 0; k < alphamaps.GetLength(2) - 1; k++) { newAlphaMaps[i, j, k] = ((k != 0) ? 0f : 1f); } } } } SplatPrototype[] newSplat = new SplatPrototype[td.splatPrototypes.Length - 1]; for (int i = 0; i < index; i++) { newSplat[i] = td.splatPrototypes[i]; } for (int i = index + 1; i < alphamaps.GetLength(2); i++) { newSplat[i - 1] = td.splatPrototypes[i]; } td.splatPrototypes = newSplat; td.SetAlphamaps(0, 0, newAlphaMaps); }
/// <summary> /// Create terrain for the given tile /// </summary> private Terrain CreateTerrainTile(int x, int z) { float height = _terrainSettings.TerrainHeight; var centerTile = x == (_tilesX / 2) && z == (_tilesZ / 2); //Create terrain data and set prototypes var data = new TerrainData { heightmapResolution = _terrainSettings.HeightmapSize, alphamapResolution = _terrainSettings.AlphamapSize, size = new Vector3(_terrainSize, height, _terrainSize), splatPrototypes = _splatPrototypes, treePrototypes = _treePrototypes, detailPrototypes = _detailPrototypes }; //Generate heightmap data.SetHeights(0, 0, GenerateHeightMap(x, z)); //create terrain gameobject and position it correctly var xPos = _terrainSize * x + _terrainOffset.x; var zPos = _terrainSize * z + _terrainOffset.y; var terrain = Terrain.CreateTerrainGameObject(data).GetComponent<Terrain>(); terrain.transform.position = new Vector3(xPos, 0, zPos); terrain.gameObject.SetParent(_terrainGameObject); terrain.name = string.Format("tile{0}x{1}", x, z); terrain.castShadows = false; terrain.detailObjectDensity = _terrainSettings.GrassDensity; terrain.detailObjectDistance = 200.0f; terrain.treeDistance = 1000.0f; terrain.treeBillboardDistance = 400.0f; terrain.treeCrossFadeLength = 20.0f; terrain.treeMaximumFullLODCount = 400; //Generate trees if (!centerTile) { //Possibly generate some lakes var rng = Random.value; if (_terrainSettings.GenerateLake && rng < 0.75f) { var it = Random.Range(1, 4); for (int i = 0; i < it; i++) { //add a lake o the terrain with a random size AddLake(terrain, x, z, Random.Range(25, 60)); } } var trees = GenerateTrees(data, x, z); if (trees != null) { foreach (var tree in trees) { terrain.AddTreeInstance(tree); } } } //Generate alphamap if valid var alphamap = GenerateAlphaMap(data); if (alphamap != null) { data.SetAlphamaps(0, 0, alphamap); } //Generate Detailsmap if valid for every layer var detailLayers = GenerateDetailLayers(data, x, z); if (detailLayers != null) { //set some detail settings data.SetDetailResolution(_terrainSettings.DetailMapSize, _terrainSettings.DetailResolution); data.wavingGrassStrength = 0.1f; data.wavingGrassAmount = 0.1f; data.wavingGrassSpeed = 0.2f; data.wavingGrassTint = Color.white; for (int layer = 0; layer < detailLayers.Count; ++layer) { data.SetDetailLayer(0, 0, layer, detailLayers[layer]); } } //make sure the changes are updated terrain.Flush(); return terrain; }
void FillAlphaMap(TerrainData terrainData) { float[,,] map = new float[m_alphaMapSize, m_alphaMapSize, 2]; Random.seed = 0; for(int x = 0; x < m_alphaMapSize; x++) { for (int z = 0; z < m_alphaMapSize; z++) { // Get the normalized terrain coordinate that // corresponds to the the point. float normX = x * 1.0f / (m_alphaMapSize - 1); float normZ = z * 1.0f / (m_alphaMapSize - 1); // Get the steepness value at the normalized coordinate. float angle = terrainData.GetSteepness(normX, normZ); // Steepness is given as an angle, 0..90 degrees. Divide // by 90 to get an alpha blending value in the range 0..1. float frac = angle / 90.0f; map[z, x, 0] = frac; map[z, x, 1] = 1.0f - frac; } } terrainData.alphamapResolution = m_alphaMapSize; terrainData.SetAlphamaps(0, 0, map); }
internal static void RemoveSplatTexture(TerrainData terrainData, int index) { Undo.RegisterCompleteObjectUndo(terrainData, "Remove texture"); int alphamapWidth = terrainData.alphamapWidth; int alphamapHeight = terrainData.alphamapHeight; float[,,] alphamaps = terrainData.GetAlphamaps(0, 0, alphamapWidth, alphamapHeight); int length = alphamaps.GetLength(2); int num = length - 1; float[,,] array = new float[alphamapHeight, alphamapWidth, num]; for (int i = 0; i < alphamapHeight; i++) { for (int j = 0; j < alphamapWidth; j++) { for (int k = 0; k < index; k++) { array[i, j, k] = alphamaps[i, j, k]; } for (int l = index + 1; l < length; l++) { array[i, j, l - 1] = alphamaps[i, j, l]; } } } for (int m = 0; m < alphamapHeight; m++) { for (int n = 0; n < alphamapWidth; n++) { float num2 = 0f; for (int num3 = 0; num3 < num; num3++) { num2 += array[m, n, num3]; } if ((double)num2 >= 0.01) { float num4 = 1f / num2; for (int num5 = 0; num5 < num; num5++) { array[m, n, num5] *= num4; } } else { for (int num6 = 0; num6 < num; num6++) { array[m, n, num6] = ((num6 != 0) ? 0f : 1f); } } } } SplatPrototype[] splatPrototypes = terrainData.splatPrototypes; SplatPrototype[] array2 = new SplatPrototype[splatPrototypes.Length - 1]; for (int num7 = 0; num7 < index; num7++) { array2[num7] = splatPrototypes[num7]; } for (int num8 = index + 1; num8 < length; num8++) { array2[num8 - 1] = splatPrototypes[num8]; } terrainData.splatPrototypes = array2; terrainData.SetAlphamaps(0, 0, array); }
private void ApplyTextures(TerrainData terrainData) { var flatSplat = new SplatPrototype(); var steepSplat = new SplatPrototype(); flatSplat.texture = Settings.FlatTexture; steepSplat.texture = Settings.SteepTexture; terrainData.splatPrototypes = new SplatPrototype[] { flatSplat, steepSplat }; terrainData.RefreshPrototypes(); var splatMap = new float[terrainData.alphamapResolution, terrainData.alphamapResolution, 2]; for (var zRes = 0; zRes < terrainData.alphamapHeight; zRes++) { for (var xRes = 0; xRes < terrainData.alphamapWidth; xRes++) { var normalizedX = (float)xRes / (terrainData.alphamapWidth - 1); var normalizedZ = (float)zRes / (terrainData.alphamapHeight - 1); var steepness = terrainData.GetSteepness(normalizedX, normalizedZ); var steepnessNormalized = Mathf.Clamp(steepness / 1.5f, 0, 1f); splatMap[zRes, xRes, 0] = 1f - steepnessNormalized; splatMap[zRes, xRes, 1] = steepnessNormalized; } } terrainData.SetAlphamaps(0, 0, splatMap); }
private void CreateLand() { #region Preparations var mapData = Data.Battle["gamebody"]["map_info"]["types"]; var worldSize = realMapSize * Settings.DimensionScaleFactor; var resolution = Mathf.RoundToInt(Mathf.Sqrt(realMapSize.x * realMapSize.y) * Settings.Terrain.Smoothness); var terrainData = new TerrainData { heightmapResolution = Mathf.ClosestPowerOfTwo(resolution) + 1, size = new Vector3(worldSize.y, Settings.Map.HeightOfLevel[2], worldSize.x), alphamapResolution = resolution, baseMapResolution = resolution }; #endregion #region Set Heights float landArea = 0; var heights = new float[terrainData.heightmapHeight, terrainData.heightmapWidth]; var mapRect = new Rect(0, 0, Data.MapSize.x, Data.MapSize.y); for (int bumpNum = Mathf.RoundToInt(realMapSize.x * realMapSize.y / 10), i = 0; i < bumpNum; ++i) { var sigmaX = Random.Range(0.8f, 2) * terrainData.heightmapHeight / realMapSize.x; var sigmaY = Random.Range(0.8f, 2) * terrainData.heightmapWidth / realMapSize.y; var muX = Random.Range(0, terrainData.heightmapHeight); var muY = Random.Range(0, terrainData.heightmapWidth); var h = Random.Range(-0.6f, 0.4f); for (var x = Mathf.Max(-muX, -Mathf.RoundToInt(sigmaX * 3)); x < Mathf.Min(terrainData.heightmapHeight - muX, Mathf.RoundToInt(sigmaX * 3)); ++x) for (var y = Mathf.Max(-muY, -Mathf.RoundToInt(sigmaY * 3)); y < Mathf.Min(terrainData.heightmapWidth - muY, Mathf.RoundToInt(sigmaY * 3)); ++y) heights[muX + x, muY + y] += h * Mathf.Exp(-Mathf.Pow(x / sigmaX, 2) - Mathf.Pow(y / sigmaY, 2)); } var threshold = Settings.Map.HeightOfLevel[0] / Settings.Map.HeightOfLevel[2] * 0.8f; for (var x = 0; x < terrainData.heightmapHeight; ++x) for (var y = 0; y < terrainData.heightmapWidth; ++y) { if ((heights[x, y] += threshold / 2) > threshold) heights[x, y] = threshold; var i = (float)x / (terrainData.heightmapHeight - 1) * realMapSize.x - Settings.Map.MapSizeOffset.top; var j = (1 - (float)y / (terrainData.heightmapWidth - 1)) * realMapSize.y - Settings.Map.MapSizeOffset.left; int i0 = Mathf.FloorToInt(i), j0 = Mathf.FloorToInt(j); float ul = 0, ur = 0, br = 0, bl = 0, di = i - i0, dj = j - j0; if (mapRect.Contains(new Vector2(i0, j0))) ul = mapData[i0][j0].n; if (mapRect.Contains(new Vector2(i0, j0 + 1))) ur = mapData[i0][j0 + 1].n; if (mapRect.Contains(new Vector2(i0 + 1, j0 + 1))) br = mapData[i0 + 1][j0 + 1].n; if (mapRect.Contains(new Vector2(i0 + 1, j0))) bl = mapData[i0 + 1][j0].n; var height = (1 - di) * (1 - dj) * ul + (1 - di) * dj * ur + di * (1 - dj) * bl + di * dj * br; if (Math.Abs(height) < Mathf.Epsilon) continue; heights[x, y] = Mathf.Max(heights[x, y], height = Mathf.Sign(height - 0.5f) * Mathf.Pow(Mathf.Abs(height * 2 - 1), 0.25f) / 2 + 0.5f); landArea += height; } terrainData.SetHeights(0, 0, heights); landArea *= realMapSize.x * realMapSize.y / (terrainData.heightmapHeight * terrainData.heightmapWidth); #endregion #region Paint Texture var splatPrototypes = new SplatPrototype[splatTextures.Length]; for (var i = 0; i < splatPrototypes.Length; i++) { var splatPrototype = new SplatPrototype { texture = splatTextures[i], tileSize = Vector2.one * Settings.DimensionScaleFactor * 4 }; splatPrototypes[i] = splatPrototype; } terrainData.splatPrototypes = splatPrototypes; var alphamapResolution = terrainData.alphamapResolution; var alphamaps = new float[alphamapResolution, alphamapResolution, splatPrototypes.Length]; for (var i = 0; i < alphamapResolution; i++) for (var j = 0; j < alphamapResolution; j++) { var height = heights[Mathf.RoundToInt((float)i / (alphamapResolution - 1) * (terrainData.heightmapHeight - 1)), Mathf.RoundToInt((float)j / (alphamapResolution - 1) * (terrainData.heightmapWidth - 1))]; alphamaps[i, j, 0] = height; alphamaps[i, j, 1] = 1 - height; } terrainData.SetAlphamaps(0, 0, alphamaps); #endregion #region Place Trees var treePrototypes = new TreePrototype[treePrefabs.Length]; for (var i = 0; i < treePrototypes.Length; i++) { var treePrototype = new TreePrototype { prefab = treePrefabs[i], bendFactor = 1 }; treePrototypes[i] = treePrototype; } terrainData.treePrototypes = treePrototypes; var treeInstances = new TreeInstance[Mathf.RoundToInt(landArea * Settings.Terrain.Tree.Density)]; var range = new Vector4(Settings.Map.MapSizeOffset.right / realMapSize.y, 1 - Settings.Map.MapSizeOffset.left / realMapSize.y, Settings.Map.MapSizeOffset.top / realMapSize.x, 1 - Settings.Map.MapSizeOffset.bottom / realMapSize.x); for (var i = 0; i < treeInstances.Length; i++) { var treeScale = Random.Range(0.08f, 0.16f) * Settings.DimensionScaleFactor; Vector3 treePosition; do treePosition = new Vector3(Random.Range(range.x, range.y), 0, Random.Range(range.z, range.w)); while ((treePosition.y = heights[Mathf.RoundToInt(treePosition.z * (terrainData.heightmapHeight - 1)), Mathf.RoundToInt(treePosition.x * (terrainData.heightmapWidth - 1))]) < Mathf.Lerp(Settings.Map.HeightOfLevel[1] / Settings.Map.HeightOfLevel[2], 1, 0.6f) || Methods.Coordinates.IsOccupied(Methods.Coordinates.InternalToExternal(Vector3.Scale(treePosition, new Vector3(worldSize.y, 0, worldSize.x))))); var treeInstance = new TreeInstance { prototypeIndex = Random.Range(0, treePrototypes.Length), position = treePosition + Vector3.up * Settings.Terrain.Tree.VerticalPositionOffset * treeScale, color = new Color(0, 0.8f, 0, 1), lightmapColor = new Color(1, 1, 1, 1), heightScale = treeScale, widthScale = treeScale }; treeInstances[i] = treeInstance; } terrainData.treeInstances = treeInstances; #endregion #region Paint Details var detailPrototypes = new DetailPrototype[detailTextures.Length]; for (var i = 0; i < detailPrototypes.Length; i++) { var detailPrototype = new DetailPrototype { prototypeTexture = detailTextures[i], minWidth = Settings.Terrain.Detail.MinDimension, minHeight = Settings.Terrain.Detail.MinDimension, maxWidth = Settings.Terrain.Detail.MaxDimension, maxHeight = Settings.Terrain.Detail.MaxDimension, renderMode = DetailRenderMode.GrassBillboard }; detailPrototypes[i] = detailPrototype; } terrainData.detailPrototypes = detailPrototypes; terrainData.SetDetailResolution(resolution, Mathf.Clamp(resolution, 8, 128)); var detailLayers = new int[detailPrototypes.Length][,]; for (var i = 0; i < detailPrototypes.Length; i++) detailLayers[i] = new int[terrainData.detailResolution, terrainData.detailResolution]; for (var i = 0; i < terrainData.detailResolution; i++) for (var j = 0; j < terrainData.detailResolution; j++) { var layer = Random.Range(0, detailPrototypes.Length); var height = heights[Mathf.RoundToInt((float)i / (terrainData.detailResolution - 1) * (terrainData.heightmapHeight - 1)), Mathf.RoundToInt((float)j / (terrainData.detailResolution - 1) * (terrainData.heightmapWidth - 1))]; if (height > Mathf.Lerp(Settings.Map.HeightOfLevel[1] / Settings.Map.HeightOfLevel[2], 1, 0.4f)) detailLayers[layer][i, j] = 1; } for (var i = 0; i < detailPrototypes.Length; i++) terrainData.SetDetailLayer(0, 0, i, detailLayers[i]); terrainData.wavingGrassAmount = Settings.Terrain.Detail.Waving.Amount; terrainData.wavingGrassSpeed = Settings.Terrain.Detail.Waving.Speed; terrainData.wavingGrassStrength = Settings.Terrain.Detail.Waving.Strength; #endregion #region Final Settings var terrain = Terrain.CreateTerrainGameObject(terrainData).GetComponent<Terrain>(); terrain.treeBillboardDistance = Settings.Terrain.Tree.BillboardDistance; terrain.detailObjectDistance = Settings.Terrain.Detail.MaxVisibleDistance; terrain.detailObjectDensity = Settings.Terrain.Detail.Density; #endregion }