Untitled
unknown
plain_text
a year ago
5.0 kB
9
Indexable
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
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 NativeList<int> PointQueue;
public NativeArray<bool> Filled;
private int _pixelsCount;
private int _remaining;
private int _filledCount;
private int _colorId;
private int _currentGradation;
private int _pixelsPerColor;
public void Execute()
{
Unity.Mathematics.Random random = new Unity.Mathematics.Random((uint)Environment.TickCount);
_pixelsCount = Width * Height;
_pixelsPerColor = _pixelsCount / Gradations;
int expectedCount = _pixelsPerColor * Gradations;
_filledCount = 0;
_remaining = 0;
_colorId = -1;
// Ініціалізуємо заповнення для кожного кольору
for (int i = 0; i < Gradations; i++)
{
int currentX = random.NextInt(0, Width);
int currentY = random.NextInt(0, Height);
_currentGradation = i;
FillCircle(currentX, currentY, i);
}
// Продовжуємо заповнювати поки не заповнимо очікувану кількість пікселів
while (_filledCount < expectedCount)
{
if (PointQueue.Length > 0)
{
int currentPoint = PointQueue[0];
PointQueue.RemoveAtSwapBack(0);
int x = currentPoint % Width;
int y = currentPoint / Width;
TryFillCircle(x, y);
}
else
{
break;
}
}
}
private void FillCircle(int startX, int startY, int gradation)
{
PointQueue.Clear();
PointQueue.Add(startX + startY * Width);
SetFilledValue(startX, startY, true);
GradationMap[startX + startY * Width] = gradation;
_filledCount++;
_remaining = _pixelsPerColor - 1; // Мінус один, бо початкова точка вже заповнена
int radius = 1;
while (_remaining > 0 && PointQueue.Length > 0)
{
int currentPoint = PointQueue[0];
PointQueue.RemoveAtSwapBack(0);
int x = currentPoint % Width;
int y = currentPoint / Width;
for (int dx = -radius; dx <= radius; dx++)
{
for (int dy = -radius; dy <= radius; dy++)
{
if (dx * dx + dy * dy <= radius * radius)
{
Fill(x + dx, y + dy);
}
}
}
radius++;
}
}
private void TryFillCircle(int x, int y)
{
int radius = 1;
while (_remaining > 0 && _filledCount < _pixelsCount)
{
for (int dx = -radius; dx <= radius; dx++)
{
for (int dy = -radius; dy <= radius; dy++)
{
if (dx * dx + dy * dy <= radius * radius)
{
Fill(x + dx, y + dy);
}
}
}
radius++;
}
}
private void Fill(int x, int y)
{
if (x < 0 || x >= Width || y < 0 || y >= Height || GetFilledValue(x, y))
{
return;
}
if (_remaining == 0)
{
return;
}
int index = x + y * Width;
PointQueue.Add(index);
SetFilledValue(x, y, true);
_filledCount++;
GradationMap[index] = _currentGradation;
_remaining--;
}
private bool GetFilledValue(int x, int y)
{
if (x < 0 || x >= Width || y < 0 || y >= Height)
{
throw new ArgumentOutOfRangeException("Error 0");
}
int index = y * Width + x;
bool result = Filled[index];
return result;
}
private void SetFilledValue(int x, int y, bool value)
{
if (x < 0 || x >= Width || y < 0 || y >= Height)
{
throw new ArgumentOutOfRangeException("Error 1");
}
int index = y * Width + x;
Filled[index] = value;
}
}
}
Editor is loading...
Leave a Comment