public void PlaceTrees(ProgressDelegate progressDelegate) { if (!Validate()) return; instances = new ArrayList(); TreesPosition = new List<TreePosition>(); //get alpha map width and height of terrain int alphamapWidth = terrainData.alphamapWidth; int alphamapHeight = terrainData.alphamapHeight; //get splat map of terrain splatmap = terrainData.GetAlphamaps(0,0,alphamapWidth,alphamapHeight); //dimension of splatmaps int xDim = splatmap.GetUpperBound(0); int yDim = splatmap.GetUpperBound(1); //how big is one unit in real world xUnit = (float)terrainData.size.x / (float)(xDim + 1); yUnit = (float)terrainData.size.z / (float)(yDim + 1); float percentPosition = 0.1f; progressDelegate("Placing trees", "Determining basic position", percentPosition); float calculation = 0.4f / xDim; for(int x = 0; x <= xDim; x ++) { for(int y = 0; y <= yDim; y ++) { foreach(TreeTextureSettings treeTexture in TreeTextures) { //this texture is not used for planting trees if (treeTexture.IsUsed == false) continue; float alphaMap = splatmap[x,y,treeTexture.Index]; //this texture is not where we are currently in if (alphaMap < treeTexture.AlphamapValue) continue; //check distance from the nearest tree if (IsTreePositionClose(x, y, treeTexture.TreeDistance, treeTexture.Index)) continue; TreePosition position = new TreePosition(); position.PosX = x; position.PosY = y; position.TreeIndex = treeTexture.DetermineTreePrototype; position.TextureIndex = treeTexture.Index; TreesPosition.Add(position); } } percentPosition += calculation; progressDelegate("Placing trees", "Determining basic position", percentPosition); } Place(progressDelegate); }
/// <summary> /// Get the bound of a (multidimensional) array /// </summary> /// <param name="data">the array (might be multidimentional or not)</param> /// <returns>the bitmap generated using the data in the error histogram</returns> internal static float[] GetBounds(object data) { float max = float.MinValue; float min = float.MaxValue; float[] sdata = data as float[]; if (sdata != null) { int w = sdata.Length; for (int j = 0; j < w; j++) { if (sdata[j] > max) { max = sdata[j]; } if (sdata[j] < min) { min = sdata[j]; } } } float[,] bwdata = data as float[, ]; if (bwdata != null) { int w = bwdata.GetUpperBound(0); int h = bwdata.GetUpperBound(1); for (int j = 0; j < w; j++) { for (int i = 0; i < h; i++) { if (bwdata[j, i] > max) { max = bwdata[j, i]; } if (bwdata[j, i] < min) { min = bwdata[j, i]; } } } } float[,,] rgbdata = data as float[, , ]; if (rgbdata != null) { int w = rgbdata.GetUpperBound(1); int h = rgbdata.GetUpperBound(2); for (int k = 0; k < 3; k++) { for (int j = 0; j < w; j++) { for (int i = 0; i < h; i++) { if (rgbdata[k, j, i] > max) { max = rgbdata[k, j, i]; } if (rgbdata[k, j, i] < min) { min = rgbdata[k, j, i]; } } } } } float[] bounds = { min, max }; return(bounds); }
/// <summary> /// Build an histogram based on a multidimentinal array (2 or 3) /// </summary> /// <param name="tval">the multidimentional array containing the data</param> /// <returns>an array of float representing the histogram</returns> internal static float[] getFHistogram(object tval) { float[] hist = new float[256]; float [,] data = tval as float[, ]; if (data != null) { int w = data.GetUpperBound(0); int h = data.GetUpperBound(1); float [] bd = IPUtil.GetBounds(data); Console.WriteLine("miinimaxx " + bd[0] + " " + bd[1]); bd[1] = 2000; bd[1] -= bd[0]; for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { int idx = (int)(255.0 * (data[i, j] - bd[0]) / bd[1]); if (idx > 255) { idx = 255; } if (idx < 0) { idx = 9; } hist[idx] += 1.0f; } } float nbp = w * h; for (int j = 0; j < hist.Length; j++) { hist[j] /= nbp; } } float [,,] ddata = tval as float[, , ]; if (ddata != null) { int w = ddata.GetUpperBound(1); int h = ddata.GetUpperBound(2); float [] bd = IPUtil.GetBounds(ddata); for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { float val = RGBfloat2Yfloat(ddata[0, i, j], ddata[1, i, j], ddata[2, i, j]); int idx = (int)(255.0 * (val - bd[0]) / bd[1]); if (idx > 255) { idx = 255; } if (idx < 0) { idx = 9; } hist[idx] += 1.0f; } } float nbp = w * h; for (int j = 0; j < hist.Length; j++) { hist[j] /= nbp; } } mHist.Add(hist); return(hist); }
protected override void Init() { if (splatSettings == null || splatSettings.Length == 0) { splatSettings = new TerrainVoxelDefinitionMapping[64]; } if (detailSettings == null || detailSettings.Length == 0) { detailSettings = new VegetationVoxelDefinitionMapping[64]; } if (treeSettings == null || treeSettings.Length == 0) { treeSettings = new TerrainModelDefinitionMapping[32]; } if (detailLayers == null || detailLayers.Length < 32) { detailLayers = new DetailLayerInfo[32]; } if (waterVoxel == null) { waterVoxel = Resources.Load <VoxelDefinition> ("VoxelPlay/Defaults/Water/VoxelWaterSea"); } env.AddVoxelDefinition(bedrockVoxel); #if UNITY_EDITOR if (world != null && world.terrainGenerator == null) { world.terrainGenerator = this; } if (terrainData == null) { Terrain activeTerrain = Terrain.activeTerrain; if (activeTerrain != null) { terrainData = activeTerrain.terrainData; ExamineTerrainData(); } } #endif if (terrainData == null) { return; } if (lastTerrainDataLoaded != null && lastTerrainDataLoaded == terrainData && heights != null && heights.Length > 0) { return; } lastTerrainDataLoaded = terrainData; maxHeight = terrainData.size.y; int th = terrainData.heightmapResolution; int tw = terrainData.heightmapResolution; int len = tw * th; if (heights == null || heights.Length != len) { heights = new TerrainHeightInfo[len]; } float[,,] heightInfo = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight); int detailLayerCount = terrainData.detailPrototypes.Length; for (int d = 0; d < detailLayerCount; d++) { detailLayers [d].detailLayer = terrainData.GetDetailLayer(0, 0, terrainData.detailWidth, terrainData.detailHeight, d); } int i = 0; int alphaMapsLayerCount = heightInfo.GetUpperBound(2); int currentDetailLayer = 0; int vegDensity = (int)(16 * (1f - vegetationDensity)); for (int y = 0; y < th; y++) { int alphamapY = y * terrainData.alphamapHeight / th; int detailY = y * terrainData.detailHeight / th; for (int x = 0; x < tw; x++, i++) { int alphamapX = x * terrainData.alphamapWidth / tw; heights [i].altitude = terrainData.GetHeight(x, y) / maxHeight; float maxBlend = -1; for (int a = 0; a <= alphaMapsLayerCount; a++) { float alphamapValue = heightInfo [alphamapY, alphamapX, a]; if (alphamapValue > maxBlend) { maxBlend = alphamapValue; heights [i].terrainVoxelTop = splatSettings [a].top; heights [i].terrainVoxelDirt = splatSettings [a].dirt; if (maxBlend >= 1f) { break; } } } if (detailLayerCount > 0) { for (int v = 0; v < detailLayerCount; v++) { currentDetailLayer++; if (currentDetailLayer >= detailLayerCount) { currentDetailLayer = 0; } if (detailSettings [currentDetailLayer].vd != null) { int detailX = x * terrainData.detailWidth / tw; int o = detailLayers [currentDetailLayer].detailLayer [detailY, detailX]; if (o > vegDensity) { heights [i].vegetationVoxel = detailSettings [currentDetailLayer].vd; break; } } } } } } float sx = terrainData.size.x; float sz = terrainData.size.z; for (int t = 0; t < terrainData.treeInstances.Length; t++) { TreeInstance ti = terrainData.treeInstances [t]; int hindex = GetHeightIndex(ti.position.x * sx - sx / 2, ti.position.z * sz - sz / 2); heights [hindex].treeModel = treeSettings [ti.prototypeIndex].md; } }
//v2.1.1 void PlantGrass(RaycastHit hit, Collider collider1, Transform transform1, int Grass_selector, bool growInEditor, bool registerToManager) { bool is_Terrain = false; if ((Terrain.activeTerrain != null && collider1.gameObject != null && collider1.gameObject == Terrain.activeTerrain.gameObject)) { is_Terrain = true; } if (is_Terrain | (collider1.gameObject != null && collider1.gameObject.tag == "PPaint")) //v1.1 //DONT PLANT if hit another grass collider { if (collider1.GetComponent <GrassChopCollider> () != null) { } else { GameObject TEMP = Instantiate(Grassmanager.GrassPrefabs [Grass_selector]); TEMP.transform.position = hit.point; INfiniDyGrassField TREE = TEMP.GetComponent <INfiniDyGrassField> (); TREE.Intial_Up_Vector = hit.normal; //v2.1 if (Application.isPlaying) { TREE.Grow_tree = true; } else { //TREE.Grow_tree = false; TREE.Grow_in_Editor = true; } //v1.1 - terrain adapt if (Grassmanager.AdaptOnTerrain & is_Terrain) { int Xpos = (int)(((hit.point.x - Grassmanager.Tpos.x) * Grassmanager.Tdata.alphamapWidth / Grassmanager.Tdata.size.x)); int Zpos = (int)(((hit.point.z - Grassmanager.Tpos.z) * Grassmanager.Tdata.alphamapHeight / Grassmanager.Tdata.size.z)); float[,,] splats = Grassmanager.Tdata.GetAlphamaps(Xpos, Zpos, 1, 1); float[] Tarray = new float[splats.GetUpperBound(2) + 1]; for (int j = 0; j < Tarray.Length; j++) { Tarray[j] = splats[0, 0, j]; //Debug.Log(Tarray[j]); // ScalePerTexture } float Scaling = 0; for (int j = 0; j < Tarray.Length; j++) { if (j > Grassmanager.ScalePerTexture.Count - 1) { Scaling = Scaling + (1 * Tarray[j]); } else { Scaling = Scaling + (Grassmanager.ScalePerTexture[j] * Tarray[j]); } } TREE.End_scale = Scaling * UnityEngine.Random.Range(Grassmanager.min_scale, Grassmanager.max_scale); //Debug.Log(Tarray); } else { TREE.End_scale = UnityEngine.Random.Range(Grassmanager.min_scale, Grassmanager.max_scale); } TREE.Max_interact_holder_items = Grassmanager.Max_interactive_group_members; //Define max number of trees grouped in interactive batcher that opens up. //Increase to lower draw calls, decrease to lower spikes when group is opened for interaction TREE.Max_trees_per_group = Grassmanager.Max_static_group_members; TREE.Interactive_tree = Grassmanager.Interactive; //v2.1 if (Application.isPlaying) { TREE.transform.localScale *= TREE.End_scale * Grassmanager.Collider_scale; } else { TREE.colliderScale = Vector3.one * Grassmanager.Collider_scale; } if (Grassmanager.Override_spread) { TREE.PosSpread = new Vector2(UnityEngine.Random.Range(Grassmanager.Min_spread, Grassmanager.Max_spread), UnityEngine.Random.Range(Grassmanager.Min_spread, Grassmanager.Max_spread)); } if (Grassmanager.Override_density) { TREE.Min_Max_Branching = new Vector2(Grassmanager.Min_density, Grassmanager.Max_density); } TREE.PaintedOnOBJ = transform1.gameObject.transform; TREE.GridOnNormal = Grassmanager.GridOnNormal; TREE.max_ray_dist = Grassmanager.rayCastDist; TREE.MinAvoidDist = Grassmanager.MinAvoidDist; TREE.MinScaleAvoidDist = Grassmanager.MinScaleAvoidDist; TREE.InteractionSpeed = Grassmanager.InteractionSpeed; TREE.InteractSpeedThres = Grassmanager.InteractSpeedThres; //v1.4 TREE.Interaction_thres = Grassmanager.Interaction_thres; TREE.Max_tree_dist = Grassmanager.Max_tree_dist; //v1.4.6 TREE.Disable_after_growth = Grassmanager.Disable_after_growth; //v1.5 TREE.WhenCombinerFull = Grassmanager.WhenCombinerFull; //v1.5 TREE.Eliminate_original_mesh = Grassmanager.Eliminate_original_mesh; //v1.5 TREE.Interaction_offset = Grassmanager.Interaction_offset; TREE.LOD_distance = Grassmanager.LOD_distance; TREE.LOD_distance1 = Grassmanager.LOD_distance1; TREE.LOD_distance2 = Grassmanager.LOD_distance2; TREE.Cutoff_distance = Grassmanager.Cutoff_distance; TREE.Tag_based = false; TREE.GrassManager = Grassmanager; ////////////////////////// v2.1.1 TREE.Type = Grass_selector + 1; TREE.Start_tree_scale = TREE.End_scale / 4; TREE.RandomRot = Grassmanager.RandomRot; TREE.RandRotMin = Grassmanager.RandRotMin; TREE.RandRotMax = Grassmanager.RandRotMax; TREE.GroupByObject = Grassmanager.GroupByObject; TREE.ParentToObject = Grassmanager.ParentToObject; TREE.MoveWithObject = Grassmanager.MoveWithObject; TREE.AvoidOwnColl = Grassmanager.AvoidOwnColl; TEMP.transform.parent = Grassmanager.GrassHolder.transform; //v1.8 // TREE.BatchColliders = Grassmanager.BatchColliders; // TREE.BatchInstantiation = Grassmanager.BatchInstantiation; // TREE.RandomPositions = Grassmanager.RandomPositions; // TREE.BatchCopiesCount = Grassmanager.BatchCopiesCount; // TREE.CopiedBatchSpread = Grassmanager.CopiedBatchSpread; // // //v2.0.3 // TREE.noOutofPlaneBlades = Grassmanager.noOutofPlaneBlades; // TREE.maxOutofPlaneSlopeHeight = Grassmanager.maxOutofPlaneSlopeHeight; //Add to holder, in order to mass change properties Grassmanager.Grasses.Add(TREE); Grassmanager.GrassesType.Add(Grass_selector); TEMP.name = "GrassPatch" + Grassmanager.Grasses.Count.ToString(); TREE.Grass_Holder_Index = Grassmanager.Grasses.Count - 1; //register id in grasses list //RECONFIG TREE.transform.parent = Grassmanager.GrassHolder.transform; Grassmanager.CleanUp = false; INfiniDyGrassField forest = Grassmanager.Grasses[Grassmanager.Grasses.Count - 1]; //forest.gameObject.SetActive(false);//ADDED v1.8 forest.Combiner = null; forest.Grow_in_Editor = false; forest.growth_over = false; forest.Registered_Brances.Clear(); // //forest.root_tree = null; forest.Branch_grew.Clear(); forest.Registered_Leaves.Clear(); // forest.Registered_Leaves_Rot.Clear(); // forest.batching_ended = false; forest.Branch_levels.Clear(); forest.BranchID_per_level.Clear(); //forest.Grass_Holder_Index = 0; forest.Grow_level = 0; forest.Grow_tree_ended = false; forest.Health = forest.Max_Health; forest.is_moving = false; forest.Leaf_belongs_to_branch.Clear(); forest.scaleVectors.Clear(); forest.Leaves.Clear(); forest.Tree_Holder_Index = 0; // forest.Grow_tree = true;//v1.5 - fix issue with start scale when entering play mode from ungrown mode //v2.1.3 if (grow_grass) { forest.Grow_tree = true; forest.Start_tree_scale = forest.End_scale * start_size_factor; //v1.5 } else { forest.Grow_tree = false; forest.Start_tree_scale = forest.End_scale; //v1.5 } forest.rotation_over = false; forest.Forest_holder = null; //Grassmanager.UnGrown = true; } } }
public static void ExportTerrainTexture() { TerrainData terrainData = Selection.activeObject as TerrainData; if (terrainData == null) { EditorUtility.DisplayDialog("Select Terrain", "You Must Select a Terrain first!", "Ok"); return; } EditorUtility.DisplayDialog("Select Terrain", "You select the Terrain of " + terrainData.name, "Ok"); var path = EditorUtility.SaveFilePanel("Save Resource", "", terrainData.name, "png"); if (path.Length == 0) { return; } //Get Ratio withRatio = terrainData.size.x / terrainData.alphamapWidth; heightRatio = terrainData.size.z / terrainData.alphamapHeight; // //get Terrain size // terrainWith = terrainData.size.x; // terrainHeight = terrainData.size.z; // // //Get AlphaMap size // alphaMapWith = terrainData.alphamapWidth; // alphaMapHeight = terrainData.alphamapHeight; // return; //Create return texture Texture2D texture = new Texture2D(terrainData.alphamapWidth, terrainData.alphamapHeight, TextureFormat.RGBA32, false); //blend map float [,,] splatmapData = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight); // Color[] colorList = new Color[ splatmapData.GetUpperBound(2) ];//newList<Color>( splatmapData.GetUpperBound(2) ); for (int i = splatmapData.GetLowerBound(0); i <= splatmapData.GetUpperBound(0); i++) { for (int j = splatmapData.GetLowerBound(1); j <= splatmapData.GetUpperBound(1); j++) { int channel = splatmapData.GetUpperBound(2); Color blendColor = Color.white; if (channel == 2) { blendColor = new Color(splatmapData[j, i, 0], splatmapData[j, i, 1], splatmapData[j, i, 2], 1); } else if (channel == 3) { blendColor = new Color(splatmapData[j, i, 0], splatmapData[j, i, 1], splatmapData[j, i, 2], splatmapData[j, i, 3]); } //for ( int k = splatmapData.GetLowerBound(2); k <= splatmapData.GetUpperBound(2); k++ ) //{ // Color color = GetSplatColor( terrainData.splatPrototypes[k], i , j ); // blendColor += splatmapData[i, j, k]; //} texture.SetPixel(i, j, blendColor); } } // float [,,] splatmapData = terrainData.GetAlphamaps( 0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight ); // Texture2D texture = new Texture2D( terrainData.alphamapWidth, terrainData.alphamapHeight,TextureFormat.RGB24, false ); byte[] bytes = texture.EncodeToPNG(); File.WriteAllBytes(path, bytes); }
void GetSurfaceSound() { if (onTerrain) { TerrainData terrainData = terrain.terrainData; #region Texture Mix // calculate which splat map cell the worldPos falls within (ignoring y) int mapX = (int)(((transform.position.x - terrain.GetPosition().x) / terrainData.size.x) * terrainData.alphamapWidth); int mapZ = (int)(((transform.position.z - terrain.GetPosition().z) / terrainData.size.z) * terrainData.alphamapHeight); // get the splat data for this cell as a 1x1xN 3d array (where N = number of textures) float[,,] splatmapData = terrainData.GetAlphamaps(mapX, mapZ, 1, 1); // extract the 3D array data to a 1D array: float[] textureMix = new float[splatmapData.GetUpperBound(2) + 1]; for (int n = 0; n < textureMix.Length; n++) { textureMix[n] = splatmapData[0, 0, n]; } #endregion #region Texture Index float maxMix = 0; int maxIndex = 0; // loop through each mix value and find the maximum for (int n = 0; n < textureMix.Length; n++) { if (textureMix[n] > maxMix) { maxIndex = n; maxMix = textureMix[n]; } } int textureIndex = maxIndex; #endregion #region Set Footstep Sound string textureName = terrainData.splatPrototypes[textureIndex].texture.name; foreach (var texture in textureAttributes) { if (texture.texture.name == textureName) { footstepSound = textureAttributes[texture.index].footstepSounds; canRun = textureAttributes[texture.index].canRun; GetComponent <PlayerController>().canRun = textureAttributes[texture.index].canRun; GetComponent <PlayerController>().walkSpeed = textureAttributes[texture.index].walkSpeed; GetComponent <PlayerController>().runSpeed = textureAttributes[texture.index].runSpeed; } } #endregion } else if (onMesh) { //Physics Material if (detectionType == _type.TerrainTextureAndPhysicsMaterial) { foreach (var physicsMaterial in physicsMaterials) { if (currentPhysicsMaterial == physicsMaterial.material) { footstepSound = physicsMaterial.footstepSounds; canRun = physicsMaterial.canRun; GetComponent <PlayerController>().canRun = physicsMaterial.canRun; /* if(!physicsMaterial.canRun) * if (GetComponent<PlayerController>().isRunning) * GetComponent<PlayerController>().isRunning = false; */ GetComponent <PlayerController>().walkSpeed = physicsMaterial.walkSpeed; GetComponent <PlayerController>().runSpeed = physicsMaterial.runSpeed; } } } //Tag else if (detectionType == _type.TerrainTextureAndTag) { foreach (var tag in tags) { if (currentMeshTag == tag.tagName) { footstepSound = tag.footstepSounds; canRun = tag.canRun; GetComponent <PlayerController>().canRun = tag.canRun; /* if (!tag.canRun) * if (GetComponent<PlayerController>().isRunning) * GetComponent<PlayerController>().isRunning = false; */ GetComponent <PlayerController>().walkSpeed = tag.walkSpeed; GetComponent <PlayerController>().runSpeed = tag.runSpeed; } } } } }