Michael Michael - 3 months ago 10
C# Question

Array Shifting / Wrong Index / i = [x+y*size+z*size*size]

I have a simple question. How can I shift a linear array in 3 dimensions?‚Äč
It seems too work but in the X & Y axis i got an index problem.
The reson why I wanna do this is simple. I want to create a volumetric terrain with a chunk buffer, so i only have to recalulate values on the edges when the viewport is moving.

I have read an article about this system :


Essentially they provide a way to scroll a potentially infinite data
field through a fixed size multi-resolution cache.


So my pipline for the generation part would be:


  1. When viewport moves get axis

  2. Shift the axis

  3. Generate some noise only for the new cells

  4. Triangulate the new cells

  5. Update all cell positions



enter image description here

Here are my other images:
http://forum.unity3d.com/threads/array-shifting-wrong-index-i-x-y-size-z-size-size.425448/#post-2751774

Nobody in the unity forums could answer my question...

public int size;
public float speed;

private byte[] volume;
private byte[] shifted;

public bool widthShift, heightShift, depthShift;

private int widthOffset = 0;
private int heightOffset = 0;
private int depthOffset = 0;

private float time = 0;
private int cube;

void Start()
{
volume = new byte[size * size * size];
shifted = new byte[size * size * size];

cube = size * size * size;

for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
for(int z = 0; z < size; z++)
volume[x + y * size + z * size * size] = (x == 0 || y == 0 || z == 0) ? (byte)1 : (byte)0;
}

void Update()
{
time += Time.fixedDeltaTime * speed;

if (time > 1)
{
time = 0;

widthOffset = (widthOffset >= size) ? 0 : widthOffset;
heightOffset = (heightOffset >= size) ? 0 : heightOffset;
depthOffset = (depthOffset >= size) ? 0 : depthOffset;

if (widthShift)
widthOffset++;
else
widthOffset = 0;

if (heightShift)
heightOffset++;
else
heightOffset = 0;

if (depthShift)
depthOffset++;
else
depthOffset = 0;

Shift(widthOffset, heightOffset, depthOffset);
}
}

void Shift(int xOff, int yOff, int zOff)
{
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
for(int z = 0; z < size; z++)
{
int i = ((x + xOff) + (y + yOff) * size + (z + zOff) * size * size);
i = (i >= cube) ? (i - cube) : i;

shifted[x + y * size + z * size * size] = volume[i];
}
}

void OnDrawGizmos()
{
if(Application.isPlaying)
for(int x = 0; x < size; x++)
for(int y = 0; y < size; y++)
for(int z = 0; z < size; z++)
{
Gizmos.color = (shifted[x + y * size + z * size * size] == 1) ? new Color32(0, 255, 0, 255) : new Color32(255, 0, 0, 4);
Gizmos.DrawWireCube(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f), new Vector3(0.95f, 0.95f, 0.95f));
}
}

Answer

Give it a try:

void Shift(int xOff, int yOff, int zOff)
{
    for (int x = 0; x < size; x++)
        for (int y = 0; y < size; y++)
            for(int z = 0; z < size; z++)
            {
                int nx = (x + xOff) % size;
                int ny = (y + yOff) % size;
                int nz = (z + zOff) % size;
                int i = (nx + ny * size + nz * size * size);

                shifted[x + y * size + z * size * size] = volume[i];
            }
}
Comments