3D and 2D Coordinates to 1D Indexes

Feb 3, 2022

Going from coordinates to indexes and back can be very useful. For example textures store pixel info as a 1d array so if you want to sample a pixel at x and y you need to convert your coordinates to the pixel index.

Here's how to turn 3d and 2d coordinates into 1d indexes.

int ThreeToOne (int x, int y, int z, int xSize, int ySize, int zSize) {
    return x + y * xSize + z * xSize * ySize;
}
int TwoToOne (int x, int y, int xSize, int ySize) {
    return x + y * xSize;
}

Here's how to turn the 1d indexes back into coordinates.

int3 OneToThree (int index, int xSize, ySize, zSize) {
    int3 result = new int3(0, 0, 0);
    result.x = index % xSize;
    result.y = (index / xSize) % ySize;
    result.z = index / (xSize * ySize);
    return result;
}
int2 OneToTwo (int index, int xSize, ySize) {
    int2 result;
    result.x = index % xSize;
    result.y = index / xSize;
    return result;
}

One example where this is useful is setting pixels in a Unity Texture2D.

void FillTextureWithBlack (Texture2D texture) {
    Color[] colors = new Color[texture.width * texture.height];

    for (int x = 0; x < texture.width; x++) {
        for (int y = 0; y < texture.height; y++) {
            colors[x + y * texture.width] = new Color(0f, 0f, 0f);
        }
    }

    texture.SetPixels(colors);
    texture.Apply();
}

Here's another example where going from indexes to coordinates is useful. Of course this could be made faster with texture.GetPixels()

Color GetAverageColorOfTexture (Texture2D texture) {
    Vector3 averageColor = new Vector3(0f, 0f, 0f);

    for (int i = 0; i < texture.width * texture.height; i++) {
        int x = i % texture.width;
        int y = i / texture.width;

        Color color = texture.GetPixel(x, y);
        averageColor += new Vector3(color.r, color.g, color.b);
    }

    averageColor /= (float)(texture.width * texture.height);
    return new Color(averageColor.x, averageColor.y, averageColor.z, 1f);
}