protected void RemoveInvisibleTiles(CameraBase camera) { ArrayList deletionList = new ArrayList(); lock (m_topmostTiles.SyncRoot) { foreach (long key in m_topmostTiles.Keys) { QuadTile qt = (QuadTile)m_topmostTiles[key]; if (!camera.ViewFrustum.Intersects(qt.BoundingBox)) { deletionList.Add(key); } } foreach (long deleteThis in deletionList) { QuadTile qt = (QuadTile)m_topmostTiles[deleteThis]; if (qt != null) { m_topmostTiles.Remove(deleteThis); qt.Dispose(); } } } }
/// <summary> /// Initializes a new instance of the <see cref= "T:WorldWind.Renderable.GeoSpatialDownloadRequest"/> class. /// </summary> /// <param name="quadTile"></param> public GeoSpatialDownloadRequest(QuadTile quadTile, ImageStore imageStore, string localFilePath, string downloadUrl) { m_quadTile = quadTile; m_url = downloadUrl; m_localFilePath = localFilePath; m_imageStore = imageStore; }
public virtual void ResetCacheForCurrentView(WorldWind.Camera.CameraBase camera) { // if (!ImageStore.IsDownloadableLayer) // return; ArrayList deletionList = new ArrayList(); //reset "root" tiles that intersect current view lock (m_topmostTiles.SyncRoot) { foreach (long key in m_topmostTiles.Keys) { QuadTile qt = (QuadTile)m_topmostTiles[key]; if (camera.ViewFrustum.Intersects(qt.BoundingBox)) { qt.ResetCache(); deletionList.Add(key); } } foreach (long deletionKey in deletionList) { m_topmostTiles.Remove(deletionKey); } } }
/// <summary> /// Initializes a new instance of the <see cref= "T:WorldWind.Net.ImageTileRequest"/> class. /// </summary> /// <param name="owner"></param> /// <param name="quadTile"></param> public ImageTileRequest(object owner, QuadTile quadTile) : base( owner, quadTile.ImageTileInfo.Uri ) { m_quadTile = quadTile; download.DownloadType = DownloadType.Wms; SaveFilePath = QuadTile.ImageTileInfo.ImagePath; }
public virtual void ComputeChildren(DrawArgs drawArgs) { if (Level + 1 >= QuadTileSet.ImageStore.LevelCount) { return; } double CenterLat = 0.5f * (South + North); double CenterLon = 0.5f * (East + West); if (northWestChild == null) { northWestChild = ComputeChild(CenterLat, North, West, CenterLon); } if (northEastChild == null) { northEastChild = ComputeChild(CenterLat, North, CenterLon, East); } if (southWestChild == null) { southWestChild = ComputeChild(South, CenterLat, West, CenterLon); } if (southEastChild == null) { southEastChild = ComputeChild(South, CenterLat, CenterLon, East); } }
/// <summary> /// Finds the "best" tile from queue /// </summary> public virtual GeoSpatialDownloadRequest GetClosestDownloadRequest() { GeoSpatialDownloadRequest closestRequest = null; float largestArea = float.MinValue; lock (m_downloadRequests.SyncRoot) { foreach (GeoSpatialDownloadRequest curRequest in m_downloadRequests.Values) { if (curRequest.IsDownloading) { continue; } QuadTile qt = curRequest.QuadTile; if (!m_camera.ViewFrustum.Intersects(qt.BoundingBox)) { continue; } float screenArea = qt.BoundingBox.CalcRelativeScreenArea(m_camera); if (screenArea > largestArea) { largestArea = screenArea; closestRequest = curRequest; } } } return(closestRequest); }
/// <summary> /// Removes a request from the download queue. /// </summary> public virtual void RemoveFromDownloadQueue(GeoSpatialDownloadRequest removeRequest) { lock (m_downloadRequests.SyncRoot) { QuadTile key = removeRequest.QuadTile; GeoSpatialDownloadRequest request = (GeoSpatialDownloadRequest)m_downloadRequests[key]; if (request != null) { m_downloadRequests.Remove(key); request.QuadTile.DownloadRequest = null; } } }
/// <summary> /// Render one of the 4 quadrants with optional download indicator /// </summary> private void Render(Device device, CustomVertex.PositionTextured[] verts, QuadTile child) { bool isMultitexturing = false; if (World.Settings.ShowDownloadIndicator && child != null) { // Check/display download activity GeoSpatialDownloadRequest request = child.DownloadRequest; if (child.isDownloadingTerrain) { device.SetTexture(1, QuadTileSet.DownloadTerrainTexture); isMultitexturing = true; } //else if (request != null) else if (child.WaitingForDownload) { if (child.IsDownloadingImage) { device.SetTexture(1, QuadTileSet.DownloadInProgressTexture); } else { device.SetTexture(1, QuadTileSet.DownloadQueuedTexture); } isMultitexturing = true; } } if (isMultitexturing) { device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int)TextureOperation.BlendTextureAlpha); } if (verts != null && vertexIndexes != null) { device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, verts.Length, vertexIndexes.Length / 3, vertexIndexes, true, verts); } if (isMultitexturing) { device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int)TextureOperation.Disable); } }
public virtual void AddToDownloadQueue(CameraBase camera, GeoSpatialDownloadRequest newRequest) { QuadTile key = newRequest.QuadTile; key.WaitingForDownload = true; lock (m_downloadRequests.SyncRoot) { if (m_downloadRequests.Contains(key)) { return; } m_downloadRequests.Add(key, newRequest); if (m_downloadRequests.Count >= m_maxQueueSize) { //remove spatially farthest request GeoSpatialDownloadRequest farthestRequest = null; Angle curDistance = Angle.Zero; Angle farthestDistance = Angle.Zero; foreach (GeoSpatialDownloadRequest curRequest in m_downloadRequests.Values) { curDistance = MathEngine.SphericalDistance( curRequest.QuadTile.CenterLatitude, curRequest.QuadTile.CenterLongitude, camera.Latitude, camera.Longitude); if (curDistance > farthestDistance) { farthestRequest = curRequest; farthestDistance = curDistance; } } farthestRequest.Dispose(); farthestRequest.QuadTile.DownloadRequest = null; m_downloadRequests.Remove(farthestRequest.QuadTile); } } ServiceDownloadQueue(); }
public virtual void Dispose() { try { isInitialized = false; if (texture != null && !texture.Disposed) { texture.Dispose(); texture = null; } if (northWestChild != null) { northWestChild.Dispose(); northWestChild = null; } if (southWestChild != null) { southWestChild.Dispose(); southWestChild = null; } if (northEastChild != null) { northEastChild.Dispose(); northEastChild = null; } if (southEastChild != null) { southEastChild.Dispose(); southEastChild = null; } if (DownloadRequest != null) { QuadTileSet.RemoveFromDownloadQueue(DownloadRequest); DownloadRequest.Dispose(); DownloadRequest = null; } } catch {} }
/// <summary> /// Render one of the 4 quadrants with optional download indicator /// </summary> private void Render(Device device, CustomVertex.PositionTextured[] verts, QuadTile child) { bool isMultitexturing = false; if (World.Settings.ShowDownloadIndicator && child != null) { // Check/display download activity GeoSpatialDownloadRequest request = child.DownloadRequest; if (child.isDownloadingTerrain) { device.SetTexture(1, QuadTileSet.DownloadTerrainTexture); isMultitexturing = true; } //else if (request != null) else if (child.WaitingForDownload) { if (child.IsDownloadingImage) { device.SetTexture(1, QuadTileSet.DownloadInProgressTexture); } else { device.SetTexture(1, QuadTileSet.DownloadQueuedTexture); } isMultitexturing = true; } } if (isMultitexturing) { device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int) TextureOperation.BlendTextureAlpha); } if (verts != null && vertexIndexes != null) { device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, verts.Length, vertexIndexes.Length/3, vertexIndexes, true, verts); } if (isMultitexturing) { device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int) TextureOperation.Disable); } }
/// <summary> /// Returns the QuadTile for specified location if available. /// Tries to queue a download if not available. /// </summary> /// <returns>Initialized QuadTile if available locally, else null.</returns> private QuadTile ComputeChild(double childSouth, double childNorth, double childWest, double childEast) { QuadTile child = new QuadTile(childSouth, childNorth, childWest, childEast, this.Level + 1, QuadTileSet); return(child); }
public override void Update(DrawArgs drawArgs) { if (!isInitialized) Initialize(drawArgs); if (m_effectPath != null && m_effect == null) { string errs = string.Empty; m_effect = Effect.FromFile(DrawArgs.Device, m_effectPath, null, "", ShaderFlags.None, m_effectPool, out errs); if (errs != null && errs != string.Empty) { Log.Write(Log.Levels.Warning, "Could not load effect " + m_effectPath + ": " + errs); Log.Write(Log.Levels.Warning, "Effect has been disabled."); m_effectPath = null; m_effect = null; } } if (ImageStores[0].LevelZeroTileSizeDegrees < 180) { // Check for layer outside view double vrd = DrawArgs.Camera.ViewRange.Degrees; double latitudeMax = DrawArgs.Camera.Latitude.Degrees + vrd; double latitudeMin = DrawArgs.Camera.Latitude.Degrees - vrd; double longitudeMax = DrawArgs.Camera.Longitude.Degrees + vrd; double longitudeMin = DrawArgs.Camera.Longitude.Degrees - vrd; if (latitudeMax < m_south || latitudeMin > m_north || longitudeMax < m_west || longitudeMin > m_east) return; } if (DrawArgs.Camera.ViewRange * 0.5f > Angle.FromDegrees(TileDrawDistance * ImageStores[0].LevelZeroTileSizeDegrees)) { lock (m_topmostTiles.SyncRoot) { foreach (QuadTile qt in m_topmostTiles.Values) qt.Dispose(); m_topmostTiles.Clear(); ClearDownloadRequests(); } return; } RemoveInvisibleTiles(DrawArgs.Camera); try { int middleRow = MathEngine.GetRowFromLatitude(DrawArgs.Camera.Latitude, ImageStores[0].LevelZeroTileSizeDegrees); int middleCol = MathEngine.GetColFromLongitude(DrawArgs.Camera.Longitude, ImageStores[0].LevelZeroTileSizeDegrees); double middleSouth = -90.0f + middleRow * ImageStores[0].LevelZeroTileSizeDegrees; double middleNorth = -90.0f + middleRow * ImageStores[0].LevelZeroTileSizeDegrees + ImageStores[0].LevelZeroTileSizeDegrees; double middleWest = -180.0f + middleCol * ImageStores[0].LevelZeroTileSizeDegrees; double middleEast = -180.0f + middleCol * ImageStores[0].LevelZeroTileSizeDegrees + ImageStores[0].LevelZeroTileSizeDegrees; double middleCenterLat = 0.5f * (middleNorth + middleSouth); double middleCenterLon = 0.5f * (middleWest + middleEast); int tileSpread = 4; for (int i = 0; i < tileSpread; i++) { for (double j = middleCenterLat - i * ImageStores[0].LevelZeroTileSizeDegrees; j < middleCenterLat + i * ImageStores[0].LevelZeroTileSizeDegrees; j += ImageStores[0].LevelZeroTileSizeDegrees) { for (double k = middleCenterLon - i * ImageStores[0].LevelZeroTileSizeDegrees; k < middleCenterLon + i * ImageStores[0].LevelZeroTileSizeDegrees; k += ImageStores[0].LevelZeroTileSizeDegrees) { int curRow = MathEngine.GetRowFromLatitude(Angle.FromDegrees(j), ImageStores[0].LevelZeroTileSizeDegrees); int curCol = MathEngine.GetColFromLongitude(Angle.FromDegrees(k), ImageStores[0].LevelZeroTileSizeDegrees); long key = ((long)curRow << 32) + curCol; QuadTile qt = (QuadTile)m_topmostTiles[key]; if (qt != null) { qt.Update(drawArgs); continue; } // Check for tile outside layer boundaries double west = -180.0f + curCol * ImageStores[0].LevelZeroTileSizeDegrees; if (west > m_east) continue; double east = west + ImageStores[0].LevelZeroTileSizeDegrees; if (east < m_west) continue; double south = -90.0f + curRow * ImageStores[0].LevelZeroTileSizeDegrees; if (south > m_north) continue; double north = south + ImageStores[0].LevelZeroTileSizeDegrees; if (north < m_south) continue; qt = new QuadTile(south, north, west, east, 0, this); if (DrawArgs.Camera.ViewFrustum.Intersects(qt.BoundingBox)) { lock (m_topmostTiles.SyncRoot) m_topmostTiles.Add(key, qt); qt.Update(drawArgs); } } } } } catch (System.Threading.ThreadAbortException) { } catch (Exception caught) { Log.Write(caught); } }
/// <summary> /// Render one of the 4 quadrants with optional download indicator /// </summary> private void Render(Device device, CustomVertex.PositionNormalTextured[] verts, QuadTile child) { bool isMultitexturing = false; if (!World.Settings.EnableSunShading) { if (World.Settings.ShowDownloadIndicator && child != null) { // Check/display download activity //GeoSpatialDownloadRequest request = child.DownloadRequest; if (child.isDownloadingTerrain) { device.SetTexture(1, QuadTileSet.DownloadTerrainTexture); isMultitexturing = true; } //else if (request != null) else if (child.WaitingForDownload) { if (child.IsDownloadingImage) device.SetTexture(1, QuadTileSet.DownloadInProgressTexture); else device.SetTexture(1, QuadTileSet.DownloadQueuedTexture); isMultitexturing = true; } } } if (isMultitexturing) device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int)TextureOperation.BlendTextureAlpha); if (verts != null && vertexIndexes != null) { if (quadTileSet.Effect != null) { Effect effect = quadTileSet.Effect; int tc1 = device.GetTextureStageStateInt32(1, TextureStageStates.TextureCoordinateIndex); device.SetTextureStageState(1, TextureStageStates.TextureCoordinateIndex, 1); // FIXME: just use the first technique for now effect.Technique = effect.GetTechnique(0); EffectHandle param; param = (EffectHandle)quadTileSet.EffectParameters["WorldViewProj"]; if (param != null) effect.SetValue(param, Matrix.Multiply(device.Transform.World, Matrix.Multiply(device.Transform.View, device.Transform.Projection))); try { param = (EffectHandle)quadTileSet.EffectParameters["World"]; if (param != null) effect.SetValue(param, device.Transform.World); param = (EffectHandle)quadTileSet.EffectParameters["ViewInverse"]; if (param != null) { Matrix viewInv = Matrix.Invert(device.Transform.View); effect.SetValue(param, viewInv); } // set textures as available for (int i = 0; i < textures.Length; i++) { string name = string.Format("Tex{0}", i); param = (EffectHandle)quadTileSet.EffectParameters[name]; if (param != null) { effect.SetValue(param, textures[i]); } } // brightness & opacity values param = (EffectHandle)quadTileSet.EffectParameters["Brightness"]; if (param != null) effect.SetValue(param, quadTileSet.GrayscaleBrightness); param = (EffectHandle)quadTileSet.EffectParameters["Opacity"]; if (param != null) { float opacity = (float)quadTileSet.Opacity / 255.0f; effect.SetValue(param, opacity); } param = (EffectHandle)quadTileSet.EffectParameters["LayerRadius"]; if (param != null) { effect.SetValue(param, (float)quadTileSet.LayerRadius); } param = (EffectHandle)quadTileSet.EffectParameters["TileLevel"]; if (param != null) { effect.SetValue(param, level); } param = (EffectHandle)quadTileSet.EffectParameters["LocalOrigin"]; if (param != null) { effect.SetValue(param, localOrigin.Vector4); } // sun position param = (EffectHandle)quadTileSet.EffectParameters["LightDirection"]; if (param != null) { Point3d sunPosition = SunCalculator.GetGeocentricPosition(TimeKeeper.CurrentTimeUtc); sunPosition.normalize(); Vector4 sunVector = new Vector4( (float)sunPosition.X, (float)sunPosition.Y, (float)sunPosition.Z, 0.0f); effect.SetValue(param, sunVector); } // local origin param = (EffectHandle)quadTileSet.EffectParameters["LocalFrameOrigin"]; if (param != null) { //localOrigin = BoundingBox.CalculateCenter(); Point3d centerPoint = MathEngine.SphericalToCartesian(centerLatitude, centerLongitude, quadTileSet.LayerRadius); Point3d northHalf = MathEngine.SphericalToCartesian(Angle.FromDegrees(north), centerLongitude, quadTileSet.LayerRadius); Point3d eastHalf = MathEngine.SphericalToCartesian(centerLatitude, Angle.FromDegrees(east), quadTileSet.LayerRadius); Vector4 xdir = (2 * (eastHalf - centerPoint)).Vector4; Vector4 ydir = (2 * (northHalf - centerPoint)).Vector4; // up vector is radius at center point, normalized Point3d zdir3 = centerPoint; zdir3.normalize(); Vector4 zdir = zdir3.Vector4; // local frame origin at SW corner, relative to local origin Point3d localFrameOrigin = northHalf + eastHalf - centerPoint - localOrigin; Vector4 lfoW = localFrameOrigin.Vector4; lfoW.W = 1; lfoW.Transform(device.Transform.World); effect.SetValue(param, localFrameOrigin.Vector4); // JBTODO: Should this be lfoW? param = (EffectHandle)quadTileSet.EffectParameters["LocalFrameXAxis"]; if (param != null) effect.SetValue(param, xdir); param = (EffectHandle)quadTileSet.EffectParameters["LocalFrameYAxis"]; if (param != null) effect.SetValue(param, ydir); param = (EffectHandle)quadTileSet.EffectParameters["LocalFrameZAxis"]; if (param != null) effect.SetValue(param, zdir); } } catch { } int numPasses = effect.Begin(0); for (int i = 0; i < numPasses; i++) { effect.BeginPass(i); device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, verts.Length, vertexIndexes.Length / 3, vertexIndexes, true, verts); effect.EndPass(); } effect.End(); device.SetTextureStageState(1, TextureStageStates.TextureCoordinateIndex, tc1); } else { if (World.Settings.EnableSunShading) { Point3d sunPosition = SunCalculator.GetGeocentricPosition(TimeKeeper.CurrentTimeUtc); Vector3 sunVector = new Vector3( (float)sunPosition.X, (float)sunPosition.Y, (float)sunPosition.Z); device.RenderState.Lighting = true; Material material = new Material(); material.Diffuse = Color.White; material.Ambient = Color.White; device.Material = material; device.RenderState.AmbientColor = World.Settings.ShadingAmbientColor.ToArgb(); device.RenderState.NormalizeNormals = true; device.RenderState.AlphaBlendEnable = true; device.Lights[0].Enabled = true; device.Lights[0].Type = LightType.Directional; device.Lights[0].Diffuse = LightColor; device.Lights[0].Direction = sunVector; device.TextureState[0].ColorOperation = TextureOperation.Modulate; device.TextureState[0].ColorArgument1 = TextureArgument.Diffuse; device.TextureState[0].ColorArgument2 = TextureArgument.TextureColor; } else { device.RenderState.Lighting = false; device.RenderState.Ambient = World.Settings.StandardAmbientColor; } device.RenderState.TextureFactor = Color.FromArgb(m_CurrentOpacity, 255, 255, 255).ToArgb(); device.TextureState[0].AlphaOperation = TextureOperation.Modulate; device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor; device.TextureState[0].AlphaArgument2 = TextureArgument.TFactor; device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, verts.Length, vertexIndexes.Length / 3, vertexIndexes, true, verts); device.RenderState.TextureFactor = Color.FromArgb(255, 255, 255, 255).ToArgb(); } } if (isMultitexturing) device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int)TextureOperation.Disable); }
private void QueueDownload(QuadTile qt, string filePath) { string url = GetDownloadUrl(qt); qt.QuadTileSet.AddToDownloadQueue(qt.QuadTileSet.Camera, new GeoSpatialDownloadRequest(qt, filePath, url)); }
/// <summary> /// ����ͼƬ������ص�ַ�������ͼ���������ظ�ͼƬ·��������ֱ�ӵ�������������أ�������Ҫ��д�÷����� /// </summary> protected virtual string GetDownloadUrl(QuadTile qt) { // No local image, return our "duplicate" tile if any if (_duplicateTexturePath != null && File.Exists(_duplicateTexturePath)) { return _duplicateTexturePath; } // No image available anywhere, give up return string.Empty; }
public override void Update(DrawArgs drawArgs) { if (!Inited) { Initialize(drawArgs); } if (ImageStore.LevelZeroTileSizeDegrees < 180) { // Check for layer outside view double vrd = DrawArgs.Camera.ViewRange.Degrees; double latitudeMax = DrawArgs.Camera.Latitude.Degrees + vrd; double latitudeMin = DrawArgs.Camera.Latitude.Degrees - vrd; double longitudeMax = DrawArgs.Camera.Longitude.Degrees + vrd; double longitudeMin = DrawArgs.Camera.Longitude.Degrees - vrd; if (latitudeMax < m_south || latitudeMin > m_north || longitudeMax < m_west || longitudeMin > m_east) { return; } } if (DrawArgs.Camera.ViewRange*0.5f > Angle.FromDegrees(TileDrawDistance*ImageStore.LevelZeroTileSizeDegrees)) { lock (m_topmostTiles.SyncRoot) { foreach (QuadTile qt in m_topmostTiles.Values) { qt.Dispose(); } m_topmostTiles.Clear(); ClearDownloadRequests(); } return; } RemoveInvisibleTiles(DrawArgs.Camera); try { int middleRow = MathEngine.GetRowFromLatitude(DrawArgs.Camera.Latitude, ImageStore.LevelZeroTileSizeDegrees); int middleCol = MathEngine.GetColFromLongitude(DrawArgs.Camera.Longitude, ImageStore.LevelZeroTileSizeDegrees); double middleSouth = -90.0f + middleRow*ImageStore.LevelZeroTileSizeDegrees; double middleNorth = -90.0f + middleRow*ImageStore.LevelZeroTileSizeDegrees + ImageStore.LevelZeroTileSizeDegrees; double middleWest = -180.0f + middleCol*ImageStore.LevelZeroTileSizeDegrees; double middleEast = -180.0f + middleCol*ImageStore.LevelZeroTileSizeDegrees + ImageStore.LevelZeroTileSizeDegrees; double middleCenterLat = 0.5f*(middleNorth + middleSouth); double middleCenterLon = 0.5f*(middleWest + middleEast); int tileSpread = 4; for (int i = 0; i < tileSpread; i++) { for (double j = middleCenterLat - i*ImageStore.LevelZeroTileSizeDegrees; j < middleCenterLat + i*ImageStore.LevelZeroTileSizeDegrees; j += ImageStore.LevelZeroTileSizeDegrees) { for (double k = middleCenterLon - i*ImageStore.LevelZeroTileSizeDegrees; k < middleCenterLon + i*ImageStore.LevelZeroTileSizeDegrees; k += ImageStore.LevelZeroTileSizeDegrees) { int curRow = MathEngine.GetRowFromLatitude(Angle.FromDegrees(j), ImageStore.LevelZeroTileSizeDegrees); int curCol = MathEngine.GetColFromLongitude(Angle.FromDegrees(k), ImageStore.LevelZeroTileSizeDegrees); long key = ((long) curRow << 32) + curCol; QuadTile qt = (QuadTile) m_topmostTiles[key]; if (qt != null) { qt.Update(drawArgs); continue; } // Check for tile outside layer boundaries double west = -180.0f + curCol*ImageStore.LevelZeroTileSizeDegrees; if (west > m_east) { continue; } double east = west + ImageStore.LevelZeroTileSizeDegrees; if (east < m_west) { continue; } double south = -90.0f + curRow*ImageStore.LevelZeroTileSizeDegrees; if (south > m_north) { continue; } double north = south + ImageStore.LevelZeroTileSizeDegrees; if (north < m_south) { continue; } qt = new QuadTile(south, north, west, east, 0, this); if (DrawArgs.Camera.ViewFrustum.Intersects(qt.BoundingBox)) { lock (m_topmostTiles.SyncRoot) m_topmostTiles.Add(key, qt); qt.Update(drawArgs); } } } } } catch (ThreadAbortException) {} catch (Exception caught) { Log.Write(caught); } }
public virtual void Dispose() { isInitialized = false; if (textures != null) { for (int i = 0; i < textures.Length; i++) { if (textures[i] != null && !textures[i].Disposed) { textures[i].Dispose(); textures[i] = null; } } } if (northWestChild != null) { northWestChild.Dispose(); northWestChild = null; } if (southWestChild != null) { southWestChild.Dispose(); southWestChild = null; } if (northEastChild != null) { northEastChild.Dispose(); northEastChild = null; } if (southEastChild != null) { southEastChild.Dispose(); southEastChild = null; } if (downloadRequests != null) { foreach (GeoSpatialDownloadRequest request in downloadRequests) { quadTileSet.RemoveFromDownloadQueue(request, false); request.Dispose(); } downloadRequests.Clear(); } }
public virtual void Dispose() { try { isInitialized = false; for (int i = 0; i < textures.Length; i++) { if (textures[i] != null && !textures[i].Disposed) { textures[i].Dispose(); textures[i] = null; } } textures = null; if (northWestChild != null) { northWestChild.Dispose(); northWestChild = null; } if (southWestChild != null) { southWestChild.Dispose(); southWestChild = null; } if (northEastChild != null) { northEastChild.Dispose(); northEastChild = null; } if (southEastChild != null) { southEastChild.Dispose(); southEastChild = null; } if(DownloadRequest != null) { QuadTileSet.RemoveFromDownloadQueue(DownloadRequest); DownloadRequest.Dispose(); DownloadRequest = null; } } catch { } }
/// <summary> /// Returns the QuadTile for specified location if available. /// Tries to queue a download if not available. /// </summary> /// <returns>Initialized QuadTile if available locally, else null.</returns> private QuadTile ComputeChild(double childSouth, double childNorth, double childWest, double childEast) { QuadTile child = new QuadTile( childSouth, childNorth, childWest, childEast, this.Level + 1, QuadTileSet); return child; }
internal virtual void ComputeChildren(DrawArgs drawArgs) { if (level + 1 >= quadTileSet.ImageStores[0].LevelCount) return; double CenterLat = 0.5f * (south + north); double CenterLon = 0.5f * (east + west); if (northWestChild == null) northWestChild = ComputeChild(CenterLat, north, west, CenterLon); if (northEastChild == null) northEastChild = ComputeChild(CenterLat, north, CenterLon, east); if (southWestChild == null) southWestChild = ComputeChild(south, CenterLat, west, CenterLon); if (southEastChild == null) southEastChild = ComputeChild(south, CenterLat, CenterLon, east); }
protected override string GetDownloadUrl(QuadTile qt) { if (m_serverGetMapUrl.IndexOf('?') >= 0) { // Allow custom format string url // http://server.net/path?imageformat=png&width={WIDTH}&north={NORTH}... string url = m_serverGetMapUrl; url = url.Replace("{WIDTH}", m_textureSizePixels.ToString(CultureInfo.InvariantCulture)); url = url.Replace("{HEIGHT}", m_textureSizePixels.ToString(CultureInfo.InvariantCulture)); url = url.Replace("{WEST}", qt.West.ToString(CultureInfo.InvariantCulture)); url = url.Replace("{EAST}", qt.East.ToString(CultureInfo.InvariantCulture)); url = url.Replace("{NORTH}", qt.North.ToString(CultureInfo.InvariantCulture)); url = url.Replace("{SOUTH}", qt.South.ToString(CultureInfo.InvariantCulture)); return url; } else { string url = string.Format(CultureInfo.InvariantCulture, "{0}?request=GetMap&layers={1}&srs=EPSG:4326&width={2}&height={3}&bbox={4},{5},{6},{7}&format={8}&version={9}&styles={10}", m_serverGetMapUrl, m_wmsLayerName, m_textureSizePixels, m_textureSizePixels, qt.West, qt.South, qt.East, qt.North, m_imageFormat, m_version, m_wmsLayerStyle); return url; } }
/// <summary> /// ����һ��QuadTile������һ��Texture /// </summary> /// <param name="qt"></param> /// <returns></returns> public Texture LoadFile(QuadTile qt) { string filePath = GetLocalPath(qt); qt.ImageFilePath = filePath; if (!File.Exists(filePath)) { // �ļ�����ǣ� string badFlag = filePath + ".txt"; if (File.Exists(badFlag)) { FileInfo fi = new FileInfo(badFlag); if (DateTime.Now - fi.LastWriteTime < TimeSpan.FromDays(1)) { // δ���ڣ����ܻ������ض����� return null; } // Timeout period elapsed, retry File.Delete(badFlag); } if (IsDownloadableLayer) { // ���ͼ���ܹ������أ������¿�ʼ���� QueueDownload(qt, filePath); return null; } if (DuplicateTexturePath == null) { // No image available, neither local nor online. return null; } filePath = DuplicateTexturePath; } // Use color key Texture texture = null; if (qt.QuadTileSet.HasTransparentRange) { texture = ImageHelper.LoadTexture(filePath, qt.QuadTileSet.ColorKey, qt.QuadTileSet.ColorKeyMax); } else { texture = ImageHelper.LoadTexture(filePath, qt.QuadTileSet.ColorKey); } if (qt.QuadTileSet.CacheExpirationTime != TimeSpan.MaxValue) { FileInfo fi = new FileInfo(filePath); DateTime expiry = fi.LastWriteTimeUtc.Add(qt.QuadTileSet.CacheExpirationTime); if (DateTime.UtcNow > expiry) { QueueDownload(qt, filePath); } } if (World.Settings.ConvertDownloadedImagesToDds) { ConvertImage(texture, filePath); } return texture; }
/// <summary> /// Updates this layer (background) /// </summary> public virtual void Update(DrawArgs drawArgs) { if (m_isResetingCache) { return; } try { double tileSize = North - South; if (!isInitialized) { if (DrawArgs.Camera.ViewRange * 0.5f < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize) && MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize * 1.25f) && DrawArgs.Camera.ViewFrustum.Intersects(BoundingBox)) { Initialize(); } } if (isInitialized && World.Settings.VerticalExaggeration != verticalExaggeration || m_CurrentOpacity != QuadTileSet.Opacity || QuadTileSet.RenderStruts != renderStruts) { CreateTileMesh(); } if (isInitialized) { if (DrawArgs.Camera.ViewRange < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize) && MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize) && DrawArgs.Camera.ViewFrustum.Intersects(BoundingBox)) { if (northEastChild == null || northWestChild == null || southEastChild == null || southWestChild == null) { ComputeChildren(drawArgs); } if (northEastChild != null) { northEastChild.Update(drawArgs); } if (northWestChild != null) { northWestChild.Update(drawArgs); } if (southEastChild != null) { southEastChild.Update(drawArgs); } if (southWestChild != null) { southWestChild.Update(drawArgs); } } else { if (northWestChild != null) { northWestChild.Dispose(); northWestChild = null; } if (northEastChild != null) { northEastChild.Dispose(); northEastChild = null; } if (southEastChild != null) { southEastChild.Dispose(); southEastChild = null; } if (southWestChild != null) { southWestChild.Dispose(); southWestChild = null; } } } if (isInitialized) { if (DrawArgs.Camera.ViewRange / 2 > Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize * 1.5f) || MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) > Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize * 1.5f)) { if (Level != 0 || (Level == 0 && !QuadTileSet.AlwaysRenderBaseTiles)) { this.Dispose(); } } } } catch {} }
public override void Update(DrawArgs drawArgs) { if (!isInitialized) { Initialize(drawArgs); } if (m_effectPath != null && m_effect == null) { string errs = string.Empty; m_effect = Effect.FromFile(DrawArgs.Device, m_effectPath, null, "", ShaderFlags.None, m_effectPool, out errs); if (errs != null && errs != string.Empty) { Log.Write(Log.Levels.Warning, "Could not load effect " + m_effectPath + ": " + errs); Log.Write(Log.Levels.Warning, "Effect has been disabled."); m_effectPath = null; m_effect = null; } } if (ImageStores[0].LevelZeroTileSizeDegrees < 180) { // Check for layer outside view double vrd = DrawArgs.Camera.ViewRange.Degrees; double latitudeMax = DrawArgs.Camera.Latitude.Degrees + vrd; double latitudeMin = DrawArgs.Camera.Latitude.Degrees - vrd; double longitudeMax = DrawArgs.Camera.Longitude.Degrees + vrd; double longitudeMin = DrawArgs.Camera.Longitude.Degrees - vrd; if (latitudeMax < m_south || latitudeMin > m_north || longitudeMax < m_west || longitudeMin > m_east) { return; } } if (DrawArgs.Camera.ViewRange * 0.5f > Angle.FromDegrees(TileDrawDistance * ImageStores[0].LevelZeroTileSizeDegrees)) { lock (m_topmostTiles.SyncRoot) { foreach (QuadTile qt in m_topmostTiles.Values) { qt.Dispose(); } m_topmostTiles.Clear(); ClearDownloadRequests(); } return; } RemoveInvisibleTiles(DrawArgs.Camera); try { int middleRow = MathEngine.GetRowFromLatitude(DrawArgs.Camera.Latitude, ImageStores[0].LevelZeroTileSizeDegrees); int middleCol = MathEngine.GetColFromLongitude(DrawArgs.Camera.Longitude, ImageStores[0].LevelZeroTileSizeDegrees); double middleSouth = -90.0f + middleRow * ImageStores[0].LevelZeroTileSizeDegrees; double middleNorth = -90.0f + middleRow * ImageStores[0].LevelZeroTileSizeDegrees + ImageStores[0].LevelZeroTileSizeDegrees; double middleWest = -180.0f + middleCol * ImageStores[0].LevelZeroTileSizeDegrees; double middleEast = -180.0f + middleCol * ImageStores[0].LevelZeroTileSizeDegrees + ImageStores[0].LevelZeroTileSizeDegrees; double middleCenterLat = 0.5f * (middleNorth + middleSouth); double middleCenterLon = 0.5f * (middleWest + middleEast); int tileSpread = 4; for (int i = 0; i < tileSpread; i++) { for (double j = middleCenterLat - i * ImageStores[0].LevelZeroTileSizeDegrees; j < middleCenterLat + i * ImageStores[0].LevelZeroTileSizeDegrees; j += ImageStores[0].LevelZeroTileSizeDegrees) { for (double k = middleCenterLon - i * ImageStores[0].LevelZeroTileSizeDegrees; k < middleCenterLon + i * ImageStores[0].LevelZeroTileSizeDegrees; k += ImageStores[0].LevelZeroTileSizeDegrees) { int curRow = MathEngine.GetRowFromLatitude(Angle.FromDegrees(j), ImageStores[0].LevelZeroTileSizeDegrees); int curCol = MathEngine.GetColFromLongitude(Angle.FromDegrees(k), ImageStores[0].LevelZeroTileSizeDegrees); long key = ((long)curRow << 32) + curCol; QuadTile qt = (QuadTile)m_topmostTiles[key]; if (qt != null) { qt.Update(drawArgs); continue; } // Check for tile outside layer boundaries double west = -180.0f + curCol * ImageStores[0].LevelZeroTileSizeDegrees; if (west > m_east) { continue; } double east = west + ImageStores[0].LevelZeroTileSizeDegrees; if (east < m_west) { continue; } double south = -90.0f + curRow * ImageStores[0].LevelZeroTileSizeDegrees; if (south > m_north) { continue; } double north = south + ImageStores[0].LevelZeroTileSizeDegrees; if (north < m_south) { continue; } qt = new QuadTile(south, north, west, east, 0, this); if (DrawArgs.Camera.ViewFrustum.Intersects(qt.BoundingBox)) { lock (m_topmostTiles.SyncRoot) m_topmostTiles.Add(key, qt); qt.Update(drawArgs); } } } } } catch (System.Threading.ThreadAbortException) { } catch (Exception caught) { Log.Write(caught); } }
/// <summary> /// Render one of the 4 quadrants with optional download indicator /// </summary> void Render(Device device, CustomVertex.PositionNormalTextured[] verts, QuadTile child) { bool isMultitexturing = false; if(!World.Settings.EnableSunShading) { if (World.Settings.ShowDownloadIndicator && child != null) { // Check/display download activity GeoSpatialDownloadRequest request = child.DownloadRequest; if (child.isDownloadingTerrain) { device.SetTexture(1, QuadTileSet.DownloadTerrainTexture); isMultitexturing = true; } //else if (request != null) else if(child.WaitingForDownload) { if (child.IsDownloadingImage) device.SetTexture(1, QuadTileSet.DownloadInProgressTexture); else device.SetTexture(1, QuadTileSet.DownloadQueuedTexture); isMultitexturing = true; } } } if (isMultitexturing) device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int)TextureOperation.BlendTextureAlpha); if(verts != null && vertexIndexes != null) { if (QuadTileSet.Effect != null) { Effect effect = QuadTileSet.Effect; // FIXME: just use the first technique for now effect.Technique = effect.GetTechnique(0); effect.SetValue("WorldViewProj", Matrix.Multiply(device.Transform.World, Matrix.Multiply(device.Transform.View, device.Transform.Projection))); try { effect.SetValue("Tex0", textures[0]); effect.SetValue("Tex1", textures[1]); effect.SetValue("Brightness", QuadTileSet.GrayscaleBrightness); float opacity = (float)QuadTileSet.Opacity / 255.0f; effect.SetValue("Opacity", opacity); } catch { } int numPasses = effect.Begin(0); for (int i = 0; i < numPasses; i++) { effect.BeginPass(i); device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, verts.Length, vertexIndexes.Length / 3, vertexIndexes, true, verts); effect.EndPass(); } effect.End(); } else if (!QuadTileSet.RenderGrayscale || (device.DeviceCaps.PixelShaderVersion.Major < 1)) { if (World.Settings.EnableSunShading) { Point3d sunPosition = SunCalculator.GetGeocentricPosition(TimeKeeper.CurrentTimeUtc); Vector3 sunVector = new Vector3( (float)sunPosition.X, (float)sunPosition.Y, (float)sunPosition.Z); device.RenderState.Lighting = true; Material material = new Material(); material.Diffuse = System.Drawing.Color.White; material.Ambient = System.Drawing.Color.White; device.Material = material; device.RenderState.AmbientColor = World.Settings.ShadingAmbientColor.ToArgb(); device.RenderState.NormalizeNormals = true; device.RenderState.AlphaBlendEnable = true; device.Lights[0].Enabled = true; device.Lights[0].Type = LightType.Directional; device.Lights[0].Diffuse = System.Drawing.Color.White; device.Lights[0].Direction = sunVector; device.TextureState[0].ColorOperation = TextureOperation.Modulate; device.TextureState[0].ColorArgument1 = TextureArgument.Diffuse; device.TextureState[0].ColorArgument2 = TextureArgument.TextureColor; } else { device.RenderState.Lighting = false; device.RenderState.Ambient = World.Settings.StandardAmbientColor; } device.RenderState.TextureFactor = System.Drawing.Color.FromArgb(m_CurrentOpacity, 0, 0, 0).ToArgb(); device.TextureState[0].AlphaOperation = TextureOperation.BlendFactorAlpha; device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor; device.TextureState[0].AlphaArgument2 = TextureArgument.TFactor; device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, verts.Length, vertexIndexes.Length / 3, vertexIndexes, true, verts); } else { if (grayscaleEffect == null) { device.DeviceReset += new EventHandler(device_DeviceReset); device_DeviceReset(device, null); } grayscaleEffect.Technique = "RenderGrayscaleBrightness"; grayscaleEffect.SetValue("WorldViewProj", Matrix.Multiply(device.Transform.World, Matrix.Multiply(device.Transform.View, device.Transform.Projection))); grayscaleEffect.SetValue("Tex0", textures[0]); grayscaleEffect.SetValue("Brightness", QuadTileSet.GrayscaleBrightness); float opacity = (float)QuadTileSet.Opacity / 255.0f; grayscaleEffect.SetValue("Opacity", opacity); int numPasses = grayscaleEffect.Begin(0); for (int i = 0; i < numPasses; i++) { grayscaleEffect.BeginPass(i); device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, verts.Length, vertexIndexes.Length / 3, vertexIndexes, true, verts); grayscaleEffect.EndPass(); } grayscaleEffect.End(); } } if (isMultitexturing) device.SetTextureStageState(1, TextureStageStates.ColorOperation, (int)TextureOperation.Disable); }
public virtual string GetLocalPath(QuadTile qt) { if(qt.Level >= m_levelCount) throw new ArgumentException(string.Format("Level {0} not available.", qt.Level)); string relativePath = String.Format(@"{0}\{1:D4}\{1:D4}_{2:D4}.{3}", qt.Level, qt.Row, qt.Col, m_imageFileExtension); if(m_dataDirectory != null) { // Search data directory first string rawFullPath = Path.Combine( m_dataDirectory, relativePath ); if(File.Exists(rawFullPath)) return rawFullPath; } // If cache doesn't exist, fall back to duplicate texture path. if (m_cacheDirectory == null) return m_duplicateTexturePath; // Try cache with default file extension string cacheFullPath = Path.Combine( m_cacheDirectory, relativePath ); if(File.Exists(cacheFullPath)) return cacheFullPath; // Try cache but accept any valid image file extension const string ValidExtensions = ".bmp.dds.dib.hdr.jpg.jpeg.pfm.png.ppm.tga.gif.tif"; string cacheSearchPath = Path.GetDirectoryName(cacheFullPath); if(Directory.Exists(cacheSearchPath)) { foreach( string imageFile in Directory.GetFiles( cacheSearchPath, Path.GetFileNameWithoutExtension(cacheFullPath) + ".*") ) { string extension = Path.GetExtension(imageFile).ToLower(); if(ValidExtensions.IndexOf(extension)<0) continue; return imageFile; } } return cacheFullPath; }
public virtual void ComputeChildren(DrawArgs drawArgs) { if (Level + 1 >= QuadTileSet.ImageStores[0].LevelCount) return; double CenterLat = 0.5f * (South + North); double CenterLon = 0.5f * (East + West); if (northWestChild == null) northWestChild = ComputeChild(CenterLat, North, West, CenterLon); if (northEastChild == null) northEastChild = ComputeChild(CenterLat, North, CenterLon, East); if (southWestChild == null) southWestChild = ComputeChild(South, CenterLat, West, CenterLon); if (southEastChild == null) southEastChild = ComputeChild(South, CenterLat, CenterLon, East); }
/// <summary> /// ɾ��ͼƬ��ı��ذ汾 /// </summary> /// <param name="qt"></param> public virtual void DeleteLocalCopy(QuadTile qt) { string filename = GetLocalPath(qt); if (File.Exists(filename)) { File.Delete(filename); } }
/// <summary> /// Updates this layer (background) /// </summary> public virtual void Update(DrawArgs drawArgs) { if (m_isResetingCache) return; try { double tileSize = North - South; if (!isInitialized) { if (DrawArgs.Camera.ViewRange * 0.5f < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize) && MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize * 1.25f) && DrawArgs.Camera.ViewFrustum.Intersects(BoundingBox) ) Initialize(); } if (isInitialized && World.Settings.VerticalExaggeration != verticalExaggeration || m_CurrentOpacity != QuadTileSet.Opacity || QuadTileSet.RenderStruts != renderStruts) { CreateTileMesh(); } if (isInitialized) { if (DrawArgs.Camera.ViewRange < Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize) && MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) < Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize) && DrawArgs.Camera.ViewFrustum.Intersects(BoundingBox) ) { if (northEastChild == null || northWestChild == null || southEastChild == null || southWestChild == null) { ComputeChildren(drawArgs); } if (northEastChild != null) { northEastChild.Update(drawArgs); } if (northWestChild != null) { northWestChild.Update(drawArgs); } if (southEastChild != null) { southEastChild.Update(drawArgs); } if (southWestChild != null) { southWestChild.Update(drawArgs); } } else { if (northWestChild != null) { northWestChild.Dispose(); northWestChild = null; } if (northEastChild != null) { northEastChild.Dispose(); northEastChild = null; } if (southEastChild != null) { southEastChild.Dispose(); southEastChild = null; } if (southWestChild != null) { southWestChild.Dispose(); southWestChild = null; } } } if (isInitialized) { if (DrawArgs.Camera.ViewRange / 2 > Angle.FromDegrees(QuadTileSet.TileDrawDistance * tileSize * 1.5f) || MathEngine.SphericalDistance(CenterLatitude, CenterLongitude, DrawArgs.Camera.Latitude, DrawArgs.Camera.Longitude) > Angle.FromDegrees(QuadTileSet.TileDrawSpread * tileSize * 1.5f)) { if (Level != 0 || (Level == 0 && !QuadTileSet.AlwaysRenderBaseTiles)) this.Dispose(); } } } catch { } }
/// <summary> /// ��ȡ���ش洢��·�� /// </summary> /// <param name="qt">ͼ���е�һ��ͼƬ</param> /// <returns>ͼƬӦ�ñ���ı���·��</returns> public virtual string GetLocalPath(QuadTile qt) { if (qt.Level >= _levelCount) { throw new ArgumentException(string.Format("Level {0} not available.", qt.Level)); } string relativePath = String.Format(@"{0}\{1:D4}\{1:D4}_{2:D4}.{3}", qt.Level, qt.Row, qt.Col, _imageFileExtension); if (_dataDirectory != null) { // Search data directory first string rawFullPath = Path.Combine(_dataDirectory, relativePath); if (File.Exists(rawFullPath)) { return rawFullPath; } } // Try cache with default file extension string cacheFullPath = Path.Combine(_cacheDirectory, relativePath); if (File.Exists(cacheFullPath)) { return cacheFullPath; } // Try cache but accept any valid image file extension string cacheSearchPath = Path.GetDirectoryName(cacheFullPath); if (Directory.Exists(cacheSearchPath)) { foreach (string imageFile in Directory.GetFiles(cacheSearchPath, Path.GetFileNameWithoutExtension(cacheFullPath) + ".*")) { string extension = Path.GetExtension(imageFile).ToLower(); if (ValidExtensions.IndexOf(extension) < 0) { continue; } return imageFile; } } return cacheFullPath; }
protected override string GetDownloadUrl(QuadTile qt) { return string.Format(CultureInfo.InvariantCulture, "{0}?T={1}&L={2}&X={3}&Y={4}", m_serverUri, m_dataSetName, qt.Level, qt.Col, qt.Row); }
public override void Update(DrawArgs drawArgs) { if (!System.Threading.Thread.CurrentThread.Name.Equals(ThreadNames.WorldWindowBackground)) throw new System.InvalidOperationException("QTS.Update() must be called from WorkerThread!"); if (!isInitialized) Initialize(drawArgs); ServiceDownloadQueue(); if (m_effectEnabled && (m_effectPath != null) && !File.Exists(m_effectPath)) { Log.Write(Log.Levels.Warning, string.Format("Effect {0} not found - disabled", m_effectPath)); m_effectEnabled = false; } if (m_effectEnabled && m_effectPath != null && m_effect == null) { string errs = string.Empty; m_effectHandles.Clear(); try { Log.Write(Log.Levels.Warning, string.Format("Loading effect from {0}", m_effectPath)); m_effect = Effect.FromFile(DrawArgs.Device, m_effectPath, null, "", ShaderFlags.None, m_effectPool, out errs); // locate effect handles and store for rendering. m_effectHandles.Add("WorldViewProj", m_effect.GetParameter(null, "WorldViewProj")); m_effectHandles.Add("World", m_effect.GetParameter(null, "World")); m_effectHandles.Add("ViewInverse", m_effect.GetParameter(null, "ViewInverse")); for (int i = 0; i < 8; i++) { string name = string.Format("Tex{0}", i); m_effectHandles.Add(name, m_effect.GetParameter(null, name)); } m_effectHandles.Add("Brightness", m_effect.GetParameter(null, "Brightness")); m_effectHandles.Add("Opacity", m_effect.GetParameter(null, "Opacity")); m_effectHandles.Add("TileLevel", m_effect.GetParameter(null, "TileLevel")); m_effectHandles.Add("LightDirection", m_effect.GetParameter(null, "LightDirection")); m_effectHandles.Add("LocalOrigin", m_effect.GetParameter(null, "LocalOrigin")); m_effectHandles.Add("LayerRadius", m_effect.GetParameter(null, "LayerRadius")); m_effectHandles.Add("LocalFrameOrigin", m_effect.GetParameter(null, "LocalFrameOrigin")); m_effectHandles.Add("LocalFrameXAxis", m_effect.GetParameter(null, "LocalFrameXAxis")); m_effectHandles.Add("LocalFrameYAxis", m_effect.GetParameter(null, "LocalFrameYAxis")); m_effectHandles.Add("LocalFrameZAxis", m_effect.GetParameter(null, "LocalFrameZAxis")); } catch (Exception ex) { Log.Write(Log.Levels.Error, "Effect load caused exception:" + ex.ToString()); Log.Write(Log.Levels.Warning, "Effect has been disabled."); m_effectEnabled = false; } if (errs != null && errs != string.Empty) { Log.Write(Log.Levels.Warning, "Could not load effect " + m_effectPath + ": " + errs); Log.Write(Log.Levels.Warning, "Effect has been disabled."); m_effectEnabled = false; m_effect = null; } } if (ImageStores[0].LevelZeroTileSizeDegrees < 180) { // Check for layer outside view double vrd = DrawArgs.Camera.ViewRange.Degrees; double latitudeMax = DrawArgs.Camera.Latitude.Degrees + vrd; double latitudeMin = DrawArgs.Camera.Latitude.Degrees - vrd; double longitudeMax = DrawArgs.Camera.Longitude.Degrees + vrd; double longitudeMin = DrawArgs.Camera.Longitude.Degrees - vrd; if (latitudeMax < m_south || latitudeMin > m_north || longitudeMax < m_west || longitudeMin > m_east) return; } if (!m_alwaysRenderBaseTiles && DrawArgs.Camera.ViewRange * 0.5f > Angle.FromDegrees(TileDrawDistance * ImageStores[0].LevelZeroTileSizeDegrees)) { lock (((System.Collections.IDictionary)m_topmostTiles).SyncRoot) { // Don't dispose of the quadtiles like WorldWind does here (they may be nice to look at) // Do however clear the download requests /* foreach (QuadTile qt in m_topmostTiles.Values) qt.Dispose(); m_topmostTiles.Clear(); */ ClearDownloadRequests(); } return; } // 'Spiral' from the centre tile outward adding tiles that's in the view // Defer the updates to after the loop to prevent tiles from updating twice // If the tilespread is huge we are likely looking at a small dataset in the view // so just test all the tiles in the dataset. int iTileSpread = Math.Max(5, (int)Math.Ceiling(drawArgs.WorldCamera.TrueViewRange.Degrees / (2.0 * ImageStores[0].LevelZeroTileSizeDegrees))); int iMiddleRow, iMiddleCol; double dRowInc = ImageStores[0].LevelZeroTileSizeDegrees; double dColInc = ImageStores[0].LevelZeroTileSizeDegrees; if (iTileSpread > 10) { iTileSpread = Math.Max(5, (int)Math.Ceiling(Math.Max(North - South, East - West) / (2.0 * ImageStores[0].LevelZeroTileSizeDegrees))); iMiddleRow = MathEngine.GetRowFromLatitude(South + (North - South) / 2.0, ImageStores[0].LevelZeroTileSizeDegrees); iMiddleCol = MathEngine.GetColFromLongitude(West + (East - West) / 2.0, ImageStores[0].LevelZeroTileSizeDegrees); } else { iMiddleRow = MathEngine.GetRowFromLatitude(drawArgs.WorldCamera.Latitude, ImageStores[0].LevelZeroTileSizeDegrees); iMiddleCol = MathEngine.GetColFromLongitude(drawArgs.WorldCamera.Longitude, ImageStores[0].LevelZeroTileSizeDegrees); } // --- Calculate the bounding box of the middle tile, and from this, its latitude and longitude size --- double dMiddleSouth = -90.0f + iMiddleRow * dRowInc; double dMiddleNorth = -90.0f + iMiddleRow * dRowInc + dRowInc; double dMiddleWest = -180.0f + iMiddleCol * dColInc; double dMiddleEast = -180.0f + iMiddleCol * dColInc + dColInc; double dMiddleCenterLat = 0.5f * (dMiddleNorth + dMiddleSouth); double dMiddleCenterLon = 0.5f * (dMiddleWest + dMiddleEast); Dictionary<long, QuadTile> oTilesToUpdate = new Dictionary<long, QuadTile>(); // --- Create tiles radially outward from the center tile --- for (int iSpread = 0; iSpread < iTileSpread; iSpread++) { for (double dNewTileCenterLat = dMiddleCenterLat - iSpread * dRowInc; dNewTileCenterLat < dMiddleCenterLat + iSpread * dRowInc; dNewTileCenterLat += dRowInc) { for (double dNewTileCenterLon = dMiddleCenterLon - iSpread * dColInc; dNewTileCenterLon < dMiddleCenterLon + iSpread * dColInc; dNewTileCenterLon += dColInc) { QuadTile qt; int iCurRow = MathEngine.GetRowFromLatitude(Angle.FromDegrees(dNewTileCenterLat), dRowInc); int iCurCol = MathEngine.GetColFromLongitude(Angle.FromDegrees(dNewTileCenterLon), dColInc); long lKey = ((long)iCurRow << 32) + iCurCol; // Index keys by row-col packed into a single long if (m_topmostTiles.ContainsKey(lKey)) { qt = m_topmostTiles[lKey]; if (!oTilesToUpdate.ContainsKey(lKey)) oTilesToUpdate.Add(lKey, qt); continue; } // Check for tile outside layer boundaries double west = -180.0 + iCurCol * dColInc; if (west > m_east) continue; double east = west + dColInc; if (east < m_west) continue; double south = -90.0 + iCurRow * dRowInc; if (south > m_north) continue; double north = south + dRowInc; if (north < m_south) continue; qt = new QuadTile(south, north, west, east, 0, this); if (DrawArgs.Camera.ViewFrustum.Intersects(qt.BoundingBox)) { lock (((System.Collections.IDictionary)m_topmostTiles).SyncRoot) { m_topmostTiles.Add(lKey, qt); } if (!oTilesToUpdate.ContainsKey(lKey)) { oTilesToUpdate.Add(lKey, qt); } } } } } List<long> oTileIndicesToDelete = new List<long>(); foreach (long key in m_topmostTiles.Keys) { QuadTile qt = (QuadTile)m_topmostTiles[key]; if (!drawArgs.WorldCamera.ViewFrustum.Intersects(qt.BoundingBox)) { if (oTilesToUpdate.ContainsKey(key)) oTilesToUpdate.Remove(key); oTileIndicesToDelete.Add(key); } } // Do updates before cleanup for performance reasons. foreach (long key in oTilesToUpdate.Keys) m_topmostTiles[key].Update(drawArgs); lock (((System.Collections.IDictionary)m_topmostTiles).SyncRoot) { foreach (long key in oTileIndicesToDelete) { if (m_topmostTiles.ContainsKey(key)) { QuadTile qt = (QuadTile)m_topmostTiles[key]; m_topmostTiles.Remove(key); qt.Dispose(); } } } }