FreshRSS

Zobrazení pro čtení

Jsou dostupné nové články, klikněte pro obnovení stránky.

Adjusting texture generation inside a quadtree

Well, I'm trying to adjust the position of generated textures using this approach.

I replicated this in Unity3D for a complete texture of 4096x4096:

texture generated

The point is that I need to generate the same texture on a quadtree using different level of details / zoom per each node.

I have almost the code finished, but I cannot calibrate textures inside the grid/nodes:

enter image description here

With grid:

biomes with grid

The point is that I'm unsure at which point of the code execution, I have two main parts that I doubt about.

The first one is on the OnGUI() call, read comments FMI.

private void OnGUI()
{
    // Skipped logic
    var totalTimeExecution = DrawBiomeTextureLogic();
    // Skipped logic
}

private long DrawBiomeTextureLogic()
{
    var octreeKey = world.worldSettings.TargetOctreeKey;
    var regions = world.worldState.ChunkData.Get_Regions();

    if (!regions.ContainsKey(octreeKey))
        return -1;

    var region = regions[octreeKey];

    // will draw the smaller ones first (Depth = 0, 2^0=1 * textureSize)
    // but we draw everything as 16x16 because we are doing a level of detail with textures
    var map = region.NodeMap.AsEnumerable().OrderByDescending(x => x.Value.Depth);

    foreach (var (key, octree) in map)
    {
        // fields from the octree node
        var position = octree.Position;
        var depth = octree.Depth;
        var mult = 1 << depth;

        // first intPosition, needs to refactgor
        var size = world.worldSettings.ChunkSize * mult;
        var intPosition = new Vector2Int(position.x - size / 2, position.y - size / 2);

        DrawTexture(octree);
    }

    return totalTimeExecution;
}

private void DrawTexture(OctreeNode octree)
{
    // fields from the octree node
    // note: I say quadtree on the question, but because I'm skipping z axis values with a HashSet, 
    // I will create another question to create another algorithm for it
    var position = octree.Position;
    var key = octree.LocCode;
    var depth = octree.Depth;
    var mult = 1 << depth;

    var size = world.worldSettings.ChunkSize * mult;

    // use Y position because we need a bird view of the map (edit: but i need)
    // the problem could be here
    var intPosition = new Vector2Int(position.x - size / 2, position.y - size / 2);
    var targetPosition = new long2(intPosition.x, intPosition.y);

    // or maybe, but this is for adjusting inside scroll view
    var texRect = new Rect(intPosition.x, -intPosition.y - MAP_SIZE_HEIGHT, size, size);

    // pass targetPosition into second stage
    TextureSettings.InitializeTextureParams(targetPosition, depth, key);

    // Get the texture from the biomeTextureController
    var texture = biomeTextureController.GetTexture(TextureSettings, out var textureTask);

    if (texture != null)
    {
        Textures.TryAdd(new Vector2Int(intPosition.x, -intPosition.y), (texture, size));
    }

    var color = texture != null ? Color.green : Color.red;

    if (texture != null)
    {
        GUI.DrawTexture(texRect, texture);

        // not relevant
        UIUtils.DrawOutlinedRect(texRect, color, 1);
    }
}

The second stage mentioned in code (line 59), is the Job (Unity Jobs) that I use, I did it parallel with bounds checking for index and the mentioned document from Cuberite above, the call is explained here:

[BurstCompile(OptimizeFor = OptimizeFor.Performance)]
public struct BiomeTextureParallelJob : IJobParallelFor, IDisposable
{
    // colors of the texture
    public NativeArray<Color32> data;

    // used to get Biome color depending on its index (enumeration)
    [ReadOnly]
    public NativeParallelHashMap<short, Color> colorsCollection;

    public BiomeGenenerationSettings settings;
    public BiomeTextureJobSettings jobSettings;

    public long2 TargetPosition => jobSettings.TargetPosition;
    public int Depth => jobSettings.Depth;
    public int TextureSize => jobSettings.textureSize;

    public void Execute(int index)
    {
        OnStart();

        To2D(index, TextureSize, out var x, out var y);

        if (showPercentage)
            counter[threadIndex]++;

        // same octree fields calculated again
        var d = 1 << (Depth + 4);
        var p = d / TextureSize; // example: 64 / 16 = 4
        var s = TextureSize * (1 << Depth); // textureSize multiplied by its 2^n node size

        // maybe the problem start here
        // this is from the first stage
        var tx = TargetPosition.x;
        var ty = TargetPosition.y;

        // I tried some operations, but I'm unable to adjust it
        var xx = x * p; // - p / 2; // * (tx < 0 ? -1 : 1); // + p / 2;
        var yy = y * p; // - p / 2; // * (ty < 0 ? -1 : 1); // + p / 2;

        long wx = tx + xx - s / 2; // * (tx < 0 ? -1 : 1);
        long wy = ty + yy - s / 2; // * (ty < 0 ? -1 : 1);


        if (!IsInBounds(index, data.Length))
            return;

        data[index] =
            BiomeTextureUtils.CalcPixelColor(settings, colorsCollection, wx, wy, 1,
            false, AlphaChannel);
    }

    [BurstDiscard]
    public void Dispose()
    {
        try
        {
            if (data.IsCreated)
                data.Dispose();
        }
        catch { }
    }
}

As you can see the problem could be found in two places. It could be some simple, as you can see on UI, more zoomed:

UI view

I'd like to share a demo with the minimum code, I'll prepare one if needed.

Note: I'd like to add a spoiler to hide such big images. I'm sorry.

❌