Untitled

mail@pastecode.io avatar
unknown
plain_text
5 months ago
3.3 kB
3
Indexable
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;

namespace Game.World.Views.Spreads.Jobs
{
    [BurstCompile]
    public struct CreateGradationMapJob : IJob
    {
        public NativeArray<int> GradationMap;
        public int Gradations;
        public int Width;
        public int Height;

        public NativeArray<int2> InitialPoints;
        public NativeArray<bool> Filled;

        private int _pixelsCount;
        private int _pixelsPerColor;

        public void Execute()
        {
            _pixelsCount = Width * Height;
            _pixelsPerColor = _pixelsCount / Gradations;

            for (int colorId = 0; colorId < Gradations; colorId++)
            {
                int2 startPoint = InitialPoints[colorId];
                int startX = startPoint.x;
                int startY = startPoint.y;

                if (startX >= 0 && startX < Width && startY >= 0 && startY < Height)
                {
                    NativeList<int2> queue = new NativeList<int2>(Allocator.Temp);
                    queue.Add(new int2(startX, startY));

                    int filledCount = 0;
                    int radius = 0;

                    while (filledCount < _pixelsPerColor)
                    {
                        NativeList<int2> newPoints = new NativeList<int2>(Allocator.Temp);

                        for (int i = 0; i < queue.Length; i++)
                        {
                            int2 point = queue[i];
                            int x = point.x;
                            int y = point.y;

                            if (Fill(x, y, colorId))
                            {
                                filledCount++;
                            }
                        }

                        radius++;
                        queue.Clear();

                        for (int angle = 0; angle < 360; angle++)
                        {
                            float rad = math.radians(angle);
                            int newX = startX + (int)(radius * math.cos(rad));
                            int newY = startY + (int)(radius * math.sin(rad));

                            if (newX >= 0 && newX < Width && newY >= 0 && newY < Height && !GetFilledValue(newX, newY))
                            {
                                newPoints.Add(new int2(newX, newY));
                            }
                        }

                        queue.AddRange(newPoints);
                        newPoints.Dispose();
                    }

                    queue.Dispose();
                }
            }
        }

        private bool Fill(int x, int y, int colorId)
        {
            if (x < 0 || x >= Width || y < 0 || y >= Height || GetFilledValue(x, y))
            {
                return false;
            }

            int index = x + y * Width;
            SetFilledValue(x, y, true);
            GradationMap[index] = colorId;
            return true;
        }

        private bool GetFilledValue(int x, int y)
        {
            int index = y * Width + x;
            return Filled[index];
        }

        private void SetFilledValue(int x, int y, bool value)
        {
            int index = y * Width + x;
            Filled[index] = value;
        }
    }
}
Leave a Comment