public static float[,] GetInterpolatedTerrain(OSMBoundingBox boundingBox, out float height) { float[,] result = new float[257, 257]; float minHeight = float.MaxValue; float maxHeight = float.MinValue; for (int i = 0; i < 257; i++) { for (int j = 0; j < 257; j++) { result[i, j] = SRTMHeightProvider.GetInterpolatedHeight(boundingBox.MinLatitude + ((double)i / 257) * (boundingBox.MaxLatitude - boundingBox.MinLatitude), boundingBox.MinLongitude + ((double)j / 257) * (boundingBox.MaxLongitude - boundingBox.MinLongitude)); if (result[i, j] < -32767) { continue; } minHeight = Mathf.Min(result[i, j], minHeight); maxHeight = Mathf.Max(result[i, j], maxHeight); } } for (int i = 0; i < 257; i++) { for (int j = 0; j < 257; j++) { if (result[i, j] < -32767) { result[i, j] = minHeight; } else { result[i, j] = result[i, j] / maxHeight; } } } // Prevent zerodivision by TerrainComponent if (maxHeight > 0f) { height = maxHeight; } else { height = 1f; } TerrainLayer.MinTerrainHeight = minHeight; TerrainLayer.MaxTerrainHeight = maxHeight; return(result); }
public Building(OSMWay way, OSMData osm) { if (way.Tags.ContainsKey("building:height")) { float.TryParse(way.Tags["building:height"], out height); } else { height = Random.Range(20f, 40f); } layout = new Polygon(); OSMNode node; //Discard last waynode if its the same as first if (way.WayNodes[0] == way.WayNodes[way.WayNodes.Count - 1]) { for (int i = 0; i < way.WayNodes.Count - 1; i++) { if (osm.nodes.TryGetValue(way.WayNodes[i], out node)) { Vector3 pos = new Vector3(node.X, SRTMHeightProvider.GetInterpolatedHeight(node.Latitude, node.Longitude), node.Z); layout.Add(new Vertex(pos)); } } } else { for (int i = 0; i < way.WayNodes.Count; i++) { if (osm.nodes.TryGetValue(way.WayNodes[i], out node)) { Vector3 pos = new Vector3(node.X, SRTMHeightProvider.GetInterpolatedHeight(node.Latitude, node.Longitude), node.Z); layout.Add(new Vertex(pos)); } } } layout.MakeClockwise(); }
public void CreateMesh(ModularMesh mesh) { layout = new Polygon(); OSMNode node; //Discard last waynode if its the same as first if (way.WayNodes[0] == way.WayNodes[way.WayNodes.Count - 1]) { for (int i = 0; i < way.WayNodes.Count - 1; i++) { if (osm.nodes.TryGetValue(way.WayNodes[i], out node)) { Vector3 pos = new Vector3(node.X, SRTMHeightProvider.GetInterpolatedHeight(node.Latitude, node.Longitude), node.Z); layout.Add(new Vertex(pos)); } } } else { for (int i = 0; i < way.WayNodes.Count; i++) { if (osm.nodes.TryGetValue(way.WayNodes[i], out node)) { Vector3 pos = new Vector3(node.X, SRTMHeightProvider.GetInterpolatedHeight(node.Latitude, node.Longitude), node.Z); layout.Add(new Vertex(pos)); } } } layout.MakeClockwise(); leveledLayout = layout.LevelUp(); area = leveledLayout.Triangulate(mesh, MaterialManager.GetMaterial("diffuseBlue")); }
//public float GetInterpolatedHeight(double latitude, double longitude) //{ // int pixelIndexX = (int)Math.Floor((latitude - latIndex) * 1201); // int pixelIndexY = (int)Math.Floor((longitude - longIndex) * 1201); // float x = (float)(((latitude - latIndex) * 1201) % 1); // float y = (float)(((longitude - longIndex) * 1201) % 1); // float f00 = Data[pixelIndexX, pixelIndexY]; // float f01 = Data[pixelIndexX, pixelIndexY + 1]; // float f10 = Data[pixelIndexX + 1, pixelIndexY]; // float f11 = Data[pixelIndexX + 1, pixelIndexY + 1]; // //Bilinear Interpolation // //return f00 * (1f - x) * (1f - y) + f10 * x * (1f - y) + f01 * (1 - x) * y + f11 * x * y; // return BilinearInterpolation(f00, f01, f10, f11, x, y); //} //private float BilinearInterpolation(float f00, float f01, float f10, float f11, float u, float w) //{ // return f00 * (1 - u) * (1 - w) + f01 * (1 - u) * w + f10 * u * (1 - w) + f11 * u * w; //} public float GetInterpolatedHeight(double latitude, double longitude) { int pixelIndexX = (int)Math.Floor((latitude - latIndex) * 1200); int pixelIndexY = (int)Math.Floor((longitude - longIndex) * 1200); float xParam = (float)(((latitude - latIndex) * 1200) % 1); float yParam = (float)(((longitude - longIndex) * 1200) % 1); float[,] controlPoints = new float[4, 4]; int counterX = 0; int counterY = 0; for (int x = pixelIndexX - 1; x <= pixelIndexX + 2; x++) { counterY = 0; for (int y = pixelIndexY - 1; y <= pixelIndexY + 2; y++) { if (x == -1) { // | // * * * * // * * * * // ----*-*-*-*----- // X * * * // | if (y == -1) { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex - 1, longIndex - 1); controlPoints[counterX, counterY] = cell.Data[1199, 1199]; if (xParam >= 0.5f || yParam >= 0.5f) { Debug.Log("Parameter: " + x + ", " + y); } } // | // X * * * // ----*-*-*-*----- // * * * * // * * * * // | else if (y == 1201) { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex - 1, longIndex + 1); controlPoints[counterX, counterY] = cell.Data[1199, 1]; } // | // X * * * // * * * * // ----*-*-*-*----- // * * * * // | else if (y == 1202) { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex - 1, longIndex + 1); controlPoints[counterX, counterY] = cell.Data[1199, 2]; } // | //X * ** //X * ** //X * ** //X * ** // | else { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex - 1, longIndex); controlPoints[counterX, counterY] = cell.Data[1199, y]; } } else if (x == 1201) { // | // * * * * // * * * * // ----*-*-*-*----- // * * * X // | if (y == -1) { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex + 1, longIndex - 1); controlPoints[counterX, counterY] = cell.Data[1, 1199]; } // | // * * * x // ----*-*-*-*----- // * * * * // * * * * // | else if (y == 1201) { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex + 1, longIndex + 1); controlPoints[counterX, counterY] = cell.Data[1, 1]; } //// | //// * * * x //// * * * * //// ----*-*-*-*----- //// * * * * //// | //else if (y == 1202) //{ // SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex + 1, longIndex + 1); // controlPoints[counterX, counterY] = cell.Data[1, 2]; //} // | // * * * x // * * * x // * * * x // * * * x // | else { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex + 1, longIndex); controlPoints[counterX, counterY] = Data[1, y]; } } //else if (x == 1202) //{ // // | // // * * * * // // * * * * // // ----*-*-*-*----- // // * * * X // // | // if (y == -1) // { // SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex + 1, longIndex - 1); // controlPoints[counterX, counterY] = cell.Data[2, 1199]; // } // // | // // * * * x // // ----*-*-*-*----- // // * * * * // // * * * * // // | // else if (y == 1201) // { // SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex + 1, longIndex + 1); // controlPoints[counterX, counterY] = cell.Data[2, 1]; // } // // | // // * * * x // // * * * * // // ----*-*-*-*----- // // * * * * // // | // else if (y == 1202) // { // SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex + 1, longIndex + 1); // controlPoints[counterX, counterY] = cell.Data[2, 2]; // } // // | // // * * * x // // * * * x // // * * * x // // * * * x // // | // else // { // SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex + 1, longIndex); // controlPoints[counterX, counterY] = Data[2, y]; // } //} else { // // * * * * // * * * * // ----*-*-*-*----- // X X X X // if (y == -1) { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex, longIndex - 1); controlPoints[counterX, counterY] = cell.Data[x, 1199]; } // // X X X X // ----*-*-*-*----- // * * * * // * * * * // else if (y == 1201) { SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex, longIndex + 1); controlPoints[counterX, counterY] = cell.Data[x, 1]; } //// //// X X X X //// * * * * //// ----*-*-*-*----- //// * * * * //// //else if (y == 1202) //{ // SRTMDataCell cell = SRTMHeightProvider.GetSRTMDataCell(latIndex, longIndex + 1); // controlPoints[counterX, counterY] = cell.Data[x, 1]; //} // // X X X X // X X X X // X X X X // X X X X // else { controlPoints[counterX, counterY] = Data[x, y]; } } counterY++; } counterX++; } //Bilinear Interpolation //return f00 * (1f - x) * (1f - y) + f10 * x * (1f - y) + f01 * (1 - x) * y + f11 * x * y; return(CardinalSplinePatchPoint(controlPoints, xParam, yParam)); }
IEnumerator ProceduralLocal() { msg.Stop(Job.StartProcedural); msg.Start(Job.ProceduralPreparation); SimpleClient.jobStatus[jobNumber] = msg; this.transform.position = TilePosition - new Vector3((float)TileManager.TileWidth * (float)TileManager.Scaling / 2f, 0f, (float)TileManager.TileWidth * (float)TileManager.Scaling / 2f); terrain = this.gameObject.GetOrAddComponent <Terrain>(); tC = this.gameObject.GetOrAddComponent <TerrainCollider>(); Building.Clear(); Intersection.Clear(); Street.Clear(); Water.Clear(); River.Clear(); Bridge.Clear(); unusedWays.Clear(); streets.Clear(); streetPolygons.Clear(); msg.Stop(Job.ProceduralPreparation); #region LOD0 if (lOD == 0) { Console.AddMessage("Procedural lod 0"); Debug.Log("Procedural lod 0"); #region terrain TerrainData terrainData = new TerrainData(); //HeightMap terrainData.heightmapResolution = 257; float[,] heights = new float[257, 257]; for (int x = 0; x < heights.GetLength(0); x++) { for (int y = 0; y < heights.GetLength(1); y++) { heights[x, y] = 1f; } } terrainData.SetHeights(0, 0, heights); terrainData.size = new Vector3((float)TileManager.TileWidth * (float)TileManager.Scaling, 10f, (float)TileManager.TileWidth * (float)TileManager.Scaling); ////SplatPrototypes //SplatPrototype[] splatPrototypes = new SplatPrototype[1]; //splatPrototypes[0] = new SplatPrototype(); ////splatPrototypes[0].texture = (Texture2D)Resources.Load("Textures/White1px"); //splatPrototypes[0].texture = (Texture2D)Resources.Load("Textures/Terrain/Grass (Hill)"); //terrainData.splatPrototypes = splatPrototypes; terrain.terrainData = terrainData; tC.terrainData = terrainData; #endregion terrain #region mesh TileMesh.Clear(); Vertex[] tileQuadVertices = new Vertex[4]; tileQuadVertices[0] = new Vertex(new Vector3((float)(-TileManager.TileWidth * TileManager.Scaling / 2d), 0f, (float)(-TileManager.TileWidth * TileManager.Scaling / 2d)) + TilePosition); tileQuadVertices[1] = new Vertex(new Vector3((float)(-TileManager.TileWidth * TileManager.Scaling / 2d), 0f, (float)(TileManager.TileWidth * TileManager.Scaling / 2d)) + TilePosition); tileQuadVertices[2] = new Vertex(new Vector3((float)(TileManager.TileWidth * TileManager.Scaling / 2d), 0f, (float)(TileManager.TileWidth * TileManager.Scaling / 2d)) + TilePosition); tileQuadVertices[3] = new Vertex(new Vector3((float)(TileManager.TileWidth * TileManager.Scaling / 2d), 0f, (float)(-TileManager.TileWidth * TileManager.Scaling / 2d)) + TilePosition); new Quad(tileQuadVertices, TileMesh, MaterialManager.GetMaterial("diffuseBrown")); TileMesh.FillMeshDivideMaterialsKeepMeshStructure(transform, true); #endregion Debug.Log("Procedural lod 0 - Done"); } #endregion #region LOD5 if (lOD == 5) { msg.Start(Job.CreateTerrain); SimpleClient.jobStatus[jobNumber] = msg; #region terrain if (terrain.terrainData == null) { terrain.terrainData = new TerrainData(); } //HeightMap terrain.terrainData.heightmapResolution = 257; terrain.terrainData.alphamapResolution = 257; float height = 0f; terrain.terrainData.SetHeights(0, 0, SRTMHeightProvider.GetInterpolatedTerrain(this.Query.BoundingBox, out height)); terrain.terrainData.size = new Vector3((float)TileManager.TileWidth * (float)TileManager.Scaling, height, (float)TileManager.TileWidth * (float)TileManager.Scaling); tC.terrainData = terrain.terrainData; msg.Stop(Job.CreateTerrain); #endregion terrain #region mesh msg.Start(Job.MeshPreparation); SimpleClient.jobStatus[jobNumber] = msg; TileMesh.Clear(); if (BackgroundMesh != null) { BackgroundMesh.Clear(); } else { BackgroundMesh = new ModularMesh(TileMesh, "BackgroundMesh"); } if (BuildingMesh != null) { BuildingMesh.Clear(); } else { BuildingMesh = new ModularMesh(TileMesh, "BuildingMesh"); } if (StreetMesh != null) { StreetMesh.Clear(); } else { StreetMesh = new ModularMesh(TileMesh, "StreetMesh"); } if (OtherMesh != null) { OtherMesh.Clear(); } else { OtherMesh = new ModularMesh(TileMesh, "OtherMesh"); } msg.Stop(Job.MeshPreparation); msg.Start(Job.TileQuad); SimpleClient.jobStatus[jobNumber] = msg; Vertex[] tileQuadVertices = new Vertex[4]; tileQuadVertices[0] = new Vertex(new Vector3((float)(-TileManager.TileWidth * TileManager.Scaling / 2d), 0f, (float)(-TileManager.TileWidth * TileManager.Scaling / 2d)) + TilePosition); tileQuadVertices[1] = new Vertex(new Vector3((float)(-TileManager.TileWidth * TileManager.Scaling / 2d), 0f, (float)(TileManager.TileWidth * TileManager.Scaling / 2d)) + TilePosition); tileQuadVertices[2] = new Vertex(new Vector3((float)(TileManager.TileWidth * TileManager.Scaling / 2d), 0f, (float)(TileManager.TileWidth * TileManager.Scaling / 2d)) + TilePosition); tileQuadVertices[3] = new Vertex(new Vector3((float)(TileManager.TileWidth * TileManager.Scaling / 2d), 0f, (float)(-TileManager.TileWidth * TileManager.Scaling / 2d)) + TilePosition); new Quad(tileQuadVertices, BackgroundMesh, MaterialManager.GetMaterial("diffuseBlack")); msg.Stop(Job.TileQuad); yield return(null); msg.Start(Job.River); SimpleClient.jobStatus[jobNumber] = msg; //Create Domain Objects ///Relations foreach (KeyValuePair <long, OSMRelation> kV in Query.OSM.relations) { OSMRelation relation = kV.Value; River.TryCreateFromOSM(relation, this); yield return(null); } msg.Stop(Job.River); msg.Start(Job.Ways); SimpleClient.jobStatus[jobNumber] = msg; ///Ways foreach (KeyValuePair <long, OSMWay> kV in Query.OSM.ways) { OSMWay way = kV.Value; if (!way.FirstInBounds(Query.BoundingBox, Query.OSM)) { continue; } if (!Building.TryCreateFromOSM(way, this)) { if (!Intersection.TryCreateFromOSM(way, this)) { if (!Water.TryCreateFromOSM(way, this)) { } } } yield return(null); } msg.Stop(Job.Ways); //Nodes!? //foreach (KeyValuePair<long, OSMNode> kV in Query.OSM.nodes) //{ // OSMNode node = kV.Value; // TrafficSignal.TryCreateFromOSM(node, this); //} //Debug.Log("CreateStreets"); ////Create Streets (and Bridges) //Street.CreateStreets(this); //CreateTheMeshes //Debug.Log("CreateAllMeshes StreetMesh"); //Street.CreateAllMeshes(StreetMesh); //Debug.Log("CreateAllMeshes StreetMesh Bridge"); //Bridge.CreateAllMeshes(StreetMesh); //Debug.Log("CreateAllMeshes StreetMesh Intersection"); //Intersection.CreateAllMeshes(StreetMesh); //Debug.Log("CreateAllMeshes StreetMesh Street"); //Street.CreateAllMeshes(StreetMesh); // A second time, cause Intersections change streetproperties msg.Start(Job.CreateBuildingMesh); SimpleClient.jobStatus[jobNumber] = msg; Building.CreateAllMeshes(BuildingMesh); msg.Stop(Job.CreateBuildingMesh); //Debug.Log("CreateAllMeshes Water"); //Water.CreateAllMeshes(OtherMesh); //Debug.Log("CreateAllMeshes TrafficSignal"); //TrafficSignal.CreateAllMeshes(OtherMesh); //StreetPolygon currentStreetPolygon; //bool hasLeftPolygon = false; //bool hasRightPolygon = false; //for (int i = 0; i < streets.Count; i++) //{ // for (int j = 0; j < streetPolygons.Count; j++) // { // hasLeftPolygon = streetPolygons[j].IsLefthandPolygonOf(streets[i]); // hasRightPolygon = streetPolygons[j].IsRighthandPolygonOf(streets[i]); // } // if (!hasLeftPolygon) // { // if (StreetPolygon.GetLefthandStreetPolygon(streets[i], out currentStreetPolygon)) // streetPolygons.Add(currentStreetPolygon); // } // if (!hasRightPolygon) // { // if (StreetPolygon.GetRighthandStreetPolygon(streets[i], out currentStreetPolygon)) // streetPolygons.Add(currentStreetPolygon); // } // hasLeftPolygon = false; // hasRightPolygon = false; //} //for (int i = 0; i < streetPolygons.Count; i++) //{ // streetPolygons[i].Triangulate(StreetMesh , MaterialManager.GetMaterial("error")); //} msg.Start(Job.FillMeshDivideMaterials); SimpleClient.jobStatus[jobNumber] = msg; TileMesh.FillMeshDivideMaterialsKeepMeshStructure(transform, true); msg.Stop(Job.FillMeshDivideMaterials); #endregion } #endregion msg.Start(Job.GarbageCollection); SimpleClient.jobStatus[jobNumber] = msg; System.GC.Collect(); msg.Stop(Job.GarbageCollection); yield return(null); msg.Start(Job.ProceduralDone); SimpleClient.jobStatus[jobNumber] = msg; OnProceduralDoneLocal(); msg.Stop(Job.Worker); msg.Stop(); yield return(true); }