// Use this for initialization void Start () { // Grab the tree array from the terrain treeArray = new ArrayList(Terrain.activeTerrain.terrainData.treeInstances); int originalCount = treeArray.Count -1; //Debug.Log("Tree instances: " + originalCount); // Substitute all the trees for game objects for(int i = 0; i <= originalCount; i++) { GameObject newTree = null; switch(((TreeInstance)treeArray[0]).prototypeIndex) { case 0 : { newTree = GameObject.Instantiate(Resources.Load("PoC Prefabs/OakTree")) as GameObject; }; break; case 1 : { newTree = GameObject.Instantiate(Resources.Load("PoC Prefabs/PalmTree")) as GameObject; }; break; default : { return; } } // Set the properties newTree.transform.position = new Vector3( Terrain.activeTerrain.terrainData.size.x * ((TreeInstance)treeArray[0]).position.x, Terrain.activeTerrain.terrainData.size.y * ((TreeInstance)treeArray[0]).position.y, Terrain.activeTerrain.terrainData.size.z * ((TreeInstance)treeArray[0]).position.z ); newTree.transform.localScale = new Vector3( ((TreeInstance)treeArray[0]).widthScale, ((TreeInstance)treeArray[0]).heightScale, ((TreeInstance)treeArray[0]).widthScale ); // Remove this tree treeArray.RemoveAt(0); } // Remove the built-in trees from the terrain TreeInstance[] tmpArray = new TreeInstance[0]; treeArray.CopyTo(tmpArray); Terrain.activeTerrain.terrainData.treeInstances = tmpArray; // Refresh the terrain float[,] heights = Terrain.activeTerrain.terrainData.GetHeights(0, 0, 0, 0); Terrain.activeTerrain.terrainData.SetHeights(0, 0, heights); //Debug.Log("Done"); }
/// <summary> /// Compares two instances of <see cref="T:UnityEngine.TreeInstance"/>. /// </summary> /// <param name="instance1"> /// One of the <see cref="T:UnityEngine.TreeInstance"/>. /// </param> /// <param name="instance2"> /// The other <see cref="T:UnityEngine.TreeInstance"/>. /// </param> /// <returns> /// true if the state of both instances are the same; otherwise false. /// </returns> public static bool Same(this TreeInstance instance1, TreeInstance instance2) { // comparison ordered by what fields are most likely to be different return instance1.position == instance2.position && instance1.prototypeIndex == instance2.prototypeIndex && instance1.heightScale == instance2.heightScale && instance1.widthScale == instance2.widthScale && instance1.color.Equals(instance2.color) && instance1.lightmapColor.Equals(instance2.lightmapColor) ; }
public static void PlaceTrees(Terrain terrain, float xBase, float yBase) { int prototypeCount = TerrainInspectorUtil.GetPrototypeCount(terrain.terrainData); if (TreePainter.selectedTree == -1 || TreePainter.selectedTree >= prototypeCount || !TerrainInspectorUtil.PrototypeIsRenderable(terrain.terrainData, TreePainter.selectedTree)) return; int num1 = 0; TreeInstance instance = new TreeInstance(); instance.position = new Vector3(xBase, 0.0f, yBase); instance.color = (Color32) TreePainter.GetTreeColor(); instance.lightmapColor = (Color32) Color.white; instance.prototypeIndex = TreePainter.selectedTree; instance.heightScale = TreePainter.GetTreeHeight(); instance.widthScale = !TreePainter.lockWidthToHeight ? TreePainter.GetTreeWidth() : instance.heightScale; instance.rotation = TreePainter.GetTreeRotation(); if (Event.current.type != EventType.MouseDrag && (double) TreePainter.brushSize <= 1.0 || TerrainInspectorUtil.CheckTreeDistance(terrain.terrainData, instance.position, instance.prototypeIndex, TreePainter.spacing)) { terrain.AddTreeInstance(instance); ++num1; } Vector3 prototypeExtent = TerrainInspectorUtil.GetPrototypeExtent(terrain.terrainData, TreePainter.selectedTree); prototypeExtent.y = 0.0f; float num2 = TreePainter.brushSize / (float) ((double) prototypeExtent.magnitude * (double) TreePainter.spacing * 0.5); int num3 = Mathf.Clamp((int) ((double) num2 * (double) num2 * 0.5), 0, 100); for (int index = 1; index < num3 && num1 < num3; ++index) { Vector2 insideUnitCircle = UnityEngine.Random.insideUnitCircle; insideUnitCircle.x *= TreePainter.brushSize / terrain.terrainData.size.x; insideUnitCircle.y *= TreePainter.brushSize / terrain.terrainData.size.z; Vector3 position = new Vector3(xBase + insideUnitCircle.x, 0.0f, yBase + insideUnitCircle.y); if ((double) position.x >= 0.0 && (double) position.x <= 1.0 && ((double) position.z >= 0.0 && (double) position.z <= 1.0) && TerrainInspectorUtil.CheckTreeDistance(terrain.terrainData, position, TreePainter.selectedTree, TreePainter.spacing * 0.5f)) { instance = new TreeInstance(); instance.position = position; instance.color = (Color32) TreePainter.GetTreeColor(); instance.lightmapColor = (Color32) Color.white; instance.prototypeIndex = TreePainter.selectedTree; instance.heightScale = TreePainter.GetTreeHeight(); instance.widthScale = !TreePainter.lockWidthToHeight ? TreePainter.GetTreeWidth() : instance.heightScale; instance.rotation = TreePainter.GetTreeRotation(); terrain.AddTreeInstance(instance); ++num1; } } }
/// <summary> /// game objects to terrain treeinstance /// currently unused /// </summary> public void InstancesToTerrain() { Map map = FindObjectOfType(typeof(Map)) as Map; if (map != null) { Object[] objTrees = FindObjectsOfType(typeof (ITree)); if (objTrees.GetLongLength(0) == 0) { Debug.Log("no trees instances, all in terrain?"); } System.IO.File.Delete("Debug.txt"); System.IO.File.AppendAllText("Debug.txt", "Debug log gameobject -> treeinstances:" + System.DateTime.Now.ToShortTimeString()); long percent = (long)Mathf.Max(1,objTrees.GetLongLength(0) / 100); long counter = percent; int currentPercent = 0; for (long i = objTrees.GetLongLength(0)-1; i >=0; i--) { ITree tree =(ITree)objTrees[i]; TreeInstance tI = new TreeInstance(); float healtScale = ((float)tree.GetHealth()) / 1000.0f; tI.color = new Color(1, 1, 1); tI.lightmapColor = new Color(255, 255, 255); tI.position = new Vector3(tree.transform.position.x / map.terrain.terrainData.size.x, tree.transform.position.y / map.terrain.terrainData.size.y, tree.transform.position.z / map.terrain.terrainData.size.z); tI.prototypeIndex = tree.GetPrefabID(); float scale = 0.3f + Mathf.Min(0.7f, (float)tree.GetAge() / (float)Tree1.MAXAGE); tI.heightScale = scale - healtScale; tI.widthScale = scale; map.terrain.AddTreeInstance(tI); GameObject.DestroyImmediate(((ITree)objTrees[i]).gameObject); counter--; if (counter == 0) { System.IO.File.AppendAllText("Debug.txt", currentPercent.ToString() + "% " + System.DateTime.Now.ToShortTimeString()); currentPercent++; } } System.GC.Collect(); } else { Debug.Log("set map/terrain"); } }
public static void MassPlaceTrees(TerrainData terrainData, int numberOfTrees, bool randomTreeColor, bool keepExistingTrees) { int length = terrainData.treePrototypes.Length; if (length == 0) { Debug.Log("Can't place trees because no prototypes are defined"); } else { Undo.RegisterCompleteObjectUndo(terrainData, "Mass Place Trees"); TreeInstance[] sourceArray = new TreeInstance[numberOfTrees]; int num2 = 0; while (num2 < sourceArray.Length) { TreeInstance instance = new TreeInstance { position = new Vector3(UnityEngine.Random.value, 0f, UnityEngine.Random.value) }; if (terrainData.GetSteepness(instance.position.x, instance.position.z) < 30f) { instance.color = !randomTreeColor ? Color.white : GetTreeColor(); instance.lightmapColor = Color.white; instance.prototypeIndex = UnityEngine.Random.Range(0, length); instance.heightScale = GetTreeHeight(); instance.widthScale = !lockWidthToHeight ? GetTreeWidth() : instance.heightScale; instance.rotation = GetTreeRotation(); sourceArray[num2++] = instance; } } if (keepExistingTrees) { TreeInstance[] treeInstances = terrainData.treeInstances; TreeInstance[] destinationArray = new TreeInstance[treeInstances.Length + sourceArray.Length]; Array.Copy(treeInstances, 0, destinationArray, 0, treeInstances.Length); Array.Copy(sourceArray, 0, destinationArray, treeInstances.Length, sourceArray.Length); sourceArray = destinationArray; } terrainData.treeInstances = sourceArray; terrainData.RecalculateTreePositions(); } }
void FillTreeInstances() { terrain.treeDistance = m_treeDistance; terrain.treeBillboardDistance = m_treeBillboardDistance; terrain.treeCrossFadeLength = m_treeCrossFadeLength; terrain.treeMaximumFullLODCount = m_treeMaximumFullLODCount; m_treeProtoTypes = new TreePrototype[2]; m_treeProtoTypes[0] = new TreePrototype(); m_treeProtoTypes [0].prefab = m_tree0; m_treeProtoTypes [1] = new TreePrototype (); m_treeProtoTypes[1].prefab = m_tree1; terrain.terrainData.treePrototypes = m_treeProtoTypes; PerlinNoise m_treeNoise = new PerlinNoise(Random.Range(0,100)); //ArrayList instances = new ArrayList(); for(int x = 0; x < m_terrainSize; x += m_treeSpacing) { for (int z = 0; z < m_terrainSize; z += m_treeSpacing) { float unit = 1.0f / (m_terrainSize - 1); float offsetX = Random.value * unit * m_treeSpacing; float offsetZ = Random.value * unit * m_treeSpacing; float normX = x * unit + offsetX; float normZ = z * unit + offsetZ; // Get the steepness value at the normalized coordinate. float angle = terrain.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; if(frac < 0.45f) //make sure tree are not on steep slopes { float worldPosX = x; float worldPosZ = z; float noise = m_treeNoise.FractalNoise2D(worldPosX, worldPosZ, 3, m_treeFrq, 1.0f); float ht = terrain.terrainData.GetInterpolatedHeight(normX, normZ); if(noise > 0.0f && ht < m_terrainHeight*0.4f) { TreeInstance temp = new TreeInstance(); temp.position = new Vector3(normX,ht,normZ); temp.prototypeIndex = Random.Range (0, 2); temp.widthScale = 1f; temp.heightScale = 1f; temp.color = Color.white; temp.lightmapColor = Color.white; terrain.AddTreeInstance(temp); } } } } //terrain.terrainData.treeInstances = (TreeInstance[])instances.ToArray(typeof(TreeInstance)); terrain.terrainData.SetHeights(0, 0, new float[,] { { } }); terrain.Flush (); }
void fillTreeInstances() { Random.seed = 0; for(int x = 0; x < terrainSizeX; x ++) { for (int y = 0; y < terrainSizeY; y ++) { float ratio = (float)(heightMapSize-1)/terrainSizeX; Center.BiomeTypes biome = p_graphVoronoi.getNearestCenter((int)(x*ratio),(int)(y*ratio)).biome; //int space=0; int tree = 10; if ((int)biome == 4) {tree = 0;} if ((int)biome ==9) {tree = 1;} if ((int)biome == 10) { tree = 2;} if ((int)biome == 11 ){ tree =3; } if( (int) biome==13) { tree =4; } float unit = 1.0f / (terrainSizeX - 1); //float offsetX = Random.value * unit * m_treeSpacing; //float offsetZ = Random.value * unit * m_treeSpacing; float normX = x * unit;// + offsetX; float normZ = y * unit;// + offsetZ; // Get the steepness value at the normalized coordinate. float angle = p_terrain.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; float height = p_heightMap.getHeight(y*heightMapSize/terrainSizeY,x*heightMapSize/terrainSizeX); if (tree<5) { if(frac < 0.5f && height> waterLevel+0.05f && Random.Range(0,m_treeSpacing[tree]) == 0) //make sure tree are not on steep slopes & in the sea { float worldPosX = x+(terrainSizeX-1); float worldPosZ = y+(terrainSizeY-1); float ht = p_terrain.terrainData.GetInterpolatedHeight(normX, normZ); if( ht < terrainHeight*0.4f ) { TreeInstance temp = new TreeInstance(); temp.position = new Vector3(normX,ht,normZ); temp.prototypeIndex = tree; temp.widthScale = 1; temp.heightScale = 1; temp.color = Color.white; temp.lightmapColor = Color.white; p_terrain.AddTreeInstance(temp); } } } } } }
private extern void Internal_GetTreeInstance_Injected(int index, out TreeInstance ret);
public TreeInstance[] MakeTrees(){ if(TreesOld == null || TreesOld.Length < 1){ return null; } int tSize = TreesOld.Length; TreeInstance[] tTrees = new TreeInstance[tSize]; GSDTreeInstance tTree = null; TreeInstance xTree; for(int i=0;i<tSize;i++){ tTree = TreesOld[i]; xTree = new TreeInstance(); xTree.color = new Color(tTree.colorR,tTree.colorG,tTree.colorB,tTree.colorA); xTree.heightScale = tTree.heightScale; xTree.lightmapColor = new Color(tTree.lightmapColorR,tTree.lightmapColorG,tTree.lightmapColorB,tTree.lightmapColorA); xTree.position = new Vector3(tTree.positionX,tTree.positionY,tTree.positionZ); xTree.prototypeIndex = tTree.prototypeIndex; xTree.widthScale = tTree.widthScale; tTrees[i] = xTree; } return tTrees; }
void FillTreeInstances(Terrain terrain, int tileX, int tileZ) { Random.seed = 0; for(int x = 0; x < m_terrainSize; x += m_treeSpacing) { for (int z = 0; z < m_terrainSize; z += m_treeSpacing) { float unit = 1.0f / (m_terrainSize - 1); float offsetX = Random.value * unit * m_treeSpacing; float offsetZ = Random.value * unit * m_treeSpacing; float normX = x * unit + offsetX; float normZ = z * unit + offsetZ; // Get the steepness value at the normalized coordinate. float angle = terrain.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; if(frac < 0.5f) //make sure tree are not on steep slopes { float worldPosX = x+tileX*(m_terrainSize-1); float worldPosZ = z+tileZ*(m_terrainSize-1); float noise = m_treeNoise.FractalNoise2D(worldPosX, worldPosZ, 3, m_treeFrq, 1.0f); float ht = terrain.terrainData.GetInterpolatedHeight(normX, normZ); if(noise > 0.0f && ht < m_terrainHeight*0.4f) { TreeInstance temp = new TreeInstance(); temp.position = new Vector3(normX,ht,normZ); temp.prototypeIndex = Random.Range(0, 3); temp.widthScale = 1; temp.heightScale = 1; temp.color = Color.white; temp.lightmapColor = Color.white; terrain.AddTreeInstance(temp); } } } } terrain.treeDistance = m_treeDistance; terrain.treeBillboardDistance = m_treeBillboardDistance; terrain.treeCrossFadeLength = m_treeCrossFadeLength; terrain.treeMaximumFullLODCount = m_treeMaximumFullLODCount; }
private static extern void INTERNAL_CALL_AddTreeInstance(Terrain self, ref TreeInstance instance);
private static extern void INTERNAL_CALL_SetTreeInstance(TerrainData self, int index, ref TreeInstance instance);
// generates nautre void GenerateNature(float[,] hm) { // wipe old trees terrain.terrainData.treeInstances = new TreeInstance[0]; // iterate through vertecies for(int i=0;i<terrain.terrainData.heightmapWidth;i++){ for(int j=0;j<terrain.terrainData.heightmapHeight;j++){ // TREES // is it above sea level? if(terrain.terrainData.GetHeight(i,j) > 1){ // is it relatively flat? Vector3 thisPoint = new Vector3(i,0,j); float vna = GetVonNeumannAverage(hm,thisPoint); if(vna/hm[i,j]< 1.5 && hm[i,j]/vna < 1.5){ // chance to generate tree if(Mathf.Round(Random.Range(0,15))==0){ // generate trees TreeInstance treeInst = new TreeInstance(); treeInst.prototypeIndex = Random.Range(0,2); Vector3 position = new Vector3(((float)i)/terrain.terrainData.heightmapWidth,0,((float)j)/terrain.terrainData.heightmapHeight); //Vector3 position = new Vector3(i,0,j); position.y = terrain.terrainData.GetInterpolatedHeight((float)i/terrain.terrainData.heightmapWidth, (float)j/terrain.terrainData.heightmapHeight) / terrain.terrainData.size.y; treeInst.position = position; float sizeMod = Random.Range(.8f,1.2f); treeInst.heightScale = sizeMod; treeInst.widthScale = sizeMod; float colorMod = Random.Range(.8f,1f); treeInst.color = new Color (colorMod, colorMod, colorMod); treeInst.lightmapColor = new Color (1, 1, 1); terrain.AddTreeInstance(treeInst); //print(position); } } } } } // flush and print terrain.Flush(); print(terrain.terrainData.treeInstances.Length); //does show trees are being added to the treeInstances array }
internal extern void AddTree(out TreeInstance tree);
public void SetTreeInstance(int index, TreeInstance instance) { INTERNAL_CALL_SetTreeInstance(this, index, ref instance); }
private void PopulateTreeInstances(float[,] heightMap, List<TreeInstance> treeInstances, int[,] randomArray) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // read the height at this location float locationHeight = heightMap[y, x]; // used for slope texturing var maxDifference = 0.0f; // Use a full Moore neighborhood. A Von Neumann is faster but can result // in weird artifacts sometimes. for (int dx = -1; dx <= 1; dx += 1) { for (int dy = -1; dy <= 1; dy += 1) { int nx = x + dx; int ny = y + dy; if (nx < 0 || ny < 0 || nx >= width || ny >= height || (nx == 0 && ny == 0)) { // Skip neighbor cells that fall off the map. continue; } var temp = Mathf.Abs(heightMap[y, x] - heightMap[ny, nx]); if (temp > maxDifference) { maxDifference = temp; } } } if (locationHeight < mountainPeekStart && maxDifference < slopeValue && locationHeight > waterHeight) { int rnd = randomArray[y, x]; // random location of trees var temp = Mathf.Floor(locationHeight * (float)treeStrength) - 0.4f * (float)treeStrength; float rndBasedOnLocation = (float)rnd; if (temp != 0) { rndBasedOnLocation += (float)treeStrength / 2.0f; } if (rndBasedOnLocation < (float)treeStrength) { // smaller trees where the altitude increases (less o2) float rndHeight = treeHeightFactor - (rnd % treeHeightFactor); if (treeStrength < 3) { rnd += (int)temp; } int rndPrototype = (y + x) % 3; // mix of three tree prototypes // add random trees var tI = new TreeInstance(); tI.prototypeIndex = rndPrototype; tI.heightScale = rndHeight; tI.widthScale = tI.heightScale; tI.color = Color.white; tI.position = new Vector3((float) x / width, -0.1f, (float) y / height); treeInstances.Add(tI); } } } } }
private static extern void INTERNAL_CALL_GetTreeInstance(TerrainData self, int index, out TreeInstance value);
void Setup() { if(target.terrainTemplate == null) throw new UnityException("No terrain template assigned."); if(target.terrainTemplate.terrainData == null) throw new UnityException("Terrain template has no terrain data."); if(target.terrainTemplate.materialTemplate == null) throw new UnityException("Terrain template has no base material template data."); var ooBoundsSize = target.transform.localScale; var ooBoundsExtents = ooBoundsSize * 0.5f; var targetPos = target.transform.position; var targetRight = target.transform.right; var targetForward = target.transform.forward; var ooPlanes = new [] { new Plane( targetRight, targetPos + targetRight * ooBoundsExtents.x), new Plane(-targetRight, targetPos - targetRight * ooBoundsExtents.x), new Plane( targetForward, targetPos + targetForward * ooBoundsExtents.z), new Plane(-targetForward, targetPos - targetForward * ooBoundsExtents.z), }; var aaBounds = new Bounds(Vector3.zero, Vector3.one); aaBounds.Encapsulate( targetRight * ooBoundsExtents.x + Vector3.up * ooBoundsExtents.y + targetForward * ooBoundsExtents.z); aaBounds.Encapsulate(-targetRight * ooBoundsExtents.x + -Vector3.up * ooBoundsExtents.y + -targetForward * ooBoundsExtents.z); aaBounds.Encapsulate(-targetRight * ooBoundsExtents.x + Vector3.up * ooBoundsExtents.y + targetForward * ooBoundsExtents.z); aaBounds.Encapsulate( targetRight * ooBoundsExtents.x + -Vector3.up * ooBoundsExtents.y + -targetForward * ooBoundsExtents.z); var aaBoundsSize = aaBounds.size; var aaBoundsExtents = aaBounds.extents; if(target.autoColliders) { // GeometryUtility.TestPlanesAABB won't accept my OO planes, so // let's just use a world space AABB test instead. var aaBoundsWorld = new Bounds(targetPos + aaBounds.center, aaBounds.size); foreach(var mr in Object.FindObjectsOfType<MeshRenderer>()) if(mr.GetComponent<Collider>() == null) if(aaBoundsWorld.Intersects(mr.bounds)) target.autoColliderList.Add(mr.gameObject.AddComponent<MeshCollider>()); } var terrainCorner = targetPos - aaBoundsExtents; var xStepCount = Mathf.NextPowerOfTwo(Mathf.CeilToInt(aaBoundsSize.x * target.density)); var zStepCount = Mathf.NextPowerOfTwo(Mathf.CeilToInt(aaBoundsSize.z * target.density)); int ZM = zStepCount; int XM = xStepCount; int XZM = Mathf.Max(XM, ZM); var xStep = (float)XM / (float)XZM * aaBoundsSize.x / (float)xStepCount; var zStep = (float)ZM / (float)XZM * aaBoundsSize.z / (float)zStepCount; GameObject[] paintingObjects = target.paintingObjects; GameObject[] blockingObjects = target.blockingObjects; bool hasExplicitPaint = paintingObjects != null && paintingObjects.Length > 0; bool hasExplicitBlock = blockingObjects != null && blockingObjects.Length > 0; LayerMask paintingLayers = hasExplicitPaint ? (LayerMask)~0 : target.paintingLayers; LayerMask blockingLayers = hasExplicitBlock ? (LayerMask)~0 : target.blockingLayers; float rayLength = aaBoundsSize.y; float heightScale = 1f / rayLength; var castRadius = target.castRadius; var heightmap = new float[XZM, XZM]; var maskmap = new float[XZM, XZM]; var oldSelfTerrainCollider = target.workingObject ? target.workingObject.GetComponent<TerrainCollider>() : null; for(int z = 0; z < XZM; ++z) { for(int x = 0; x < XZM; ++x) { var pos = terrainCorner + new Vector3(x * xStep, aaBoundsSize.y, z * zStep); if(ooPlanes[0].GetSide(pos) || ooPlanes[1].GetSide(pos) || ooPlanes[2].GetSide(pos) || ooPlanes[3].GetSide(pos)) { heightmap[z, x] = 0f; maskmap[z, x] = 0f; continue; } float targetDist = rayLength; float targetMask = 1f; var rhisDown = Physics.SphereCastAll(pos, castRadius, Vector3.down, rayLength, paintingLayers); if(rhisDown.Length > 0) { for(int i = 0, n = rhisDown.Length; i < n; ++i) { var rhiDown = rhisDown[i]; var validTerrain = !(rhiDown.collider is TerrainCollider) || (target.allowTerrainColliders && (oldSelfTerrainCollider == null || rhiDown.collider != oldSelfTerrainCollider)); if( validTerrain && (!hasExplicitPaint || System.Array.IndexOf(paintingObjects, rhiDown.collider.gameObject) != -1) && System.Array.IndexOf(blockingObjects, rhiDown.collider.gameObject) == -1 ) { var curDist = pos.y - rhiDown.point.y;// rhiDown.distance + castRadius; if(curDist < targetDist) { targetMask = MaskSlope(rhiDown.normal.y); targetDist = curDist; } } } } bool hasClearance = true; if(targetDist < rayLength && (hasExplicitBlock || blockingLayers.value != 0)) { float blockedDist = rayLength; var rhisDownBlockers = Physics.SphereCastAll(pos, castRadius, Vector3.down, rayLength, blockingLayers); for(int i = 0, n = rhisDownBlockers.Length; i < n; ++i) { var rhiDown = rhisDownBlockers[i]; if(!(rhiDown.collider is TerrainCollider)) if(!hasExplicitBlock || System.Array.IndexOf(blockingObjects, rhiDown.collider.gameObject) != -1) if(!hasExplicitPaint || System.Array.IndexOf(paintingObjects, rhiDown.collider.gameObject) == -1) blockedDist = Mathf.Min(blockedDist, pos.y - rhiDown.point.y /*rhiDown.distance + castRadius*/); } if(blockedDist < targetDist) { const float cBelow = 25f; var upPos = pos + Vector3.down * (targetDist + cBelow); RaycastHit[] rhisUpBlockers = Physics.SphereCastAll(upPos, castRadius, Vector3.up, targetDist + cBelow, blockingLayers); for(int i = 0, n = rhisUpBlockers.Length; i < n && hasClearance; ++i) { var rhiUp = rhisUpBlockers[i]; if(!(rhiUp.collider is TerrainCollider)) if(!hasExplicitBlock || System.Array.IndexOf(blockingObjects, rhiUp.collider.gameObject) != -1) if(!hasExplicitPaint || System.Array.IndexOf(paintingObjects, rhiUp.collider.gameObject) == -1) hasClearance = rhiUp.point.y - upPos.y /*rhiUp.distance + castRadius*/ - cBelow > target.heightClearance; } } } bool hasValidSample = hasClearance && targetDist != rayLength; heightmap[z, x] = hasValidSample ? Mathf.Clamp01(1f - targetDist * heightScale) : 0f; maskmap[z, x] = hasValidSample ? targetMask : 0f; } } target.heightData = new float[XZM * XZM]; System.Buffer.BlockCopy(heightmap, 0, target.heightData, 0, target.heightData.Length * sizeof(float)); target.maskData = new float[XZM * XZM]; System.Buffer.BlockCopy(maskmap, 0, target.maskData, 0, target.maskData.Length * sizeof(float)); var ttc = target.terrainTemplate; var ttd = ttc.terrainData; if(target.workingObject) target.workingObject.transform.position += Vector3.up * target.pickingHackFixBias; var oldTC = target.workingObject ? target.workingObject.GetComponent<Terrain>() : null; //if(oldTC && oldTC.GetComponent<TerrainCollider>()) // oldTC.gameObject.AddComponent<TerrainCollider>(); var td = oldTC ? oldTC.terrainData : new TerrainData(); td.SetDetailResolution(XZM, 32); td.heightmapResolution = XZM; td.SetHeights(0, 0, heightmap); td.size = aaBoundsSize; td.splatPrototypes = ttd.splatPrototypes; td.detailPrototypes = ttd.detailPrototypes; td.treePrototypes = ttd.treePrototypes; for(int i = 0, offset = 0, step = target.detailLayerElements*sizeof(int), n = td.detailPrototypes.Length, m = target.detailLayerCount; i < n && i < m; ++i, offset += step) { var details = td.GetDetailLayer(0, 0, td.detailWidth, td.detailHeight, i); System.Buffer.BlockCopy(target.detailData, offset, details, 0, step); td.SetDetailLayer(0, 0, i, details); } if(target.treeInstances != null) { var tdi = new TreeInstance[target.treeInstances.Length]; for(int i = 0, n = target.treeInstances.Length; i < n; ++i) tdi[i] = (TreeInstance)target.treeInstances[i]; td.treeInstances = tdi; } var terrain = oldTC ? oldTC.gameObject : Terrain.CreateTerrainGameObject(td); if(oldTC == null) { var helper = terrain.AddComponent<PaintJobProxy>(); while(UnityEditorInternal.ComponentUtility.MoveComponentUp(helper)) ; } var tc = terrain.GetComponent<Terrain>(); tc.detailObjectDistance = 1000f;//ttc.detailObjectDistance; tc.detailObjectDensity = ttc.detailObjectDensity; target.materialInstance = tc.materialTemplate = new Material(ttc.materialTemplate); tc.castShadows = false; terrain.transform.parent = target.transform; terrain.transform.position = terrainCorner; terrain.transform.localRotation = Quaternion.identity; terrain.transform.localScale = Vector3.one; target.workingObject = terrain; target.isPainting = true; target.alignedSize = aaBoundsSize; target.materialInstance.SetFloat("_HackCullScale", 1f); tc.drawHeightmap = true; tc.terrainData.wavingGrassAmount = 0f; tc.terrainData.wavingGrassSpeed = 0f; tc.terrainData.wavingGrassStrength = 0f; tc.terrainData.wavingGrassTint = Color.white; }
/// <summary> /// Places random trees on the terrain. /// </summary> /// <param name="terrain"> /// The terrain to place trees on. /// </param> /// <param name="mtp"> /// The settings for the tree placement. /// </param> public static void PlaceRandomTrees(Terrain terrain, MassTreePlacement mtp) { var data = terrain.terrainData; var num = data.treePrototypes.Length; if (num == 0) { Debug.LogWarning("Can't place trees because no prototypes are defined. Process aborted."); return; } Undo.RegisterCompleteObjectUndo(data, "Mass Place Trees"); var start = DateTime.Now; var array = new TreeInstance[mtp.Count]; var i = 0; while (i < array.Length) { // stop if process have run for over X seconds var delta = DateTime.Now - start; if (delta.TotalSeconds >= mtp.MaxTime) { Debug.LogWarning("Process was taking too much time to run"); return; } var position = new Vector3(Random.value, 0.0f, Random.value); // don't allow placement of trees below minWorldY and above maxWorldY var y = data.GetInterpolatedHeight(position.x, position.z); var worldY = y + terrain.transform.position.y; if (worldY < mtp.MinWorldY || worldY > mtp.MaxWorldY) { continue; } // don't allow placement of trees on surfaces flatter than minSlope and steeper than maxSlope var steepness = data.GetSteepness(position.x, position.z); if (steepness < mtp.MinSlope || steepness > mtp.MaxSlope) { continue; } var color = Color.Lerp(Color.white, Color.gray * 0.7f, Random.value); color.a = 1f; var treeInstance = default(TreeInstance); treeInstance.position = position; treeInstance.color = color; treeInstance.lightmapColor = Color.white; treeInstance.prototypeIndex = Random.Range(0, num); treeInstance.widthScale = Random.Range(mtp.MinWidthScale, mtp.MaxWidthScale); treeInstance.heightScale = Random.Range(mtp.MinHeightScale, mtp.MaxHeightScale); array[i] = treeInstance; i++; } data.treeInstances = array; RecalculateTreePositions(data); terrain.Flush(); }
public static void AddVegetation(string filename) { string[] lines = OpenTextFile (filename); string trimmedLine; string result; Vector3 trans= Vector3.zero; ArrayList points= new ArrayList(); int typeVegetation=0; Terrain terrain = getMainTerrain("TerrainArbres"); TerrainData terraindata = terrain.terrainData; TreeInstance tree; List<TreeInstance> newTrees = new List<TreeInstance>(terraindata.treeInstances); Vector3 deltaY=Vector3.zero; deltaY.y+=0.0f; // int lineNumber = 0; foreach (string line in lines) { // Debug.Log (++lineNumber); trimmedLine = line.Trim(); result = MatchItem(trimmedLine, "translation "); if ((null!=result) ) { trans = stringToVector3 (result); } result = MatchItem(trimmedLine, "points ["); if (null!=result) { points = decodeArrayOfPoints(result); } result = MatchItem(trimmedLine, "pointsRemplis ["); if (null!=result) { points = decodeArrayOfPoints(result); } result = MatchItem(trimmedLine, "typeVegetation "); if (null!=result) { typeVegetation=int.Parse(result); IEnumerator e = points.GetEnumerator(); float rnd; while (e.MoveNext()) { // make more random if ((typeVegetation<=11) && (typeVegetation!=6) && (typeVegetation!=7) && (typeVegetation!=8)) { while ((rnd=Random.value)==1.0f); typeVegetation = (typeVegetation/3)*3+(int) (rnd*3); } tree = new TreeInstance(); tree.position = WorldToTerrain(terrain,(Vector3)e.Current+trans+deltaY); tree.prototypeIndex = typeVegetation; if (typeVegetation==18) Debug.Log ("invalide vegetation"); if (typeVegetation<=5) rnd = 0.3f*(Random.value-1.0f)-0.1f; else if (typeVegetation<=8) rnd = 0.2f*(Random.value-1.0f); else if (typeVegetation==9) rnd = 0.2f*(Random.value-1.0f); else rnd= 0.25f*(Random.value-1.0f); // rnd=0.0f; if ((typeVegetation>=6) && (typeVegetation<=8)) tree.widthScale = 1.0f; else tree.widthScale = 1.0f+rnd; tree.heightScale = 1.0f+rnd; Color c = Color.white; c[0] = 0.92f+Random.value*0.08f; c[1] = 0.92f+Random.value*0.08f; c[2] = 0.92f+Random.value*0.08f; tree.color = c; tree.lightmapColor = Color.white; // 1, 3, 4, 5 //if (typeVegetation==5) newTrees.Add(tree); } } } terraindata.treeInstances= newTrees.ToArray(); }
// Use this for initialization public void Run() { float[,] heights = T.terrainData.GetHeights(0, 0, 500, 500); T.terrainData.SetHeights(0, 0, heights); for (int x = 0; x < 1; x++) { for (int y = 0; y < 1; y++) { if (Random.Range(1, 3) == 3) { if (GetMainTexture(new Vector3(x/2, 0f, y/2)) == 0) { TreeInstance ti = new TreeInstance { prototypeIndex = 0, heightScale = 1.0f, widthScale = 1.0f, color = Color.white }; Vector3 v = new Vector3(x/20.0f, 0.0f, y/20.0f); ti.position = v; T.AddTreeInstance(ti); } } } } }
/// <summary> /// Removes the trees. /// </summary> /// <param name='trees'> /// Trees. /// </param> private void RemoveTrees(TreeInstance[] trees) { int treeX = 0; int treeY = 0; foreach (TreeInstance tree in trees) { treeX = (int)(tree.position.x * mWidth); treeY = (int)(tree.position.y * mHeight); // - - - // - x - // - - - if (IsTreeInRange (tree.position, treeX, treeY)) { mHeightMap [treeX, treeY] = float.MaxValue; } for (int i = 1; i < ApproximationRadius; i++) { // // checked positions // x x x // - - - // - - - if (IsTreeInRange (tree.position, treeX - i, treeY + i)) { mHeightMap [treeX - i, treeY + i] = float.MaxValue; } if (IsTreeInRange (tree.position, treeX, treeY + i)) { mHeightMap [treeX, treeY + i] = float.MaxValue; } if (IsTreeInRange (tree.position, treeX + i, treeY + i)) { mHeightMap [treeX + i, treeY + i] = float.MaxValue; } // checked positions // - - - // x - x // - - - if (IsTreeInRange (tree.position, treeX - i, treeY)) { mHeightMap [treeX - i, treeY] = float.MaxValue; } if (IsTreeInRange (tree.position, treeX + i, treeY)) { mHeightMap [treeX + i, treeY] = float.MaxValue; } // checked positions // - - - // - - - // x x x if (IsTreeInRange (tree.position, treeX - i, treeY - i)) { mHeightMap [treeX - i, treeY - i] = float.MaxValue; } if (IsTreeInRange (tree.position, treeX, treeY - i)) { mHeightMap [treeX, treeY - i] = float.MaxValue; } if (IsTreeInRange (tree.position, treeX + i, treeY - i)) { mHeightMap [treeX + i, treeY - i] = float.MaxValue; } } } }
public Tree treeInstance(TreeInstance treeInstance) { this._treeInstance = treeInstance; return this; }
static void AddVegetation(string filename) { string[] lines = OpenTextFile (filename); string trimmedLine; string result; int maxTrees = 10000; Vector3 trans= Vector3.zero; ArrayList points= new ArrayList(); int typeVegetation; Terrain terrain = getMainTerrain(); GameObject ft = GameObject.Find("ForTrees"); Terrain[] ters = ft.GetComponentsInChildren<Terrain>(); Terrain t=getNextFreeTerrain(ters, maxTrees); TerrainData terraindata = t.terrainData; TreeInstance tree; List<TreeInstance> newTrees = new List<TreeInstance>(terraindata.treeInstances); foreach (string line in lines) { trimmedLine = line.Trim(); result = MatchItem(trimmedLine, "translation "); if (null!=result) { trans = stringToVector3 (result); } result = MatchItem(trimmedLine, "points ["); if (null!=result) { points = decodeArrayOfPoints(result); } result = MatchItem(trimmedLine, "pointsRemplis ["); if (null!=result) { points = decodeArrayOfPoints(result); } result = MatchItem(trimmedLine, "typeVegetation "); if (null!=result) { typeVegetation=int.Parse(result); IEnumerator e = points.GetEnumerator(); float rnd; while (e.MoveNext()) { tree = new TreeInstance(); tree.position = WorldToTerrain(terrain,(Vector3)e.Current+trans); tree.prototypeIndex = typeVegetation; rnd= 0.5f*(Random.value-0.5f); tree.widthScale = 1.0f+rnd; tree.heightScale = 1.0f+rnd; Color c = Color.white; c[0] = 0.92f+Random.value*0.08f; c[1] = 0.92f+Random.value*0.08f; c[2] = 0.92f+Random.value*0.08f; tree.color = c; tree.lightmapColor = Color.white; treeCount++; newTrees.Add(tree); if (newTrees.Count == maxTrees) { terraindata.treeInstances= newTrees.ToArray(); t=getNextFreeTerrain(ters, maxTrees); terraindata = t.terrainData; newTrees = new List<TreeInstance>(terraindata.treeInstances); } } } } terraindata.treeInstances= newTrees.ToArray(); }
/// <summary> /// <para>Adds a tree instance to the terrain.</para> /// </summary> /// <param name="instance"></param> public void AddTreeInstance(TreeInstance instance) { INTERNAL_CALL_AddTreeInstance(this, ref instance); }
public void SetTreeInstance(int index, TreeInstance instance) { this.SetTreeInstance_Injected(index, ref instance); }
public static void AddVegetationVignes(string filename) { string[] lines = OpenTextFile (filename); string trimmedLine; string result; maxH = 0.0f; Vector3 trans= Vector3.zero; ArrayList points= new ArrayList(); int typeVegetation=0; typeVegetation+=0; // avoid a warning Terrain terrain = getMainTerrain("TerrainVignes"); TerrainData terraindata = terrain.terrainData; TreeInstance tree; List<TreeInstance> newTrees = new List<TreeInstance>(terraindata.treeInstances); // int lineNumber = 0; foreach (string line in lines) { // Debug.Log (++lineNumber); trimmedLine = line.Trim(); result = MatchItem(trimmedLine, "translation "); if ((null!=result) ) { trans = stringToVector3 (result); } result = MatchItem(trimmedLine, "points ["); if (null!=result) { points = decodeArrayOfPoints(result); } result = MatchItem(trimmedLine, "pointsRemplis ["); if (null!=result) { points = decodeArrayOfPoints(result); } result = MatchItem(trimmedLine, "typeVegetation "); if (null!=result) { typeVegetation=int.Parse(result); IEnumerator e = points.GetEnumerator(); float rnd; while (e.MoveNext()) { tree = new TreeInstance(); tree.position = WorldToTerrain(terrain,(Vector3)e.Current+trans); tree.prototypeIndex = 1; rnd= 0.25f*(Random.value-1.0f); // rnd=0.5f; tree.widthScale = 1.0f+rnd; tree.heightScale = 1.0f+rnd; Color c = Color.white; c[0] = 0.92f+Random.value*0.08f; c[1] = 0.92f+Random.value*0.08f; c[2] = 0.92f+Random.value*0.08f; tree.color = c; tree.lightmapColor = Color.white; newTrees.Add(tree); } } } terraindata.treeInstances= newTrees.ToArray(); Debug.Log (maxH); }
private extern void SetTreeInstance_Injected(int index, ref TreeInstance instance);
void AddTree(Vector3 position, int treeSpecies, int age) { //Add a tree to the terrain sized according to its age if (treeSpecies != 0) // 0 would be a gap (no tree) { int treePrototype = m_speciesList[treeSpecies]; TreeInstance tree = new TreeInstance(); tree.position = position; tree.prototypeIndex = treePrototype; //Vary the height and width of individual trees according to age float scale = m_prototypeScales[treePrototype] * ((age / (float)m_lifespans[treePrototype]) + 0.5f); tree.widthScale = scale; tree.heightScale = scale; tree.color = Color.white; tree.lightmapColor = Color.white; Terrain.activeTerrain.AddTreeInstance(tree); } }
private static void TerrainsReset_Do(ref GSDRoad tRoad){ if(tRoad.TerrainHistory == null){ return; } if(tRoad.TerrainHistory.Count < 1){ return; } Object[] TIDs = GameObject.FindObjectsOfType(typeof(GSDTerrain)); float[,] heights; int[,] tDetails; int ArrayCount; foreach(GSDTerrainHistoryMaker TH in tRoad.TerrainHistory){ Terrain tTerrain = null; foreach(GSDTerrain TID in TIDs){ if(TID.GSDID == TH.TID){ tTerrain = TID.tTerrain; } } if(!tTerrain){ continue; } //Heights: if(TH.x1 != null){ heights = tTerrain.terrainData.GetHeights(0,0,tTerrain.terrainData.heightmapWidth,tTerrain.terrainData.heightmapHeight); ArrayCount = TH.cI; for(int i=0;i<ArrayCount;i++){ heights[TH.x1[i],TH.y1[i]] = TH.h[i]; } tTerrain.terrainData.SetHeights(0,0,heights); } //Details: if(TH.DetailsI != null && TH.DetailsX != null && TH.DetailsY != null && TH.DetailsOldValue != null){ int RealLayerCount = tTerrain.terrainData.detailPrototypes.Length; int StartIndex = 0; int EndIndex = 0; for(int i=0;i<TH.DetailLayersCount;i++){ if(i >= RealLayerCount){ break; } if(TH.DetailsX.Length <= i){ break; } if(TH.DetailsY.Length <= i){ break; } if(TH.DetailsX == null || TH.DetailsY == null || TH.DetailsI == null || TH.DetailsX.Length < 1){ continue; } tDetails = tTerrain.terrainData.GetDetailLayer(0,0,tTerrain.terrainData.detailWidth,tTerrain.terrainData.detailHeight,i); ArrayCount = TH.DetailsI[i]; if(ArrayCount == 0){ continue; } EndIndex += ArrayCount; for(int j=StartIndex;j<EndIndex;j++){ tDetails[TH.DetailsX[j],TH.DetailsY[j]] = TH.DetailsOldValue[j]; } StartIndex = EndIndex; tTerrain.terrainData.SetDetailLayer(0,0,i,tDetails); tDetails = null; } } //Trees: TreeInstance[] xTress = TH.MakeTrees(); if(xTress != null){ ArrayCount = xTress.Length; if(ArrayCount > 0 && TH.TreesOld != null){ int TerrainTreeCount = tTerrain.terrainData.treeInstances.Length;; TreeInstance[] tTrees = new TreeInstance[ArrayCount+TerrainTreeCount]; System.Array.Copy(tTerrain.terrainData.treeInstances,0,tTrees,0,TerrainTreeCount); System.Array.Copy(xTress,0,tTrees,TerrainTreeCount,ArrayCount); tTerrain.terrainData.treeInstances = tTrees; } xTress = null; } } System.GC.Collect(); }
/// <summary> /// Adds the specified <paramref name="treeInstance"/> /// to the collection of trees who's collider to manage. /// </summary> /// <param name="treeInstance"> /// The <see cref="T:UnityEngine.TreeInstance"/> to add. /// </param> public bool AddTree(TreeInstance treeInstance) { var x = treeInstance.position.x * this.data.size.x + this.terrain.transform.position.x; var z = treeInstance.position.z * this.data.size.z + this.terrain.transform.position.z; return this.trees.Insert(x, z, treeInstance); }
/// <summary> /// Removes the specified <paramref name="treeInstance"/> /// from the collection of trees who's collider to manage. /// </summary> /// <param name="treeInstance"> /// The <see cref="T:UnityEngine.TreeInstance"/> to remove. /// </param> public bool RemoveTree(TreeInstance treeInstance) { // disable collider to avoid colliding with a tree that doesn't exist for (var index = 0; index < this.infos.Count; index++) { var treeInstanceInfo = this.infos[index]; if (treeInstance.Same(treeInstanceInfo.TreeInstance)) { treeInstanceInfo.gameObject.SetActive(false); break; } } // remove the tree itself var x = treeInstance.position.x * this.data.size.x + this.terrain.transform.position.x; var z = treeInstance.position.z * this.data.size.z + this.terrain.transform.position.z; return this.trees.Remove(x, z, treeInstance); }
private void GenerateTrees() { float threshold = 0.8f; float variation = 0.1f; int step = 4; //Texture2D treeSplatMap = ; ArrayList instances = new ArrayList(); for(int i=0;i<100;i++){ for(int j=0;j<100;j++){ TreeInstance instance = new TreeInstance(); Vector3 pos = new Vector3(i,0.5f,j); instance.position = pos; instance.color = Color.white; instance.prototypeIndex=0; instance.widthScale = 1.0f + Random.Range(-variation,variation); instance.heightScale = 1.0f + Random.Range(-variation,variation); instances.Add(instance); } } // td= terrain.terrainData; ///terrain.terrainData.treeInstances = (TreeInstance[])instances.ToArray(typeof(TreeInstance)); //td.RefreshPrototypes(); //terrain.terrainData.RecalculateTreePositions(); }