private void Update(Context context, ClipmapUpdate update, ClipmapLevel level, RasterDataDetails details, RasterLevel rasterLevel)
        {
            ClipmapUpdate[] updates = SplitUpdateToAvoidWrapping(update, details);
            foreach (ClipmapUpdate nonWrappingUpdate in updates)
            {
                RasterTileRegion[] tileRegions = rasterLevel.GetTilesInExtent(nonWrappingUpdate.West, nonWrappingUpdate.South, nonWrappingUpdate.East, nonWrappingUpdate.North);
                foreach (RasterTileRegion region in tileRegions)
                {
                    Texture2D tileTexture;
                    bool      loaded = details.LoadedTiles.TryGetValue(region.Tile.Identifier, out tileTexture);
                    if (loaded)
                    {
                        RenderTileToLevelTexture(context, level, details, region, tileTexture);
                    }
                    else
                    {
                        UpsampleTileData(context, level, details, region);
                    }
                }
            }

            if (details.Type == RasterType.Terrain)
            {
                // Normals at edges are incorrect, so include a one-post buffer around the update region
                // when updating normals in order to update normals that were previously at the edge.
                ClipmapUpdate   updateWithBuffer = update.AddBufferWithinLevelNextExtent();
                ClipmapUpdate[] normalUpdates    = SplitUpdateToAvoidWrapping(updateWithBuffer, details);
                foreach (ClipmapUpdate normalUpdate in normalUpdates)
                {
                    UpdateNormals(context, normalUpdate);
                }
            }
        }
Exemple #2
0
        private void UpdateImagery(ClipmapLevel level, ClipmapLevel coarserLevel, Context context, SceneState sceneState)
        {
            int deltaX = level.NextImageryExtent.West - level.CurrentImageryExtent.West;
            int deltaY = level.NextImageryExtent.South - level.CurrentImageryExtent.South;

            if (deltaX == 0 && deltaY == 0)
            {
                return;
            }

            int minLongitude = deltaX > 0 ? level.CurrentImageryExtent.East + 1 : level.NextImageryExtent.West;
            int maxLongitude = deltaX > 0 ? level.NextImageryExtent.East : level.CurrentImageryExtent.West - 1;
            int minLatitude  = deltaY > 0 ? level.CurrentImageryExtent.North + 1 : level.NextImageryExtent.South;
            int maxLatitude  = deltaY > 0 ? level.NextImageryExtent.North : level.CurrentImageryExtent.South - 1;

            int width  = maxLongitude - minLongitude + 1;
            int height = maxLatitude - minLatitude + 1;

            if (level.CurrentImageryExtent.West > level.CurrentImageryExtent.East || // initial update
                width >= level.ImageryWidth || height >= level.ImageryHeight)        // complete update
            {
                // Initial or complete update.
                width        = level.ImageryWidth;
                height       = level.ImageryHeight;
                deltaX       = level.ImageryWidth;
                deltaY       = level.ImageryHeight;
                minLongitude = level.NextImageryExtent.West;
                maxLongitude = level.NextImageryExtent.East;
                minLatitude  = level.NextImageryExtent.South;
                maxLatitude  = level.NextImageryExtent.North;
            }

            if (height > 0)
            {
                ClipmapUpdate horizontalUpdate = new ClipmapUpdate(
                    level,
                    level.NextImageryExtent.West,
                    minLatitude,
                    level.NextImageryExtent.East,
                    maxLatitude);
                _updater.UpdateImagery(context, horizontalUpdate);
            }

            if (width > 0)
            {
                ClipmapUpdate verticalUpdate = new ClipmapUpdate(
                    level,
                    minLongitude,
                    level.NextImageryExtent.South,
                    maxLongitude,
                    level.NextImageryExtent.North);
                _updater.UpdateImagery(context, verticalUpdate);
            }


            level.CurrentImageryExtent.West  = level.NextImageryExtent.West;
            level.CurrentImageryExtent.South = level.NextImageryExtent.South;
            level.CurrentImageryExtent.East  = level.NextImageryExtent.East;
            level.CurrentImageryExtent.North = level.NextImageryExtent.North;
        }
Exemple #3
0
        public void Render(Context context, SceneState sceneState)
        {
            if (_wireframe)
            {
                _renderState.RasterizationMode = RasterizationMode.Line;
            }
            else
            {
                _renderState.RasterizationMode = RasterizationMode.Fill;
            }

            Vector3D previousTarget = sceneState.Camera.Target;
            Vector3D previousEye    = sceneState.Camera.Eye;
            Vector3D previousSun    = sceneState.SunPosition;

            _levelZeroWorldScaleFactor.Value = new Vector2F((float)_clipmapLevels[0].Terrain.PostDeltaLongitude, (float)_clipmapLevels[0].Terrain.PostDeltaLatitude);

            int maxLevel = _clipmapLevels.Length - 1;

            Vector2D center = new Vector2D(0.0, 0.0);

            bool rendered = false;

            for (int i = maxLevel; i >= 0; --i)
            {
                ClipmapLevel thisLevel    = _clipmapLevels[i];
                ClipmapLevel coarserLevel = _clipmapLevels[i > 0 ? i - 1 : 0];

                rendered = RenderLevel(i, thisLevel, coarserLevel, !rendered, center, context, sceneState);
            }

            sceneState.Camera.Target = previousTarget;
            sceneState.Camera.Eye    = previousEye;
            sceneState.SunPosition   = previousSun;
        }
Exemple #4
0
        private void UpdateImageryOriginInTextures(ClipmapLevel level)
        {
            int deltaX = level.NextImageryExtent.West - level.CurrentImageryExtent.West;
            int deltaY = level.NextImageryExtent.South - level.CurrentImageryExtent.South;

            if (deltaX == 0 && deltaY == 0)
            {
                return;
            }

            if (level.CurrentImageryExtent.West > level.CurrentImageryExtent.East ||               // initial update
                Math.Abs(deltaX) >= level.ImageryWidth || Math.Abs(deltaY) >= level.ImageryHeight) // complete update
            {
                level.OriginInImagery = new Vector2I(0, 0);
            }
            else
            {
                int newOriginX = (level.OriginInImagery.X + deltaX) % level.ImageryWidth;
                if (newOriginX < 0)
                {
                    newOriginX += level.ImageryWidth;
                }
                int newOriginY = (level.OriginInImagery.Y + deltaY) % level.ImageryHeight;
                if (newOriginY < 0)
                {
                    newOriginY += level.ImageryHeight;
                }
                level.OriginInImagery = new Vector2I(newOriginX, newOriginY);
            }
        }
Exemple #5
0
        private void UpdateOriginInTextures(ClipmapLevel level)
        {
            int deltaX = level.NextExtent.West - level.CurrentExtent.West;
            int deltaY = level.NextExtent.South - level.CurrentExtent.South;

            if (deltaX == 0 && deltaY == 0)
            {
                return;
            }

            if (level.CurrentExtent.West > level.CurrentExtent.East ||                  // initial update
                Math.Abs(deltaX) >= _clipmapPosts || Math.Abs(deltaY) >= _clipmapPosts) // complete update
            {
                level.OriginInTextures = new Vector2I(0, 0);
            }
            else
            {
                int newOriginX = (level.OriginInTextures.X + deltaX) % _clipmapPosts;
                if (newOriginX < 0)
                {
                    newOriginX += _clipmapPosts;
                }
                int newOriginY = (level.OriginInTextures.Y + deltaY) % _clipmapPosts;
                if (newOriginY < 0)
                {
                    newOriginY += _clipmapPosts;
                }
                level.OriginInTextures = new Vector2I(newOriginX, newOriginY);
            }
        }
        private void UpdateNormals(Context context, ClipmapUpdate update)
        {
            ClipmapLevel level = update.Level;

            context.TextureUnits[0].Texture        = update.Level.HeightTexture;
            context.TextureUnits[0].TextureSampler = Device.TextureSamplers.NearestRepeat;

            _framebuffer.ColorAttachments[_normalOutput] = level.NormalTexture;

            int clipmapSize = level.NextExtent.East - level.NextExtent.West + 1;
            int west        = (level.OriginInTextures.X + (update.West - level.NextExtent.West)) % clipmapSize;
            int south       = (level.OriginInTextures.Y + (update.South - level.NextExtent.South)) % clipmapSize;

            _computeNormalsUpdateSize.Value           = new Vector2F(update.Width, update.Height);
            _computeNormalsOrigin.Value               = new Vector2F(west, south);
            _computeNormalsOneOverHeightMapSize.Value = new Vector2F(1.0f / update.Level.HeightTexture.Description.Width, 1.0f / update.Level.HeightTexture.Description.Height);
            _postDelta.Value = (float)update.Level.Terrain.PostDeltaLongitude;

            // Save the current state of the context
            Rectangle   oldViewport    = context.Viewport;
            Framebuffer oldFramebuffer = context.Framebuffer;

            // Update the context and draw
            context.Viewport    = new Rectangle(0, 0, level.NormalTexture.Description.Width, level.NormalTexture.Description.Height);
            context.Framebuffer = _framebuffer;
            context.Draw(_unitQuadPrimitiveType, _computeNormalsDrawState, _sceneState);

            // Restore the context to its original state
            context.Framebuffer = oldFramebuffer;
            context.Viewport    = oldViewport;
        }
 public ClipmapUpdate(ClipmapLevel level, int west, int south, int east, int north)
 {
     _level = level;
     _west = west;
     _south = south;
     _east = east;
     _north = north;
 }
 public ClipmapUpdate(ClipmapLevel level, int west, int south, int east, int north)
 {
     _level = level;
     _west  = west;
     _south = south;
     _east  = east;
     _north = north;
 }
        private void ApplyIfNotLoaded(Context context, RasterDataDetails details, ClipmapLevel level, RasterTile tile)
        {
            Texture2D texture;

            if (!details.LoadedTiles.TryGetValue(tile.Identifier, out texture) || texture == null)
            {
                ApplyNewTile(context, details, level, tile);
            }
        }
        public ClipmapUpdater(Context context, ClipmapLevel[] clipmapLevels)
        {
            ShaderVertexAttributeCollection vertexAttributes = new ShaderVertexAttributeCollection();

            vertexAttributes.Add(new ShaderVertexAttribute("position", VertexLocations.Position, ShaderVertexAttributeType.FloatVector2, 1));

            Mesh unitQuad = RectangleTessellator.Compute(new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(1.0, 1.0)), 1, 1);

            _unitQuad = context.CreateVertexArray(unitQuad, vertexAttributes, BufferHint.StaticDraw);
            _unitQuadPrimitiveType = unitQuad.PrimitiveType;
            _sceneState            = new SceneState();
            _framebuffer           = context.CreateFramebuffer();

            _updateShader = Device.CreateShaderProgram(
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapUpdateVS.glsl"),
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapUpdateFS.glsl"));
            _updateTexelOutput = _updateShader.FragmentOutputs["texelOutput"];
            _updateDrawState   = new DrawState(new RenderState(), _updateShader, _unitQuad);
            _updateDrawState.RenderState.FacetCulling.FrontFaceWindingOrder = unitQuad.FrontFaceWindingOrder;
            _updateDrawState.RenderState.DepthTest.Enabled = false;
            _updateDestinationOffset = (Uniform <Vector2F>)_updateShader.Uniforms["u_destinationOffset"];
            _updateUpdateSize        = (Uniform <Vector2F>)_updateShader.Uniforms["u_updateSize"];
            _updateSourceOrigin      = (Uniform <Vector2F>)_updateShader.Uniforms["u_sourceOrigin"];

            _upsampleShader = Device.CreateShaderProgram(
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapUpsampleVS.glsl"),
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapUpsampleFS.glsl"));
            _upsampleTexelOutput = _upsampleShader.FragmentOutputs["texelOutput"];
            _upsampleDrawState   = new DrawState(new RenderState(), _upsampleShader, _unitQuad);
            _upsampleDrawState.RenderState.FacetCulling.FrontFaceWindingOrder = unitQuad.FrontFaceWindingOrder;
            _upsampleDrawState.RenderState.DepthTest.Enabled = false;
            _upsampleSourceOrigin       = (Uniform <Vector2F>)_upsampleShader.Uniforms["u_sourceOrigin"];
            _upsampleUpdateSize         = (Uniform <Vector2F>)_upsampleShader.Uniforms["u_updateSize"];
            _upsampleDestinationOffset  = (Uniform <Vector2F>)_upsampleShader.Uniforms["u_destinationOffset"];
            _upsampleOneOverTextureSize = (Uniform <Vector2F>)_upsampleShader.Uniforms["u_oneOverTextureSize"];

            _computeNormalsShader = Device.CreateShaderProgram(
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapComputeNormalsVS.glsl"),
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapComputeNormalsFS.glsl"));
            _normalOutput            = _computeNormalsShader.FragmentOutputs["normalOutput"];
            _computeNormalsDrawState = new DrawState(new RenderState(), _computeNormalsShader, _unitQuad);
            _computeNormalsDrawState.RenderState.FacetCulling.FrontFaceWindingOrder = unitQuad.FrontFaceWindingOrder;
            _computeNormalsDrawState.RenderState.DepthTest.Enabled = false;
            _computeNormalsOrigin               = (Uniform <Vector2F>)_computeNormalsShader.Uniforms["u_origin"];
            _computeNormalsUpdateSize           = (Uniform <Vector2F>)_computeNormalsShader.Uniforms["u_updateSize"];
            _computeNormalsOneOverHeightMapSize = (Uniform <Vector2F>)_computeNormalsShader.Uniforms["u_oneOverHeightMapSize"];
            _heightExaggeration = (Uniform <float>)_computeNormalsShader.Uniforms["u_heightExaggeration"];
            _postDelta          = (Uniform <float>)_computeNormalsShader.Uniforms["u_postDelta"];

            HeightExaggeration = 1.0f;

            ClipmapLevel levelZero = clipmapLevels[0];

            InitializeRequestThreads(context, _terrain, levelZero, levelZero.Terrain);
            InitializeRequestThreads(context, _imagery, levelZero, levelZero.Imagery);
        }
Exemple #11
0
        private void DrawBlock(VertexArray block, ClipmapLevel level, ClipmapLevel coarserLevel, int overallWest, int overallSouth, int blockWest, int blockSouth, Context context, SceneState sceneState)
        {
            int textureWest  = blockWest - overallWest;
            int textureSouth = blockSouth - overallSouth;

            _patchOriginInClippedLevel.Value = new Vector2F(textureWest, textureSouth);
            DrawState drawState = new DrawState(_renderState, _shaderProgram, block);

            context.Draw(_primitiveType, drawState, sceneState);
        }
 private void RequestTileResidency(Context context, ClipmapLevel level, RasterDataDetails details, RasterLevel rasterLevel, ClipmapLevel.Extent nextExtent)
 {
     RasterTileRegion[] tileRegions = rasterLevel.GetTilesInExtent(nextExtent.West, nextExtent.South, nextExtent.East, nextExtent.North);
     foreach (RasterTileRegion region in tileRegions)
     {
         if (!details.LoadedTiles.ContainsKey(region.Tile.Identifier))
         {
             RequestTileLoad(details, level, region.Tile);
         }
     }
 }
        public ClipmapUpdater(Context context, ClipmapLevel[] clipmapLevels)
        {
            ShaderVertexAttributeCollection vertexAttributes = new ShaderVertexAttributeCollection();
            vertexAttributes.Add(new ShaderVertexAttribute("position", VertexLocations.Position, ShaderVertexAttributeType.FloatVector2, 1));

            Mesh unitQuad = RectangleTessellator.Compute(new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(1.0, 1.0)), 1, 1);
            _unitQuad = context.CreateVertexArray(unitQuad, vertexAttributes, BufferHint.StaticDraw);
            _unitQuadPrimitiveType = unitQuad.PrimitiveType;
            _sceneState = new SceneState();
            _framebuffer = context.CreateFramebuffer();

            _updateShader = Device.CreateShaderProgram(
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapUpdateVS.glsl"),
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapUpdateFS.glsl"));
            _updateTexelOutput = _updateShader.FragmentOutputs["texelOutput"];
            _updateDrawState = new DrawState(new RenderState(), _updateShader, _unitQuad);
            _updateDrawState.RenderState.FacetCulling.FrontFaceWindingOrder = unitQuad.FrontFaceWindingOrder;
            _updateDrawState.RenderState.DepthTest.Enabled = false;
            _updateDestinationOffset = (Uniform<Vector2F>)_updateShader.Uniforms["u_destinationOffset"];
            _updateUpdateSize = (Uniform<Vector2F>)_updateShader.Uniforms["u_updateSize"];
            _updateSourceOrigin = (Uniform<Vector2F>)_updateShader.Uniforms["u_sourceOrigin"];

            _upsampleShader = Device.CreateShaderProgram(
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapUpsampleVS.glsl"),
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapUpsampleFS.glsl"));
            _upsampleTexelOutput = _upsampleShader.FragmentOutputs["texelOutput"];
            _upsampleDrawState = new DrawState(new RenderState(), _upsampleShader, _unitQuad);
            _upsampleDrawState.RenderState.FacetCulling.FrontFaceWindingOrder = unitQuad.FrontFaceWindingOrder;
            _upsampleDrawState.RenderState.DepthTest.Enabled = false;
            _upsampleSourceOrigin = (Uniform<Vector2F>)_upsampleShader.Uniforms["u_sourceOrigin"];
            _upsampleUpdateSize = (Uniform<Vector2F>)_upsampleShader.Uniforms["u_updateSize"];
            _upsampleDestinationOffset = (Uniform<Vector2F>)_upsampleShader.Uniforms["u_destinationOffset"];
            _upsampleOneOverTextureSize = (Uniform<Vector2F>)_upsampleShader.Uniforms["u_oneOverTextureSize"];

            _computeNormalsShader = Device.CreateShaderProgram(
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapComputeNormalsVS.glsl"),
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.ClipmapComputeNormalsFS.glsl"));
            _normalOutput = _computeNormalsShader.FragmentOutputs["normalOutput"];
            _computeNormalsDrawState = new DrawState(new RenderState(), _computeNormalsShader, _unitQuad);
            _computeNormalsDrawState.RenderState.FacetCulling.FrontFaceWindingOrder = unitQuad.FrontFaceWindingOrder;
            _computeNormalsDrawState.RenderState.DepthTest.Enabled = false;
            _computeNormalsOrigin = (Uniform<Vector2F>)_computeNormalsShader.Uniforms["u_origin"];
            _computeNormalsUpdateSize = (Uniform<Vector2F>)_computeNormalsShader.Uniforms["u_updateSize"];
            _computeNormalsOneOverHeightMapSize = (Uniform<Vector2F>)_computeNormalsShader.Uniforms["u_oneOverHeightMapSize"];
            _heightExaggeration = (Uniform<float>)_computeNormalsShader.Uniforms["u_heightExaggeration"];
            _postDelta = (Uniform<float>)_computeNormalsShader.Uniforms["u_postDelta"];

            HeightExaggeration = 1.0f;

            ClipmapLevel levelZero = clipmapLevels[0];
            InitializeRequestThreads(context, _terrain, levelZero, levelZero.Terrain);
            InitializeRequestThreads(context, _imagery, levelZero, levelZero.Imagery);
        }
        private void RequestTileLoad(RasterDataDetails details, ClipmapLevel level, RasterTile tile)
        {
            LinkedListNode <TileLoadRequest> requestNode;
            bool exists = details.LoadingTiles.TryGetValue(tile.Identifier, out requestNode);

            if (!exists)
            {
                // Create a new request.
                TileLoadRequest request = new TileLoadRequest();
                request.Level = level;
                request.Tile  = tile;
                requestNode   = new LinkedListNode <TileLoadRequest>(request);
            }

            lock (details.RequestList)
            {
                if (exists)
                {
                    // Remove the existing request from the queue so we can re-insert it
                    // in its new location.
                    if (requestNode.List == null)
                    {
                        // Request was in the queue at one point, but it's not anymore.
                        // That means it's been loaded,  so we don't need to do anything.
                        return;
                    }
                    details.RequestList.Remove(requestNode);
                }

                if (details.RequestInsertionPoint == null || details.RequestInsertionPoint.List == null)
                {
                    details.RequestList.AddLast(requestNode);
                }
                else
                {
                    details.RequestList.AddBefore(details.RequestInsertionPoint, requestNode);
                }
                details.RequestInsertionPoint = requestNode;

                // If the request list has too many entries, delete from the beginning
                const int MaxRequests = 500;
                while (details.RequestList.Count > MaxRequests)
                {
                    LinkedListNode <TileLoadRequest> nodeToRemove = details.RequestList.First;
                    details.RequestList.RemoveFirst();
                    details.LoadingTiles.Remove(nodeToRemove.Value.Tile.Identifier);
                }

                Monitor.Pulse(details.RequestList);
            }

            details.LoadingTiles[tile.Identifier] = requestNode;
        }
        private void RenderTileToLevelTexture(Context context, ClipmapLevel level, RasterDataDetails details, RasterTileRegion region, Texture2D tileTexture)
        {
            Texture2D levelTexture;
            Vector2I  originInTextures;

            ClipmapLevel.Extent nextExtent;

            if (details.Type == RasterType.Terrain)
            {
                levelTexture     = level.HeightTexture;
                originInTextures = level.OriginInTextures;
                nextExtent       = level.NextExtent;
            }
            else
            {
                levelTexture     = level.ImageryTexture;
                originInTextures = level.OriginInImagery;
                nextExtent       = level.NextImageryExtent;
            }

            context.TextureUnits[0].Texture        = tileTexture;
            context.TextureUnits[0].TextureSampler = Device.TextureSamplers.NearestClamp;

            _framebuffer.ColorAttachments[_updateTexelOutput] = levelTexture;

            int clipmapSize = nextExtent.East - nextExtent.West + 1;
            int destWest    = (originInTextures.X + (region.Tile.West + region.West - nextExtent.West)) % clipmapSize;
            int destSouth   = (originInTextures.Y + (region.Tile.South + region.South - nextExtent.South)) % clipmapSize;

            int width  = region.East - region.West + 1;
            int height = region.North - region.South + 1;

            _updateSourceOrigin.Value      = new Vector2F(region.West, region.South);
            _updateUpdateSize.Value        = new Vector2F(width, height);
            _updateDestinationOffset.Value = new Vector2F(destWest, destSouth);

            // Save the current state of the context
            Rectangle   oldViewport    = context.Viewport;
            Framebuffer oldFramebuffer = context.Framebuffer;

            // Update the context and draw
            context.Viewport    = new Rectangle(0, 0, levelTexture.Description.Width, levelTexture.Description.Height);
            context.Framebuffer = _framebuffer;
            context.Draw(_unitQuadPrimitiveType, _updateDrawState, _sceneState);

            // Restore the context to its original state
            context.Framebuffer = oldFramebuffer;
            context.Viewport    = oldViewport;
        }
        private void InitializeRequestThreads(Context context, RasterDataDetails details, ClipmapLevel clipmapLevelZero, RasterLevel rasterLevelZero)
        {
            details.WorkerWindow = Device.CreateWindow(1, 1);
            context.MakeCurrent();

#if !SingleThreaded
            Thread requestThread = new Thread(RequestThreadEntryPoint);
            requestThread.IsBackground = true;
            requestThread.Start(details);
#endif

            // Preload the entire world at level 0
            RasterTileRegion[] regions = rasterLevelZero.GetTilesInExtent(0, 0, rasterLevelZero.LongitudePosts - 1, rasterLevelZero.LatitudePosts - 1);
            foreach (RasterTileRegion region in regions)
            {
                RequestTileLoad(details, clipmapLevelZero, region.Tile);
            }
        }
        private void ApplyNewTile(Context context, RasterDataDetails details, ClipmapLevel level, RasterTile tile)
        {
            ClipmapLevel.Extent nextExtent  = details.Type == RasterType.Terrain ? level.NextExtent : level.NextImageryExtent;
            RasterLevel         rasterLevel = details.Type == RasterType.Terrain ? level.Terrain : level.Imagery;

            ClipmapUpdate entireLevel = new ClipmapUpdate(
                level,
                nextExtent.West,
                nextExtent.South,
                nextExtent.East,
                nextExtent.North);

            ClipmapUpdate thisTile = new ClipmapUpdate(
                level,
                tile.West - 1,
                tile.South - 1,
                tile.East + 1,
                tile.North + 1);

            ClipmapUpdate intersection = IntersectUpdates(entireLevel, thisTile);

            if (intersection.Width > 0 && intersection.Height > 0)
            {
                Update(context, intersection, level, details, rasterLevel);

                // Recurse on child tiles if they're NOT loaded.  Unloaded children will use data from this tile.
                ClipmapLevel finer = level.FinerLevel;
                if (finer != null)
                {
                    ApplyIfNotLoaded(context, details, finer, tile.SouthwestChild);
                    ApplyIfNotLoaded(context, details, finer, tile.SoutheastChild);
                    ApplyIfNotLoaded(context, details, finer, tile.NorthwestChild);
                    ApplyIfNotLoaded(context, details, finer, tile.NortheastChild);
                }
            }
        }
        private ClipmapUpdate[] SplitUpdateToAvoidWrapping(ClipmapUpdate update, RasterDataDetails details)
        {
            ClipmapLevel level  = update.Level;
            Vector2I     origin = details.Type == RasterType.Terrain ? level.OriginInTextures : level.OriginInImagery;

            ClipmapLevel.Extent extent = details.Type == RasterType.Terrain ? level.NextExtent : level.NextImageryExtent;

            int clipmapSizeX = extent.East - extent.West + 1;
            int clipmapSizeY = extent.North - extent.South + 1;

            int west  = (origin.X + (update.West - extent.West)) % clipmapSizeX;
            int east  = (origin.X + (update.East - extent.West)) % clipmapSizeX;
            int south = (origin.Y + (update.South - extent.South)) % clipmapSizeY;
            int north = (origin.Y + (update.North - extent.South)) % clipmapSizeY;

            if (east < west && north < south)
            {
                // Horizontal AND vertical wrap
                ClipmapUpdate bottomLeftUpdate = new ClipmapUpdate(
                    level,
                    update.West,
                    update.South,
                    extent.West + (clipmapSizeX - origin.X - 1),
                    extent.South + (clipmapSizeY - origin.Y - 1));

                ClipmapUpdate bottomRightUpdate = new ClipmapUpdate(
                    level,
                    extent.West + clipmapSizeX - origin.X,
                    update.South,
                    update.East,
                    extent.South + (clipmapSizeY - origin.Y - 1));

                ClipmapUpdate topLeftUpdate = new ClipmapUpdate(
                    level,
                    update.West,
                    extent.South + clipmapSizeY - origin.Y,
                    extent.West + (clipmapSizeX - origin.X - 1),
                    update.North);

                ClipmapUpdate topRightUpdate = new ClipmapUpdate(
                    level,
                    extent.West + clipmapSizeX - origin.X,
                    extent.South + clipmapSizeY - origin.Y,
                    update.East,
                    update.North);

                ClipmapUpdate[] result = new ClipmapUpdate[4];
                result[0] = bottomLeftUpdate;
                result[1] = bottomRightUpdate;
                result[2] = topLeftUpdate;
                result[3] = topRightUpdate;
                return(result);
            }
            else if (east < west)
            {
                // Horizontal wrap
                ClipmapUpdate leftUpdate = new ClipmapUpdate(
                    level,
                    update.West,
                    update.South,
                    extent.West + (clipmapSizeX - origin.X - 1),
                    update.North);

                ClipmapUpdate rightUpdate = new ClipmapUpdate(
                    level,
                    extent.West + clipmapSizeX - origin.X,
                    update.South,
                    update.East,
                    update.North);

                ClipmapUpdate[] result = new ClipmapUpdate[2];
                result[0] = leftUpdate;
                result[1] = rightUpdate;
                return(result);
            }
            else if (north < south)
            {
                // Vertical wrap
                ClipmapUpdate bottomUpdate = new ClipmapUpdate(
                    level,
                    update.West,
                    update.South,
                    update.East,
                    extent.South + (clipmapSizeY - origin.Y - 1));

                ClipmapUpdate topUpdate = new ClipmapUpdate(
                    level,
                    update.West,
                    extent.South + clipmapSizeY - origin.Y,
                    update.East,
                    update.North);

                ClipmapUpdate[] result = new ClipmapUpdate[2];
                result[0] = bottomUpdate;
                result[1] = topUpdate;
                return(result);
            }
            else
            {
                // No wrap
                ClipmapUpdate[] result = new ClipmapUpdate[1];
                result[0] = update;
                return(result);
            }
        }
 public void RequestTileResidency(Context context, ClipmapLevel level)
 {
     RequestTileResidency(context, level, _terrain, level.Terrain, level.NextExtent);
     RequestTileResidency(context, level, _imagery, level.Imagery, level.NextImageryExtent);
 }
        public void UpdateImagery(Context context, ClipmapUpdate update)
        {
            ClipmapLevel level = update.Level;

            Update(context, update, level, _imagery, level.Imagery);
        }
Exemple #21
0
        private bool RenderLevel(int levelIndex, ClipmapLevel level, ClipmapLevel coarserLevel, bool fillRing, Vector2D center, Context context, SceneState sceneState)
        {
            context.TextureUnits[0].Texture        = level.HeightTexture;
            context.TextureUnits[0].TextureSampler = Device.TextureSamplers.NearestRepeat;
            context.TextureUnits[1].Texture        = coarserLevel.HeightTexture;
            context.TextureUnits[1].TextureSampler = Device.TextureSamplers.LinearRepeat;
            context.TextureUnits[2].Texture        = level.NormalTexture;
            context.TextureUnits[2].TextureSampler = Device.TextureSamplers.LinearRepeat;
            context.TextureUnits[3].Texture        = coarserLevel.NormalTexture;
            context.TextureUnits[3].TextureSampler = Device.TextureSamplers.LinearRepeat;
            context.TextureUnits[4].Texture        = level.ImageryTexture;
            context.TextureUnits[4].TextureSampler = Device.TextureSamplers.LinearRepeat;

            if (_colorClipmapLevels)
            {
                _color.Value            = _colors[levelIndex];
                _blendRegionColor.Value = levelIndex == 0 ? _colors[levelIndex] : _colors[levelIndex - 1];
            }
            else
            {
                _color.Value            = new Vector3F(0.0f, 1.0f, 0.0f);
                _blendRegionColor.Value = new Vector3F(0.0f, 0.0f, 1.0f);
            }

            int west  = level.CurrentExtent.West;
            int south = level.CurrentExtent.South;
            int east  = level.CurrentExtent.East;
            int north = level.CurrentExtent.North;

            float levelScaleFactor = (float)Math.Pow(2.0, -levelIndex);

            _levelScaleFactor.Value = new Vector2F(levelScaleFactor, levelScaleFactor);

            _levelOffsetFromWorldOrigin.Value = new Vector2F((float)((double)level.CurrentExtent.West - level.Terrain.LongitudeToIndex(0.0)),
                                                             (float)((double)level.CurrentExtent.South - level.Terrain.LatitudeToIndex(0.0)));

            int coarserWest  = coarserLevel.CurrentExtent.West;
            int coarserSouth = coarserLevel.CurrentExtent.South;

            _fineLevelOriginInCoarse.Value = coarserLevel.OriginInTextures.ToVector2F() +
                                             new Vector2F(west / 2 - coarserWest + 0.5f,
                                                          south / 2 - coarserSouth + 0.5f);

            _viewPosInClippedLevel.Value = new Vector2F((float)(level.Terrain.LongitudeToIndex(Trig.ToDegrees(_clipmapCenter.Longitude)) - level.CurrentExtent.West),
                                                        (float)(level.Terrain.LatitudeToIndex(Trig.ToDegrees(_clipmapCenter.Latitude)) - level.CurrentExtent.South));

            _fineTextureOrigin.Value = level.OriginInTextures.ToVector2F() + new Vector2F(0.5f, 0.5f);

            _useBlendRegions.Value = _blendRegionsEnabled && level != coarserLevel;

            _terrainToImageryResolutionRatio.Value = new Vector2F((float)(level.Terrain.PostDeltaLongitude / level.Imagery.PostDeltaLongitude),
                                                                  (float)(level.Terrain.PostDeltaLatitude / level.Imagery.PostDeltaLatitude));

            double terrainWest       = level.Terrain.IndexToLongitude(level.CurrentExtent.West);
            double terrainSouth      = level.Terrain.IndexToLatitude(level.CurrentExtent.South);
            double imageryWestIndex  = level.Imagery.LongitudeToIndex(terrainWest);
            double imagerySouthIndex = level.Imagery.LatitudeToIndex(terrainSouth);

            Vector2D terrainOffsetInImagery = level.OriginInImagery.ToVector2D() +
                                              new Vector2D(imageryWestIndex - level.CurrentImageryExtent.West,
                                                           imagerySouthIndex - level.CurrentImageryExtent.South);

            _terrainOffsetInImagery.Value = terrainOffsetInImagery.ToVector2F();
            _oneOverImagerySize.Value     = new Vector2F((float)(1.0 / level.ImageryWidth), (float)(1.0 / level.ImageryHeight));

            DrawBlock(_fillPatch, level, coarserLevel, west, south, west, south, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, west + _fillPatchSegments, south, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - 2 * _fillPatchSegments, south, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - _fillPatchSegments, south, context, sceneState);

            DrawBlock(_fillPatch, level, coarserLevel, west, south, west, south + _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - _fillPatchSegments, south + _fillPatchSegments, context, sceneState);

            DrawBlock(_fillPatch, level, coarserLevel, west, south, west, north - 2 * _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - _fillPatchSegments, north - 2 * _fillPatchSegments, context, sceneState);

            DrawBlock(_fillPatch, level, coarserLevel, west, south, west, north - _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, west + _fillPatchSegments, north - _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - 2 * _fillPatchSegments, north - _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - _fillPatchSegments, north - _fillPatchSegments, context, sceneState);

            DrawBlock(_horizontalFixupPatch, level, coarserLevel, west, south, west, south + 2 * _fillPatchSegments, context, sceneState);
            DrawBlock(_horizontalFixupPatch, level, coarserLevel, west, south, east - _fillPatchSegments, south + 2 * _fillPatchSegments, context, sceneState);

            DrawBlock(_verticalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, south, context, sceneState);
            DrawBlock(_verticalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, north - _fillPatchSegments, context, sceneState);

            DrawBlock(_degenerateTrianglePatch, level, coarserLevel, west, south, west, south, context, sceneState);

            // Fill the center of the highest-detail ring
            if (fillRing)
            {
                DrawBlock(_fillPatch, level, coarserLevel, west, south, west + _fillPatchSegments, south + _fillPatchSegments, context, sceneState);
                DrawBlock(_fillPatch, level, coarserLevel, west, south, west + 2 * _fillPatchPosts, south + _fillPatchSegments, context, sceneState);
                DrawBlock(_fillPatch, level, coarserLevel, west, south, west + _fillPatchSegments, south + 2 * _fillPatchPosts, context, sceneState);
                DrawBlock(_fillPatch, level, coarserLevel, west, south, west + 2 * _fillPatchPosts, south + 2 * _fillPatchPosts, context, sceneState);

                DrawBlock(_horizontalFixupPatch, level, coarserLevel, west, south, west + _fillPatchSegments, south + 2 * _fillPatchSegments, context, sceneState);
                DrawBlock(_horizontalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchPosts, south + 2 * _fillPatchSegments, context, sceneState);

                DrawBlock(_verticalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, south + _fillPatchSegments, context, sceneState);
                DrawBlock(_verticalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, south + 2 * _fillPatchPosts, context, sceneState);

                DrawBlock(_centerPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, south + 2 * _fillPatchSegments, context, sceneState);
            }
            else
            {
                int offset = level.OffsetStripOnNorth
                                ? north - _fillPatchPosts
                                : south + _fillPatchSegments;
                DrawBlock(_horizontalOffsetPatch, level, coarserLevel, west, south, west + _fillPatchSegments, offset, context, sceneState);

                int southOffset = level.OffsetStripOnNorth ? 0 : 1;
                offset = level.OffsetStripOnEast
                                ? east - _fillPatchPosts
                                : west + _fillPatchSegments;
                DrawBlock(_verticalOffsetPatch, level, coarserLevel, west, south, offset, south + _fillPatchSegments + southOffset, context, sceneState);
            }

            return(true);
        }
        private void UpdateImageryOriginInTextures(ClipmapLevel level)
        {
            int deltaX = level.NextImageryExtent.West - level.CurrentImageryExtent.West;
            int deltaY = level.NextImageryExtent.South - level.CurrentImageryExtent.South;
            if (deltaX == 0 && deltaY == 0)
                return;

            if (level.CurrentImageryExtent.West > level.CurrentImageryExtent.East ||  // initial update
                Math.Abs(deltaX) >= level.ImageryWidth || Math.Abs(deltaY) >= level.ImageryHeight)      // complete update
            {
                level.OriginInImagery = new Vector2I(0, 0);
            }
            else
            {
                int newOriginX = (level.OriginInImagery.X + deltaX) % level.ImageryWidth;
                if (newOriginX < 0)
                    newOriginX += level.ImageryWidth;
                int newOriginY = (level.OriginInImagery.Y + deltaY) % level.ImageryHeight;
                if (newOriginY < 0)
                    newOriginY += level.ImageryHeight;
                level.OriginInImagery = new Vector2I(newOriginX, newOriginY);
            }
        }
        private void Update(Context context, ClipmapUpdate update, ClipmapLevel level, RasterDataDetails details, RasterLevel rasterLevel)
        {
            ClipmapUpdate[] updates = SplitUpdateToAvoidWrapping(update, details);
            foreach (ClipmapUpdate nonWrappingUpdate in updates)
            {
                RasterTileRegion[] tileRegions = rasterLevel.GetTilesInExtent(nonWrappingUpdate.West, nonWrappingUpdate.South, nonWrappingUpdate.East, nonWrappingUpdate.North);
                foreach (RasterTileRegion region in tileRegions)
                {
                    Texture2D tileTexture;
                    bool loaded = details.LoadedTiles.TryGetValue(region.Tile.Identifier, out tileTexture);
                    if (loaded)
                    {
                        RenderTileToLevelTexture(context, level, details, region, tileTexture);
                    }
                    else
                    {
                        UpsampleTileData(context, level, details, region);
                    }
                }
            }

            if (details.Type == RasterType.Terrain)
            {
                // Normals at edges are incorrect, so include a one-post buffer around the update region
                // when updating normals in order to update normals that were previously at the edge.
                ClipmapUpdate updateWithBuffer = update.AddBufferWithinLevelNextExtent();
                ClipmapUpdate[] normalUpdates = SplitUpdateToAvoidWrapping(updateWithBuffer, details);
                foreach (ClipmapUpdate normalUpdate in normalUpdates)
                {
                    UpdateNormals(context, normalUpdate);
                }
            }
        }
        private void RenderTileToLevelTexture(Context context, ClipmapLevel level, RasterDataDetails details, RasterTileRegion region, Texture2D tileTexture)
        {
            Texture2D levelTexture;
            Vector2I originInTextures;
            ClipmapLevel.Extent nextExtent;

            if (details.Type == RasterType.Terrain)
            {
                levelTexture = level.HeightTexture;
                originInTextures = level.OriginInTextures;
                nextExtent = level.NextExtent;
            }
            else
            {
                levelTexture = level.ImageryTexture;
                originInTextures = level.OriginInImagery;
                nextExtent = level.NextImageryExtent;
            }

            context.TextureUnits[0].Texture = tileTexture;
            context.TextureUnits[0].TextureSampler = Device.TextureSamplers.NearestClamp;

            _framebuffer.ColorAttachments[_updateTexelOutput] = levelTexture;

            int clipmapSize = nextExtent.East - nextExtent.West + 1;
            int destWest = (originInTextures.X + (region.Tile.West + region.West - nextExtent.West)) % clipmapSize;
            int destSouth = (originInTextures.Y + (region.Tile.South + region.South - nextExtent.South)) % clipmapSize;

            int width = region.East - region.West + 1;
            int height = region.North - region.South + 1;

            _updateSourceOrigin.Value = new Vector2F(region.West, region.South);
            _updateUpdateSize.Value = new Vector2F(width, height);
            _updateDestinationOffset.Value = new Vector2F(destWest, destSouth);

            // Save the current state of the context
            Rectangle oldViewport = context.Viewport;
            Framebuffer oldFramebuffer = context.Framebuffer;

            // Update the context and draw
            context.Viewport = new Rectangle(0, 0, levelTexture.Description.Width, levelTexture.Description.Height);
            context.Framebuffer = _framebuffer;
            context.Draw(_unitQuadPrimitiveType, _updateDrawState, _sceneState);

            // Restore the context to its original state
            context.Framebuffer = oldFramebuffer;
            context.Viewport = oldViewport;
        }
        public GlobeClipmapTerrain(Context context, RasterSource terrainSource, EsriRestImagery imagery, Ellipsoid ellipsoid, int clipmapPosts)
        {
            _terrainSource = terrainSource;
            _ellipsoid = ellipsoid;

            _clipmapPosts = clipmapPosts;
            _clipmapSegments = _clipmapPosts - 1;

            int clipmapLevels = _terrainSource.Levels.Count;
            _clipmapLevels = new ClipmapLevel[clipmapLevels];

            for (int i = 0; i < _clipmapLevels.Length; ++i)
            {
                _clipmapLevels[i] = new ClipmapLevel();
            }

            for (int i = 0; i < _clipmapLevels.Length; ++i)
            {
                RasterLevel terrainLevel = _terrainSource.Levels[i];
                _clipmapLevels[i].Terrain = terrainLevel;
                _clipmapLevels[i].HeightTexture = Device.CreateTexture2D(new Texture2DDescription(_clipmapPosts, _clipmapPosts, TextureFormat.Red32f));
                _clipmapLevels[i].NormalTexture = Device.CreateTexture2D(new Texture2DDescription(_clipmapPosts, _clipmapPosts, TextureFormat.RedGreenBlue32f));
                _clipmapLevels[i].CoarserLevel = i == 0 ? null : _clipmapLevels[i - 1];
                _clipmapLevels[i].FinerLevel = i == _clipmapLevels.Length - 1 ? null : _clipmapLevels[i + 1];

                // Aim for roughly one imagery texel per geometry texel.
                // Find the first imagery level that meets our resolution needs.
                double longitudeResRequired = terrainLevel.PostDeltaLongitude;
                double latitudeResRequired = terrainLevel.PostDeltaLatitude;
                RasterLevel imageryLevel = null;
                for (int j = 0; j < imagery.Levels.Count; ++j)
                {
                    imageryLevel = imagery.Levels[j];
                    if (imageryLevel.PostDeltaLongitude <= longitudeResRequired &&
                        imageryLevel.PostDeltaLatitude <= latitudeResRequired)
                    {
                        break;
                    }
                }

                _clipmapLevels[i].Imagery = imageryLevel;
                _clipmapLevels[i].ImageryWidth = (int)Math.Ceiling(_clipmapPosts * terrainLevel.PostDeltaLongitude / imageryLevel.PostDeltaLongitude);
                _clipmapLevels[i].ImageryHeight = (int)Math.Ceiling(_clipmapPosts * terrainLevel.PostDeltaLatitude / imageryLevel.PostDeltaLatitude);
                _clipmapLevels[i].ImageryTexture = Device.CreateTexture2D(new Texture2DDescription(_clipmapLevels[i].ImageryWidth, _clipmapLevels[i].ImageryHeight, TextureFormat.RedGreenBlue8, false));
            }

            _shaderProgram = Device.CreateShaderProgram(
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.GlobeClipmapVS.glsl"),
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.GlobeClipmapFS.glsl"));

            _fillPatchPosts = (clipmapPosts + 1) / 4; // M
            _fillPatchSegments = _fillPatchPosts - 1;

            // Create the MxM block used to fill the ring and the field.
            Mesh fieldBlockMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(_fillPatchSegments, _fillPatchSegments)),
                _fillPatchSegments, _fillPatchSegments);
            _fillPatch = context.CreateVertexArray(fieldBlockMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            // Create the Mx3 block used to fill the space between the MxM blocks in the ring
            Mesh ringFixupHorizontalMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(_fillPatchSegments, 2.0)),
                _fillPatchSegments, 2);
            _horizontalFixupPatch = context.CreateVertexArray(ringFixupHorizontalMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            // Create the 3xM block used to fill the space between the MxM blocks in the ring
            Mesh ringFixupVerticalMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(2.0, _fillPatchSegments)),
                2, _fillPatchSegments);
            _verticalFixupPatch = context.CreateVertexArray(ringFixupVerticalMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            Mesh offsetStripHorizontalMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(2 * _fillPatchPosts, 1.0)),
                2 * _fillPatchPosts, 1);
            _horizontalOffsetPatch = context.CreateVertexArray(offsetStripHorizontalMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            Mesh offsetStripVerticalMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(1.0, 2 * _fillPatchPosts - 1)),
                1, 2 * _fillPatchPosts - 1);
            _verticalOffsetPatch = context.CreateVertexArray(offsetStripVerticalMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            Mesh centerMesh = RectangleTessellator.Compute(new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(2.0, 2.0)), 2, 2);
            _centerPatch = context.CreateVertexArray(centerMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            Mesh degenerateTriangleMesh = CreateDegenerateTriangleMesh();
            _degenerateTrianglePatch = context.CreateVertexArray(degenerateTriangleMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            _patchOriginInClippedLevel = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_patchOriginInClippedLevel"];
            _levelScaleFactor = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_levelScaleFactor"];
            _levelZeroWorldScaleFactor = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_levelZeroWorldScaleFactor"];
            _levelOffsetFromWorldOrigin = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_levelOffsetFromWorldOrigin"];
            _heightExaggeration = (Uniform<float>)_shaderProgram.Uniforms["u_heightExaggeration"];
            _viewPosInClippedLevel = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_viewPosInClippedLevel"];
            _fineLevelOriginInCoarse = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_fineLevelOriginInCoarse"];
            _unblendedRegionSize = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_unblendedRegionSize"];
            _oneOverBlendedRegionSize = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_oneOverBlendedRegionSize"];
            _fineTextureOrigin = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_fineTextureOrigin"];
            _showBlendRegions = (Uniform<bool>)_shaderProgram.Uniforms["u_showBlendRegions"];
            _useBlendRegions = (Uniform<bool>)_shaderProgram.Uniforms["u_useBlendRegions"];
            _oneOverClipmapSize = (Uniform<float>)_shaderProgram.Uniforms["u_oneOverClipmapSize"];
            _color = (Uniform<Vector3F>)_shaderProgram.Uniforms["u_color"];
            _blendRegionColor = (Uniform<Vector3F>)_shaderProgram.Uniforms["u_blendRegionColor"];
            _terrainToImageryResolutionRatio = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_terrainToImageryResolutionRatio"];
            _terrainOffsetInImagery = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_terrainOffsetInImagery"];
            _oneOverImagerySize = (Uniform<Vector2F>)_shaderProgram.Uniforms["u_oneOverImagerySize"];
            _showImagery = (Uniform<bool>)_shaderProgram.Uniforms["u_showImagery"];
            _lighting = (Uniform<bool>)_shaderProgram.Uniforms["u_shade"];

            ((Uniform<Vector3F>)_shaderProgram.Uniforms["u_globeRadiiSquared"]).Value =
                ellipsoid.RadiiSquared.ToVector3F();
            
            _renderState = new RenderState();
            _renderState.FacetCulling.FrontFaceWindingOrder = fieldBlockMesh.FrontFaceWindingOrder;
            _primitiveType = fieldBlockMesh.PrimitiveType;

            float oneOverBlendedRegionSize = (float)(10.0 / _clipmapPosts);
            _oneOverBlendedRegionSize.Value = new Vector2F(oneOverBlendedRegionSize, oneOverBlendedRegionSize);

            float unblendedRegionSize = (float)(_clipmapSegments / 2 - _clipmapPosts / 10.0 - 1);
            _unblendedRegionSize.Value = new Vector2F(unblendedRegionSize, unblendedRegionSize);

            _useBlendRegions.Value = true;
            _showImagery.Value = true;

            _oneOverClipmapSize.Value = 1.0f / clipmapPosts;

            _updater = new ClipmapUpdater(context, _clipmapLevels);

            HeightExaggeration = 0.00001f;
        }
        private void UpsampleTileData(Context context, ClipmapLevel level, RasterDataDetails details, RasterTileRegion region)
        {
            ClipmapLevel coarserLevel = level.CoarserLevel;

            if (coarserLevel == null)
            {
                return;
            }

            Texture2D levelTexture;
            Texture2D coarserLevelTexture;
            Vector2I  originInTextures;
            Vector2I  coarserOriginInTextures;

            ClipmapLevel.Extent nextExtent;
            ClipmapLevel.Extent coarserNextExtent;

            if (details.Type == RasterType.Terrain)
            {
                levelTexture            = level.HeightTexture;
                coarserLevelTexture     = coarserLevel.HeightTexture;
                originInTextures        = level.OriginInTextures;
                coarserOriginInTextures = coarserLevel.OriginInTextures;
                nextExtent        = level.NextExtent;
                coarserNextExtent = coarserLevel.NextExtent;
            }
            else
            {
                levelTexture            = level.ImageryTexture;
                coarserLevelTexture     = coarserLevel.ImageryTexture;
                originInTextures        = level.OriginInImagery;
                coarserOriginInTextures = coarserLevel.OriginInImagery;
                nextExtent        = level.NextImageryExtent;
                coarserNextExtent = coarserLevel.NextImageryExtent;
            }

            context.TextureUnits[0].Texture        = coarserLevelTexture;
            context.TextureUnits[0].TextureSampler = Device.TextureSamplers.LinearRepeat;

            _framebuffer.ColorAttachments[_upsampleTexelOutput] = levelTexture;

            int fineClipmapSize = nextExtent.East - nextExtent.West + 1;
            int destWest        = (originInTextures.X + (region.Tile.West + region.West - nextExtent.West)) % fineClipmapSize;
            int destSouth       = (originInTextures.Y + (region.Tile.South + region.South - nextExtent.South)) % fineClipmapSize;

            int    coarseClipmapSize = coarserNextExtent.East - coarserNextExtent.West + 1;
            double sourceWest        = (coarserOriginInTextures.X + ((region.Tile.West + region.West) / 2.0 - coarserNextExtent.West)) % coarseClipmapSize;
            double sourceSouth       = (coarserOriginInTextures.Y + ((region.Tile.South + region.South) / 2.0 - coarserNextExtent.South)) % coarseClipmapSize;

            int width  = region.East - region.West + 1;
            int height = region.North - region.South + 1;

            _upsampleSourceOrigin.Value       = new Vector2F((float)sourceWest, (float)sourceSouth);
            _upsampleUpdateSize.Value         = new Vector2F(width, height);
            _upsampleDestinationOffset.Value  = new Vector2F(destWest, destSouth);
            _upsampleOneOverTextureSize.Value = new Vector2F(1.0f / coarserLevelTexture.Description.Width, 1.0f / coarserLevelTexture.Description.Height);

            // Save the current state of the context
            Rectangle   oldViewport    = context.Viewport;
            Framebuffer oldFramebuffer = context.Framebuffer;

            // Update the context and draw
            context.Viewport    = new Rectangle(0, 0, levelTexture.Description.Width, levelTexture.Description.Height);
            context.Framebuffer = _framebuffer;
            context.Draw(_unitQuadPrimitiveType, _upsampleDrawState, _sceneState);

            // Restore the context to its original state
            context.Framebuffer = oldFramebuffer;
            context.Viewport    = oldViewport;
        }
Exemple #27
0
        public GlobeClipmapTerrain(Context context, RasterSource terrainSource, EsriRestImagery imagery, Ellipsoid ellipsoid, int clipmapPosts)
        {
            _terrainSource = terrainSource;
            _ellipsoid     = ellipsoid;

            _clipmapPosts    = clipmapPosts;
            _clipmapSegments = _clipmapPosts - 1;

            int clipmapLevels = _terrainSource.Levels.Count;

            _clipmapLevels = new ClipmapLevel[clipmapLevels];

            for (int i = 0; i < _clipmapLevels.Length; ++i)
            {
                _clipmapLevels[i] = new ClipmapLevel();
            }

            for (int i = 0; i < _clipmapLevels.Length; ++i)
            {
                RasterLevel terrainLevel = _terrainSource.Levels[i];
                _clipmapLevels[i].Terrain       = terrainLevel;
                _clipmapLevels[i].HeightTexture = Device.CreateTexture2D(new Texture2DDescription(_clipmapPosts, _clipmapPosts, TextureFormat.Red32f));
                _clipmapLevels[i].NormalTexture = Device.CreateTexture2D(new Texture2DDescription(_clipmapPosts, _clipmapPosts, TextureFormat.RedGreenBlue32f));
                _clipmapLevels[i].CoarserLevel  = i == 0 ? null : _clipmapLevels[i - 1];
                _clipmapLevels[i].FinerLevel    = i == _clipmapLevels.Length - 1 ? null : _clipmapLevels[i + 1];

                // Aim for roughly one imagery texel per geometry texel.
                // Find the first imagery level that meets our resolution needs.
                double      longitudeResRequired = terrainLevel.PostDeltaLongitude;
                double      latitudeResRequired  = terrainLevel.PostDeltaLatitude;
                RasterLevel imageryLevel         = null;
                for (int j = 0; j < imagery.Levels.Count; ++j)
                {
                    imageryLevel = imagery.Levels[j];
                    if (imageryLevel.PostDeltaLongitude <= longitudeResRequired &&
                        imageryLevel.PostDeltaLatitude <= latitudeResRequired)
                    {
                        break;
                    }
                }

                _clipmapLevels[i].Imagery        = imageryLevel;
                _clipmapLevels[i].ImageryWidth   = (int)Math.Ceiling(_clipmapPosts * terrainLevel.PostDeltaLongitude / imageryLevel.PostDeltaLongitude);
                _clipmapLevels[i].ImageryHeight  = (int)Math.Ceiling(_clipmapPosts * terrainLevel.PostDeltaLatitude / imageryLevel.PostDeltaLatitude);
                _clipmapLevels[i].ImageryTexture = Device.CreateTexture2D(new Texture2DDescription(_clipmapLevels[i].ImageryWidth, _clipmapLevels[i].ImageryHeight, TextureFormat.RedGreenBlue8, false));
            }

            _shaderProgram = Device.CreateShaderProgram(
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.GlobeClipmapVS.glsl"),
                EmbeddedResources.GetText("OpenGlobe.Scene.Terrain.ClipmapTerrain.GlobeClipmapFS.glsl"));

            _fillPatchPosts    = (clipmapPosts + 1) / 4; // M
            _fillPatchSegments = _fillPatchPosts - 1;

            // Create the MxM block used to fill the ring and the field.
            Mesh fieldBlockMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(_fillPatchSegments, _fillPatchSegments)),
                _fillPatchSegments, _fillPatchSegments);

            _fillPatch = context.CreateVertexArray(fieldBlockMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            // Create the Mx3 block used to fill the space between the MxM blocks in the ring
            Mesh ringFixupHorizontalMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(_fillPatchSegments, 2.0)),
                _fillPatchSegments, 2);

            _horizontalFixupPatch = context.CreateVertexArray(ringFixupHorizontalMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            // Create the 3xM block used to fill the space between the MxM blocks in the ring
            Mesh ringFixupVerticalMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(2.0, _fillPatchSegments)),
                2, _fillPatchSegments);

            _verticalFixupPatch = context.CreateVertexArray(ringFixupVerticalMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            Mesh offsetStripHorizontalMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(2 * _fillPatchPosts, 1.0)),
                2 * _fillPatchPosts, 1);

            _horizontalOffsetPatch = context.CreateVertexArray(offsetStripHorizontalMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            Mesh offsetStripVerticalMesh = RectangleTessellator.Compute(
                new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(1.0, 2 * _fillPatchPosts - 1)),
                1, 2 * _fillPatchPosts - 1);

            _verticalOffsetPatch = context.CreateVertexArray(offsetStripVerticalMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            Mesh centerMesh = RectangleTessellator.Compute(new RectangleD(new Vector2D(0.0, 0.0), new Vector2D(2.0, 2.0)), 2, 2);

            _centerPatch = context.CreateVertexArray(centerMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            Mesh degenerateTriangleMesh = CreateDegenerateTriangleMesh();

            _degenerateTrianglePatch = context.CreateVertexArray(degenerateTriangleMesh, _shaderProgram.VertexAttributes, BufferHint.StaticDraw);

            _patchOriginInClippedLevel  = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_patchOriginInClippedLevel"];
            _levelScaleFactor           = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_levelScaleFactor"];
            _levelZeroWorldScaleFactor  = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_levelZeroWorldScaleFactor"];
            _levelOffsetFromWorldOrigin = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_levelOffsetFromWorldOrigin"];
            _heightExaggeration         = (Uniform <float>)_shaderProgram.Uniforms["u_heightExaggeration"];
            _viewPosInClippedLevel      = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_viewPosInClippedLevel"];
            _fineLevelOriginInCoarse    = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_fineLevelOriginInCoarse"];
            _unblendedRegionSize        = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_unblendedRegionSize"];
            _oneOverBlendedRegionSize   = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_oneOverBlendedRegionSize"];
            _fineTextureOrigin          = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_fineTextureOrigin"];
            _showBlendRegions           = (Uniform <bool>)_shaderProgram.Uniforms["u_showBlendRegions"];
            _useBlendRegions            = (Uniform <bool>)_shaderProgram.Uniforms["u_useBlendRegions"];
            _oneOverClipmapSize         = (Uniform <float>)_shaderProgram.Uniforms["u_oneOverClipmapSize"];
            _color            = (Uniform <Vector3F>)_shaderProgram.Uniforms["u_color"];
            _blendRegionColor = (Uniform <Vector3F>)_shaderProgram.Uniforms["u_blendRegionColor"];
            _terrainToImageryResolutionRatio = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_terrainToImageryResolutionRatio"];
            _terrainOffsetInImagery          = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_terrainOffsetInImagery"];
            _oneOverImagerySize = (Uniform <Vector2F>)_shaderProgram.Uniforms["u_oneOverImagerySize"];
            _showImagery        = (Uniform <bool>)_shaderProgram.Uniforms["u_showImagery"];
            _lighting           = (Uniform <bool>)_shaderProgram.Uniforms["u_shade"];

            ((Uniform <Vector3F>)_shaderProgram.Uniforms["u_globeRadiiSquared"]).Value =
                ellipsoid.RadiiSquared.ToVector3F();

            _renderState = new RenderState();
            _renderState.FacetCulling.FrontFaceWindingOrder = fieldBlockMesh.FrontFaceWindingOrder;
            _primitiveType = fieldBlockMesh.PrimitiveType;

            float oneOverBlendedRegionSize = (float)(10.0 / _clipmapPosts);

            _oneOverBlendedRegionSize.Value = new Vector2F(oneOverBlendedRegionSize, oneOverBlendedRegionSize);

            float unblendedRegionSize = (float)(_clipmapSegments / 2 - _clipmapPosts / 10.0 - 1);

            _unblendedRegionSize.Value = new Vector2F(unblendedRegionSize, unblendedRegionSize);

            _useBlendRegions.Value = true;
            _showImagery.Value     = true;

            _oneOverClipmapSize.Value = 1.0f / clipmapPosts;

            _updater = new ClipmapUpdater(context, _clipmapLevels);

            HeightExaggeration = 0.00001f;
        }
        private void ApplyNewTile(Context context, RasterDataDetails details, ClipmapLevel level, RasterTile tile)
        {
            ClipmapLevel.Extent nextExtent = details.Type == RasterType.Terrain ? level.NextExtent : level.NextImageryExtent;
            RasterLevel rasterLevel = details.Type == RasterType.Terrain ? level.Terrain : level.Imagery;

            ClipmapUpdate entireLevel = new ClipmapUpdate(
                level,
                nextExtent.West,
                nextExtent.South,
                nextExtent.East,
                nextExtent.North);

            ClipmapUpdate thisTile = new ClipmapUpdate(
                level,
                tile.West - 1,
                tile.South - 1,
                tile.East + 1,
                tile.North + 1);

            ClipmapUpdate intersection = IntersectUpdates(entireLevel, thisTile);

            if (intersection.Width > 0 && intersection.Height > 0)
            {
                Update(context, intersection, level, details, rasterLevel);

                // Recurse on child tiles if they're NOT loaded.  Unloaded children will use data from this tile.
                ClipmapLevel finer = level.FinerLevel;
                if (finer != null)
                {
                    ApplyIfNotLoaded(context, details, finer, tile.SouthwestChild);
                    ApplyIfNotLoaded(context, details, finer, tile.SoutheastChild);
                    ApplyIfNotLoaded(context, details, finer, tile.NorthwestChild);
                    ApplyIfNotLoaded(context, details, finer, tile.NortheastChild);
                }
            }
        }
        private void UpsampleTileData(Context context, ClipmapLevel level, RasterDataDetails details, RasterTileRegion region)
        {
            ClipmapLevel coarserLevel = level.CoarserLevel;

            if (coarserLevel == null)
                return;

            Texture2D levelTexture;
            Texture2D coarserLevelTexture;
            Vector2I originInTextures;
            Vector2I coarserOriginInTextures;
            ClipmapLevel.Extent nextExtent;
            ClipmapLevel.Extent coarserNextExtent;

            if (details.Type == RasterType.Terrain)
            {
                levelTexture = level.HeightTexture;
                coarserLevelTexture = coarserLevel.HeightTexture;
                originInTextures = level.OriginInTextures;
                coarserOriginInTextures = coarserLevel.OriginInTextures;
                nextExtent = level.NextExtent;
                coarserNextExtent = coarserLevel.NextExtent;
            }
            else
            {
                levelTexture = level.ImageryTexture;
                coarserLevelTexture = coarserLevel.ImageryTexture;
                originInTextures = level.OriginInImagery;
                coarserOriginInTextures = coarserLevel.OriginInImagery;
                nextExtent = level.NextImageryExtent;
                coarserNextExtent = coarserLevel.NextImageryExtent;
            }

            context.TextureUnits[0].Texture = coarserLevelTexture;
            context.TextureUnits[0].TextureSampler = Device.TextureSamplers.LinearRepeat;

            _framebuffer.ColorAttachments[_upsampleTexelOutput] = levelTexture;

            int fineClipmapSize = nextExtent.East - nextExtent.West + 1;
            int destWest = (originInTextures.X + (region.Tile.West + region.West - nextExtent.West)) % fineClipmapSize;
            int destSouth = (originInTextures.Y + (region.Tile.South + region.South - nextExtent.South)) % fineClipmapSize;

            int coarseClipmapSize = coarserNextExtent.East - coarserNextExtent.West + 1;
            double sourceWest = (coarserOriginInTextures.X + ((region.Tile.West + region.West) / 2.0 - coarserNextExtent.West)) % coarseClipmapSize;
            double sourceSouth = (coarserOriginInTextures.Y + ((region.Tile.South + region.South) / 2.0 - coarserNextExtent.South)) % coarseClipmapSize;

            int width = region.East - region.West + 1;
            int height = region.North - region.South + 1;

            _upsampleSourceOrigin.Value = new Vector2F((float)sourceWest, (float)sourceSouth);
            _upsampleUpdateSize.Value = new Vector2F(width, height);
            _upsampleDestinationOffset.Value = new Vector2F(destWest, destSouth);
            _upsampleOneOverTextureSize.Value = new Vector2F(1.0f / coarserLevelTexture.Description.Width, 1.0f / coarserLevelTexture.Description.Height);

            // Save the current state of the context
            Rectangle oldViewport = context.Viewport;
            Framebuffer oldFramebuffer = context.Framebuffer;

            // Update the context and draw
            context.Viewport = new Rectangle(0, 0, levelTexture.Description.Width, levelTexture.Description.Height);
            context.Framebuffer = _framebuffer;
            context.Draw(_unitQuadPrimitiveType, _upsampleDrawState, _sceneState);

            // Restore the context to its original state
            context.Framebuffer = oldFramebuffer;
            context.Viewport = oldViewport;
        }
        private void RequestTileLoad(RasterDataDetails details,  ClipmapLevel level, RasterTile tile)
        {
            LinkedListNode<TileLoadRequest> requestNode;
            bool exists = details.LoadingTiles.TryGetValue(tile.Identifier, out requestNode);

            if (!exists)
            {
                // Create a new request.
                TileLoadRequest request = new TileLoadRequest();
                request.Level = level;
                request.Tile = tile;
                requestNode = new LinkedListNode<TileLoadRequest>(request);
            }

            lock (details.RequestList)
            {
                if (exists)
                {
                    // Remove the existing request from the queue so we can re-insert it
                    // in its new location.
                    if (requestNode.List == null)
                    {
                        // Request was in the queue at one point, but it's not anymore.
                        // That means it's been loaded,  so we don't need to do anything.
                        return;
                    }
                    details.RequestList.Remove(requestNode);
                }

                if (details.RequestInsertionPoint == null || details.RequestInsertionPoint.List == null)
                {
                    details.RequestList.AddLast(requestNode);
                }
                else
                {
                    details.RequestList.AddBefore(details.RequestInsertionPoint, requestNode);
                }
                details.RequestInsertionPoint = requestNode;

                // If the request list has too many entries, delete from the beginning
                const int MaxRequests = 500;
                while (details.RequestList.Count > MaxRequests)
                {
                    LinkedListNode<TileLoadRequest> nodeToRemove = details.RequestList.First;
                    details.RequestList.RemoveFirst();
                    details.LoadingTiles.Remove(nodeToRemove.Value.Tile.Identifier);
                }

                Monitor.Pulse(details.RequestList);
            }

            details.LoadingTiles[tile.Identifier] = requestNode;
        }
Exemple #31
0
        public void PreRender(Context context, SceneState sceneState)
        {
            if (!_lodUpdateEnabled)
            {
                return;
            }

            _clipmapCenter = _ellipsoid.ToGeodetic3D(sceneState.Camera.Eye);

            //Geodetic2D center = Ellipsoid.ScaledWgs84.ToGeodetic2D(sceneState.Camera.Target / Ellipsoid.Wgs84.MaximumRadius);
            Geodetic2D center          = new Geodetic2D(_clipmapCenter.Longitude, _clipmapCenter.Latitude);
            double     centerLongitude = Trig.ToDegrees(center.Longitude);
            double     centerLatitude  = Trig.ToDegrees(center.Latitude);

            ClipmapLevel level                 = _clipmapLevels[_clipmapLevels.Length - 1];
            double       longitudeIndex        = level.Terrain.LongitudeToIndex(centerLongitude);
            double       latitudeIndex         = level.Terrain.LatitudeToIndex(centerLatitude);
            double       imageryLongitudeIndex = level.Imagery.LongitudeToIndex(centerLongitude);
            double       imageryLatitudeIndex  = level.Imagery.LatitudeToIndex(centerLatitude);

            int west = (int)(longitudeIndex - _clipmapPosts / 2);

            if ((west % 2) != 0)
            {
                ++west;
            }
            int south = (int)(latitudeIndex - _clipmapPosts / 2);

            if ((south % 2) != 0)
            {
                ++south;
            }

            int imageryWest  = (int)(imageryLongitudeIndex - level.ImageryWidth / 2);
            int imagerySouth = (int)(imageryLatitudeIndex - level.ImageryHeight / 2);

            level.NextExtent.West  = west;
            level.NextExtent.East  = west + _clipmapSegments;
            level.NextExtent.South = south;
            level.NextExtent.North = south + _clipmapSegments;

            level.NextImageryExtent.West  = imageryWest;
            level.NextImageryExtent.East  = imageryWest + level.ImageryWidth;
            level.NextImageryExtent.South = imagerySouth;
            level.NextImageryExtent.North = imagerySouth + level.ImageryHeight;

            UpdateOriginInTextures(level);
            UpdateImageryOriginInTextures(level);

            for (int i = _clipmapLevels.Length - 2; i >= 0; --i)
            {
                level = _clipmapLevels[i];
                ClipmapLevel finerLevel = _clipmapLevels[i + 1];

                // Terrain
                level.NextExtent.West   = finerLevel.NextExtent.West / 2 - _fillPatchSegments;
                level.OffsetStripOnEast = (level.NextExtent.West % 2) == 0;
                if (!level.OffsetStripOnEast)
                {
                    --level.NextExtent.West;
                }
                level.NextExtent.East = level.NextExtent.West + _clipmapSegments;

                level.NextExtent.South   = finerLevel.NextExtent.South / 2 - _fillPatchSegments;
                level.OffsetStripOnNorth = (level.NextExtent.South % 2) == 0;
                if (!level.OffsetStripOnNorth)
                {
                    --level.NextExtent.South;
                }
                level.NextExtent.North = level.NextExtent.South + _clipmapSegments;

                // Imagery
                imageryWest  = (int)level.Imagery.LongitudeToIndex(level.Terrain.IndexToLongitude(level.NextExtent.West));
                imagerySouth = (int)level.Imagery.LatitudeToIndex(level.Terrain.IndexToLatitude(level.NextExtent.South));

                level.NextImageryExtent.West  = imageryWest;
                level.NextImageryExtent.East  = imageryWest + level.ImageryWidth - 1;
                level.NextImageryExtent.South = imagerySouth;
                level.NextImageryExtent.North = imagerySouth + level.ImageryHeight - 1;

                UpdateOriginInTextures(level);
                UpdateImageryOriginInTextures(level);
            }

            _updater.ApplyNewData(context);

            for (int i = 0; i < _clipmapLevels.Length; ++i)
            {
                ClipmapLevel thisLevel    = _clipmapLevels[i];
                ClipmapLevel coarserLevel = _clipmapLevels[i > 0 ? i - 1 : 0];

                _updater.RequestTileResidency(context, thisLevel);
                UpdateTerrain(thisLevel, coarserLevel, context, sceneState);
                UpdateImagery(thisLevel, coarserLevel, context, sceneState);
            }
        }
 public void RequestTileResidency(Context context, ClipmapLevel level)
 {
     RequestTileResidency(context, level, _terrain, level.Terrain, level.NextExtent);
     RequestTileResidency(context, level, _imagery, level.Imagery, level.NextImageryExtent);
 }
        private void InitializeRequestThreads(Context context, RasterDataDetails details, ClipmapLevel clipmapLevelZero, RasterLevel rasterLevelZero)
        {
            details.WorkerWindow = Device.CreateWindow(1, 1);
            context.MakeCurrent();

#if !SingleThreaded
            Thread requestThread = new Thread(RequestThreadEntryPoint);
            requestThread.IsBackground = true;
            requestThread.Start(details);
#endif

            // Preload the entire world at level 0
            RasterTileRegion[] regions = rasterLevelZero.GetTilesInExtent(0, 0, rasterLevelZero.LongitudePosts - 1, rasterLevelZero.LatitudePosts - 1);
            foreach (RasterTileRegion region in regions)
            {
                RequestTileLoad(details, clipmapLevelZero, region.Tile);
            }
        }
        private bool RenderLevel(int levelIndex, ClipmapLevel level, ClipmapLevel coarserLevel, bool fillRing, Vector2D center, Context context, SceneState sceneState)
        {
            context.TextureUnits[0].Texture = level.HeightTexture;
            context.TextureUnits[0].TextureSampler = Device.TextureSamplers.NearestRepeat;
            context.TextureUnits[1].Texture = coarserLevel.HeightTexture;
            context.TextureUnits[1].TextureSampler = Device.TextureSamplers.LinearRepeat;
            context.TextureUnits[2].Texture = level.NormalTexture;
            context.TextureUnits[2].TextureSampler = Device.TextureSamplers.LinearRepeat;
            context.TextureUnits[3].Texture = coarserLevel.NormalTexture;
            context.TextureUnits[3].TextureSampler = Device.TextureSamplers.LinearRepeat;
            context.TextureUnits[4].Texture = level.ImageryTexture;
            context.TextureUnits[4].TextureSampler = Device.TextureSamplers.LinearRepeat;

            if (_colorClipmapLevels)
            {
                _color.Value = _colors[levelIndex];
                _blendRegionColor.Value = levelIndex == 0 ? _colors[levelIndex] : _colors[levelIndex - 1];
            }
            else
            {
                _color.Value = new Vector3F(0.0f, 1.0f, 0.0f);
                _blendRegionColor.Value = new Vector3F(0.0f, 0.0f, 1.0f);
            }

            int west = level.CurrentExtent.West;
            int south = level.CurrentExtent.South;
            int east = level.CurrentExtent.East;
            int north = level.CurrentExtent.North;

            float levelScaleFactor = (float)Math.Pow(2.0, -levelIndex);
            _levelScaleFactor.Value = new Vector2F(levelScaleFactor, levelScaleFactor);

            _levelOffsetFromWorldOrigin.Value = new Vector2F((float)((double)level.CurrentExtent.West - level.Terrain.LongitudeToIndex(0.0)),
                                                             (float)((double)level.CurrentExtent.South - level.Terrain.LatitudeToIndex(0.0)));

            int coarserWest = coarserLevel.CurrentExtent.West;
            int coarserSouth = coarserLevel.CurrentExtent.South;
            _fineLevelOriginInCoarse.Value = coarserLevel.OriginInTextures.ToVector2F() +
                                             new Vector2F(west / 2 - coarserWest + 0.5f,
                                                          south / 2 - coarserSouth + 0.5f);

            _viewPosInClippedLevel.Value = new Vector2F((float)(level.Terrain.LongitudeToIndex(Trig.ToDegrees(_clipmapCenter.Longitude)) - level.CurrentExtent.West),
                                                        (float)(level.Terrain.LatitudeToIndex(Trig.ToDegrees(_clipmapCenter.Latitude)) - level.CurrentExtent.South));

            _fineTextureOrigin.Value = level.OriginInTextures.ToVector2F() + new Vector2F(0.5f, 0.5f);

            _useBlendRegions.Value = _blendRegionsEnabled && level != coarserLevel;

            _terrainToImageryResolutionRatio.Value = new Vector2F((float)(level.Terrain.PostDeltaLongitude / level.Imagery.PostDeltaLongitude),
                                                                  (float)(level.Terrain.PostDeltaLatitude / level.Imagery.PostDeltaLatitude));

            double terrainWest = level.Terrain.IndexToLongitude(level.CurrentExtent.West);
            double terrainSouth = level.Terrain.IndexToLatitude(level.CurrentExtent.South);
            double imageryWestIndex = level.Imagery.LongitudeToIndex(terrainWest);
            double imagerySouthIndex = level.Imagery.LatitudeToIndex(terrainSouth);

            Vector2D terrainOffsetInImagery = level.OriginInImagery.ToVector2D() +
                                              new Vector2D(imageryWestIndex - level.CurrentImageryExtent.West,
                                                           imagerySouthIndex - level.CurrentImageryExtent.South);
            _terrainOffsetInImagery.Value = terrainOffsetInImagery.ToVector2F();
            _oneOverImagerySize.Value = new Vector2F((float)(1.0 / level.ImageryWidth), (float)(1.0 / level.ImageryHeight));

            DrawBlock(_fillPatch, level, coarserLevel, west, south, west, south, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, west + _fillPatchSegments, south, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - 2 * _fillPatchSegments, south, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - _fillPatchSegments, south, context, sceneState);

            DrawBlock(_fillPatch, level, coarserLevel, west, south, west, south + _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - _fillPatchSegments, south + _fillPatchSegments, context, sceneState);

            DrawBlock(_fillPatch, level, coarserLevel, west, south, west, north - 2 * _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - _fillPatchSegments, north - 2 * _fillPatchSegments, context, sceneState);

            DrawBlock(_fillPatch, level, coarserLevel, west, south, west, north - _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, west + _fillPatchSegments, north - _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - 2 * _fillPatchSegments, north - _fillPatchSegments, context, sceneState);
            DrawBlock(_fillPatch, level, coarserLevel, west, south, east - _fillPatchSegments, north - _fillPatchSegments, context, sceneState);

            DrawBlock(_horizontalFixupPatch, level, coarserLevel, west, south, west, south + 2 * _fillPatchSegments, context, sceneState);
            DrawBlock(_horizontalFixupPatch, level, coarserLevel, west, south, east - _fillPatchSegments, south + 2 * _fillPatchSegments, context, sceneState);

            DrawBlock(_verticalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, south, context, sceneState);
            DrawBlock(_verticalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, north - _fillPatchSegments, context, sceneState);

            DrawBlock(_degenerateTrianglePatch, level, coarserLevel, west, south, west, south, context, sceneState);

            // Fill the center of the highest-detail ring
            if (fillRing)
            {
                DrawBlock(_fillPatch, level, coarserLevel, west, south, west + _fillPatchSegments, south + _fillPatchSegments, context, sceneState);
                DrawBlock(_fillPatch, level, coarserLevel, west, south, west + 2 * _fillPatchPosts, south + _fillPatchSegments, context, sceneState);
                DrawBlock(_fillPatch, level, coarserLevel, west, south, west + _fillPatchSegments, south + 2 * _fillPatchPosts, context, sceneState);
                DrawBlock(_fillPatch, level, coarserLevel, west, south, west + 2 * _fillPatchPosts, south + 2 * _fillPatchPosts, context, sceneState);

                DrawBlock(_horizontalFixupPatch, level, coarserLevel, west, south, west + _fillPatchSegments, south + 2 * _fillPatchSegments, context, sceneState);
                DrawBlock(_horizontalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchPosts, south + 2 * _fillPatchSegments, context, sceneState);

                DrawBlock(_verticalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, south + _fillPatchSegments, context, sceneState);
                DrawBlock(_verticalFixupPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, south + 2 * _fillPatchPosts, context, sceneState);

                DrawBlock(_centerPatch, level, coarserLevel, west, south, west + 2 * _fillPatchSegments, south + 2 * _fillPatchSegments, context, sceneState);
            }
            else
            {
                int offset = level.OffsetStripOnNorth
                                ? north - _fillPatchPosts
                                : south + _fillPatchSegments;
                DrawBlock(_horizontalOffsetPatch, level, coarserLevel, west, south, west + _fillPatchSegments, offset, context, sceneState);

                int southOffset = level.OffsetStripOnNorth ? 0 : 1;
                offset = level.OffsetStripOnEast
                                ? east - _fillPatchPosts
                                : west + _fillPatchSegments;
                DrawBlock(_verticalOffsetPatch, level, coarserLevel, west, south, offset, south + _fillPatchSegments + southOffset, context, sceneState);
            }

            return true;
        }
        private void UpdateOriginInTextures(ClipmapLevel level)
        {
            int deltaX = level.NextExtent.West - level.CurrentExtent.West;
            int deltaY = level.NextExtent.South - level.CurrentExtent.South;
            if (deltaX == 0 && deltaY == 0)
                return;

            if (level.CurrentExtent.West > level.CurrentExtent.East ||  // initial update
                Math.Abs(deltaX) >= _clipmapPosts || Math.Abs(deltaY) >= _clipmapPosts)      // complete update
            {
                level.OriginInTextures = new Vector2I(0, 0);
            }
            else
            {
                int newOriginX = (level.OriginInTextures.X + deltaX) % _clipmapPosts;
                if (newOriginX < 0)
                    newOriginX += _clipmapPosts;
                int newOriginY = (level.OriginInTextures.Y + deltaY) % _clipmapPosts;
                if (newOriginY < 0)
                    newOriginY += _clipmapPosts;
                level.OriginInTextures = new Vector2I(newOriginX, newOriginY);
            }
        }
 private void ApplyIfNotLoaded(Context context, RasterDataDetails details, ClipmapLevel level, RasterTile tile)
 {
     Texture2D texture;
     if (!details.LoadedTiles.TryGetValue(tile.Identifier, out texture) || texture == null)
     {
         ApplyNewTile(context, details, level, tile);
     }
 }
        private void UpdateImagery(ClipmapLevel level, ClipmapLevel coarserLevel, Context context, SceneState sceneState)
        {
            int deltaX = level.NextImageryExtent.West - level.CurrentImageryExtent.West;
            int deltaY = level.NextImageryExtent.South - level.CurrentImageryExtent.South;
            if (deltaX == 0 && deltaY == 0)
                return;

            int minLongitude = deltaX > 0 ? level.CurrentImageryExtent.East + 1 : level.NextImageryExtent.West;
            int maxLongitude = deltaX > 0 ? level.NextImageryExtent.East : level.CurrentImageryExtent.West - 1;
            int minLatitude = deltaY > 0 ? level.CurrentImageryExtent.North + 1 : level.NextImageryExtent.South;
            int maxLatitude = deltaY > 0 ? level.NextImageryExtent.North : level.CurrentImageryExtent.South - 1;

            int width = maxLongitude - minLongitude + 1;
            int height = maxLatitude - minLatitude + 1;

            if (level.CurrentImageryExtent.West > level.CurrentImageryExtent.East || // initial update
                width >= level.ImageryWidth || height >= level.ImageryHeight) // complete update
            {
                // Initial or complete update.
                width = level.ImageryWidth;
                height = level.ImageryHeight;
                deltaX = level.ImageryWidth;
                deltaY = level.ImageryHeight;
                minLongitude = level.NextImageryExtent.West;
                maxLongitude = level.NextImageryExtent.East;
                minLatitude = level.NextImageryExtent.South;
                maxLatitude = level.NextImageryExtent.North;
            }

            if (height > 0)
            {
                ClipmapUpdate horizontalUpdate = new ClipmapUpdate(
                    level,
                    level.NextImageryExtent.West,
                    minLatitude,
                    level.NextImageryExtent.East,
                    maxLatitude);
                _updater.UpdateImagery(context, horizontalUpdate);
            }

            if (width > 0)
            {
                ClipmapUpdate verticalUpdate = new ClipmapUpdate(
                    level,
                    minLongitude,
                    level.NextImageryExtent.South,
                    maxLongitude,
                    level.NextImageryExtent.North);
                _updater.UpdateImagery(context, verticalUpdate);
            }


            level.CurrentImageryExtent.West = level.NextImageryExtent.West;
            level.CurrentImageryExtent.South = level.NextImageryExtent.South;
            level.CurrentImageryExtent.East = level.NextImageryExtent.East;
            level.CurrentImageryExtent.North = level.NextImageryExtent.North;
        }
 private void RequestTileResidency(Context context, ClipmapLevel level, RasterDataDetails details, RasterLevel rasterLevel, ClipmapLevel.Extent nextExtent)
 {
     RasterTileRegion[] tileRegions = rasterLevel.GetTilesInExtent(nextExtent.West, nextExtent.South, nextExtent.East, nextExtent.North);
     foreach (RasterTileRegion region in tileRegions)
     {
         if (!details.LoadedTiles.ContainsKey(region.Tile.Identifier))
         {
             RequestTileLoad(details, level, region.Tile);
         }
     }
 }
        private void DrawBlock(VertexArray block, ClipmapLevel level, ClipmapLevel coarserLevel, int overallWest, int overallSouth, int blockWest, int blockSouth, Context context, SceneState sceneState)
        {
            int textureWest = blockWest - overallWest;
            int textureSouth = blockSouth - overallSouth;

            _patchOriginInClippedLevel.Value = new Vector2F(textureWest, textureSouth);
            DrawState drawState = new DrawState(_renderState, _shaderProgram, block);
            context.Draw(_primitiveType, drawState, sceneState);
        }
        public void UpdateTerrain(Context context, ClipmapUpdate update)
        {
            ClipmapLevel level = update.Level;

            Update(context, update, level, _terrain, level.Terrain);
        }