private bool Vector3RDIsInside(Vector3RD vector) { double vector1Pos = 0; if (vector.x > extentRD.x) { vector1Pos += 1; } ; //positive if vector1.x > extent minX if (vector.y > extentRD.y) { vector1Pos += 1; } ; //positive if vector1.y > extent minY if (extentRD.z > vector.x) { vector1Pos += 1; } ; // postive if vector1.x < extent maxX if (extentRD.w > vector.y) { vector1Pos += 1; } ; // postive if vector1.y < extent maxY if (vector1Pos < 4) { return(false); } else { return(true); } }
public List <GameObject> GetTilesInLayer(Layer layer, Vector3RD bottomLeftRD, Vector3RD topRightRD) { if (layer == null) { return(new List <GameObject>()); } List <GameObject> output = new List <GameObject>(); double tilesize = layer.tileSize; Debug.Log(tilesize); int tileX; int tileY; foreach (var tile in layer.tiles) { tileX = tile.Key.x; tileY = tile.Key.y; if (tileX + tilesize < bottomLeftRD.x || tileX > topRightRD.x) { continue; } if (tileY + tilesize < bottomLeftRD.y || tileY > topRightRD.y) { continue; } MeshFilter[] meshFilters = tile.Value.gameObject.GetComponentsInChildren <MeshFilter>(); foreach (var meshFilter in meshFilters) { output.Add(meshFilter.gameObject); } } return(output); }
public void Generate(TileChange tileChange, Tile tile, System.Action <TileChange> callback = null) { napOffset = Config.activeConfiguration.zeroGroundLevelY; Vector3RD boundingBoxMinimum = new Vector3RD(tileChange.X, tileChange.Y, napOffset); Vector3RD boundingBoxMaximum = new Vector3RD(tileChange.X + tileSize, tileChange.Y + tileSize, napOffset);; StartCoroutine(GetSewerLinesInBoundingBox(tileChange, tile, boundingBoxMinimum, boundingBoxMaximum, callback)); }
/// <summary> /// Starts genering the sewage network based on the geometry data and points in a WFS service /// </summary> /// <param name="boxMinimum">The RD coordinates min point of a bounding box area</param> /// <param name="boxMaximum">The RD coordinates maximum point of a bounding box area</param> public void Generate(Vector3RD boxMinimum = default, Vector3RD boxMaximum = default) { napOffset = Config.activeConfiguration.zeroGroundLevelY; boundingBoxMinimum = boxMinimum; boundingBoxMaximum = boxMaximum; StartCoroutine(GetSewerLinesInBoundingBox()); }
private Vector3RD RestoreRDVertex(Vector3 vector, Vector3RD temporaryOrigin) { Vector3RD output = new Vector3RD(); output.x = vector.x + temporaryOrigin.x; output.y = vector.z + temporaryOrigin.y; output.z = vector.y + temporaryOrigin.z; return(output); }
private void CreateOverlapTriangles(Vector3RD[] verticesRD, int[] originalTriangles, Vector3[] verticesUnity, Vector3 unityOrigin, Vector3RD coordinateOffset) { List <Vector3> clippingPolygon = new List <Vector3>(); Vector3 vector = new Vector3(); vector.x = (float)(extentRD.x - coordinateOffset.x); vector.z = (float)(extentRD.y - coordinateOffset.y); clippingPolygon.Add(vector); vector = new Vector3(); vector.x = (float)(extentRD.z - coordinateOffset.x); vector.z = (float)(extentRD.y - coordinateOffset.y); clippingPolygon.Add(vector); vector = new Vector3(); vector.x = (float)(extentRD.z - coordinateOffset.x); vector.z = (float)(extentRD.w - coordinateOffset.y); clippingPolygon.Add(vector); vector = new Vector3(); vector.x = (float)(extentRD.x - coordinateOffset.x); vector.z = (float)(extentRD.w - coordinateOffset.y); clippingPolygon.Add(vector); int originalTriangleCount = originalTriangles.Length - 2; for (int i = 0; i < originalTriangleCount; i += 3) { Vector3RD vector1 = verticesRD[originalTriangles[i]]; Vector3RD vector2 = verticesRD[originalTriangles[i + 1]]; Vector3RD vector3 = verticesRD[originalTriangles[i + 2]]; if (Vector3RDIsInside(vector1) && Vector3RDIsInside(vector2) && Vector3RDIsInside(vector3)) { } else { List <Vector3> vectors = new List <Vector3>(); // to use overlap.cs y en z must be flipped and winding-order must be counter-clockwise // to prevent inaccuracy due to large number we offset the coordinates so the first vertex is at 0,0,0 vector = new Vector3(); vector.x = (float)(verticesRD[originalTriangles[i + 2]].x - coordinateOffset.x); vector.y = (float)(verticesRD[originalTriangles[i + 2]].z - coordinateOffset.z); vector.z = (float)(verticesRD[originalTriangles[i + 2]].y - coordinateOffset.y); vectors.Add(vector); vector = new Vector3(); vector.x = (float)(verticesRD[originalTriangles[i + 1]].x - coordinateOffset.x); vector.y = (float)(verticesRD[originalTriangles[i + 1]].z - coordinateOffset.z); vector.z = (float)(verticesRD[originalTriangles[i + 1]].y - coordinateOffset.y); vectors.Add(vector); vector = new Vector3(); vector.x = (float)(verticesRD[originalTriangles[i]].x - coordinateOffset.x); vector.y = (float)(verticesRD[originalTriangles[i]].z - coordinateOffset.z); vector.z = (float)(verticesRD[originalTriangles[i]].y - coordinateOffset.y); vectors.Add(vector); CreateClippedMesh(vectors, clippingPolygon, coordinateOffset, unityOrigin); } } }
private Vector3 OffsetRDVertex(Vector3RD vector, Vector3RD temporaryOrigin) { Vector3 output = new Vector3(); output.x = (float)(vector.x - temporaryOrigin.x); output.y = (float)(vector.z); output.z = (float)(vector.y - temporaryOrigin.y); return(output); }
public void ClipSubMesh(RDBoundingBox boundingBox, int subMeshNumber) { clippedVerticesRD = new List <Vector3RD>(); if (subMeshNumber >= mesh.subMeshCount) { return; } int[] indices = mesh.GetIndices(subMeshNumber); temporaryOrigin = new Vector3RD(boundingBox.minX, boundingBox.minY, 0); Vector3 point1; Vector3 point2; Vector3 point3; List <Vector3> clippingPolygon = CreateClippingPolygon(boundingBox); List <Vector3> clippingVectorList = new List <Vector3>(); clippingVectorList.Capacity = 3; for (int i = 0; i < indices.Length; i += 3) { point1 = OffsetRDVertex(rdVertices[indices[i]], temporaryOrigin); point2 = OffsetRDVertex(rdVertices[indices[i + 1]], temporaryOrigin); point3 = OffsetRDVertex(rdVertices[indices[i + 2]], temporaryOrigin); trianglePosition position = GetTrianglePosition(point1, point2, point3, boundingBox); if (position == trianglePosition.inside) { clippedVerticesRD.Add(RestoreRDVertex(point1, temporaryOrigin)); clippedVerticesRD.Add(RestoreRDVertex(point2, temporaryOrigin)); clippedVerticesRD.Add(RestoreRDVertex(point3, temporaryOrigin)); } else if (position == trianglePosition.overlap) { clippingVectorList.Clear(); clippingVectorList.Add(point1); clippingVectorList.Add(point2); clippingVectorList.Add(point3); List <Vector3> clippedTriangle = Netherlands3D.Utilities.TriangleClipping.SutherlandHodgman.ClipPolygon(clippingVectorList, clippingPolygon); int vertexcount = clippedTriangle.Count; if (vertexcount < 3) { continue; } clippedVerticesRD.Add(RestoreRDVertex(clippedTriangle[0], temporaryOrigin)); clippedVerticesRD.Add(RestoreRDVertex(clippedTriangle[1], temporaryOrigin)); clippedVerticesRD.Add(RestoreRDVertex(clippedTriangle[2], temporaryOrigin)); // add extra vectors. vector makes a triangle with the first and the previous vector. for (int j = 3; j < vertexcount; j++) { clippedVerticesRD.Add(RestoreRDVertex(clippedTriangle[0], temporaryOrigin)); clippedVerticesRD.Add(RestoreRDVertex(clippedTriangle[j - 1], temporaryOrigin)); clippedVerticesRD.Add(RestoreRDVertex(clippedTriangle[j], temporaryOrigin)); } } } }
public GameObject CreateMesh(CityModel cityModel, Vector3RD origin) { GameObject container = new GameObject(); //Terraindata terrainData = container.AddComponent<Terraindata>(); verts = GetVerts(cityModel, origin); List <Vector3> newVerts = new List <Vector3>(); triangleLists = GetTriangleLists(cityModel); Vector2Int textureSize = ObjectIDMapping.GetTextureSize(triangleLists.Count); Debug.Log(textureSize); Mesh mesh = new Mesh(); List <int> triangles = new List <int>(); List <string> objectIDs = new List <string>(); List <Vector2> uvs = new List <Vector2>(); List <int> vectorIDs = new List <int>(); List <int> triangleCount = new List <int>(); int objectIDNumber = 0; int vertexCounter = 0; foreach (var item in triangleLists) { vertexCounter = 0; Vector2 uv = ObjectIDMapping.GetUV(objectIDNumber, textureSize); foreach (int vertexIndex in item.Value) { newVerts.Add(verts[vertexIndex]); uvs.Add(uv); vectorIDs.Add(objectIDNumber); triangles.Add(newVerts.Count - 1); vertexCounter++; } triangleCount.Add(vertexCounter); objectIDs.Add(item.Key); objectIDNumber++; } mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; mesh.vertices = newVerts.ToArray(); mesh.triangles = triangles.ToArray(); mesh.uv = uvs.ToArray(); //mesh.RecalculateNormals(); //mesh.Optimize(); container.AddComponent <MeshFilter>().mesh = mesh; ObjectMapping objectMapping = container.AddComponent <ObjectMapping>(); objectMapping.vectorIDs = vectorIDs; objectMapping.BagID = objectIDs; objectMapping.TriangleCount = triangleCount; return(container); }
/// <summary> /// Load all the large ground tiles from AssetBundles, spawn it in our world, and start filling it with the trees that match the tile /// its RD coordinate rectangle. The tiles are named after the RD coordinates in origin at the bottomleft of the tile. /// </summary> private IEnumerator TraverseTileFiles() { var info = new DirectoryInfo(sourceGroundTilesFolder); var fileInfo = info.GetFiles(); var currentFile = 0; while (currentFile < fileInfo.Length) { FileInfo file = fileInfo[currentFile]; if (!file.Name.Contains(".manifest") && file.Name.Contains("_")) { Debug.Log($"Filling tile {currentFile}/{fileInfo.Length} {file.Name}"); yield return(new WaitForEndOfFrame()); string[] splitted = file.Name.Split('_'); string[] coordinates = splitted[1].Split('-'); Vector3RD tileRDCoordinatesBottomLeft = new Vector3RD(double.Parse(coordinates[0]), double.Parse(coordinates[1]), 0); var assetBundleTile = AssetBundle.LoadFromFile(file.FullName); var mesh = assetBundleTile.LoadAllAssets <Mesh>().First(); if (mesh.bounds.size == Vector3.zero) { Debug.Log($"mesh bound is zero {file.Name}"); currentFile++; continue; } GameObject newTile = new GameObject(); newTile.isStatic = true; newTile.name = file.Name; newTile.AddComponent <MeshFilter>().sharedMesh = mesh; newTile.AddComponent <MeshCollider>().sharedMesh = mesh; newTile.AddComponent <MeshRenderer>().material = previewMaterial; newTile.GetComponent <MeshRenderer>().materials = _terrainMaterials.ToArray(); newTile.transform.position = CoordConvert.RDtoUnity(tileRDCoordinatesBottomLeft); GameObject treeRoot = new GameObject(); treeRoot.name = file.Name.Replace("terrain", "trees"); treeRoot.transform.position = newTile.transform.position; yield return(new WaitForEndOfFrame()); //Make sure collider is processed // yield return new WaitForSeconds(0.3f); SpawnTreesInTile(treeRoot, tileRDCoordinatesBottomLeft); } currentFile++; } }
IEnumerator GetSewerLinesInBoundingBox(TileChange tileChange, Tile tile, Vector3RD boundingBoxMinimum, Vector3RD boundingBoxMaximum, System.Action <TileChange> callback = null) { yield return(null); yield return(new WaitUntil(() => activeCount < maxSimultaneous)); activeCount++; tile.gameObject.SetActive(true); string escapedUrl = sewerPipesWfsUrl; escapedUrl += UnityWebRequest.EscapeURL((boundingBoxMinimum.x).ToString(CultureInfo.InvariantCulture) + "," + (boundingBoxMinimum.y).ToString(CultureInfo.InvariantCulture) + "," + (boundingBoxMaximum.x).ToString(CultureInfo.InvariantCulture) + "," + (boundingBoxMaximum.y).ToString(CultureInfo.InvariantCulture)); var sewerageRequest = UnityWebRequest.Get(escapedUrl); yield return(sewerageRequest.SendWebRequest()); if (!sewerageRequest.isNetworkError && !sewerageRequest.isHttpError) { GeoJSON customJsonHandler = new GeoJSON(sewerageRequest.downloadHandler.text); yield return(null); Vector3 startpoint; Vector3 endpoint; int parseCounter = 0; while (customJsonHandler.GotoNextFeature()) { parseCounter++; if ((parseCounter % maxParsesPerFrame) == 0) { yield return(null); } double diameter = customJsonHandler.getPropertyFloatValue("diameter"); double bobBeginPunt = customJsonHandler.getPropertyFloatValue("bob_beginpunt"); List <double> coordinates = customJsonHandler.getGeometryLineString(); endpoint = ConvertCoordinates.CoordConvert.WGS84toUnity(new Vector3WGS(coordinates[0], coordinates[1], bobBeginPunt + Config.activeConfiguration.zeroGroundLevelY)); for (int i = 2; i < coordinates.Count; i += 2) { startpoint = endpoint; double bobEindPunt = customJsonHandler.getPropertyFloatValue("bob_eindpunt"); endpoint = ConvertCoordinates.CoordConvert.WGS84toUnity(new Vector3WGS(coordinates[i], coordinates[(i + 1)], bobEindPunt + Config.activeConfiguration.zeroGroundLevelY)); sewerPipeSpawner.CreateSewerLine(startpoint, endpoint, diameter, tile.gameObject); } } StartCoroutine(GetSewerManholesInBoundingBox(tileChange, boundingBoxMinimum, boundingBoxMaximum, tile, callback)); } else { //callback if weberror Debug.Log("sewerlinedata not found"); activeCount--; callback(tileChange); } yield return(null); }
/// <summary> /// Load all the large ground tiles from AssetBundles, spawn it in our world, and start filling it with the trees that match the tile /// its RD coordinate rectangle. The tiles are named after the RD coordinates in origin at the bottomleft of the tile. /// </summary> private IEnumerator TraverseTileFiles() { var info = new DirectoryInfo(sourceGroundTilesFolder); var fileInfo = info.GetFiles(); var currentFile = 0; while (currentFile < fileInfo.Length) { FileInfo file = fileInfo[currentFile]; if (!file.Name.Contains(".manifest") && file.Name.Contains("_")) { Debug.Log("Filling tile " + currentFile + "/" + fileInfo.Length); yield return(new WaitForEndOfFrame()); string filename = file.Name; filename = filename.Replace("terrain_", ""); string[] coordinates = filename.Split('-'); Vector3RD tileRDCoordinatesBottomLeft = new Vector3RD(double.Parse(coordinates[0], System.Globalization.CultureInfo.InvariantCulture), double.Parse(coordinates[1], System.Globalization.CultureInfo.InvariantCulture), 0); Vector3RD tileCenter = new Vector3RD(tileRDCoordinatesBottomLeft.x + 500, tileRDCoordinatesBottomLeft.y + 500, tileRDCoordinatesBottomLeft.z); var assetBundleTile = AssetBundle.LoadFromFile(file.FullName); Mesh[] meshesInAssetbundle = new Mesh[0]; try { meshesInAssetbundle = assetBundleTile.LoadAllAssets <Mesh>(); } catch (Exception) { Debug.Log("Could not find a mesh in this assetbundle."); assetBundleTile.Unload(true); } GameObject newTile = new GameObject(); newTile.isStatic = true; newTile.name = file.Name; newTile.AddComponent <MeshFilter>().sharedMesh = meshesInAssetbundle[0]; newTile.AddComponent <MeshCollider>().sharedMesh = meshesInAssetbundle[0]; newTile.AddComponent <MeshRenderer>().material = previewMaterial; newTile.transform.position = CoordConvert.RDtoUnity(tileCenter); GameObject treeRoot = new GameObject(); treeRoot.name = file.Name.Replace("terrain", "trees"); treeRoot.transform.position = newTile.transform.position; yield return(new WaitForEndOfFrame()); //Make sure collider is processed SpawnTreesInTile(treeRoot, tileRDCoordinatesBottomLeft); } currentFile++; } }
private bool PointISInsideArea(Vector3RD point, double OriginX, double OriginY, float tileSize) { if (point.x < OriginX || point.x > (OriginX + tileSize)) { return(false); } if (point.y < OriginY || point.y > (OriginY + tileSize)) { return(false); } return(true); }
private List <Vector3RD> GetVertsRD(CityModel cityModel) { List <Vector3RD> vertsRD = new List <Vector3RD>(); Vector3RD vertexCoordinate = new Vector3RD(); foreach (Vector3Double vertex in cityModel.vertices) { vertexCoordinate.x = vertex.x; vertexCoordinate.y = vertex.y; vertexCoordinate.z = vertex.z; vertsRD.Add(vertexCoordinate); } return(vertsRD); }
public void TestGetRDCoordinate() { var testFilePaths1 = new string[] { "123000_443000_utrecht_lod1", "utrecht_123000_443000_lod1", "buildings_123000_443000.1.2", "terrain_123000-443000", "terrain_123000-443000-lod1", "trees_123000-443000", "trees_123000-443000-lod1", }; foreach (var filePath in testFilePaths1) { var expectedRd = new Vector3RD(123000, 443000, 0); var result = filePath.GetRDCoordinate(); Assert.AreEqual(expectedRd, result); } var testFilePaths2 = new string[] { "7000_392000_zee_land_lod1", "zee_land_7000_392000_lod1", "buildings_7000_392000.1.2", "terrain_7000-392000", "terrain_7000-392000-lod1", "trees_7000-392000", "trees_7000-392000-lod1", }; foreach (var filePath in testFilePaths2) { var expectedRd = new Vector3RD(7000, 392000, 0); var result = filePath.GetRDCoordinate(); Assert.AreEqual(expectedRd, result); } var testFilePaths3 = new string[] { "AssetBundles", "move.py" }; foreach (var filePath in testFilePaths3) { Assert.Throws <Exception>( delegate { filePath.GetRDCoordinate(); }); } Exception ex = Assert.Throws <Exception>( delegate { "AssetBundles".GetRDCoordinate(); }); }
private List <Vector3> GetVerts(CityModel cityModel, Vector3RD origin) { List <Vector3> verts = new List <Vector3>(); Vector3 unityOrigin = CoordConvert.RDtoUnity(origin); Vector3RD vertexCoordinate = new Vector3RD(); foreach (Vector3Double vertex in cityModel.vertices) { vertexCoordinate.x = vertex.x; vertexCoordinate.y = vertex.y; vertexCoordinate.z = vertex.z; verts.Add(CoordConvert.RDtoUnity(vertexCoordinate) - unityOrigin); } return(verts); }
private IEnumerator createFile(Bounds UnityBounds, List <Layer> layerList) { freezeLayers(layerList, true); Debug.Log(layerList.Count); Vector3RD bottomLeftRD = CoordConvert.UnitytoRD(UnityBounds.min); Vector3RD topRightRD = CoordConvert.UnitytoRD(UnityBounds.max); boundingbox = new MeshClipper.RDBoundingBox(bottomLeftRD.x, bottomLeftRD.y, topRightRD.x, topRightRD.y); DxfFile file = new DxfFile(); file.SetupDXF(); yield return(null); MeshClipper meshClipper = new MeshClipper(); loadingScreen.ShowMessage("dxf-bestand genereren..."); loadingScreen.ProgressBar.Percentage(0f); int layercounter = 0; foreach (var layer in layerList) { List <GameObject> gameObjectsToClip = getTilesInLayer(layer, bottomLeftRD, topRightRD); if (gameObjectsToClip.Count == 0) { continue; } foreach (var gameObject in gameObjectsToClip) { meshClipper.SetGameObject(gameObject); for (int submeshID = 0; submeshID < gameObject.GetComponent <MeshFilter>().sharedMesh.subMeshCount; submeshID++) { meshClipper.clipSubMesh(boundingbox, submeshID); string layerName = gameObject.GetComponent <MeshRenderer>().sharedMaterials[submeshID].name.Replace(" (Instance)", ""); file.AddLayer(meshClipper.clippedVerticesRD, layerName, getColor(gameObject.GetComponent <MeshRenderer>().sharedMaterials[submeshID])); yield return(null); } } loadingScreen.ProgressBar.Percentage(50 * layercounter / layerList.Count); layercounter++; } freezeLayers(layerList, false); file.Save(); loadingScreen.Hide(); Debug.Log("file saved"); }
private Vector2[] RDuv2(Vector3[] verts, Vector3 UnityOrigin, float tileSize) { Vector3 UnityCoordinate; Vector3RD rdCoordinate; Vector3RD rdOrigin = CoordConvert.UnitytoRD(UnityOrigin); float offset = -tileSize / 2; Vector2[] uv2 = new Vector2[verts.Length]; for (int i = 0; i < verts.Length; i++) { UnityCoordinate = verts[i] + UnityOrigin; rdCoordinate = CoordConvert.UnitytoRD(UnityCoordinate); uv2[i].x = ((float)(rdCoordinate.x - rdOrigin.x) + offset) / tileSize; uv2[i].y = ((float)(rdCoordinate.y - rdOrigin.y) + offset) / tileSize; } return(uv2); }
public void Start() { //Calculate offset. ( Our viewer expects tiles with the origin in the center ) tileOffset = new Vector3RD() { x = Config.activeConfiguration.RelativeCenterRD.x, y = Config.activeConfiguration.RelativeCenterRD.y, z = 0 }; tileOffset.x -= 500; tileOffset.y -= 500; unityTileOffset = CoordConvert.RDtoUnity(tileOffset); trees = new List <Tree>(); treeLines = new List <string>(); noPrefabFoundNames = new List <string>(); ParseTreeData(); }
/// <summary> /// /// </summary> /// <param name="vectors">triangleVertices (unity-format, so Y is up)</param> /// <param name="clipboundary">coordinates of vertices of (square) clipboundary</param> /// <param name="coordinateOffset"></param> /// <param name="unityOrigin"></param> private void CreateClippedMesh(List <Vector3> vectors, List <Vector3> clipboundary, Vector3RD coordinateOffset, Vector3 unityOrigin) { List <Vector3> defshape = TriangleClipping.SutherlandHodgman.ClipPolygon(vectors, clipboundary); if (defshape.Count < 3) { return; } List <Vector3RD> verticesRD = new List <Vector3RD>(); Vector3RD vector; //restore coordinates for (int i = 0; i < defshape.Count; i++) { vector = new Vector3RD(); vector.x = defshape[i].x + coordinateOffset.x; vector.y = defshape[i].z + coordinateOffset.y; vector.z = defshape[i].y + coordinateOffset.z; verticesRD.Add(vector); } verticesRD.Reverse(); List <int> indices = new List <int>(); indices.Add(0); indices.Add(1); indices.Add(2); for (int i = 3; i < defshape.Count; i++) { indices.Add(0); indices.Add(indices[indices.Count - 2]); indices.Add(i); } Vector3[] verticesUnity = VerticesRDtoUnity(verticesRD.ToArray(), unityOrigin); Mesh newSubMesh = new Mesh(); newSubMesh.vertices = verticesUnity; newSubMesh.triangles = indices.ToArray(); newSubMesh.uv = getUVs(verticesRD.ToArray()); newSubMesh.Optimize(); newSubMesh.RecalculateNormals(); submeshes.Add(newSubMesh); }
/// <summary> /// Converts the VISSIM RD coordinate string into a Vector3 /// </summary> /// <param name="stringVector"></param> /// <returns></returns> public Vector3 convertStringToVector(string stringVector) { //0 value is X //1 value is Y //2 value is Z stringVector = stringVector.Replace(".", ","); // Transforms decimal from US standard which uses a Period to European with a Comma string[] splitString = stringVector.Split(' '); // Splits the string into individual vectors double x = double.Parse(splitString[0]); double y = double.Parse(splitString[1]); double z = double.Parse(splitString[2]); Vector3RD rdVector = new Vector3RD(x, y, z); // Creates the Double Vector Vector3 convertedCoordinates = ConvertCoordinates.CoordConvert.RDtoUnity(rdVector); // Y Coordinates will be calculated by the vehicle to connect with the Map (Maaiveld). return convertedCoordinates; }
IEnumerator GetSewerManholesInBoundingBox(TileChange tileChange, Vector3RD boundingBoxMinimum, Vector3RD boundingBoxMaximum, Tile tile, System.Action <TileChange> callback = null) { string escapedUrl = sewerManholesWfsUrl; escapedUrl += UnityWebRequest.EscapeURL((boundingBoxMinimum.x).ToString(CultureInfo.InvariantCulture) + "," + (boundingBoxMinimum.y).ToString(CultureInfo.InvariantCulture) + "," + (boundingBoxMaximum.x).ToString(CultureInfo.InvariantCulture) + "," + (boundingBoxMaximum.y).ToString(CultureInfo.InvariantCulture)); var sewerageRequest = UnityWebRequest.Get(escapedUrl); yield return(sewerageRequest.SendWebRequest()); if (!sewerageRequest.isNetworkError && !sewerageRequest.isHttpError) { StartCoroutine(SpawnManHoleObjects(sewerageRequest.downloadHandler.text, tileChange, tile, callback)); } else { activeCount--; callback(tileChange); } yield return(null); }
//private IEnumerator LoadAreas() //{ // for (int x = areaXmin; x < areaXmax; x+=(int)tileSize) // { // for (int y = areaYmin; y < areaYmax; y += (int)tileSize) // { // yield return new WaitWhile(() => areaLoadingFinished == false); // areaLoadingFinished = false; // LoadArea((float)x, (float)y); // } // } //} //void LoadArea(float rdX, float rdY) //{ // submeshes = new List<Mesh>(); // extentRD.x = rdX; // extentRD.y = rdY; // extentRD.z = extentRD.x + tileSize; // extentRD.w = extentRD.y + tileSize; // Vector3WGS RDVector = CoordConvert.RDtoWGS84(extentRD.x, extentRD.y); // extentWGS.x = (float)RDVector.lon; // extentWGS.y = (float)RDVector.lat; // RDVector = CoordConvert.RDtoWGS84(extentRD.z, extentRD.w); // extentWGS.z = (float)RDVector.lon; // extentWGS.w = (float)RDVector.lat; // StartCoroutine(IdentifyQMTileNames(extentWGS, (didError) => { // HandleTiles(); // })); //} //private void HandleTiles() //{ // int submeshcount = submeshes.Count; // CombineInstance[] combine = new CombineInstance[submeshcount]; // for (int i = 0; i < submeshcount; i++) // { // combine[i].mesh = submeshes[i]; // } // Vector3 position = CoordConvert.RDtoUnity(new Vector3RD(extentRD.x, (extentRD.y), 0)); // position.y = 0; // Mesh combinedMesh = new Mesh(); // combinedMesh.CombineMeshes(combine,true,false); // Debug.Log(combinedMesh.bounds.extents); // GameObject go = new GameObject(); // go.transform.position = position; // go.AddComponent<MeshFilter>().mesh = combinedMesh; // SaveMesh(combinedMesh); // Debug.Log("Tile Handled"); // areaLoadingFinished = true; //} //private void SaveMesh(Mesh mesh) //{ // string meshname = "Terrain_"+extentRD.x.ToString()+"_"+extentRD.y.ToString() + "_lod0.mesh"; // string meshFolderName = "Assets/Terrain/LOD0/"; // AssetDatabase.CreateAsset(mesh, meshFolderName + meshname); // AssetDatabase.SaveAssets(); // AssetImporter.GetAtPath(meshFolderName + meshname).SetAssetBundleNameAndVariant(extentRD.x.ToString() + "_" + extentRD.y.ToString() + "_terrain_lod0",""); // AssetDatabase.SaveAssets(); //} //private void CreateClippedMesh(Mesh mesh, int X, int Y) //{ // Debug.Log(X + "-" + Y + " :overlapTile"); // Vector3WGS originWGS = TerrainTileCenterWGS(X, Y); // Vector3 unityOrigin = CoordConvert.WGS84toUnity(extentWGS.x, extentWGS.y); // Vector3RD[] verticesRD = getVerticesRD(terrainTile, X, Y, originWGS); // int[] originalTriangles = getTriangles(terrainTile); // List<int> insideTriangles = GetInsideTriangles(verticesRD, originalTriangles); // Vector3[] verticesUnity = VerticesRDtoUnity(verticesRD, unityOrigin); // CreateOverlapTriangles(verticesRD, originalTriangles, verticesUnity, unityOrigin); // Mesh newSubMesh = new Mesh(); // newSubMesh.vertices = verticesUnity; // newSubMesh.triangles = insideTriangles.ToArray(); // newSubMesh.uv = getUVs(verticesRD); // newSubMesh.Optimize(); // newSubMesh.RecalculateNormals(); // submeshes.Add(newSubMesh); // activeTiles--; //} private List <Vector3> CreateClippingPolygon(Vector4 extendRD, Vector3RD coordinateOffset) { List <Vector3> clippingPolygon = new List <Vector3>(); Vector3 vector = new Vector3(); vector.x = (float)(extentRD.x - coordinateOffset.x); vector.z = (float)(extentRD.y - coordinateOffset.y); clippingPolygon.Add(vector); vector = new Vector3(); vector.x = (float)(extentRD.z - coordinateOffset.x); vector.z = (float)(extentRD.y - coordinateOffset.y); clippingPolygon.Add(vector); vector = new Vector3(); vector.x = (float)(extentRD.z - coordinateOffset.x); vector.z = (float)(extentRD.w - coordinateOffset.y); clippingPolygon.Add(vector); vector = new Vector3(); vector.x = (float)(extentRD.x - coordinateOffset.x); vector.z = (float)(extentRD.w - coordinateOffset.y); clippingPolygon.Add(vector); return(clippingPolygon); }
private List <int> GetInsideTriangles(Vector3RD[] verticesRD, int[] originalTriangles) { List <int> Triangles = new List <int>(); int originalTriangleCount = originalTriangles.Length - 2; for (int i = 0; i < originalTriangleCount; i += 3) { Vector3RD vector1 = verticesRD[originalTriangles[i]]; Vector3RD vector2 = verticesRD[originalTriangles[i + 1]]; Vector3RD vector3 = verticesRD[originalTriangles[i + 2]]; if (Vector3RDIsInside(vector1) && Vector3RDIsInside(vector2) && Vector3RDIsInside(vector3)) { //winding-order is clockwise Triangles.Add(originalTriangles[i]); Triangles.Add(originalTriangles[i + 1]); Triangles.Add(originalTriangles[i + 2]); } else { } } return(Triangles); }
IEnumerator GetSewerManholesInBoundingBox(TileChange tileChange, Vector3RD boundingBoxMinimum, Vector3RD boundingBoxMaximum, Tile tile, System.Action <TileChange> callback = null) { string escapedUrl = Config.activeConfiguration.sewerManholesWfsUrl; escapedUrl += UnityWebRequest.EscapeURL($"{boundingBoxMinimum.x.ToInvariant()},{boundingBoxMinimum.y.ToInvariant()},{boundingBoxMaximum.x.ToInvariant()},{boundingBoxMaximum.y.ToInvariant()}"); var sewerageRequest = UnityWebRequest.Get(escapedUrl); tile.runningWebRequest = sewerageRequest; yield return(sewerageRequest.SendWebRequest()); tile.runningWebRequest = null; if (!sewerageRequest.isNetworkError && !sewerageRequest.isHttpError) { yield return(SpawnManHoleObjects(sewerageRequest.downloadHandler.text, tileChange, tile, callback)); } else { callback(tileChange); } yield return(null); }
/// <summary> /// Spawn all the trees located within the RD coordinate bounds of the 1x1km tile. /// </summary> /// <param name="treeTile">The target 1x1 km ground tile</param> /// <param name="tileCoordinates">RD Coordinates of the tile</param> /// <returns></returns> private void SpawnTreesInTile(GameObject treeTile, Vector3RD tileCoordinates) { //TODO: Add all trees within this tile (1x1km) int treeChecked = trees.Count - 1; while (treeChecked >= 0) { Tree tree = trees[treeChecked]; if (tree.RD.x > tileCoordinates.x && tree.RD.y > tileCoordinates.y && tree.RD.x < tileCoordinates.x + tileSize && tree.RD.y < tileCoordinates.y + tileSize) { SpawnTreeOnGround(treeTile, tree); trees.RemoveAt(treeChecked); } treeChecked--; } //Define a preview position to preview the tree tile in our scene Vector3 previewPosition = treeTile.transform.position + Vector3.down * Config.activeConfiguration.zeroGroundLevelY; treeTile.transform.position = unityTileOffset; CreateTreeTile(treeTile, previewPosition); }
public GameObject CreateMesh(CityModel cityModel, Vector3RD origin) { GameObject container = new GameObject(); //Terraindata terrainData = container.AddComponent<Terraindata>(); verts = GetVerts(cityModel, origin); triangleLists = GetTriangleLists(cityModel); Mesh mesh = new Mesh(); mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; mesh.SetVertices(verts.ToArray()); mesh.subMeshCount = triangleLists.Count; int submeshnumber = 0; foreach (var item in triangleLists) { //terrainData.terrainTypes.Add(item.Key); //if (submeshnumber==0 || submeshnumber==1) //{ mesh.SetTriangles(item.Value.ToArray(), submeshnumber); //} submeshnumber++; } mesh.RecalculateNormals(); mesh.Optimize(); container.AddComponent <MeshFilter>().mesh = mesh; container.AddComponent <MeshRenderer>().sharedMaterials = new Material[submeshnumber]; return(container); }
/// <summary> /// Parse files whose name contains coordinates that overlap the provided tile area /// </summary> /// <param name="rdCoordinates">Bottom left RD coordinates of the tile</param> /// <returns></returns> private IEnumerator ParseSpecificFiles(Vector2Int rdCoordinates) { //Read files list var info = new DirectoryInfo(geoJsonSourceFilesFolder); var fileInfo = info.GetFiles(); //First create gameobjects for all the buildigns we parse int parsed = 0; for (int i = 0; i < fileInfo.Length; i++) { var file = fileInfo[i]; string[] fileNameParts = file.Name.Replace(".json", "").Split('_'); //Determine parts of the filename var id = fileNameParts[0]; var count = fileNameParts[1]; var xmin = double.Parse(fileNameParts[3]); var ymin = double.Parse(fileNameParts[4]); var xmax = double.Parse(fileNameParts[5]); var ymax = double.Parse(fileNameParts[6]); //Skip if these filename bounds are not within our selected rectangle if (xmin > rdCoordinates.x + tileSize || xmax < rdCoordinates.x || ymin > rdCoordinates.y + tileSize || ymax < rdCoordinates.y) { continue; } Debug.Log("Parsing " + file.Name); if (!Application.isBatchMode) { yield return(new WaitForEndOfFrame()); } //Parse the file var jsonstring = File.ReadAllText(file.FullName); var cityjsonNode = JSON.Parse(jsonstring); if (cityjsonNode["CityObjects"] == null) { Debug.Log("FAILURE PARSING: " + file.Name); continue; //Failed to parse the json } //Get vertices allVerts = new List <Vector3>(); //Optionaly parse transform scale and offset var transformScale = (cityjsonNode["transform"] != null && cityjsonNode["transform"]["scale"] != null) ? new Vector3Double( cityjsonNode["transform"]["scale"][0].AsDouble, cityjsonNode["transform"]["scale"][1].AsDouble, cityjsonNode["transform"]["scale"][2].AsDouble ) : new Vector3Double(1, 1, 1); var transformOffset = (cityjsonNode["transform"] != null && cityjsonNode["transform"]["translate"] != null) ? new Vector3Double( cityjsonNode["transform"]["translate"][0].AsDouble, cityjsonNode["transform"]["translate"][1].AsDouble, cityjsonNode["transform"]["translate"][2].AsDouble ) : new Vector3Double(0, 0, 0); //Now load all the vertices with the scaler and offset applied foreach (JSONNode node in cityjsonNode["vertices"]) { var rd = new Vector3RD( node[0].AsDouble * transformScale.x + transformOffset.x, node[1].AsDouble * transformScale.y + transformOffset.y, node[2].AsDouble * transformScale.z + transformOffset.z ); var unityCoordinates = CoordConvert.RDtoUnity(rd); allVerts.Add(unityCoordinates); } //Now build the meshes and create objects for these buildings int buildingCount = 0; foreach (JSONNode buildingNode in cityjsonNode["CityObjects"]) { //A building var name = buildingNode["attributes"]["identificatie"].Value.Replace("NL.IMBAG.Pand.", ""); //Check if this name/ID exists in our list of manualy added child objects. If it is there, skip it. if (overrideChildObjects.Where(overrideGameObject => overrideGameObject.name == name).SingleOrDefault()) { print("Skipped parsing " + name + " because we have added a custom object for that"); continue; } GameObject building = new GameObject(); building.transform.SetParent(this.transform, false); building.name = name; //The building verts/triangles var boundaries = buildingNode["geometry"][lodSlot]["boundaries"][0]; meshTriangles = new List <int>(); List <Vector3> thisMeshVerts = new List <Vector3>(); foreach (JSONNode boundary in boundaries) { JSONNode triangle = boundary[0]; vertIndex = triangle[2].AsInt; thisMeshVerts.Add(allVerts[vertIndex]); meshTriangles.Add(thisMeshVerts.Count - 1); //TODO. Group same verts vertIndex = triangle[1].AsInt; thisMeshVerts.Add(allVerts[vertIndex]); meshTriangles.Add(thisMeshVerts.Count - 1); vertIndex = triangle[0].AsInt; thisMeshVerts.Add(allVerts[vertIndex]); meshTriangles.Add(thisMeshVerts.Count - 1); } //Construct the mesh Mesh buildingMesh = new Mesh(); if (thisMeshVerts.Count > Mathf.Pow(2, 16)) { buildingMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; } buildingMesh.vertices = thisMeshVerts.ToArray(); buildingMesh.triangles = meshTriangles.ToArray(); buildingMesh.RecalculateNormals(); var meshRenderer = building.AddComponent <MeshRenderer>(); meshRenderer.material = DefaultMaterial; meshRenderer.enabled = renderInViewport; building.AddComponent <MeshFilter>().sharedMesh = buildingMesh; buildingCount++; } parsed++; print("Parsed GeoJSONS to fill tile: " + parsed + ". Buildings in tile: " + buildingCount); } }
private IEnumerator SpawnLineObjects(SewerLines sewerLines, TileChange tileChange, Vector3RD boundingBoxMinimum, Vector3RD boundingBoxMaximum, Tile tile, System.Action <TileChange> callback = null) { tile.gameObject.SetActive(isEnabled); SewerLines.Feature sewerLineFeature; for (int i = 0; i < sewerLines.features.Length; i++) { if ((i % maxSpawnsPerFrame) == 0) { yield return(new WaitForEndOfFrame()); } sewerLineFeature = sewerLines.features[i]; sewerPipeSpawner.CreateSewerLine( sewerLineFeature.geometry.unity_coordinates[0], sewerLineFeature.geometry.unity_coordinates[1], float.Parse(sewerLineFeature.properties.diameter), tile.gameObject ); } //Lines are done spawing. Start loading and spawing the manholes. StartCoroutine(GetSewerManholesInBoundingBox(tileChange, boundingBoxMinimum, boundingBoxMaximum, tile, callback)); yield return(null); }
private Mesh CreateCityObjectMesh(CityModel cityModel, string cityObjectType, double originX, double originY, float tileSize, string bgtProperty, List <string> bgtValues, bool include) { List <Vector3RD> RDTriangles = GetTriangleListRD(cityModel, cityObjectType, bgtProperty, bgtValues, include); List <Vector3RD> clippedRDTriangles = new List <Vector3RD>(); List <Vector3> vectors = new List <Vector3>(); List <Vector3> clipboundary = CreateClippingPolygon(tileSize); if (RDTriangles.Count == 0) { return(CreateEmptyMesh()); } //clip all the triangles for (int i = 0; i < RDTriangles.Count; i += 3) { if (PointISInsideArea(RDTriangles[i], originX, originY, tileSize) && PointISInsideArea(RDTriangles[i + 1], originX, originY, tileSize) && PointISInsideArea(RDTriangles[i + 2], originX, originY, tileSize)) { clippedRDTriangles.Add(RDTriangles[i + 2]); clippedRDTriangles.Add(RDTriangles[i + 1]); clippedRDTriangles.Add(RDTriangles[i]); continue; } //offset RDvertices so coordinates can be saved as a float // flip y and z-axis so clippingtool works //reverse order to make them clockwise so the clipping-algorithm can use them vectors.Clear(); vectors.Add(new Vector3((float)(RDTriangles[i + 2].x - originX), (float)RDTriangles[i + 2].z, (float)(RDTriangles[i + 2].y - originY))); vectors.Add(new Vector3((float)(RDTriangles[i + 1].x - originX), (float)RDTriangles[i + 1].z, (float)(RDTriangles[i + 1].y - originY))); vectors.Add(new Vector3((float)(RDTriangles[i].x - originX), (float)RDTriangles[i].z, (float)(RDTriangles[i].y - originY))); List <Vector3> defshape = Netherlands3D.Utilities.TriangleClipping.SutherlandHodgman.ClipPolygon(vectors, clipboundary); if (defshape.Count < 3) { continue; } if (defshape[0].x.ToString() == "NaN") { continue; } Vector3RD vectorRD = new Vector3RD(); // add first three vectors vectorRD.x = defshape[0].x + originX; vectorRD.y = defshape[0].z + originY; vectorRD.z = defshape[0].y; clippedRDTriangles.Add(vectorRD); vectorRD.x = defshape[1].x + originX; vectorRD.y = defshape[1].z + originY; vectorRD.z = defshape[1].y; clippedRDTriangles.Add(vectorRD); vectorRD.x = defshape[2].x + originX; vectorRD.y = defshape[2].z + originY; vectorRD.z = defshape[2].y; clippedRDTriangles.Add(vectorRD); // add extra vectors. vector makes a triangle with the first and the previous vector. for (int j = 3; j < defshape.Count; j++) { vectorRD.x = defshape[0].x + originX; vectorRD.y = defshape[0].z + originY; vectorRD.z = defshape[0].y; clippedRDTriangles.Add(vectorRD); vectorRD.x = defshape[j - 1].x + originX; vectorRD.y = defshape[j - 1].z + originY; vectorRD.z = defshape[j - 1].y; clippedRDTriangles.Add(vectorRD); vectorRD.x = defshape[j].x + originX; vectorRD.y = defshape[j].z + originY; vectorRD.z = defshape[j].y; clippedRDTriangles.Add(vectorRD); } } //createMesh List <Vector3> verts = new List <Vector3>(); Vector3RD tileCenterRD = new Vector3RD(); tileCenterRD.x = originX + (tileSize / 2); tileCenterRD.y = originY + (tileSize / 2); tileCenterRD.z = 0; Vector3 tileCenterUnity = CoordConvert.RDtoUnity(tileCenterRD); List <int> ints = new List <int>(); for (int i = 0; i < clippedRDTriangles.Count; i++) { Vector3 coord = CoordConvert.RDtoUnity(clippedRDTriangles[i]) - tileCenterUnity; ints.Add(i); verts.Add(coord); } ints.Reverse(); //reverse the trianglelist to make the triangles counter-clockwise again if (ints.Count == 0) { return(CreateEmptyMesh()); } Mesh mesh = new Mesh(); mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; mesh.vertices = verts.ToArray(); mesh.triangles = ints.ToArray(); mesh = WeldVertices(mesh); mesh.RecalculateNormals(); mesh.Optimize(); return(mesh); }