public float GetRegionZoomExtents(Region region) { // Compute world positions of region corners Vector2 min = region.latlonRect2D.min; Vector2 max = region.latlonRect2D.max; // Width Vector2 minL = new Vector2((min.x + max.x) * 0.5f, min.y); Vector2 maxR = new Vector2((min.x + max.x) * 0.5f, max.y); Vector3 wsLeft = Conversion.GetSpherePointFromLatLon(minL); Vector3 wsRight = Conversion.GetSpherePointFromLatLon(maxR); float width = Vector3.Distance(wsLeft, wsRight); // Height Vector2 minB = new Vector2(min.x, (max.y + min.y) * 0.5f); Vector2 maxT = new Vector2(max.x, (max.y + min.y) * 0.5f); Vector3 wsBottom = Conversion.GetSpherePointFromLatLon(minB); Vector3 wsTop = Conversion.GetSpherePointFromLatLon(maxT); float height = Vector3.Distance(wsBottom, wsTop); // Apply to sphere float scale = transform.lossyScale.x; return(GetFrustumZoomLevel(width * scale, height * scale)); }
/// <summary> /// Moves the gameobject obj onto the globe at the path given by latlon array and progress factor. /// </summary> /// <param name="obj">Object.</param> /// <param name="progress">Progress expressed in 0..1.</param> public void MoveTo(float progress) { // Iterate again until we reach progress int steps = latLon.Count; float acum = 0, acumPrev = 0; for (int k = 0; k < steps - 1; k++) { acumPrev = acum; acum += stepLengths[k] / totalLength; if (acum > progress) { // This is the step where "progress" is contained. if (k > 0) { progress = (progress - acumPrev) / (acum - acumPrev); } Vector3 pos0 = Conversion.GetSpherePointFromLatLon(latLon[k]); Vector3 pos1 = Conversion.GetSpherePointFromLatLon(latLon[k + 1]); Vector3 pos = Vector3.Lerp(pos0, pos1, progress); pos = pos.normalized * 0.5f; map.AddMarker(gameObject, pos, 0.01f, false); map.FlyToLocation(pos, 2f); break; } } }
/// <summary> /// Adds a line to the globe with options (returns the line gameobject). /// </summary> /// <param name="Color">line color</param> /// <param name="arcElevation">arc elevation relative to the sphere size (0-1 range).</param> /// <param name="duration">drawing speed (0 for instant drawing)</param> /// <param name="fadeOutAfter">duration of the line once drawn after which it fades out (set this to 0 to make the line stay forever)</param> public LineMarkerAnimator AddLine(Vector2 latLonStart, Vector2 latLonEnd, Color color, float arcElevation, float duration, float lineWidth, float fadeOutAfter) { Vector3 start = Conversion.GetSpherePointFromLatLon(latLonStart.x, latLonStart.y); Vector3 end = Conversion.GetSpherePointFromLatLon(latLonEnd.x, latLonEnd.y); return(AddLine(start, end, color, arcElevation, duration, lineWidth, fadeOutAfter)); }
/// <summary> /// Adds a line to the globe with options (returns the line gameobject). /// </summary> /// <param name="Color">line color</param> /// <param name="arcElevation">arc elevation relative to the sphere size (0-1 range).</param> /// <param name="duration">drawing speed (0 for instant drawing)</param> /// <param name="fadeOutAfter">duration of the line once drawn after which it fades out (set this to 0 to make the line stay forever)</param> public LineMarkerAnimator AddLine(float latitudeStart, float longitudeStart, float latitudeEnd, float longitudeEnd, Color color, float arcElevation, float duration, float lineWidth, float fadeOutAfter) { Vector3 start = Conversion.GetSpherePointFromLatLon(latitudeStart, longitudeStart); Vector3 end = Conversion.GetSpherePointFromLatLon(latitudeEnd, longitudeEnd); return(AddLine(start, end, color, arcElevation, duration, lineWidth, fadeOutAfter)); }
/// <summary> /// Moves the gameobject obj onto the globe at the path given by latlon array and progress factor. /// </summary> /// <param name="obj">Object.</param> /// <param name="progress">Progress expressed in 0..1.</param> public void MoveTo(float progress) { currentProgress = progress; //This seems pointless if (latlonIndex < 0 || (latlonIndex + 1) > latLon.Count) { errorHandler.ReportError("Attempting to move beyond latlon range", ErrorState.close_window); return; } try { Vector3 pos0 = Conversion.GetSpherePointFromLatLon(latLon[latlonIndex]); Vector3 pos1 = Conversion.GetSpherePointFromLatLon(latLon[latlonIndex + 1]); Vector3 pos = Vector3.Lerp(pos0, pos1, progress); pos = pos.normalized * 0.5f; float playerSize = AnimatedObject.Size; worldMapGlobe.AddMarker(gameObject, pos, playerSize, false); // Make it look towards destination Vector3 dir = (pos0 - pos1).normalized; Vector3 proj = Vector3.ProjectOnPlane(dir, pos0); transform.LookAt(worldMapGlobe.transform.TransformPoint(proj + pos0), worldMapGlobe.transform.transform.TransformDirection(pos0)); } catch (System.Exception ex) { errorHandler.CatchException(ex, ErrorState.close_window); } }
public void SetVertices(Vector2[] latlon) { if (latlon == null || latlon.Length < 2) { return; } Vector3[] spherePoints = new Vector3[latlon.Length]; for (int k = 0; k < latlon.Length; k++) { spherePoints [k] = Conversion.GetSpherePointFromLatLon(latlon [k]); } startAltitude = spherePoints [0].magnitude; endAltitude = spherePoints [latlon.Length - 1].magnitude; this.start = spherePoints [0]; this.end = spherePoints [latlon.Length - 1]; Vector3 start, end; vertices = new Vector3[numPoints]; for (int s = 0; s < numPoints; s++) { float t = (float)s / (numPoints - 1); float elevation = Mathf.Sin(t * Mathf.PI) * arcElevation; Vector3 sPos; float h = Mathf.Lerp(startAltitude, endAltitude, t); float t2; if (t >= 1f) { t2 = 1f; start = end = spherePoints [latlon.Length - 1]; } else { float ft = (latlon.Length - 1) * t; int index = (int)ft; int prev = index; int pos = prev + 1; if (pos >= latlon.Length) { pos = latlon.Length - 1; } start = spherePoints [prev]; end = spherePoints [pos]; t2 = ft - index; } if (earthInvertedMode) { sPos = Vector3.Lerp(start, end, t2).normalized *h *(1.0f - elevation); } else { sPos = Vector3.Lerp(start, end, t2).normalized *h *(1.0f + elevation); } vertices [s] = sPos; } }
/// <summary> /// Gets the cell under the latlon position /// </summary> public int GetCellIndex(Vector2 latlon) { if (cells == null) { return(-1); } Vector3 spherePosition = Conversion.GetSpherePointFromLatLon(latlon); return(GetCellAtLocalPosition(spherePosition, false)); }
public void addMarker(TweetObject tweet) { GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); Vector3 sphereLocation = Conversion.GetSpherePointFromLatLon(new Vector2(tweet.getTweetLat(), tweet.getTweetLong())); //GameObject obj = map.AddMarker(MARKER_TYPE.CIRCLE, sphereLocation, kmRadius, ringWidthStart, ringWidthEnd, Color.green); map.AddMarker(cube, sphereLocation, 0.001f); tweet.setGameObject(cube); }
public void UpdateSpherePointsFromLatLon() { int pointCount = latlon.Length; if (spherePoints == null || spherePoints.Length != pointCount) { _spherePoints = new Vector3[pointCount]; } for (int k = 0; k < pointCount; k++) { _spherePoints[k] = Conversion.GetSpherePointFromLatLon(_latlon[k]); } }
int GetTileZoomLevel() { // Get screen dimensions of central tile int zoomLevel0 = 1; int zoomLevel1 = TILE_MAX_ZOOM_LEVEL; int zoomLevel = TILE_MIN_ZOOM_LEVEL; Vector2 latLon = Conversion.GetLatLonFromSpherePoint(GetCurrentMapLocation()); int xTile, yTile; currentTileSize = _tileSize > TILE_MIN_SIZE ? _tileSize : TILE_MIN_SIZE; currentTileSize *= (3.0f - _tileResolutionFactor); float dist = 0; for (int i = 0; i < 5; i++) { zoomLevel = (zoomLevel0 + zoomLevel1) / 2; Conversion.GetTileFromLatLon(zoomLevel, latLon.x, latLon.y, out xTile, out yTile); Vector2 latLonTL = Conversion.GetLatLonFromTile(xTile, yTile, zoomLevel); Vector2 latLonBR = Conversion.GetLatLonFromTile(xTile + 0.99f, yTile + 0.99f, zoomLevel); Vector3 spherePointTL = Conversion.GetSpherePointFromLatLon(latLonTL); Vector3 spherePointBR = Conversion.GetSpherePointFromLatLon(latLonBR); Vector3 wposTL = currentCamera.WorldToScreenPoint(transform.TransformPoint(spherePointTL)); Vector3 wposBR = currentCamera.WorldToScreenPoint(transform.TransformPoint(spherePointBR)); dist = Mathf.Max(Mathf.Abs(wposBR.x - wposTL.x), Mathf.Abs(wposTL.y - wposBR.y)); if (dist > currentTileSize) { zoomLevel0 = zoomLevel; } else { zoomLevel1 = zoomLevel; } } if (dist > currentTileSize) { zoomLevel++; } zoomLevel = Mathf.Clamp(zoomLevel, TILE_MIN_ZOOM_LEVEL, TILE_MAX_ZOOM_LEVEL); return(zoomLevel); }
void Start() { float latitude = 40.71f; float longitude = -74f; WorldMapGlobe map = WorldMapGlobe.instance; Vector3 sphereLocation = Conversion.GetSpherePointFromLatLon(latitude, longitude); // Create sprite destinationSprite = new GameObject(); SpriteRenderer dest_sprite = destinationSprite.AddComponent <SpriteRenderer> (); dest_sprite.sprite = Resources.Load <Sprite> ("NewYork"); // Add sprite billboard to the map with custom scale, billboard mode and little bit elevated from surface (to prevent clipping with city spots) map.AddMarker(destinationSprite, sphereLocation, 0.02f, true, 0.1f); // Add click handlers destinationSprite.AddComponent <SpriteClickHandler> (); // Locate it on the map map.FlyToLocation(sphereLocation, 4f, 0.4f); map.autoRotationSpeed = 0f; }
/// <summary> /// Moves the gameobject obj onto the globe at the path given by latlon array and progress factor. /// </summary> /// <param name="obj">Object.</param> /// <param name="progress">Progress expressed in 0..1.</param> public void MoveTo(float progress) { currentProgress = progress; // Iterate again until we reach progress int steps = latLon.Count; float acum = 0, acumPrev = 0; for (int k = 0; k < steps - 1; k++) { acumPrev = acum; acum += stepLengths [k] / totalLength; if (acum > progress) { // This is the step where "progress" is contained. if (k > 0) { progress = (progress - acumPrev) / (acum - acumPrev); } Vector3 pos0 = Conversion.GetSpherePointFromLatLon(latLon [k]); Vector3 pos1 = Conversion.GetSpherePointFromLatLon(latLon [k + 1]); Vector3 pos = Vector3.Lerp(pos0, pos1, progress); pos = pos.normalized * 0.5f; map.AddMarker(gameObject, pos, 0.01f, false); // Make it look towards destination Vector3 dir = (pos1 - pos0).normalized; Vector3 proj = Vector3.ProjectOnPlane(dir, pos0); transform.LookAt(map.transform.TransformPoint(proj + pos0), map.transform.transform.TransformDirection(pos0)); // Follow object map.FlyToLocation(pos, 0f); break; } } }
GameObject GenerateProvinceRegionSurface(int provinceIndex, int regionIndex, Material material, Vector2 textureScale, Vector2 textureOffset, float textureRotation, bool temporary) { if (provinceIndex < 0 || provinceIndex >= provinces.Length) { return(null); } if (provinces [provinceIndex].regions == null) { ReadProvincePackedString(provinces [provinceIndex]); } if (provinces [provinceIndex].regions == null || regionIndex < 0 || regionIndex >= provinces [provinceIndex].regions.Count) { return(null); } Province province = provinces [provinceIndex]; Region region = province.regions [regionIndex]; if (!temporary) { region.customMaterial = material; region.customTextureOffset = textureOffset; region.customTextureRotation = textureRotation; region.customTextureScale = textureScale; UpdateSurfaceCount(); } // Triangulate to get the polygon vertex indices Poly2Tri.Polygon poly = new Poly2Tri.Polygon(region.latlon); if (_enableProvinceEnclaves && regionIndex == province.mainRegionIndex) { ProvinceSubstractProvinceEnclaves(provinceIndex, region, poly); } // Antarctica, Saskatchewan (Canada), British Columbia (Canada), Krasnoyarsk (Russia) - special cases due to its geometry float step = _frontiersDetail == FRONTIERS_DETAIL.High ? 2f : 5f; if (steinerPoints == null) { steinerPoints = new List <TriangulationPoint> (1000); } else { steinerPoints.Clear(); } float x0 = region.latlonRect2D.min.x + step / 2f; float x1 = region.latlonRect2D.max.x - step / 2f; float y0 = region.latlonRect2D.min.y + step / 2f; float y1 = region.latlonRect2D.max.y - step / 2f; for (float x = x0; x < x1; x += step) { for (float y = y0; y < y1; y += step) { float xp = x + UnityEngine.Random.Range(-0.0001f, 0.0001f); float yp = y + UnityEngine.Random.Range(-0.0001f, 0.0001f); if (region.Contains(xp, yp)) { steinerPoints.Add(new TriangulationPoint(xp, yp)); // GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere); // obj.transform.SetParent(WorldMapGlobe.instance.transform, false); // obj.transform.localScale = Vector3.one * 0.01f; // obj.transform.localPosition = Conversion.GetSpherePointFromLatLon(new Vector2(x,y)) * 1.01f; } } } if (steinerPoints.Count > 0) { poly.AddSteinerPoints(steinerPoints); } P2T.Triangulate(poly); int flip1, flip2; if (_earthInvertedMode) { flip1 = 2; flip2 = 1; } else { flip1 = 1; flip2 = 2; } int triCount = poly.Triangles.Count; Vector3[] revisedSurfPoints = new Vector3[triCount * 3]; for (int k = 0; k < triCount; k++) { DelaunayTriangle dt = poly.Triangles [k]; revisedSurfPoints [k * 3] = Conversion.GetSpherePointFromLatLon(dt.Points [0].X, dt.Points [0].Y); revisedSurfPoints [k * 3 + flip1] = Conversion.GetSpherePointFromLatLon(dt.Points [1].X, dt.Points [1].Y); revisedSurfPoints [k * 3 + flip2] = Conversion.GetSpherePointFromLatLon(dt.Points [2].X, dt.Points [2].Y); } int revIndex = revisedSurfPoints.Length - 1; // Generate surface mesh int cacheIndex = GetCacheIndexForProvinceRegion(provinceIndex, regionIndex); GameObject surf = Drawing.CreateSurface(SURFACE_GAMEOBJECT, revisedSurfPoints, revIndex, material, region.rect2Dbillboard, textureScale, textureOffset, textureRotation); surf.transform.SetParent(surfacesLayer.transform, false); surf.transform.localPosition = Misc.Vector3zero; if (_earthInvertedMode) { surf.transform.localScale = Misc.Vector3one * 0.998f; } surfaces [cacheIndex] = surf; return(surf); }
void CreateTile(TileInfo ti) { Vector2 latLonTL = ti.latlons [0]; Vector2 latLonBR; ZoomLevelInfo zi = zoomLevelsInfo [ti.zoomLevel]; int tileCode = GetTileHashCode(ti.x + 1, ti.y + 1, ti.zoomLevel); if (cachedTiles.ContainsKey(tileCode)) { latLonBR = cachedTiles [tileCode].latlons [0]; } else { latLonBR = GetLatLonFromTile(ti.x + 1, ti.y + 1, ti.zoomLevel); } // Create container GameObject parentObj; if (ti.parent == null) { parentObj = zi.tilesContainer; if (parentObj == null) { parentObj = new GameObject("Tiles" + ti.zoomLevel); parentObj.transform.SetParent(tilesRoot, false); zi.tilesContainer = parentObj; } } else { parentObj = ti.parent.gameObject; } // Prepare mesh vertices Vector3[] tileCorners = new Vector3[4]; tileCorners [0] = Conversion.GetSpherePointFromLatLon(latLonTL); tileCorners [1] = Conversion.GetSpherePointFromLatLon(new Vector2(latLonTL.x, latLonBR.y)); tileCorners [2] = Conversion.GetSpherePointFromLatLon(latLonBR); tileCorners [3] = Conversion.GetSpherePointFromLatLon(new Vector2(latLonBR.x, latLonTL.y)); Vector2[] meshUV; if (ti.zoomLevel < TILE_MIN_ZOOM_LEVEL) { Vector2[] uv = new Vector2[4]; uv [0] = new Vector2((latLonTL.y + 180) / 360f, (latLonTL.x + 90) / 180f); uv [1] = new Vector2((latLonBR.y + 180) / 360f, (latLonTL.x + 90) / 180f); uv [2] = new Vector2((latLonBR.y + 180) / 360f, (latLonBR.x + 90) / 180f); uv [3] = new Vector2((latLonTL.y + 180) / 360f, (latLonBR.x + 90) / 180f); meshUV = uv; } else { meshUV = tileUV; } Material tileMat; if (ti.parent != null) { if (ti.parent.normalMat == null) { ti.parent.normalMat = Instantiate(tileMatRef); ti.parent.normalMat.hideFlags = HideFlags.DontSave; } if (ti.zoomLevel < TILE_MIN_ZOOM_LEVEL) { tileMat = ti.parent.normalMat; } else { if (ti.parent.transMat == null) { ti.parent.transMat = Instantiate(tileMatTransRef); ti.parent.transMat.hideFlags = HideFlags.DontSave; } tileMat = ti.parent.transMat; } } else { ti.normalMat = Instantiate(tileMatRef); ti.normalMat.hideFlags = HideFlags.DontSave; tileMat = ti.normalMat; } ti.renderer = CreateObject(parentObj.transform, "Tile", tileCorners, tileIndices, meshUV, tileMat, ti.subquadIndex); ti.gameObject = ti.renderer.gameObject; ti.created = true; }
void CreateTile(TileInfo ti) { Vector2 latLonTL = ti.latlons [0]; Vector2 latLonBR; ZoomLevelInfo zi = zoomLevelsInfo [ti.zoomLevel]; int tileCode = GetTileHashCode(ti.x + 1, ti.y + 1, ti.zoomLevel); TileInfo cachedTile; if (cachedTiles.TryGetValue(tileCode, out cachedTile)) { latLonBR = cachedTile.latlons [0]; } else { latLonBR = Conversion.GetLatLonFromTile(ti.x + 1, ti.y + 1, ti.zoomLevel); } // Avoid seams on very close distance to surface if (ti.zoomLevel >= 16) { float tao = 0.000002f * (ti.zoomLevel - 15); latLonTL.x += tao; latLonTL.y -= tao; latLonBR.x -= tao; latLonBR.y += tao; } // Create container GameObject parentObj; if (ti.parent == null) { parentObj = zi.tilesContainer; if (parentObj == null) { parentObj = new GameObject("Tiles" + ti.zoomLevel); parentObj.transform.SetParent(tilesRoot, false); zi.tilesContainer = parentObj; } } else { parentObj = ti.parent.gameObject; } // Prepare mesh vertices Vector3[] tileCorners = new Vector3[4]; tileCorners [0] = Conversion.GetSpherePointFromLatLon(latLonTL); tileCorners [1] = Conversion.GetSpherePointFromLatLon(new Vector2(latLonTL.x, latLonBR.y)); tileCorners [2] = Conversion.GetSpherePointFromLatLon(latLonBR); tileCorners [3] = Conversion.GetSpherePointFromLatLon(new Vector2(latLonBR.x, latLonTL.y)); // Setup tile materials TileInfo parent = ti.parent != null ? ti.parent : ti; if (parent.normalMat == null) { parent.normalMat = Instantiate(tileMatRef); parent.normalMat.hideFlags = HideFlags.DontSave; } if (parent.transMat == null) { parent.transMat = Instantiate(tileMatTransRef); parent.transMat.hideFlags = HideFlags.DontSave; } Material tileMat = ti.zoomLevel < TILE_MIN_ZOOM_LEVEL ? parent.normalMat : parent.transMat; // UVs wrt Earth texture Vector2 tl = new Vector2((latLonTL.y + 180) / 360f, (latLonTL.x + 90) / 180f); Vector2 br = new Vector2((latLonBR.y + 180) / 360f, (latLonBR.x + 90) / 180f); if (tl.x > 0.5f && br.x < 0.5f) { br.x = 1f; } ti.worldTextureCoords = new Vector4(tl.x, br.y, br.x, tl.y); ti.ClearPlaceholderImage(); if (ti.zoomLevel < TILE_MIN_ZOOM_LEVEL) { ti.loadStatus = TILE_LOAD_STATUS.Loaded; } ti.texture = currentEarthTexture; ti.renderer = CreateObject(parentObj.transform, "Tile", tileCorners, tileIndices, tileUV, tileMat, ti.subquadIndex); ti.gameObject = ti.renderer.gameObject; ti.renderer.enabled = false; ti.created = true; #if DEBUG_TILES ti.gameObject.AddComponent <TileInfoEx> (); #endif }
void CheckTiles(TileInfo parent, int currentZoomLevel, int xTile, int yTile, int zoomLevel, int subquadIndex) { // Is this tile visible? TileInfo ti; int tileCode = GetTileHashCode(xTile, yTile, zoomLevel); if (!cachedTiles.TryGetValue(tileCode, out ti)) { ti = new TileInfo(xTile, yTile, zoomLevel, subquadIndex, currentEarthTexture); ti.parent = parent; if (parent != null) { if (parent.children == null) { parent.children = new List <TileInfo> (); } parent.children.Add(ti); } for (int k = 0; k < 4; k++) { Vector2 latlon = Conversion.GetLatLonFromTile(xTile + offsets [k].x, yTile + offsets [k].y, zoomLevel); ti.latlons [k] = latlon; Vector3 spherePos = Conversion.GetSpherePointFromLatLon(latlon); ti.spherePos [k] = spherePos; } cachedTiles [tileCode] = ti; } // Check if any tile corner is visible // Phase I #if DEBUG_TILES if (ti.gameObject != null && ti.gameObject.GetComponent <TileInfoEx> ().debug) { Debug.Log("this"); } #endif bool cornersOccluded = true; Vector3 minWorldPos = Misc.Vector3Max; Vector3 maxWorldPos = Misc.Vector3Min; Vector3 tmp = Misc.Vector3zero; for (int c = 0; c < 4; c++) { Vector3 wpos = transform.TransformPoint(ti.spherePos [c]); ti.cornerWorldPos [c] = wpos; if (wpos.x < minWorldPos.x) { minWorldPos.x = wpos.x; } if (wpos.y < minWorldPos.y) { minWorldPos.y = wpos.y; } if (wpos.z < minWorldPos.z) { minWorldPos.z = wpos.z; } if (wpos.x > maxWorldPos.x) { maxWorldPos.x = wpos.x; } if (wpos.y > maxWorldPos.y) { maxWorldPos.y = wpos.y; } if (wpos.z > maxWorldPos.z) { maxWorldPos.z = wpos.z; } if (cornersOccluded) { float radiusSqr = (wpos.x - globePos.x) * (wpos.x - globePos.x) + (wpos.y - globePos.y) * (wpos.y - globePos.y) + (wpos.z - globePos.z) * (wpos.z - globePos.z); // Vector3.SqrMagnitude (wpos - globePos); // Vector3 camDir = (currentCameraPosition - wpos).normalized; FastVector.NormalizedDirection(ref wpos, ref currentCameraPosition, ref tmp); // Vector3 st = wpos + ndir * (0.01f * transform.localScale.x); Vector3 st = wpos; FastVector.Add(ref st, ref tmp, localScaleFactor); float mag = (st.x - globePos.x) * (st.x - globePos.x) + (st.y - globePos.y) * (st.y - globePos.y) + (st.z - globePos.z) * (st.z - globePos.z); if (mag > radiusSqr) { cornersOccluded = false; } } } // Bounds bounds = new Bounds ((minWorldPos + maxWorldPos) * 0.5f, maxWorldPos - minWorldPos); FastVector.Average(ref minWorldPos, ref maxWorldPos, ref tmp); Bounds bounds = new Bounds(tmp, maxWorldPos - minWorldPos); Vector3 tileMidPoint = bounds.center; // Check center of quad if (cornersOccluded) { float radiusSqr = (tileMidPoint.x - globePos.x) * (tileMidPoint.x - globePos.x) + (tileMidPoint.y - globePos.y) * (tileMidPoint.y - globePos.y) + (tileMidPoint.z - globePos.z) * (tileMidPoint.z - globePos.z); // Vector3.SqrMagnitude (tileMidPoint - globePos); // Vector3 camDir = (currentCameraPosition - tileMidPoint).normalized; FastVector.NormalizedDirection(ref tileMidPoint, ref currentCameraPosition, ref tmp); // Vector3 st = tileMidPoint + tmp * (0.01f * transform.localScale.x); Vector3 st = tileMidPoint; FastVector.Add(ref st, ref tmp, localScaleFactor); float mag = (st.x - globePos.x) * (st.x - globePos.x) + (st.y - globePos.y) * (st.y - globePos.y) + (st.z - globePos.z) * (st.z - globePos.z); if (mag > radiusSqr) { cornersOccluded = false; } } #if DEBUG_TILES if (root == null) { root = new GameObject(); root.transform.SetParent(transform); root.transform.localPosition = Vector3.zero; root.transform.localRotation = Misc.QuaternionZero; //Quaternion.Euler (0, 0, 0); } #endif bool insideViewport = false; float minX = currentCamera.pixelWidth * 2f, minY = currentCamera.pixelHeight * 2f; float maxX = -minX, maxY = -minY; if (!cornersOccluded) { // Phase II for (int c = 0; c < 4; c++) { Vector3 scrPos = currentCamera.WorldToScreenPoint(ti.cornerWorldPos [c]); insideViewport = insideViewport || (scrPos.z > 0 && scrPos.x >= 0 && scrPos.x < currentCamera.pixelWidth && scrPos.y >= 0 && scrPos.y < currentCamera.pixelHeight); if (scrPos.x < minX) { minX = scrPos.x; } if (scrPos.x > maxX) { maxX = scrPos.x; } if (scrPos.y < minY) { minY = scrPos.y; } if (scrPos.y > maxY) { maxY = scrPos.y; } } if (!insideViewport) { insideViewport = GeometryUtility.TestPlanesAABB(cameraPlanes, bounds); } } ti.insideViewport = insideViewport; ti.visible = false; if (insideViewport) { if (!ti.created) { CreateTile(ti); } if (!ti.gameObject.activeSelf) { ti.gameObject.SetActive(true); } // Manage hierarchy of tiles bool tileIsBig = false; FastVector.NormalizedDirection(ref globePos, ref tileMidPoint, ref tmp); // float dd = Vector3.Dot (currentCameraForward, (tileMidPoint - globePos).normalized); float dd = Vector3.Dot(currentCameraForward, tmp); if (dd > -0.8f || currentZoomLevel > 9) // prevents big seams on initial zooms { float aparentSize = Mathf.Max(maxX - minX, maxY - minY); tileIsBig = aparentSize > currentTileSize; } else { tileIsBig = ti.zoomLevel < currentZoomLevel; } #if DEBUG_TILES if (ti.gameObject != null) { ti.gameObject.GetComponent <TileInfoEx> ().bigTile = tileIsBig; ti.gameObject.GetComponent <TileInfoEx> ().zoomLevel = ti.zoomLevel; } #endif if ((tileIsBig || zoomLevel < TILE_MIN_ZOOM_LEVEL) && zoomLevel < _tileMaxZoomLevel) { // Load nested tiles CheckTiles(ti, currentZoomLevel, xTile * 2, yTile * 2, zoomLevel + 1, 0); CheckTiles(ti, currentZoomLevel, xTile * 2 + 1, yTile * 2, zoomLevel + 1, 1); CheckTiles(ti, currentZoomLevel, xTile * 2, yTile * 2 + 1, zoomLevel + 1, 2); CheckTiles(ti, currentZoomLevel, xTile * 2 + 1, yTile * 2 + 1, zoomLevel + 1, 3); ti.renderer.enabled = false; } else { ti.visible = true; // Show tile renderer if (!ti.renderer.enabled) { ti.renderer.enabled = true; } // If parent tile is loaded then use that as placeholder texture if (ti.zoomLevel > TILE_MIN_ZOOM_LEVEL && ti.parent.loadStatus == TILE_LOAD_STATUS.Loaded && !ti.placeholderImageSet) { ti.placeholderImageSet = true; ti.parentTextureCoords = placeHolderUV [ti.subquadIndex]; ti.SetPlaceholderImage(ti.parent.texture); } if (ti.loadStatus == TILE_LOAD_STATUS.Loaded) { if (!ti.hasAnimated) { ti.hasAnimated = true; ti.Animate(1f, AnimationEnded); } } else if (ti.loadStatus == TILE_LOAD_STATUS.Inactive) { ti.distToCamera = FastVector.SqrDistance(ref ti.cornerWorldPos [0], ref currentCameraPosition) * ti.zoomLevel; ti.loadStatus = TILE_LOAD_STATUS.InQueue; ti.queueTime = Time.time; loadQueue.Add(ti); } if (ti.children != null) { for (int k = 0; k < 4; k++) { TileInfo tiChild = ti.children [k]; HideTile(tiChild); } } } } else { HideTile(ti); } }
void CreatePole(TileInfo ti) { Vector3 polePos; Vector3 latLon0; string name; bool isNorth = (ti.y == 0); if (isNorth) { if (northPoleObj != null) { return; } polePos = Misc.Vector3up * 0.5f; latLon0 = ti.latlons [0]; name = "North Pole"; } else { if (southPoleObj != null) { return; } polePos = Misc.Vector3down * 0.5f; latLon0 = ti.latlons [2]; name = "South Pole"; } Vector3 latLon3 = latLon0; float lonDX = 360f / zoomLevelsInfo [ti.zoomLevel].xMax; latLon3.y += lonDX; int steps = (int)(360f / lonDX); int vertexCount = steps * 3; List <Vector3> vertices = new List <Vector3> (vertexCount); List <int> indices = new List <int> (vertexCount); List <Vector2> uv = new List <Vector2> (vertexCount); for (int k = 0; k < steps; k++) { Vector3 p0 = Conversion.GetSpherePointFromLatLon(latLon0); Vector3 p1 = Conversion.GetSpherePointFromLatLon(latLon3); latLon0 = latLon3; latLon3.y += lonDX; vertices.Add(p0); vertices.Add(p1); vertices.Add(polePos); indices.Add(k * 3); if (isNorth) { indices.Add(k * 3 + 2); indices.Add(k * 3 + 1); } else { indices.Add(k * 3 + 1); indices.Add(k * 3 + 2); } uv.Add(Misc.Vector2zero); uv.Add(Misc.Vector2up); uv.Add(Misc.Vector2right); } Renderer obj = CreateObject(tilesRoot.transform, name, vertices.ToArray(), indices.ToArray(), uv.ToArray(), ti.parent.normalMat, 0); if (isNorth) { northPoleObj = obj; } else { southPoleObj = obj; } }
/// <summary> /// Returns the index of the nearest city to a location (lat/lon). /// </summary> public int GetCityIndex(float lat, float lon) { Vector3 spherePosition = Conversion.GetSpherePointFromLatLon(lat, lon); return(GetCityIndex(spherePosition)); }
/// <summary> /// Adds the new point to currently selected region. /// </summary> public void AddPoint(Vector3 newPoint) { if (entities == null || entityIndex < 0 || entityIndex >= entities.Length || regionIndex < 0 || entities [entityIndex].regions == null || regionIndex >= entities [entityIndex].regions.Count) { return; } // List<Region> affectedRegions = new List<Region>(); Region region = entities [entityIndex].regions [regionIndex]; float minDist = float.MaxValue; int nearest = -1, previous = -1; int max = region.latlon.Length; Vector2 latlonNew = Conversion.GetLatLonFromSpherePoint(newPoint); for (int p = 0; p < max; p++) { int q = p == 0 ? max - 1 : p - 1; Vector2 rp = (region.latlon [p] + region.latlon [q]) * 0.5f; float dist = (rp - latlonNew).sqrMagnitude; // (rp.x - newPoint.x) * (rp.x - newPoint.x)*4 + (rp.y - newPoint.y) * (rp.y - newPoint.y); if (dist < minDist) { // Get nearest point minDist = dist; nearest = p; previous = q; } } if (nearest >= 0) { Vector2 latlonToInsert = (region.latlon [nearest] + region.latlon [previous]) * 0.5f; Vector3 pointToInsert = Conversion.GetSpherePointFromLatLon(latlonToInsert); pointToInsert = pointToInsert.normalized * 0.5f; // Check if nearest and previous exists in any neighbour int nearest2 = -1, previous2 = -1; for (int n = 0; n < region.neighbours.Count; n++) { Region nregion = region.neighbours [n]; for (int p = 0; p < nregion.latlon.Length; p++) { if (nregion.latlon [p] == region.latlon [nearest]) { nearest2 = p; } if (nregion.latlon [p] == region.latlon [previous]) { previous2 = p; } } if (nearest2 >= 0 && previous2 >= 0) { nregion.latlon = InsertLatLon(nregion.latlon, previous2, latlonToInsert); // affectedRegions.Add (nregion); break; } } // Insert the point in the current region (must be done after inserting in the neighbour so nearest/previous don't unsync) region.latlon = InsertLatLon(region.latlon, nearest, latlonToInsert); // affectedRegions.Add (region); } }
/// <summary> /// Navigates to target latitude and longitude using given duration. /// </summary> public void FlyToLocation(float latitude, float longitude, float duration, float destinationZoomLevel = 0) { Vector3 destination = Conversion.GetSpherePointFromLatLon(latitude, longitude); FlyToLocation(destination, duration, destinationZoomLevel, _navigationBounceIntensity); }
/// <summary> /// Navigates to target latitude and longitude using given duration. /// </summary> public void FlyToLocation(float latitude, float longitude, float duration) { Vector3 destination = Conversion.GetSpherePointFromLatLon(latitude, longitude); FlyToLocation(destination, duration); }
// GameObject root; void CheckTiles(TileInfo parent, int currentZoomLevel, int xTile, int yTile, int zoomLevel, int subquadIndex) { // Is this tile visible? TileInfo ti; int tileCode = GetTileHashCode(xTile, yTile, zoomLevel); if (cachedTiles.ContainsKey(tileCode)) { ti = cachedTiles [tileCode]; } else { ti = new TileInfo(xTile, yTile, zoomLevel, subquadIndex); ti.parent = parent; if (parent != null) { if (parent.children == null) { parent.children = new List <TileInfo> (); } parent.children.Add(ti); } for (int k = 0; k < 4; k++) { Vector2 latlon = GetLatLonFromTile(xTile + offsets [k].x, yTile + offsets [k].y, zoomLevel); ti.latlons [k] = latlon; Vector3 spherePos = Conversion.GetSpherePointFromLatLon(latlon); ti.spherePos [k] = spherePos; } cachedTiles [tileCode] = ti; } // Check if any tile corner is visible // Phase I // float distCam = Vector3.SqrMagnitude ((transform.position - Camera.main.transform.position) * 0.95f); // float distCam = Vector3.Distance (transform.position, Camera.main.transform.position) * 0.95f; // ((transform.position - Camera.main.transform.position) * 0.95f); bool cornersOccluded = true; for (int c = 0; c < 4; c++) { ti.cornerWorldPos [c] = transform.TransformPoint(ti.spherePos [c]); if (cornersOccluded) { float radiusSqr = Vector3.SqrMagnitude(ti.cornerWorldPos [c] - transform.position); Vector3 camDir = (Camera.main.transform.position - ti.cornerWorldPos [c]).normalized; Vector3 st = ti.cornerWorldPos [c] + camDir * 0.01f; if (Vector3.SqrMagnitude(st - transform.position) > radiusSqr) { // if ( Vector3.SqrMagnitude (ti.cornerWorldPos [c] - Camera.main.transform.position) < distCam) { cornersOccluded = false; } } } bool insideViewport = false; float minX = 2f, minY = 2f, maxX = -2f, maxY = -2f, maxZ = -1; if (!cornersOccluded) { // Phase II for (int c = 0; c < 4; c++) { Vector3 scrPos = Camera.main.WorldToViewportPoint(ti.cornerWorldPos [c]); if (scrPos.z < 0) { scrPos.x *= -1f; scrPos.y *= -1f; } insideViewport = insideViewport || (scrPos.z > 0 && scrPos.x >= 0 && scrPos.x < 1f && scrPos.y >= 0 && scrPos.y < 1); if (scrPos.x < minX) { minX = scrPos.x; } if (scrPos.x > maxX) { maxX = scrPos.x; } if (scrPos.y < minY) { minY = scrPos.y; } if (scrPos.y > maxY) { maxY = scrPos.y; } if (scrPos.z > maxZ) { maxZ = scrPos.z; } } if (!insideViewport && maxZ > 0) { // Check if rectangles overlap insideViewport = !(minX > 1 || maxX < 0 || minY > 1 || maxY < 0); // completely outside of screen? } } if (ti.debug) { Debug.Log("this"); } ti.insideViewport = insideViewport; ti.visible = false; if (insideViewport) { // if (root==null) { // root = new GameObject(); // root.transform.SetParent(transform); // root.transform.localPosition = Vector3.zero; // root.transform.localRotation = Quaternion.Euler(0,0,0); // } if (!ti.created) { CreateTile(ti); } if (!ti.gameObject.activeSelf) { ti.gameObject.SetActive(true); } float aparentSize = Mathf.Max((maxX - minX) * (float)Camera.main.pixelWidth, (maxY - minY) * (float)Camera.main.pixelHeight); bool tileIsBig = aparentSize > currentTileSize; // if (zoomLevel < currentZoomLevel && (tileIsBig || zoomLevel<TILE_MIN_ZOOM_LEVEL)) { if (tileIsBig || zoomLevel < TILE_MIN_ZOOM_LEVEL) { // if (tileIsBig) { // GameObject mark = GameObject.CreatePrimitive(PrimitiveType.Cube); // mark.transform.SetParent(root.transform); // mark.transform.position = ti.cornerWorldPos[0]; // mark.transform.localScale = Vector3.one * 0.3f; // TileInfoEx tie = mark.AddComponent<TileInfoEx>(); // tie.maxX = aparentSize; // } // Load nested tiles CheckTiles(ti, currentZoomLevel, xTile * 2, yTile * 2, zoomLevel + 1, 0); CheckTiles(ti, currentZoomLevel, xTile * 2 + 1, yTile * 2, zoomLevel + 1, 1); CheckTiles(ti, currentZoomLevel, xTile * 2, yTile * 2 + 1, zoomLevel + 1, 2); CheckTiles(ti, currentZoomLevel, xTile * 2 + 1, yTile * 2 + 1, zoomLevel + 1, 3); // Should I hide this tile? Only if children are all loaded bool allLoaded = true; if (ti.children != null) { for (int k = 0; k < 4; k++) { TileInfo children = ti.children [k]; if (children.insideViewport) { allLoaded = allLoaded && children.isLoadedOrHasAllChildrenLoaded; } if (!allLoaded) { break; } } } ti.isLoadedOrHasAllChildrenLoaded = allLoaded; ti.renderer.enabled = !allLoaded && (ti.loadStatus == TILE_LOAD_STATUS.Loaded || zoomLevel < TILE_MIN_ZOOM_LEVEL); if (ti.parent != null && ti.renderer.enabled && ti.renderer.sharedMaterial == ti.parent.transMat) { ti.renderer.sharedMaterial = ti.parent.normalMat; } } else { ti.visible = true; if (ti.loadStatus == TILE_LOAD_STATUS.Loaded) { if (!ti.renderer.enabled) { ShowTile(ti); } } else { if (ti.loadStatus == TILE_LOAD_STATUS.Inactive) { ti.distToCamera = (ti.cornerWorldPos [0] - Camera.main.transform.position).sqrMagnitude * ti.zoomLevel; ti.loadStatus = TILE_LOAD_STATUS.InQueue; ti.queueTime = Time.time; loadQueue.Add(ti); } if (ti.renderer.enabled) { ti.renderer.enabled = false; } } ti.isLoadedOrHasAllChildrenLoaded = ti.renderer.enabled && ti.animationFinished; if (ti.children != null) { for (int k = 0; k < 4; k++) { TileInfo tiChild = ti.children [k]; if (tiChild.gameObject != null && tiChild.gameObject.activeSelf) { tiChild.gameObject.SetActive(false); ti.visible = false; } } } } } else { if (ti.gameObject != null && ti.gameObject.activeSelf) { ti.gameObject.SetActive(false); // if (ti.texture!=null) { // Destroy(ti.texture); // ti.texture = null; // ti.loadStatus = TILE_LOAD_STATUS.Inactive; // if (gcCount++>100) { // gcCount = 0; // Resources.UnloadUnusedAssets(); // System.GC.Collect(); // Debug.Log ("Gc collect!"); // } // } } } // if (ti.visible) { // visibleTiles++; // } }