Voxel Planet Octree Job System/ECS/DOTS

Hello everyone,

I started to work on a voxel planet game.(Octree structure and Dual contoruing algorithm)

But i don’t no what is the best way to generate Octree nodes?

In my first prototype i created a IJob which create nodes via recursive way.

    struct DistanceCheck : IJob
    {
        public int maxLodLevel;
        public float radius;
        public NativeHashMap<float3, OctreeNode2> activeNodesIndex;
        public float3 playerPosition;

        private void CheckClosesNodes(int index, float3 position, float3 voxelPosition, byte lodLevel, float size)
        {
            float diagonal = Mathf.Sqrt(2 * (size * size));

            if (lodLevel < maxLodLevel && Distance(playerPosition, position) < diagonal)
            {
                float delta = size / 4;

                for (int i = 0; i < 8; i++)
                {
                    float3 voxelPosition2 = voxelPosition + (GetVoxelBase(i) * size / 2);
                    CheckClosesNodes(i, GetPosition(i, position, delta), voxelPosition2, (byte)(lodLevel + 1), size / 2);
                }
            }
            else
            {
                OctreeNode node = new OctreeNode(position, voxelPosition, size, lodLevel);
                activeNodesIndex.TryAdd(position, node);
            }
        }

        public void Execute()
        {

            CheckClosesNodes(0, new float3(radius / 2, radius / 2, radius / 2), float3.zero, 0, radius);
        }
    }[

And save this nodes as struct:

public struct OctreeNode
{
    // node value
    public float3 position;
    public float3 voxelPosition;
    public float size;
    public byte lodLevel;

    public OctreeNode
    (
        float3 position,
        float3 voxelPosition,
        float size,
        byte lodLevel
    )
    {
        this.position = position;
        this.voxelPosition = voxelPosition;
        this.size = size;
        this.lodLevel = lodLevel;
    }
}

I call this job from Update methode.

I used this solution because the player is moving and i need the closest node every time.
But i dont feel it is the best solution to call the job every seconds and create octree nodes from 0 to max lod level again and again.

I think it is the core of my project i would be happy if somebody share experience about DOTS and octree.

I used C# task parallel library and there was i lots of crashs thats way I started to change tasks to job system

2 Likes

If you have just static acceleration structure like octree, then you can use hash map, to store nodes. Alternatively you can use entities, and link references between other entities nodes.

1 Like

Thanks it is a good idea. :slight_smile:

Hi Antypodish, I would like to share with you my github repo with a simple octree prototype:

https://github.com/patrikholler/Unity-Simple-Octree

if you are available could you please check it out and give me a few pointers for improvement?

Thank you!

Please send me riminder later, as I am busy atm and I will forget to look into it :slight_smile:

I have a few suggestions in Octree.cs:
You do not need a distance method there is math.length(floar3 a)
Instead of using the switch case in GetVoxelBase create an array of 8 values and return them by index.
Same can be done in GetPosition. Create an array of 8 int3 like:
0 => -1,-1,-1
1 => -1,-1, 1

7 => 1,1,1
and then

var deltaSign = deltaSigns[index]
return new float3(parentPosition.x + deltaSing.x*delta, parentPosition.y + deltaSing.y*delta, parentPosition.z + deltaSing.z*delta);

You will get rid of branching.
In line 160 use math.sqrt instead of Mathf.

Hi Micz84,
Thank you for your help!

I changed the code how you suggested and it was more readable and little bit faster!

I am new in Job System so I know my code not the best, but I did not find good repo about this topic. Lots of them to complicate me and other have made different game logic.

I would like to create voxel planet and i plane to content voxel data in octree nodes.

What do you think my solution?

Btw.: before i did this, i did to pre-generate all nodes in all level before game start, that’s way the program do not calculate at runtime the node data and not haet the CPU . But it was a wrong solution bcoz this way i used lots of memory. After that i did this version.

I think it will be hard to improve/optimize a spatial partition without a test scene that has the performance characteristics you intend on supporting. A static procedurally generated scene with a few moving objects? The same, but with static objects that may move? Or everything moving all the time?

Hi @jasons-novaleaf , thank for you reply! first of all I would only generate a voxel planet with Dual contouring. I haven’t got lots of experience, so if you have any idea or experience please share.
In the first time the planet will be a desert planet not need any cound of object.