コード例 #1
0
        public TextBuffer(FontStyle fontStyle)
        {
            this.fontStyle = fontStyle;

            mesh = new Mesh.Mesh();

            var vertexFormat = new VertexFormat();

            vertexFormat.Add(new Attribute(VertexUsage.Position, VertexAttribPointerType.Float, 0, 3));
            vertexFormat.Add(new Attribute(VertexUsage.TexCoord, VertexAttribPointerType.Float, 0, 2));
            vertexFormat.Add(new Attribute(VertexUsage.Color, VertexAttribPointerType.Float, 0, 3));

            vertexBuffer = BufferFactory.Create(vertexFormat, BufferUsageHint.DynamicDraw);
            indexBuffer  = BufferFactory.Create(DrawElementsType.UnsignedInt, BufferUsageHint.StaticDraw);

            mesh.VertexBufferRange = vertexBuffer.CreateVertexBufferRange();
            var indexBufferRange = mesh.FindOrCreateIndexBufferRange(
                MeshMode.PolygonFill,
                indexBuffer,
                BeginMode.Triangles
                );

            vertexWriter = new VertexBufferWriter(mesh.VertexBufferRange);
            indexWriter  = new IndexBufferWriter(indexBufferRange);
        }
コード例 #2
0
        public NinePatch(NinePatchStyle style)
        {
            this.style = style;

            //mesh = new Mesh.Mesh(BufferUsageHint.DynamicDraw);
            mesh = new RenderStack.Mesh.Mesh();

            VertexFormat vertexFormat = new VertexFormat();

            vertexFormat.Add(new Attribute(VertexUsage.Position, VertexAttribPointerType.Float, 0, 3));
            vertexFormat.Add(new Attribute(VertexUsage.TexCoord, VertexAttribPointerType.Float, 0, 2));

            // \todo Allocate vertex buffers form from UI BufferPool and use double buffered Buffers
            // \todo Share one index buffer among all UI components that have the same index buffer
            //Buffer vertexBuffer = BufferPool.Instance.GetVertexBuffer(vertexFormat, BufferUsageHint.DynamicDraw);
            //Buffer indexBuffer = BufferPool.Instance.GetIndexBuffer(DrawElementsType.UnsignedShort, BufferUsageHint.StaticDraw);
            vertexBuffer = BufferFactory.Create(vertexFormat, BufferUsageHint.DynamicDraw);
            indexBuffer  = BufferFactory.Create(DrawElementsType.UnsignedShort, BufferUsageHint.StaticDraw);

            mesh.VertexBufferRange = vertexBuffer.CreateVertexBufferRange();
            IBufferRange indexBufferRange = mesh.FindOrCreateIndexBufferRange(
                MeshMode.PolygonFill,
                indexBuffer,
                BeginMode.Triangles
                );
            var writer = new IndexBufferWriter(indexBufferRange);

            vertexWriter = new VertexBufferWriter(mesh.VertexBufferRange);

            //  12 13 14 15
            //
            //   8  9 10 11
            //
            //   4  5  6  7
            //
            //   0  1  2  3

            writer.BeginEdit();

            writer.Quad(4, 5, 1, 0); writer.CurrentIndex += 6;
            writer.Quad(5, 6, 2, 1); writer.CurrentIndex += 6;
            writer.Quad(6, 7, 3, 2); writer.CurrentIndex += 6;

            writer.Quad(8, 9, 5, 4); writer.CurrentIndex   += 6;
            writer.Quad(9, 10, 6, 5); writer.CurrentIndex  += 6;
            writer.Quad(10, 11, 7, 6); writer.CurrentIndex += 6;

            writer.Quad(12, 13, 9, 8); writer.CurrentIndex   += 6;
            writer.Quad(13, 14, 10, 9); writer.CurrentIndex  += 6;
            writer.Quad(14, 15, 11, 10); writer.CurrentIndex += 6;

            writer.EndEdit();

            // \bug
            //indexBuffer.UpdateAll();
        }
コード例 #3
0
        public MeshRenderer(Mesh.Mesh mesh, Material material)
        {
            Mesh     = mesh;
            Material = material;

            if (Mesh == null)
            {
                throw new ArgumentNullException("Mesh can't be null!");
            }
        }
コード例 #4
0
ファイル: FontStyle.cs プロジェクト: tksuoran/renderstack_net
        public void BeginPrint(Mesh.Mesh mesh)
        {
            Bounds.ResetForGrow();

            var vertexFormat =  mesh.VertexBufferRange.VertexFormat;

            position = vertexFormat.FindAttribute(VertexUsage.Position, 0);
            texCoord = vertexFormat.FindAttribute(VertexUsage.TexCoord, 0);
            color    = vertexFormat.FindAttribute(VertexUsage.Color, 0);
        }
コード例 #5
0
 public Scene(Camera mainCamera, Light light, Mesh.Mesh mainObject)
 {
     EmbientColor = Color.Black;
     Light        = new List <Light>();
     MainCamera   = mainCamera;
     Light.Add(light);
     MainCamera.Scene = this;
     Light[0].Scene   = this;
     Background       = Color.Green;
     MainObject       = mainObject;
 }
コード例 #6
0
        public SkyRenderer(GraphicsDevice device, ContentManager content, string shaderPath)
        {
            mDevice = device;

            mShader = new SkyShader(content, shaderPath);

            var model = content.Load <Model>(SkyDomePath);

            mSkyDome = new Mesh.Mesh(model);

            mTint     = content.Load <Texture2D>(TintPath);
            mSunMorph = content.Load <Texture2D>(SunMorphPath);
            mMoon     = content.Load <Texture2D>(MoonPath);
        }
コード例 #7
0
        public Animator(Mesh.Mesh mesh)
        {
            mIsSkinned = mesh.mMeshData.mIsSkinned;

            if (mIsSkinned)
            {
                mBones      = mesh.mMeshData.mBones;
                mAnimations = mesh.mMeshData.mAnimations;

                mTransformations = new Matrix[mBones.Length];
            }

            mAnimationActors   = new List <AnimationActor>();
            mAttachments       = new List <Attachment>();
            mStandardAnimation = null;
        }
コード例 #8
0
        public GrassRenderer(GraphicsDevice device, ContentManager content, string shaderPath)
        {
            mShader = new GrassShader(content, shaderPath);

            var model = content.Load <Model>("Grass/Grass");

            mGrassMesh = new Mesh.Mesh(model);

            mGrassTexture = content.Load <Texture2D>("Grass/GrassTexture");

            mDevice         = device;
            mVisiblePatches = new List <Grass.Patch>();

            mBufferBindings        = new VertexBufferBinding[2];
            mBufferBindings[0]     = new VertexBufferBinding(mGrassMesh.VertexBuffer);
            mGrassInstancingBuffer = new VertexBuffer(mDevice, GrassInstancing.VertexDeclaration, 1, BufferUsage.WriteOnly);
        }
コード例 #9
0
        public void LoadAnimation(Mesh.Mesh mesh, string filename)
        {
            var importer = new AssimpContext();

            var boneConfig = new MaxBoneCountConfig(4);

            importer.SetConfig(boneConfig);

            var scene = importer.ImportFile(filename,
                                            PostProcessSteps.LimitBoneWeights |
                                            PostProcessSteps.MakeLeftHanded |
                                            PostProcessSteps.OptimizeGraph);

            if (scene.HasAnimations)
            {
                foreach (var animation in scene.Animations)
                {
                    mesh.mMeshData.mAnimations.Add(new Animation.Animation(animation, mesh.mMeshData.mBones));
                }
            }
        }
コード例 #10
0
        private void ContextCreated(object sender, NativeWindowEventArgs e)
        {
            AttributeId[] attributes = null;

            _vao = new VertexArrayObject(true);
            {
                var texture = new TQTexture(File.ReadAllBytes("texture.tex"));
                _texture = new Texture(TextureTarget.Texture2d);
                _texture.Parameteri(TextureParameterName.TextureWrapS, TextureWrapMode.Repeat);
                _texture.Parameteri(TextureParameterName.TextureWrapT, TextureWrapMode.Repeat);
                _texture.Parameteri(TextureParameterName.TextureMinFilter, TextureMinFilter.Linear);
                _texture.Parameteri(TextureParameterName.TextureMagFilter, TextureMagFilter.Linear);
                foreach (var frame in texture)
                {
                    var            dds = new DDS.DDS(frame.Data);
                    InternalFormat internalFormat;
                    if (dds.Header.Capabilities.HasFlag(Capabilities.Complex))
                    {
                        switch (dds.Header.PixelFormat.FourCC)
                        {
                        case "DXT5": internalFormat = InternalFormat.CompressedRgbaS3tcDxt5Ext; break;

                        default: throw new NotImplementedException();
                        }
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }

                    _texture.Storage2D((int)dds.Header.MipmapCount, internalFormat, (int)dds.Header.Width, (int)dds.Header.Height);
                    foreach (var layer in dds)
                    {
                        int level = 0;
                        foreach (var mip in layer)
                        {
                            unsafe
                            {
                                fixed(byte *ptr = mip.Data)
                                {
                                    _texture.CompressedSubImage2D(
                                        level++,
                                        internalFormat,
                                        xOffset: 0,
                                        yOffset: 0,
                                        width: (int)Math.Max(1, (dds.Header.Width * 2) >> level),
                                        height: (int)Math.Max(1, (dds.Header.Height * 2) >> level),
                                        data: mip.Data);
                                    Gl.CheckErrors();
                                }
                            }
                        }
                        break; //TODO: Further layers.
                    }
                    break;     //TODO: Further frames.
                }
            }

            var mesh = new Mesh.Mesh(File.ReadAllBytes("mesh.msh"));

            foreach (var part in mesh)
            {
                if (part.Is(out VertexBuffer vertexBuffer))
                {
                    Console.Write("Loading VBO...");
                    var vbo = new Buffer(true);
                    vbo.BufferData(vertexBuffer.Buffer, BufferUsage.StaticDraw);
                    _vao.VertexBuffer(0, vbo, IntPtr.Zero, vertexBuffer.Header.Stride);
                    Console.Write(" OK!");
                    attributes = vertexBuffer.Attributes.ToArray();
                    Console.Write($" (also got {attributes.Length} attributes)");
                    _vertexCount = vertexBuffer.Header.VertexCount;
                    Console.WriteLine($" (also got vertex count {_vertexCount})");
                }
                else if (part.Is(out Shaders shaders))
                {
                    foreach (var shader in shaders)
                    {
                        {
                            Console.Write($"Sort of loading {shader.FileName}...");
                            using (var vertexShader = new Shader(ShaderType.VertexShader, File.ReadAllText($"{shader.FileName}.vertex.glsl")))
                                using (var fragmentShader = new Shader(ShaderType.FragmentShader, File.ReadAllText($"{shader.FileName}.fragment.glsl")))
                                { _program = new ShaderProgram(vertexShader, fragmentShader); }
                            _program.Link();
                            Console.WriteLine(" OK!");
                        }
                        {
                            Console.Write($"Setting up attibutes...");
                            var offset = 0u;
                            foreach (var attribute in attributes)
                            {
                                switch (attribute)
                                {
                                case AttributeId.Position: SetUpAttribute(_vao, _program, "position", 3, VertexAttribType.Float, normalized: false, offset, bindingIndex: 0); break;

                                case AttributeId.Normal: SetUpAttribute(_vao, _program, "normal", 3, VertexAttribType.Float, normalized: true, offset, bindingIndex: 0); break;

                                case AttributeId.Tangent: SetUpAttribute(_vao, _program, "tangent", 3, VertexAttribType.Float, normalized: true, offset, bindingIndex: 0); break;

                                case AttributeId.Bitangent: SetUpAttribute(_vao, _program, "bitangent", 3, VertexAttribType.Float, normalized: true, offset, bindingIndex: 0); break;

                                case AttributeId.UV: SetUpAttribute(_vao, _program, "uv", 2, VertexAttribType.Float, normalized: false, offset, bindingIndex: 0); break;

                                case AttributeId.Weights: SetUpAttribute(_vao, _program, "weights", 4, VertexAttribType.Float, normalized: false, offset, bindingIndex: 0); break;

                                case AttributeId.Bones: SetUpAttribute(_vao, _program, "bones", 4, VertexAttribType.Byte, normalized: false, offset, bindingIndex: 0); break;

                                case AttributeId.Bytes: SetUpAttribute(_vao, _program, "bytes", 4, VertexAttribType.UnsignedByte, normalized: false, offset, bindingIndex: 0); break;
                                }
                                offset += GetAttributeSize(attribute);
                            }
                            Console.WriteLine(" OK!");
                        }
                        {
                            Console.Write($"Setting up uniforms...");
                            if (_program.TryGetUniformLocation("transformation", out var transformationUniform))
                            {
                                var matrix = new Matrix4x4(
                                    .5f, 0, 0, 0,
                                    0, .5f, 0, 0,
                                    0, 0, .5f, 0,
                                    0, -.7f, 0, 1
                                    );
                                _program.UniformMatrix4f(transformationUniform, transpose: false, in matrix);
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }
                            Console.WriteLine(" OK!");
                        }
                    }
                }
                else if (part.Is(out IndexBuffer indexBuffer))
                {
                    Console.Write("Loading IBO...");
                    var ibo = new Buffer(true);
                    ibo.BufferData(indexBuffer.TriangleIndices, BufferUsage.StaticDraw);
                    _vao.ElementBuffer(ibo);
                    Console.WriteLine(" OK!");

                    var drawRanges = new List <(int, int)>();
                    foreach (var drawCall in indexBuffer)
                    {
                        drawRanges.Add((drawCall.Common.StartFaceIndex, drawCall.Common.FaceCount));
                    }
                    _drawRanges = drawRanges.ToArray();
                }
                else if (part.Is(out Bones bones))
                {
                    _boneVao = new VertexArrayObject(true);
                    Console.Write("Loading Bones...");
                    _boneMatrices  = new Matrix4x4[bones.Count];
                    _bonePositions = new Vector3[bones.Count];
                    for (int i = 0; i < _boneMatrices.Length; i++)
                    {
                        _boneMatrices[i] = Matrix4x4.Identity;
                    }

                    foreach (var bone in bones)
                    {
                        var i            = bone.Index;
                        var position     = new Vector4(bone.Position, 1);
                        var bonePosition = Vector4.Transform(position, _boneMatrices[i]);
                        _bonePositions[i] = new Vector3(bonePosition.X, bonePosition.Y, bonePosition.Z);
                        var boneMatrix = new Matrix4x4(
                            bone.Axes[0], bone.Axes[1], bone.Axes[2], 0,
                            bone.Axes[3], bone.Axes[4], bone.Axes[5], 0,
                            bone.Axes[6], bone.Axes[7], bone.Axes[8], 0,
                            bone.Position.X, bone.Position.Y, bone.Position.Z, 1
                            );
                        _boneMatrices[i] = boneMatrix * _boneMatrices[i];
                        foreach (var childBone in bone)
                        {
                            _boneMatrices[childBone.Index] = _boneMatrices[i];
                        }
                    }

                    var            boneVbo     = new Buffer(true);
                    Span <Vector3> boneVboData = (from p in _bonePositions select new Vector3(p.X / 2, p.Y / 2 - .7f, p.Z / 2)).ToArray().AsSpan();
                    _boneVao.VertexBuffer(0, boneVbo, IntPtr.Zero, 3 * sizeof(float));
                    Gl.CheckErrors();
                    boneVbo.BufferData(boneVboData, BufferUsage.StaticDraw);
                    Gl.CheckErrors();

                    //TODO: LINQ it!
                    var boneIbo = new Buffer(true);
                    Gl.CheckErrors();
                    var boneIboEntries = new List <(int, int)>();
                    foreach (var parent in bones)
                    {
                        foreach (var child in parent)
                        {
                            boneIboEntries.Add((parent.Index, child.Index));
                        }
                    }
                    boneIbo.BufferData(boneIboEntries.SelectMany(x => new[] { (ushort)x.Item1, (ushort)x.Item2 }).ToArray().AsSpan(), BufferUsage.StaticDraw);
                    _boneVao.ElementBuffer(boneIbo);
                    Gl.CheckErrors();
                    _boneLinkCount = boneIboEntries.Count;

                    using (var vertexShader = new Shader(ShaderType.VertexShader, File.ReadAllText("bones.vertex.glsl")))
                        using (var fragmentShader = new Shader(ShaderType.FragmentShader, File.ReadAllText("bones.fragment.glsl")))
                        { _boneProgram = new ShaderProgram(vertexShader, fragmentShader); }
                    _boneProgram.Link();
                    Console.WriteLine(" OK!");

                    SetUpAttribute(_boneVao, _boneProgram, "position", 3, VertexAttribType.Float, normalized: false, relativeOffset: 0, bindingIndex: 0);

                    Gl.CheckErrors();
                }
            }
        }
コード例 #11
0
 public MeshRenderer(Mesh.Mesh mesh) : this(mesh, new VertexColorMaterial())
 {
 }
コード例 #12
0
        public async Task <IActionResult> GetStaticTile(int x, int y, int z, string formatExtension, [FromQuery] Guid projectUid, [FromQuery] Guid filterUid)
        {
            // todo for now default values. these will be passed in eventually
            var testDataPath = _configuration["TestDataPath"];

            Guid projectId = projectUid;
            Guid filterid  = filterUid;
            bool isValid   = Guid.TryParse(_configuration["DefaultProjectUid"], out projectId);

            if (!isValid)
            {
                return(NotFound()); // todo
            }
            if (z < 1)              // root level
            {
                // these two tiles are standard. Use tiler to fetch the correct tile
                var basicTile = await new Tiler.Tiler().FetchTile(testDataPath, x, y, z);
                if (basicTile != null)
                {
                    HttpContext.Response.Headers.Add("Content-Encoding", "gzip"); // already compressed on disk
                    HttpContext.Response.Headers.Add("Content-Length", basicTile.Length.ToString());
                    HttpContext.Response.Headers.Add("Content-Type", "application/octet-stream");
                    HttpContext.Response.Headers.Add("Content-Disposition", $"attachment;filename={y}.terrain");
                    return(File(basicTile, _TerrainDataQM));
                }

                Console.WriteLine($"*** Tile x:{x},y:{y},z:{z} was found ***");
                return(NotFound());
            }


            var elevData = await _demSource.GetDemXYZ(x, y, z); // DI injected for single instance

            // This class constructs a cesium quantized mesh from the dem
            var vertices = new Mesh.Mesh().MakeFakeMesh(ref elevData);

            var tempHeadr = new TerrainTileHeader()
            {
                MaximumHeight          = elevData.MaximumHeight,
                MinimumHeight          = elevData.MinimumHeight,
                CenterX                = elevData.CenterX,
                CenterY                = elevData.CenterY,
                CenterZ                = elevData.CenterZ,
                BoundingSphereCenterX  = elevData.BoundingSphereCenterX,
                BoundingSphereCenterY  = elevData.BoundingSphereCenterY,
                BoundingSphereCenterZ  = elevData.BoundingSphereCenterZ,
                BoundingSphereRadius   = elevData.BoundingSphereRadius,
                HorizonOcclusionPointX = elevData.HorizonOcclusionPointX,
                HorizonOcclusionPointY = elevData.HorizonOcclusionPointY,
                HorizonOcclusionPointZ = elevData.HorizonOcclusionPointZ
            };

            // This class constructs a quantized mesh tile mesh from the original mesh
            var tile = new Tiler.Tiler().MakeTile(vertices, tempHeadr, MapUtil.GridSizeToTriangleCount(elevData.GridSize),
                                                  elevData.GridSize);

            if (tile != null)
            {
                var compressed = MapUtil.Compress(tile);
                HttpContext.Response.Headers.Add("Content-Encoding", "gzip"); // already compressed on disk
                HttpContext.Response.Headers.Add("Content-Length", compressed.Length.ToString());
                HttpContext.Response.Headers.Add("Content-Type", "application/octet-stream");
                HttpContext.Response.Headers.Add("Content-Disposition", $"attachment;filename={y}.terrain");
                return(File(compressed, _TerrainDataQM));
            }

            return(NotFound());
        }
コード例 #13
0
        public async Task <IActionResult> GetBitmapTile(int x, int y, int z, string formatExtension)
        {
            // todo for now default values. these will be passed in eventually
            var testDataPath = _configuration["TestDataPath"];

            Guid projectId;
            bool isValid = Guid.TryParse(_configuration["DefaultProjectUid"], out projectId);

            if (!isValid)
            {
                return(NotFound()); // todo
            }
            if (z < 1)
            {
                // these two tiles are standard
                // Use tiler to fetch the correct tile
                var basicTile = await new Tiler.Tiler().FetchTile(testDataPath, x, y, z);
                if (basicTile != null)
                {
                    HttpContext.Response.Headers.Add("Content-Encoding", "gzip"); // already compressed on disk
                    //   HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*"); // already compressed on disk

                    HttpContext.Response.Headers.Add("Content-Length", basicTile.Length.ToString());
                    HttpContext.Response.Headers.Add("Content-Type", "application/octet-stream");
                    HttpContext.Response.Headers.Add("Content-Disposition", $"attachment;filename={y}.terrain");
                    return(File(basicTile, _TerrainDataQM));
                }

                Console.WriteLine($"*** Tile x:{x},y:{y},z:{z} was found ***");
                return(NotFound()); // todo
            }

            // Bitmap tiler
            BitmapDEMSource demSrc   = new BitmapDEMSource();
            var             elevData = await demSrc.GetDemXYZ(x, y, z); // DI injected for single instance

            // This class constructs a cesium quantized mesh from the dem
            var vertices = new Mesh.Mesh().MakeFakeMesh(ref elevData);

            // todo fill in header details
            var tempHeadr = new TerrainTileHeader()
            {
                MaximumHeight          = elevData.MaximumHeight,
                MinimumHeight          = elevData.MinimumHeight,
                CenterX                = elevData.CenterX,
                CenterY                = elevData.CenterY,
                CenterZ                = elevData.CenterZ,
                BoundingSphereCenterX  = elevData.BoundingSphereCenterX,
                BoundingSphereCenterY  = elevData.BoundingSphereCenterY,
                BoundingSphereCenterZ  = elevData.BoundingSphereCenterZ,
                BoundingSphereRadius   = elevData.BoundingSphereRadius,
                HorizonOcclusionPointX = elevData.HorizonOcclusionPointX,
                HorizonOcclusionPointY = elevData.HorizonOcclusionPointY,
                HorizonOcclusionPointZ = elevData.HorizonOcclusionPointZ
            };

            // This class constructs a quantized mesh tile mesh from the original mesh
            var tile = new Tiler.Tiler().MakeTile(vertices, tempHeadr, MapUtil.GridSizeToTriangleCount(elevData.GridSize),
                                                  elevData.GridSize);

            // Debugging code
            string   file = $"c:\\temp\\Test-{x}-{y}-{z}.terrain";
            FileInfo fi   = new FileInfo(file);

            if (!fi.Exists && z == 8 && x == 501)
            {
                var ms = new MemoryStream(tile);
                using (FileStream fs = new FileStream(file, FileMode.Create))
                    using (GZipStream zipStream = new GZipStream(fs, CompressionMode.Compress, false))
                    {
                        zipStream.Write(ms.ToArray(), 0, ms.ToArray().Length); // .Write(bytes, 0, bytes.Length);
                    }
            }

            if (tile != null)
            {
                var compressed = MapUtil.Compress(tile);
                HttpContext.Response.Headers.Add("Content-Encoding", "gzip"); // already compressed on disk
                HttpContext.Response.Headers.Add("Content-Length", compressed.Length.ToString());
                HttpContext.Response.Headers.Add("Content-Type", "application/octet-stream");
                HttpContext.Response.Headers.Add("Content-Disposition", $"attachment;filename={y}.terrain");
                return(File(compressed, _TerrainDataQM));
                // return Ok(MapUtil.Compress(tile));
            }
            else
            {
                return(NotFound());
            }
        }
コード例 #14
0
        public async Task <IActionResult> GetFakeTile(int x, int y, int z, string formatExtension)
        {
            // todo for now default values. these will be passed in eventually
            var testDataPath = _configuration["TestDataPath"];

            Guid projectId;
            bool isValid = Guid.TryParse(_configuration["DefaultProjectUid"], out projectId);

            if (!isValid)
            {
                return(NotFound()); // todo
            }
            if (z < 1)
            {
                // these two tiles are standard
                // Use tiler to fetch the correct tile
                var basicTile = await new Tiler.Tiler().FetchTile(testDataPath, x, y, z);
                if (basicTile != null)
                {
                    HttpContext.Response.Headers.Add("Content-Encoding", "gzip"); // already compressed on disk
                    //   HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*"); // already compressed on disk

                    HttpContext.Response.Headers.Add("Content-Length", basicTile.Length.ToString());
                    HttpContext.Response.Headers.Add("Content-Type", "application/octet-stream");
                    HttpContext.Response.Headers.Add("Content-Disposition", $"attachment;filename={y}.terrain");
                    Console.WriteLine($"*** Tile x:{x},y:{y},z:{z} was found ***");
                    return(File(basicTile, _TerrainDataQM));
                }

                return(NotFound());
            }

            FakeDEMSource demSrc = new FakeDEMSource();

            demSrc.Initalize(new MapHeader()
            {
                GridSize = _GridSize
            });

            // todo x,y,z to lat lon
            var elevData = await demSrc.GetDemLL(1, 1, 1, 1); // just the same tile always for now

            // This class constructs a cesium quantized mesh from the dem
            var vertices = new Mesh.Mesh().MakeFakeMesh(ref elevData);

            // todo fill in header details
            var tempHeadr = new TerrainTileHeader()
            {
                MaximumHeight = elevData.MaximumHeight,
                MinimumHeight = elevData.MinimumHeight
            };

            // This class constructs a quantized mesh tile mesh from the original mesh
            var tile = new Tiler.Tiler().MakeTile(vertices, tempHeadr, MapUtil.GridSizeToTriangleCount(elevData.GridSize),
                                                  elevData.GridSize);

            if (tile != null)
            {
                var compressed = MapUtil.Compress(tile);
                HttpContext.Response.Headers.Add("Content-Encoding", "gzip"); // already compressed on disk
                //   HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*"); // already compressed on disk

                HttpContext.Response.Headers.Add("Content-Length", compressed.Length.ToString());
                HttpContext.Response.Headers.Add("Content-Type", "application/octet-stream");
                HttpContext.Response.Headers.Add("Content-Disposition", $"attachment;filename={y}.terrain");
                return(File(compressed, _TerrainDataQM));
            }
            else
            {
                return(NotFound());
            }
        }