private static ChunkJob MakeChunkJob(Vector3 Min, float Size, byte LOD, ChunkManageInput Input)
        {
            ChunkJob Job = new ChunkJob();

            Job.Key        = Size.ToString() + Min.ToString() + LOD.ToString();
            Job.LOD        = LOD;
            Job.Min        = Min;
            Job.Resolution = Input.Resolution;
            Job.CellSize   = Size;
            return(Job);
        }
        public static ChunkJobResult CreateChunk(ChunkJob Job)
        {
            ChunkJobResult result = new ChunkJobResult();

            try {
                Stopwatch s = new Stopwatch();
                s.Start();
                SE.OpenSimplexNoise noise = new SE.OpenSimplexNoise(1);

                result.Error       = null;
                result.OriginalJob = Job;
                result.DebugPrint  = "";


                ExtractionInput input = new ExtractionInput();
                input.Isovalue   = 0;
                input.LODSides   = Job.LOD;
                input.Resolution = new Util.Vector3i(Job.Resolution, Job.Resolution, Job.Resolution);
                input.Size       = new Vector3(Job.CellSize, Job.CellSize, Job.CellSize);

                int numTimesSampled = 0;

                input.Sample = (float x, float y, float z) => {
                    numTimesSampled++;
                    float res = sample(noise, x + Job.Min.x, y + Job.Min.y, z + Job.Min.z);
                    return(res);
                };

                ExtractionResult ExResult = SurfaceExtractor.ExtractSurface(input);
                result.Result = ExResult;



                s.Stop();
                result.ProcessingTime = s.ElapsedMilliseconds;
            }
            catch (System.Exception exc) {
                result.Error = "Error in thread " + Job.ThreadID + ": " + exc.Message + ", Stacktrace: " + exc.StackTrace;
            }
            return(result);
        }
        private static List <ChunkJob> GetChunksAroundPoint(Vector3 Point, ChunkManageInput Input)          // inspired by https://github.com/felixpalmer/lod-terrain/blob/master/js/app/terrain.js
        {
            UnityEngine.Debug.Log("GetChunksAroundPoint called");

            List <ChunkJob> ChunkJobs = new List <ChunkJob>();
            float           ChunkSize = Input.MinSizeOfCell * Input.Resolution;

            // First pretend like you're creating a chunks structure with center 0,0,0
            // Pretend Min chunk size is one
            // Then multiply all the chunk mins by the real chunk size
            // Then offset all the chunks by Point

            // Create center 2x2x2 cube first
            // No LODsides
            for (int x = -1; x < 1; x++)
            {
                for (int y = -1; y < 1; y++)
                {
                    for (int z = -1; z < 1; z++)
                    {
                        ChunkJob c = MakeChunkJob((new Vector3(x, y, z) + Point) * ChunkSize, Input.MinSizeOfCell, 0, Input);
                        ChunkJobs.Add(c);
                    }
                }
            }

            // Create hollow cubes of chunks
            // Iterate through full cube, but don't generate new chunk if not edge chunk
            for (int i = 0; i < Input.LODs; i++)
            {
                int size  = (int)Mathf.Pow(2, i);                // size of chunks (1, 2, 4, 8...)
                int dSize = size * 2;
                for (int x = -dSize; x < dSize; x += size)
                {
                    for (int y = -dSize; y < dSize; y += size)
                    {
                        for (int z = -dSize; z < dSize; z += size)
                        {
                            // Check if edge chunk by first calculating LOD sides
                            byte LOD = 0;
                            if (x == -dSize)
                            {
                                LOD |= 1;                                                    // -x
                            }
                            if (x == dSize - size)
                            {
                                LOD |= 2;                                                // +x
                            }
                            if (y == -dSize)
                            {
                                LOD |= 4;                                                    // -y
                            }
                            if (y == dSize - size)
                            {
                                LOD |= 8;                                                // +y
                            }
                            if (z == -dSize)
                            {
                                LOD |= 16;                                                   // -z
                            }
                            if (z == dSize - size)
                            {
                                LOD |= 32;                                               // +z
                            }
                            if (LOD != 0)
                            {
                                ChunkJob c = MakeChunkJob((new Vector3(x, y, z) + Point) * ChunkSize, size * Input.MinSizeOfCell, LOD, Input);
                                ChunkJobs.Add(c);
                            }
                        }
                    }
                }
            }

            return(ChunkJobs);
        }