public StreamingChunkGeneratorScript(IStage <ChunkKey, Entity> stage, StreamingStageMeshFactory meshFactory)
        {
            Contracts.Requires.That(stage != null);
            Contracts.Requires.That(meshFactory != null);

            this.meshFactory = meshFactory;

            stage.Activated.Subscribe(async pair =>
            {
                pair.Value.Transform.Position = pair.Key.Index.ToXenkoVector() * this.meshFactory.ChunkLength;
                this.Entity.AddChild(pair.Value);

                // Do not use DontMarshallContext here. Must stay on UI thread.
                var model = await this.generator?.GenerateModelAsync(pair.Key);
                if (model != null)
                {
                    pair.Value.Add(new ModelComponent(model));
                }
            });

            stage.Deactivated.Subscribe(pair =>
            {
                this.Entity.RemoveChild(pair.Value);
                pair.Value.Get <ModelComponent>()?.Model.Dispose();
                pair.Value.Dispose();
            });
        }
        public StreamingChunkGenerator(
            StreamingStageMeshFactory meshFactory, MaterialInstance material, GraphicsDevice device)
        {
            Contracts.Requires.That(meshFactory != null);
            Contracts.Requires.That(material != null);
            Contracts.Requires.That(device != null);

            this.meshFactory = meshFactory;
            this.material    = material;

            this.proceduralMesh = new ProceduralMeshFactory16 <VertexPositionNormalColorTexture>(
                VertexPositionNormalColorTexture.Format, device);

            var transferOptions = new TrackingPoolOptions <MeshDataTransfer16 <VertexPositionNormalColorTexture> >()
            {
                BoundedCapacity = this.meshFactory.ThreadsCount,
            };

            this.transferPool = Pool.New(transferOptions);

            var meshOptions = MeshDataTransferOptions.New16Bit();

            meshOptions.InitialIndices = meshOptions.InitialVertices * 2;
            this.maxVertices           = meshOptions.MaxVertices;

            this.transferPool.GiveUntilFull(
                Factory.From(() => new MeshDataTransfer16 <VertexPositionNormalColorTexture>(meshOptions)));

            this.throttler = new AsyncTaskThrottler <ChunkKey, Model>(
                this.DoGenerateModelAsync, this.meshFactory.ThreadsCount);
            ////key => Task.Run(() => this.DoGenerateModelAsync(key)), this.meshFactory.ThreadsCount);
        }
        /// <inheritdoc />
        public override void Start()
        {
            base.Start();

            var observablePosition = new ObservablePosition()
            {
                ToggleEnabledKey = Keys.D1,
                IsEnabled        = true,
            };

            var camera = this.SceneSystem.SceneInstance.RootScene.Entities.First(entity => entity.Name == "Camera");

            camera.Add(observablePosition);
            ////camera.Transform.Position += new Vector3(0, 0, 0);
            camera.Transform.Position += new Vector3(0, 256, 0);

            this.stage = new InterestStage <ChunkKey, bool, Entity>(
                Factory.From((ChunkKey key) => new Entity()), SingleInterest.Merger);

            ////var meshFactory = StreamingStageMeshFactory.CreateCubes();
            ////var meshFactory = StreamingStageMeshFactory.CreateCubeOutlines();
            ////var meshFactory = StreamingStageMeshFactory.CreateNoise();
            var meshFactory = StreamingStageMeshFactory.CreateSkyIsland();

            var viewDiameter = meshFactory.ChunkLength * ViewDiameterInChunks;
            var converter    = new TwoWayTypeConverter <Index3D, ChunkKey>(
                index => new ChunkKey(index), key => key.Index);

            AreaOfInterest.CreateCenteredSpiral(
                new ConverterInterestMap <ChunkKey, Index3D, bool>(this.stage.Interests, converter),
                true,
                observablePosition.PositionChanged.ToMono(),
                new SphereMask <bool>(viewDiameter),
                meshFactory.ChunkLength);

            var stageEntity = new Entity("Stage");

            stageEntity.Add(new StreamingChunkGeneratorScript(this.stage.Chunks, meshFactory));
            this.SceneSystem.SceneInstance.RootScene.Entities.Add(stageEntity);
        }