コード例 #1
0
        void GetTileServerInfo(TILE_SERVER server, TileInfo ti, out string url)
        {
            string[] subservers = { "a", "b", "c" };
            subserverSeq++;
            if (subserverSeq > 100000)
            {
                subserverSeq = 0;
            }

            switch (_tileServer)
            {
            case TILE_SERVER.OpenStreeMap:
                url = "http://" + subservers[subserverSeq % 3] + ".tile.openstreetmap.org/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.OpenStreeMapDE:
                url = "http://" + subservers[subserverSeq % 3] + ".tile.openstreetmap.de/tiles/osmde/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.StamenToner:
                url = "http://tile.stamen.com/toner/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.StamenTerrain:
                url = "http://tile.stamen.com/terrain/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.StamenWaterColor:
                url = "http://tile.stamen.com/watercolor/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoLightAll:
                url = "http://" + subservers[subserverSeq % 3] + ".basemaps.cartocdn.com/light_all/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoDarkAll:
                url = "http://" + subservers[subserverSeq % 3] + ".basemaps.cartocdn.com/dark_all/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoNoLabels:
                url = "http://" + subservers[subserverSeq % 3] + ".basemaps.cartocdn.com/light_nolabels/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoOnlyLabels:
                url = "http://" + subservers[subserverSeq % 3] + ".basemaps.cartocdn.com/light_only_labels/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoDarkNoLabels:
                url = "http://" + subservers[subserverSeq % 3] + ".basemaps.cartocdn.com/dark_nolabels/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoDarkOnlyLabels:
                url = "http://" + subservers[subserverSeq % 3] + ".basemaps.cartocdn.com/dark_only_labels/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.WikiMediaAtlas:
                url = "http://" + subservers[subserverSeq % 3] + ".tiles.wmflabs.org/bw-mapnik/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.ThunderForestLandscape:
                url = "http://" + subservers[subserverSeq % 3] + ".tile.thunderforest.com/landscape/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.OpenTopoMap:
                url = "http://" + subservers[subserverSeq % 3] + ".tile.opentopomap.org/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.MapBoxSatellite:
                url = "http://" + subservers[subserverSeq % 3] + ".tiles.mapbox.com/v3/tmcw.map-j5fsp01s/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.Sputnik:
                url = "http://" + subservers[subserverSeq % 3] + ".tiles.maps.sputnik.ru/tiles/kmt2/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            default:
                Debug.LogError("Tile server not defined: " + tileServer.ToString());
                url = "";
                break;
            }
        }
コード例 #2
0
        public string GetTileURL(TILE_SERVER server, TileInfo ti)
        {
            string url;

            string[] subservers = { "a", "b", "c" };
            subserverSeq++;
            if (subserverSeq > 100000)
            {
                subserverSeq = 0;
            }

            switch (_tileServer)
            {
            case TILE_SERVER.OpenStreeMap:
                url = "http://" + subservers [subserverSeq % 3] + ".tile.openstreetmap.org/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.OpenStreeMapDE:
                url = "http://" + subservers [subserverSeq % 3] + ".tile.openstreetmap.de/tiles/osmde/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.StamenToner:
                url = "http://tile.stamen.com/toner/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.StamenTerrain:
                url = "http://tile.stamen.com/terrain/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.StamenWaterColor:
                url = "http://tile.stamen.com/watercolor/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoLightAll:
                url = "http://" + subservers [subserverSeq % 3] + ".basemaps.cartocdn.com/light_all/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoDarkAll:
                url = "http://" + subservers [subserverSeq % 3] + ".basemaps.cartocdn.com/dark_all/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoNoLabels:
                url = "http://" + subservers [subserverSeq % 3] + ".basemaps.cartocdn.com/light_nolabels/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoOnlyLabels:
                url = "http://" + subservers [subserverSeq % 3] + ".basemaps.cartocdn.com/light_only_labels/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoDarkNoLabels:
                url = "http://" + subservers [subserverSeq % 3] + ".basemaps.cartocdn.com/dark_nolabels/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.CartoDarkOnlyLabels:
                url = "http://" + subservers [subserverSeq % 3] + ".basemaps.cartocdn.com/dark_only_labels/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.WikiMediaAtlas:
                url = "http://" + subservers [subserverSeq % 3] + ".tiles.wmflabs.org/bw-mapnik/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.ThunderForestLandscape:
                url = "http://" + subservers [subserverSeq % 3] + ".tile.thunderforest.com/landscape/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.OpenTopoMap:
                url = "http://" + subservers [subserverSeq % 3] + ".tile.opentopomap.org/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.MapBoxSatellite:
                url = "http://" + subservers [subserverSeq % 3] + ".tiles.mapbox.com/v3/tmcw.map-j5fsp01s/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.Sputnik:
                url = "http://" + subservers [subserverSeq % 3] + ".tiles.maps.sputnik.ru/tiles/kmt2/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + ".png";
                break;

            case TILE_SERVER.AerisWeather:
                //https://maps[server].aerisapi.com/[client_id]_[client_key]/[type]/[zoom]/[x]/[y]/[offset].png
                url = "http://maps" + ((subserverSeq % 4) + 1).ToString() + ".aerisapi.com/" + _tileServerClientId + "_" + _tileServerAPIKey + "/" + _tileServerLayerTypes + "/" + ti.zoomLevel + "/" + ti.x + "/" + ti.y + "/" + _tileServerTimeOffset + ".png";
                break;

            case TILE_SERVER.Custom:
                StringBuilder sb = new StringBuilder(_tileServerCustomUrl);
                sb.Replace("$n$", subservers [subserverSeq % 3]);
                sb.Replace("$N$", subservers [subserverSeq % 3]);
                sb.Replace("$X$", ti.x.ToString());
                sb.Replace("$x$", ti.x.ToString());
                sb.Replace("$Y$", ti.y.ToString());
                sb.Replace("$y$", ti.y.ToString());
                sb.Replace("$Z$", ti.zoomLevel.ToString());
                sb.Replace("$z$", ti.zoomLevel.ToString());
                url = sb.ToString();
                break;

            default:
                Debug.LogError("Tile server not defined: " + tileServer.ToString());
                url = "";
                break;
            }

            if (_tileServer != TILE_SERVER.Custom && _tileServerAPIKey != null && _tileServerAPIKey.Length > 0)
            {
                url += "?" + _tileServerAPIKey;
            }

            return(url);
        }
コード例 #3
0
ファイル: WPMTiles.cs プロジェクト: capitolinteractive/VietVR
        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
        }
コード例 #4
0
ファイル: WPMTiles.cs プロジェクト: capitolinteractive/VietVR
        internal IEnumerator LoadTileContentBackground(TileInfo ti)
        {
            yield return(new WaitForEndOfFrame());

            string url = GetTileURL(_tileServer, ti);

            if (string.IsNullOrEmpty(url))
            {
                Debug.LogError("Tile server url not set. Aborting");
                yield break;
            }

            long   downloadedBytes = 0;
            string error           = null;
            string filePath        = "";

            byte[] textureBytes = null;
            ti.source = TILE_SOURCE.Unknown;

            // Check if tile is given by external event
            if (OnTileRequest != null)
            {
                if (OnTileRequest(ti.zoomLevel, ti.x, ti.y, out ti.texture, out error) && ti.texture != null)
                {
                    ti.source = TILE_SOURCE.Resources;
                }
            }

            // Check if tile is in Resources
            if (ti.source == TILE_SOURCE.Unknown && _tileEnableOfflineTiles)
            {
                string          path    = GetTileResourcePath(ti.x, ti.y, ti.zoomLevel, false);
                ResourceRequest request = Resources.LoadAsync <Texture2D> (path);
                yield return(request);

                if (request.asset != null)
                {
                    ti.texture = (Texture2D)request.asset;
                    ti.source  = TILE_SOURCE.Resources;
                }
                else if (tileOfflineTilesOnly)
                {
                    ti.texture = tileResourceFallbackTexture;
                    ti.source  = TILE_SOURCE.Resources;
                }
            }

            CustomWWW www = null;

            if (ti.source == TILE_SOURCE.Unknown)
            {
                www = getCachedWWW(url, ti);
                yield return(www);

                error = www.error;
            }

            for (int tries = 0; tries < 100; tries++)
            {
                if (spreadLoadAmongFrames > 0)
                {
                    break;
                }
                yield return(new WaitForEndOfFrame());
            }
            spreadLoadAmongFrames--;
            _concurrentLoads--;

            if (!ti.visible)                    // non visible textures are ignored
            {
                ti.loadStatus = TILE_LOAD_STATUS.InQueue;
                yield break;
            }

            if (!string.IsNullOrEmpty(error))
            {
                _tileLastError     = "Error getting tile: " + error + " url=" + url;
                _tileLastErrorDate = DateTime.Now;
                if (_tileDebugErrors)
                {
                    Debug.Log(_tileLastErrorDate + " " + _tileLastError);
                }
                ti.loadStatus = TILE_LOAD_STATUS.InQueue;
                yield break;
            }

            // Load texture
            if (ti.source != TILE_SOURCE.Resources)
            {
                downloadedBytes = www.bytesDownloaded;
                textureBytes    = www.bytes;
                ti.texture      = www.textureNonReadable;
                www.Dispose();
                www = null;

                // Check texture consistency
                if (ti.loadedFromCache || _tileEnableLocalCache)
                {
                    filePath = GetLocalFilePathForURL(url, ti);
                }

                if (ti.loadedFromCache && ti.texture.width <= 16)                   // Invalid texture in local cache, retry
                {
                    if (File.Exists(filePath))
                    {
                        File.Delete(filePath);
                    }
                    ti.loadStatus = TILE_LOAD_STATUS.Inactive;
                    ti.queueTime  = Time.time;
                    yield break;
                }
            }

            ti.texture.wrapMode = TextureWrapMode.Clamp;
            _tileSize           = ti.texture.width;

            // Save texture
            if (_tileEnableLocalCache && ti.source != TILE_SOURCE.Resources && !File.Exists(filePath))
            {
                _tileCurrentCacheUsage += textureBytes.Length;
                BackgroundSaver saver = new BackgroundSaver(textureBytes, filePath);
                saver.Start();
            }

            // Update stats
            switch (ti.source)
            {
            case TILE_SOURCE.Cache:
                _cacheLoads++;
                _cacheLoadTotalSize += downloadedBytes;
                break;

            case TILE_SOURCE.Resources:
                _resourceLoads++;
                break;

            default:
                _webDownloads++;
                _webDownloadTotalSize += downloadedBytes;
                break;
            }

            if (loadQueue.Contains(ti))
            {
                loadQueue.Remove(ti);
            }

            FinishLoadingTile(ti);
        }
コード例 #5
0
ファイル: WPMTiles.cs プロジェクト: capitolinteractive/VietVR
        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);
            }
        }
コード例 #6
0
ファイル: WPMTiles.cs プロジェクト: capitolinteractive/VietVR
 void AnimationEnded(TileInfo ti)
 {
     shouldCheckTiles = true;
     // Switch tile material to solid
     ti.renderer.sharedMaterial = ti.parent.normalMat;
 }
コード例 #7
0
ファイル: WPMTiles.cs プロジェクト: capitolinteractive/VietVR
        void MonitorInactiveTiles()
        {
            int  inactiveCount  = inactiveTiles.Count;
            bool changes        = false;
            bool releasedMemory = false;

            for (int k = 0; k < inactiveCount; k++)
            {
                TileInfo ti = inactiveTiles [k];
                if (ti == null || ti.gameObject == null || ti.visible || ti.texture == currentEarthTexture || ti.loadStatus != TILE_LOAD_STATUS.Loaded)
                {
                    inactiveTiles [k]    = null;
                    ti.isAddedToInactive = false;
                    changes = true;
                    continue;
                }
                if (Time.time - ti.inactiveTime > _tileKeepAlive)
                {
                    inactiveTiles [k]    = null;
                    ti.isAddedToInactive = false;
                    ti.loadStatus        = TILE_LOAD_STATUS.Inactive;
                    // tile is now invisible, setup material for when it appears again:
                    ti.ClearPlaceholderImage();
                    if (ti.source != TILE_SOURCE.Resources)
                    {
                        Destroy(ti.texture);
                    }
                    ti.texture = currentEarthTexture;
                    // Reset parentcoords on children
                    if (ti.children != null)
                    {
                        int cCount = ti.children.Count;
                        for (int c = 0; c < cCount; c++)
                        {
                            TileInfo tiChild = ti.children [c];
                            if (!tiChild.animationFinished)
                            {
                                tiChild.ClearPlaceholderImage();
                            }
                        }
                    }
                    changes        = true;
                    releasedMemory = true;
                }
            }
            if (changes)
            {
                List <TileInfo> newInactiveList = new List <TileInfo> ();
                for (int k = 0; k < inactiveCount; k++)
                {
                    if (inactiveTiles [k] != null)
                    {
                        newInactiveList.Add(inactiveTiles [k]);
                    }
                }
                inactiveTiles.Clear();
                inactiveTiles = newInactiveList;
                if (releasedMemory)
                {
                    Resources.UnloadUnusedAssets();
                    GC.Collect();
                }
            }
        }
コード例 #8
0
ファイル: WPMTiles.cs プロジェクト: capitolinteractive/VietVR
        void CheckTilesContent(int currentZoomLevel)
        {
            int  qCount     = loadQueue.Count;
            bool cleanQueue = false;

            for (int k = 0; k < qCount; k++)
            {
                TileInfo ti = loadQueue [k];
                if (ti == null)
                {
                    cleanQueue = true;
                    continue;
                }
                if (ti.loadStatus == TILE_LOAD_STATUS.InQueue)
                {
                    if (ti.zoomLevel <= currentZoomLevel && ti.visible)
                    {
                        if (_tilePreloadTiles && ti.zoomLevel == TILE_MIN_ZOOM_LEVEL && ReloadTextureFromCacheOrMarkForDownload(ti))
                        {
                            loadQueue [k] = null;
                            cleanQueue    = true;
                            continue;
                        }
                        if (_concurrentLoads <= _tileMaxConcurrentDownloads)
                        {
                            ti.loadStatus = TILE_LOAD_STATUS.Loading;
                            _concurrentLoads++;
                            StartCoroutine(LoadTileContentBackground(ti));
                        }
                    }
                    else if (Time.time - ti.queueTime > TILE_MAX_QUEUE_TIME)
                    {
                        ti.loadStatus = TILE_LOAD_STATUS.Inactive;
                        loadQueue [k] = null;
                        cleanQueue    = true;
                    }
                }
            }

            if (cleanQueue)
            {
                if (newQueue == null)
                {
                    newQueue = new List <TileInfo> (qCount);
                }
                else
                {
                    newQueue.Clear();
                }
                for (int k = 0; k < qCount; k++)
                {
                    TileInfo ti = loadQueue [k];
                    if (ti != null)
                    {
                        newQueue.Add(ti);
                    }
                }
                loadQueue.Clear();
                loadQueue.AddRange(newQueue);
            }
        }
コード例 #9
0
ファイル: WPMTiles.cs プロジェクト: capitolinteractive/VietVR
        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;
            }
        }
コード例 #10
0
        internal IEnumerator LoadTileContentBackground(TileInfo ti)
        {
            yield return(new WaitForEndOfFrame());

            string url;

            GetTileServerInfo(_tileServer, ti, out url);
            if (url == null)
            {
                Debug.LogError("Tile server url not set. Aborting");
                yield break;
            }

            if (tileServerAPIKey != null && tileServerAPIKey.Length > 0)
            {
                url += "?" + _tileServerAPIKey;
            }

            WWW www = getCachedWWW(url, ti);

            yield return(www);

            _concurrentLoads--;

            if (www.error != null)
            {
                _tileLastError     = "Error getting tile: " + www.error + " url=" + url;
                _tileLastErrorDate = DateTime.Now;
                if (_tileDebugErrors)
                {
                    Debug.Log(_tileLastErrorDate + " " + _tileLastError);
                }
                ti.loadStatus = TILE_LOAD_STATUS.InQueue;
                yield break;
            }
            // Check texture consistency
            string filePath = GetLocalFilePathForUrl(url, ti);

            long downloadedBytes = www.size;

            ti.texture = new Texture2D(www.texture.width, www.texture.height);
            www.LoadImageIntoTexture(ti.texture);
            www.Dispose();
            www = null;

            if (ti.texture.width <= 16 && ti.loadedFromCache)               // Invalid texture in local cache, retry
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
                ti.loadStatus = TILE_LOAD_STATUS.Inactive;
                ti.queueTime  = Time.time;
                yield break;
            }
            ti.texture.wrapMode = TextureWrapMode.Clamp;
            _tileSize           = ti.texture.width;

            // Save texture
            if (!File.Exists(filePath))
            {
                byte[] texBytes = ti.texture.EncodeToJPG();
                _tileCurrentCacheUsage += texBytes.Length;
                BackgroundSaver saver = new BackgroundSaver(texBytes, filePath);
                saver.Start();
            }

            // Update stats
            if (ti.loadedFromCache)
            {
                _cacheLoads++;
                _cacheLoadTotalSize += downloadedBytes;
            }
            else
            {
                _webDownloads++;
                _webDownloadTotalSize += downloadedBytes;
            }

            // Good to go, update tile info
            switch (ti.subquadIndex)
            {
            case 0:
                ti.parent.transMat.SetTexture("_MainTex", ti.texture);
                ti.parent.normalMat.SetTexture("_MainTex", ti.texture);
                break;

            case 1:
                ti.parent.transMat.SetTexture("_MainTex1", ti.texture);
                ti.parent.normalMat.SetTexture("_MainTex1", ti.texture);
                break;

            case 2:
                ti.parent.transMat.SetTexture("_MainTex2", ti.texture);
                ti.parent.normalMat.SetTexture("_MainTex2", ti.texture);
                break;

            case 3:
                ti.parent.transMat.SetTexture("_MainTex3", ti.texture);
                ti.parent.normalMat.SetTexture("_MainTex3", ti.texture);
                break;
            }
            ti.loadStatus = TILE_LOAD_STATUS.Loaded;
            if (loadQueue.Contains(ti))
            {
                loadQueue.Remove(ti);
            }

            if (ti.zoomLevel >= TILE_MIN_ZOOM_LEVEL)
            {
                if (ti.y == 0 || ti.y == zoomLevelsInfo [ti.zoomLevel].yMax - 1)
                {
                    CreatePole(ti);
                }
            }
            shouldCheckTiles = true;
        }
コード例 #11
0
        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;
        }
コード例 #12
0
//		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++;
//			}
        }
コード例 #13
0
        bool ReloadTextureFromCacheOrMarkForDownload(TileInfo ti)
        {
            if (!_tileEnableLocalCache)
            {
                return(false);
            }

            string url;

            GetTileServerInfo(_tileServer, ti, out url);
            if (url == null)
            {
                return(false);
            }

            if (tileServerAPIKey != null && tileServerAPIKey.Length > 0)
            {
                url += "?" + _tileServerAPIKey;
            }

            string filePath = GetLocalFilePathForUrl(url, ti);

            if (System.IO.File.Exists(filePath))
            {
                //check how old
                System.DateTime written    = File.GetLastWriteTimeUtc(filePath);
                System.DateTime now        = System.DateTime.UtcNow;
                double          totalHours = now.Subtract(written).TotalHours;
                if (totalHours > 300)
                {
                    File.Delete(filePath);
                    return(false);
                }
            }
            else
            {
                return(false);
            }
            byte[] bb = System.IO.File.ReadAllBytes(filePath);
            ti.texture = new Texture2D(_tileSize, _tileSize);
            ti.texture.LoadImage(bb);
            if (ti.texture.width <= 16)               // Invalid texture in local cache, retry
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
                return(false);
            }
            ti.texture.wrapMode = TextureWrapMode.Clamp;

            _cacheLoads++;
            _cacheLoadTotalSize += bb.Length;

            // Good to go, update tile info
            switch (ti.subquadIndex)
            {
            case 0:
                ti.parent.transMat.SetTexture("_MainTex", ti.texture);
                ti.parent.normalMat.SetTexture("_MainTex", ti.texture);
                break;

            case 1:
                ti.parent.transMat.SetTexture("_MainTex1", ti.texture);
                ti.parent.normalMat.SetTexture("_MainTex1", ti.texture);
                break;

            case 2:
                ti.parent.transMat.SetTexture("_MainTex2", ti.texture);
                ti.parent.normalMat.SetTexture("_MainTex2", ti.texture);
                break;

            case 3:
                ti.parent.transMat.SetTexture("_MainTex3", ti.texture);
                ti.parent.normalMat.SetTexture("_MainTex3", ti.texture);
                break;
            }

            ti.loadStatus = TILE_LOAD_STATUS.Loaded;
            if (ti.zoomLevel >= TILE_MIN_ZOOM_LEVEL)
            {
                if (ti.y == 0 || ti.y == zoomLevelsInfo [ti.zoomLevel].yMax - 1)
                {
                    CreatePole(ti);
                }
            }
            shouldCheckTiles = true;
            return(true);
        }