Пример #1
0
    public static void UpdateDiscoveryStatusOnSideThread(DiscoveryMap discoveryMap, List <Observer.Info> observerInfo)
    {
        discoveryMap.ClearCurrentVisibilityBlock();

        pixelBlock             = discoveryMap.asPixelBlock;
        currentVisibilityBlock = discoveryMap.currentVisibilityPixelBlock;
        heightArray            = discoveryMap.heightMap;
        mapPixelWidth          = discoveryMap.pixelWidth;
        mapPixelHeight         = discoveryMap.pixelHeight;

        for (int i = 0; i < observerInfo.Count; ++i)
        {
            var observer = observerInfo[i];

            int startX = Mathf.RoundToInt(observer.mapPositionX);
            int startY = Mathf.RoundToInt(observer.mapPositionY);

            // Draw 1/8th of a circle
            int r      = Mathf.RoundToInt(observer.viewRadiusMapUnits);
            int deltaX = r;
            int deltaY = 0;

            do
            {
                if (r <= deltaY * deltaY)
                {
                    deltaX -= 1;
                    r      += 2 * deltaX + 1;
                }

                DiscoverLOS(discoveryMap, deltaX, deltaY, startX, startY, observer.height);
                deltaY++;
            } while (deltaY < deltaX);
        }
    }
Пример #2
0
    public void Setup(float worldRadius, DiscoveryMap map)
    {
        terrainOffset    = map.terrainOffset;
        terrainSize      = map.terrainSize;
        discoveryMapSize = map.mapSize;

        UpdatePosition(CachedTransform.position);
        UpdateRadius(worldRadius);
    }
Пример #3
0
    private void Start()
    {
        discoveryMap = new DiscoveryMap(terrain);

        discoveryMapMaterial.SetTexture("_Mask", discoveryMap.texture);
        discoveryMapMaterial.SetTexture("_CurrentVisibility", discoveryMap.currentVisibilityMap);
        discoveryMapMaterial.SetVector("_TerrainSize", discoveryMap.terrainSize);

        mainCamera       = Camera.main;
        mainCamTransform = mainCamera.transform;
    }
Пример #4
0
    private void AdjustHeightMap(DiscoveryMap map, bool add)
    {
        Vector2 mapCentre    = map.CalculateMapPosition(transform.position);
        Vector2 mapSpaceSize = map.CalculateMapSpaceDimensions(Size);

        float orientation = Mathf.Deg2Rad * transform.eulerAngles.y;
        float cos         = Mathf.Cos(orientation);
        float sin         = Mathf.Sin(orientation);

        Vector2 right = new Vector2(cos, sin);
        Vector2 up    = new Vector2(-sin, cos);

        Vector2    mapStartPos   = mapCentre - (right * mapSpaceSize.x / 2f) - (up * mapSpaceSize.y / 2f);
        IntVector2 mapStartIndex = new IntVector2(Mathf.RoundToInt(mapStartPos.x), Mathf.RoundToInt(mapStartPos.y));

        var actualHeights = relativeHeightMap.actualHeights;

        Vector2 pos  = mapStartPos;
        float   sign = add ? 1f : -1f;

        for (int y = 0; y < mapSpaceSize.y; ++y)
        {
            for (int x = 0; x < mapSpaceSize.x; ++x)
            {
                IntVector2 customHeightMapIndex = new IntVector2(x * relativeHeightMap.sizeX / mapSpaceSize.x,
                                                                 y * relativeHeightMap.sizeY / mapSpaceSize.y);

                IntVector2 nextCustomHeightMapIndex = new IntVector2((x + 1) * relativeHeightMap.sizeX / mapSpaceSize.x,
                                                                     (y + 1) * relativeHeightMap.sizeY / mapSpaceSize.y);

                int   affectedHeightmapPixelCount = 0;
                float heightAdjustmentValue       = 0f;
                bool  paintedAtLeastOnePixel      = false;

                for (int cy = customHeightMapIndex.y; !paintedAtLeastOnePixel || cy < nextCustomHeightMapIndex.y; ++cy)
                {
                    for (int cx = customHeightMapIndex.x; !paintedAtLeastOnePixel || cx < nextCustomHeightMapIndex.x; ++cx)
                    {
                        paintedAtLeastOnePixel = true;

                        if (cx >= 0 && cx < relativeHeightMap.sizeX &&
                            cy >= 0 && cy < relativeHeightMap.sizeY)
                        {
                            float heightDelta = actualHeights[cy, cx] * sign;

                            affectedHeightmapPixelCount++;
                            heightAdjustmentValue += heightDelta;
                        }
                    }
                }

                if (affectedHeightmapPixelCount > 0)
                {
                    Vector2 nextMapPos = mapStartPos + right * x + up * y;

                    int mapIndexX = Mathf.RoundToInt(nextMapPos.x);
                    int mapIndexY = Mathf.RoundToInt(nextMapPos.y);

                    map.heightMap[mapIndexY, mapIndexX] += (heightAdjustmentValue / affectedHeightmapPixelCount);
                }
            }
        }
    }
Пример #5
0
 public void RemoveFromMap(DiscoveryMap map)
 {
     AdjustHeightMap(map, add: false);
     isPlacedOnMap = false;
 }
Пример #6
0
 public void PlaceOnMap(DiscoveryMap map)
 {
     relativeHeightMap.CalculateActualHeight(Size.y, map.terrainSize.y);
     AdjustHeightMap(map, add: true);
     isPlacedOnMap = true;
 }
Пример #7
0
    private static bool DiscoverLOS(DiscoveryMap map, int deltaX, int deltaY, int startX, int startY, float obsHeight)
    {
        pixelBlock[startY * mapPixelWidth + startX] = discovered;

        // This is essentially a line-drawing routine that has some strong assumptions:
        // namely that deltaX > deltaY. Then, after the calculation of each point in the line,
        // it mirrors it 7 times, to replicate a filled circle.

        bool  didUpdate   = false;
        float startHeight = heightArray[startY, startX] + obsHeight;

        for (int i = 0; i < 8; ++i)
        {
            // Negative height means no blocking height found.
            wBlockerHeight[i] = -startHeight;
        }

        int maxLen = pixelBlock.Length;

        for (int circleSegment = 0; circleSegment < 8; ++circleSegment)
        {
            int counter  = deltaX / 2;
            int currentX = startX;
            int currentY = startY;

            for (int i = 0; i < deltaX; ++i)
            {
                counter += deltaY;
                if (counter > deltaX)
                {
                    counter  -= deltaX;
                    currentY += 1;
                }

                currentX += 1;

                if (currentX < 0 || currentX >= mapPixelWidth || currentY < 0 || currentY >= mapPixelHeight)
                {
                    continue;
                }

                int dx = currentX - startX;
                int dy = currentY - startY;

                // Depending on the segment of the circle we're in, we have to mirror
                // the original coordinate pair of (dx, dy), in all combinations of (+/-dx and +/-dy),
                // e.g. in the 1st segment, the pair turns into (-dx, dy), in the next one into (dx, -dy) etc.

                int wdx = circleSegment < 4 ? dx : dy;
                int wdy = circleSegment < 4 ? (circleSegment < 2 ? dy : -dy) : (circleSegment < 6 ? dx : -dx);
                if (circleSegment % 2 != 0)
                {
                    wdx *= -1;
                }

                int y = startY + wdy;
                int x = startX + wdx;

                if (x < 0 || x >= mapPixelWidth || y < 0 || y >= mapPixelHeight)
                {
                    continue;
                }

                float currentHeight = heightArray[y, x];

                // Found a blocker if the blocker height is > 0f
                if (wBlockerHeight[circleSegment] < 0f)
                {
                    if (currentHeight > startHeight)
                    {
                        wBlockerHeight[circleSegment] = currentHeight;
                    }
                }

                int index = (y * mapPixelWidth) + x;

                bool hasNotFoundBlockerYet = wBlockerHeight[circleSegment] < 0f;
                bool currentHeightHigherThanLastBlocker = currentHeight >= wBlockerHeight[circleSegment];

                if (hasNotFoundBlockerYet || currentHeightHigherThanLastBlocker)
                {
                    if (currentHeight > wBlockerHeight[circleSegment] && !hasNotFoundBlockerYet)
                    {
                        wBlockerHeight[circleSegment] = currentHeight;
                    }

                    if (index < maxLen)
                    {
                        didUpdate = didUpdate || pixelBlock[i].a <= 0;

                        pixelBlock[index]             = discovered;
                        currentVisibilityBlock[index] = discovered;

                        // Paint an extra pixel to cover accidental holes

                        if (index + mapPixelWidth < maxLen)
                        {
                            pixelBlock[index + mapPixelWidth]             = discovered;
                            currentVisibilityBlock[index + mapPixelWidth] = discovered;
                        }
                    }
                }
            }
        }

        return(didUpdate);
    }