private void ComputeQuadrant(FovData data, int deltaX, int deltaY, int maxX, int maxY) { var activeViews = new List <View>(); int i; var shallowLine = new Line(0, 1, maxX, 0); var steepLine = new Line(1, 0, 0, maxY); activeViews.Add(new View(shallowLine, steepLine)); int viewIndex = 0; // Visit the tiles diagonally and going outwards // // . // . // 9 // 58 // 247 // @136.. int maxI = maxX + maxY; for (i = 1; i <= maxI && activeViews.Count != 0; ++i) { int startJ = (0 > i - maxX ? 0 : i - maxX); int maxJ = (i < maxY ? i : maxY); int j; for (j = startJ; j <= maxJ && viewIndex < activeViews.Count; ++j) { VisitPoint(data, i - j, j, deltaX, deltaY, ref viewIndex, activeViews); } } }
public HashSet <Point> Compute(int startX, int startY, int radius) { var data = new FovData { IsTransparent = isTransparent, StartX = startX, StartY = startY, Visited = new HashSet <Point>() }; // Will always see the centre. data.Visited.Add(new Point(startX, startY)); // Get the dimensions of the actual field of view, making sure not to go off the map or beyond the radius. int minExtentX = (startX < radius ? startX : radius); int maxExtentX = (mapWidth - startX <= radius ? mapWidth - startX - 1 : radius); int minExtentY = (startY < radius ? startY : radius); int maxExtentY = (mapHeight - startY <= radius ? mapHeight - startY - 1 : radius); ComputeQuadrant(data, 1, 1, maxExtentX, maxExtentY); ComputeQuadrant(data, 1, -1, maxExtentX, minExtentY); ComputeQuadrant(data, -1, -1, minExtentX, minExtentY); ComputeQuadrant(data, -1, 1, minExtentX, maxExtentY); return(data.Visited); }
public Task UpdateCamera(FovData fovData) { var tcs = new TaskCompletionSource <object>(); PostAction(() => { _tree.UpdateLod(fovData); tcs.SetResult(null); return(TaskUtils.EmptyCompleted()); }); return(tcs.Task); }
public void UpdateHeightmap() { _ring1Tree.UpdateLod(FovData.FromCamera(_camera)); }
private static void VisitPoint(FovData data, int x, int y, int deltaX, int deltaY, ref int viewIndex, List <View> activeViews) { var topLeft = new Point(x, y + 1); var bottomRight = new Point(x + 1, y); // The top left and bottom right corners of the current coordinate. for (; viewIndex < activeViews.Count && activeViews[viewIndex].SteepLine.IsBelowOrCollinear(bottomRight.X, bottomRight.Y); ++viewIndex) { // The current coordinate is above the current view and is ignored. The steeper fields may need it though. } if (viewIndex == activeViews.Count || activeViews[viewIndex].ShallowLine.IsAboveOrCollinear(topLeft.X, topLeft.Y) ) { // Either the current coordinate is above all of the fields or it is below all of the fields. return; } // It is now known that the current coordinate is between the steep // and shallow lines of the current view. // The real quadrant coordinates int realX = x * deltaX; int realY = y * deltaY; var pt = new Point(data.StartX + realX, data.StartY + realY); data.Visited.Add(new Point(pt.X, pt.Y)); if (data.IsTransparent(pt)) { // The current coordinate does not block sight and therefore has no effect on the view. return; } // The current coordinate is an obstacle. bool shallowLineIsAboveBottomRight = activeViews[viewIndex].ShallowLine.IsAbove(bottomRight.X, bottomRight.Y); bool steepLineIsBelowTopLeft = activeViews[viewIndex].SteepLine.IsBelow(topLeft.X, topLeft.Y); if (shallowLineIsAboveBottomRight && steepLineIsBelowTopLeft) { // The obstacle is intersected by both lines in the current view. The view is completely blocked. activeViews.RemoveAt(viewIndex); } else if (shallowLineIsAboveBottomRight) { // The obstacle is intersected by the shallow line of the current view. The shallow line needs to be raised. AddShallowBump(topLeft.X, topLeft.Y, activeViews, viewIndex); CheckView(activeViews, viewIndex); } else if (steepLineIsBelowTopLeft) { // The obstacle is intersected by the steep line of the current view. The steep line needs to be lowered. AddSteepBump(bottomRight.X, bottomRight.Y, activeViews, viewIndex); CheckView(activeViews, viewIndex); } else { // The obstacle is completely between the two lines of the current view. // Split the current view into two views above and below the current coordinate. int shallowViewIndex = viewIndex; int steepViewIndex = ++viewIndex; activeViews.Insert(shallowViewIndex, activeViews[shallowViewIndex].Clone()); AddSteepBump(bottomRight.X, bottomRight.Y, activeViews, shallowViewIndex); if (!CheckView(activeViews, shallowViewIndex)) { --steepViewIndex; } AddShallowBump(topLeft.X, topLeft.Y, activeViews, steepViewIndex); CheckView(activeViews, steepViewIndex); } }
public void Start() { InitializeWelding(); /// /// VISIBILITY TEXTURE var visibilityTextureSideLength = 16; var visibilityTexture = new Texture2D(visibilityTextureSideLength, visibilityTextureSideLength, TextureFormat.RFloat, false); visibilityTexture.filterMode = FilterMode.Point; var visibilityTextureProcessorProxy = new Ring1VisibilityTextureProcessorUTProxy(new Ring1VisibilityTextureProcessor(visibilityTexture)); _ultraUpdatableContainer.Add(visibilityTextureProcessorProxy); var visibilityTextureChangeGrabber = new Ring1VisibilityTextureChangeGrabber(); var terrainParentGameObject = new GameObject("TerrainParent"); terrainParentGameObject.transform.localPosition = new Vector3(0, 0, 0); var globalSideLength = _gRingConfiguration.Ring1GlobalSideLength; var globalSize = new Vector2(globalSideLength, globalSideLength); var unityCoordsCalculator = new UnityCoordsCalculator(globalSize); var orderGrabber = new Ring1PaintingOrderGrabber(); var painterProxy = new RingTerrainPainterUTProxy(new RingTerrainPainter(_gRingConfiguration.MakeTerrainVisible)); _ultraUpdatableContainer.Add(painterProxy); painterProxy.Update(); var mainRespondingProxy = new Ring1NodeEventMainRespondingProxy(new Ring1NodeEventMainResponder()); _ultraUpdatableContainer.AddOtherThreadProxy(new OtherThreadProxyWithPerPostAction() { OtherThreadProxy = mainRespondingProxy, PerPostAction = () => { var delta = visibilityTextureChangeGrabber.RetriveVisibilityChanges(); if (delta.AnyChange) { var visibilityTextureChagnes = visibilityTextureChangeGrabber.RetriveVisibilityChanges(); visibilityTextureProcessorProxy.AddOrder(visibilityTextureChagnes); } if (orderGrabber.IsAnyOrder) { painterProxy.AddOrder(orderGrabber.RetriveOrderAndClear()); } } }); var stainTerrainResourceCreatorUtProxy = new StainTerrainResourceCreatorUTProxy(new StainTerrainResourceCreator()); _ultraUpdatableContainer.Add(stainTerrainResourceCreatorUtProxy); var stainTerrainServiceProxy = new StainTerrainServiceProxy( new StainTerrainService( new FromFileStainTerrainResourceGenerator(_configuration.StainTerrainServicePath, _gameInitializationFields.Retrive <CommonExecutorUTProxy>()), //new ComputationStainTerrainResourceGenerator( // new StainTerrainResourceComposer( // _stainTerrainResourceCreatorUtProxy // ), // new StainTerrainArrayMelder(), // new DummyStainTerrainArrayFromBiomesGenerator( // new DebugBiomeContainerGenerator().GenerateBiomesContainer(new BiomesContainerConfiguration()), // new StainTerrainArrayFromBiomesGeneratorConfiguration() // )), _gRingConfiguration.Ring1GenerationArea)); _ultraUpdatableContainer.AddOtherThreadProxy(stainTerrainServiceProxy); var ring1Tree = new Ring1Tree(_gRingConfiguration.Ring1TreeConfiguration); var ring1TreeProxy = new Ring1TreeProxy(ring1Tree); _gameInitializationFields.Retrive <LateAssignBox <Ring1TreeProxy> >().Set(ring1TreeProxy); _ultraUpdatableContainer.AddOtherThreadProxy(ring1TreeProxy); var terrainShapeDbInitialization = new FETerrainShapeDbInitialization(_ultraUpdatableContainer, _gameInitializationFields, _configuration, new FilePathsConfiguration()); terrainShapeDbInitialization.Start(); var gRing0NodeTerrainCreator = new GRing0NodeTerrainCreator( orderGrabber, terrainParentGameObject, _gameInitializationFields.Retrive <MeshGeneratorUTProxy>(), _gameInitializationFields.Retrive <ITerrainShapeDb>(), unityCoordsCalculator, _gameInitializationFields.Retrive <GRingSpotUpdater>(), _gameInitializationFields.Retrive <HeightArrayWeldingPack>(), _gRingConfiguration.GroundShapeProviderConfiguration, _gRingConfiguration.TerrainMeshProviderConfiguration); var gRing1NodeTerrainCreator = new GRing1NodeTerrainCreator( orderGrabber, terrainParentGameObject, _gameInitializationFields.Retrive <MeshGeneratorUTProxy>(), _gameInitializationFields.Retrive <ITerrainShapeDb>(), stainTerrainServiceProxy, unityCoordsCalculator, _gameInitializationFields.Retrive <GRingSpotUpdater>(), _gameInitializationFields.Retrive <HeightArrayWeldingPack>(), _gRingConfiguration.GroundShapeProviderConfiguration, _gRingConfiguration.TerrainMeshProviderConfiguration); var gRing2PatchesCreatorProxy = _gameInitializationFields.Retrive <GRing2PatchesCreatorProxy>(); var gRing2NodeTerrainCreator = new GRing2NodeTerrainCreator( orderGrabber, terrainParentGameObject, _gameInitializationFields.Retrive <MeshGeneratorUTProxy>(), _gameInitializationFields.Retrive <ITerrainShapeDb>(), unityCoordsCalculator, gRing2PatchesCreatorProxy, _gameInitializationFields.Retrive <GRingSpotUpdater>(), _gameInitializationFields.Retrive <HeightArrayWeldingPack>(), _gRingConfiguration.GroundShapeProviderConfiguration, _gRingConfiguration.TerrainMeshProviderConfiguration); var gDebugNodeTerrainCreator = new GDebugLodNodeTerrainCreator( orderGrabber, terrainParentGameObject, unityCoordsCalculator, _gameInitializationFields.Retrive <MeshGeneratorUTProxy>() ); var gDebugTerrainedNodeTerrainCreator = new GDebugTerrainedLodNodeTerrainCreator( orderGrabber, terrainParentGameObject, unityCoordsCalculator, _gameInitializationFields.Retrive <MeshGeneratorUTProxy>(), _gameInitializationFields.Retrive <ITerrainShapeDb>(), _gRingConfiguration.GroundShapeProviderConfiguration, _gameInitializationFields.Retrive <GRingSpotUpdater>() ); var gStampedRing2NodeTerrainCreator = new GStampedRing2NodeTerrainCreator( orderGrabber, terrainParentGameObject, _gameInitializationFields.Retrive <MeshGeneratorUTProxy>(), _gameInitializationFields.Retrive <ITerrainShapeDb>(), unityCoordsCalculator, gRing2PatchesCreatorProxy, _gameInitializationFields.Retrive <Ring2PatchStamplingOverseerFinalizer>(), _gameInitializationFields.Retrive <GRingSpotUpdater>(), _gameInitializationFields.Retrive <HeightArrayWeldingPack>(), _gRingConfiguration.GroundShapeProviderConfiguration, _gRingConfiguration.TerrainMeshProviderConfiguration); var gCompositeRing2NodeTerrainCreator = new GCompositeRing2NodeTerrainCreator( orderGrabber, terrainParentGameObject, _gameInitializationFields.Retrive <MeshGeneratorUTProxy>(), _gameInitializationFields.Retrive <ITerrainShapeDb>(), unityCoordsCalculator, gRing2PatchesCreatorProxy, _gameInitializationFields.Retrive <GRingSpotUpdater>(), _gameInitializationFields.Retrive <HeightArrayWeldingPack>(), _gameInitializationFields.Retrive <Ring2PatchStamplingOverseerFinalizer>(), _gRingConfiguration.GroundShapeProviderConfiguration, _gRingConfiguration.TerrainMeshProviderConfiguration); //var gCompositeRing2NodeTerrainCreator = new GCompositeRing2NodeTerrainCreator( // new List<INewGRingListenersCreator>() // { // gRing2NodeTerrainCreator, // gStampedRing2NodeTerrainCreator, // }); var subCreator = new SupremeGRingNodeTerrainCreator(new List <NewListenersCreatorWithLimitation>() { //new NewListenersCreatorWithLimitation() //{ // Creator = gDebugTerrainedNodeTerrainCreator, // MaximumLod = new FlatLod(14), // //PositionLimiter = new NewListenersCreatorPositionLimiter(new Vector2(0.5f, 0.6f), 0.025f) //}, //new NewListenersCreatorWithLimitation() //{ // Creator = gRing0NodeTerrainCreator, // MaximumLod = new FlatLod(5), //}, new NewListenersCreatorWithLimitation() { Creator = new GVoidNodeTerrainCreator(), MaximumLod = new FlatLod(5), //IsFallthroughCreator = true }, new NewListenersCreatorWithLimitation() { Creator = gRing1NodeTerrainCreator, MaximumLod = new FlatLod(10) }, new NewListenersCreatorWithLimitation() { Creator = gRing2NodeTerrainCreator, MaximumLod = new FlatLod(14) }, new NewListenersCreatorWithLimitation() { Creator = gStampedRing2NodeTerrainCreator, MaximumLod = new FlatLod(13) }, new NewListenersCreatorWithLimitation() { Creator = gCompositeRing2NodeTerrainCreator, MaximumLod = new FlatLod(14) } //new NewListenersCreatorWithLimitation() //{ // Creator = gDebugNodeTerrainCreator, // MaximumLod = new FlatLod(11) //}, }); var eventCollector = new Ring1NodeEventCollector( new DynamicFlatLodGRingNodeTerrainCreator(subCreator, new FlatLodCalculator(unityCoordsCalculator, _gRingConfiguration.FlatLodConfiguration))); _ultraUpdatableContainer.AddOtherThreadProxy( new OtherThreadProxyWithPerPostAction() { OtherThreadProxy = ring1TreeProxy, PerPostAction = () => { if (eventCollector.Any) { mainRespondingProxy.AddOrder(eventCollector.RetriveOrderAndClear()); } } } ); var repositioner = _gameInitializationFields.Retrive <Repositioner>(); _ultraUpdatableContainer.AddUpdatableElement(new FieldBasedUltraUpdatable() { UpdateCameraField = (camera) => { if (_configuration.UpdateRingTree) { ring1TreeProxy.UpdateCamera(FovData.FromCamera(camera, repositioner)); } } }); _ultraUpdatableContainer.AddUpdatableElement(new FieldBasedUltraUpdatable() { StartCameraField = (camera) => { ring1TreeProxy.CreateHeightmap( new Ring1Tree.RootNodeCreationParameters() { InitialCameraPosition = repositioner.InvMove(camera.Position), NodeListener = eventCollector, PrecisionDistances = _gRingConfiguration.QuadLodPrecisionDistances, UnityCoordsCalculator = unityCoordsCalculator }); } }); }