Skip to content

Instantly share code, notes, and snippets.

@jeffvella
Created January 18, 2019 13:25
Show Gist options
  • Save jeffvella/bf7b0478f21700de626e1346c7ca10e1 to your computer and use it in GitHub Desktop.
Save jeffvella/bf7b0478f21700de626e1346c7ca10e1 to your computer and use it in GitHub Desktop.
Wrapper around Unity3D's NativeArray<T> with 3D indexer.
using System;
using System.Collections.Generic;
using Unity.Collections.LowLevel.Unsafe;
using System.Collections;
namespace Unity.Collections
{
public struct NativeArray3D<T> : IDisposable, IEnumerable<T> where T : unmanaged
{
public NativeArray<T> Internal;
private readonly int _yLength;
private readonly int _xLength;
private readonly int _zLength;
private readonly int _yzLength;
public NativeArray3D(int x, int y, int z, Allocator allocator, NativeArrayOptions options = NativeArrayOptions.ClearMemory)
{
Internal = new NativeArray<T>(x * y * z, allocator);
_xLength = x;
_yLength = y;
_zLength = z;
_yzLength = y * z;
}
public T this[int i] => Internal[i];
public T this[int x, int y, int z]
{
get => Internal[GetIndex(x, y, z)];
set => Internal[GetIndex(x, y, z)] = value;
}
public int GetIndex(int x, int y, int z)
{
/*
(2D) 4x2 Layout:
y0 y1
x0: #0 | #1
x1: #2 | #3
x2: #4 | #5
x3: #6 | #7
>> x * yLen + y
[0,0] = 0 * 2 + 0 = 0
[0,1] = 0 * 2 + 1 = 1
[1,0] = 1 * 2 + 0 = 2
[1,1] = 1 * 2 + 1 = 3
[2,0] = 2 * 2 + 0 = 4
[2,1] = 2 * 2 + 1 = 5
[3,0] = 3 * 2 + 0 = 6
[3,1] = 3 * 2 + 1 = 7
(3D) 2x2x2 Layout:
y1 y2
z0 z1 z0 z1
x0: #0 / #1 | #3 / #4
x1: #5 / #6 | #7 / #8
>> (x * yLen * zLen) + (y * zLen) + z
[0,0,0] = (0 * 2 * 2) + (0 * 2) + 0 = 0
[0,0,1] = (0 * 2 * 2) + (0 * 2) + 1 = 1
[0,1,0] = (0 * 2 * 2) + (1 * 2) + 0 = 2
[0,1,1] = (0 * 2 * 2) + (1 * 2) + 1 = 3
[1,0,0] = (1 * 2 * 2) + (0 * 2) + 0 = 4
[1,0,1] = (1 * 2 * 2) + (0 * 2) + 1 = 5
[1,1,0] = (1 * 2 * 2) + (1 * 2) + 0 = 6
[1,1,1] = (1 * 2 * 2) + (1 * 2) + 1 = 7
(3D) 2x2x3 Layout:
>> (x * yLen * zLen) + (y * zLen) + z
y0 y1
z0 z1 z2 z0 z1 z2
x0: #0 / #1 / #2 | #3 / #4 / #5
x1: #6 / #7 / #8 | #9 / #10 / #11
[0,0,0] = (0 * 2 * 3) + (0 * 3) + 0 = 0
[0,0,1] = (0 * 2 * 3) + (0 * 3) + 1 = 1
[0,0,2] = (0 * 2 * 3) + (0 * 3) + 2 = 2
[0,1,0] = (0 * 2 * 3) + (1 * 3) + 0 = 3
[0,1,1] = (0 * 2 * 3) + (1 * 3) + 1 = 4
[0,1,2] = (0 * 2 * 3) + (1 * 3) + 2 = 5
[1,0,0] = (1 * 2 * 3) + (0 * 3) + 0 = 6
[1,0,1] = (1 * 2 * 3) + (0 * 3) + 1 = 7
[1,0,2] = (1 * 2 * 3) + (0 * 3) + 2 = 8
[1,1,0] = (1 * 2 * 3) + (1 * 3) + 0 = 9
[1,1,1] = (1 * 2 * 3) + (1 * 3) + 1 = 10
[1,1,2] = (1 * 2 * 3) + (1 * 3) + 2 = 11
*/
return x * _yzLength + y * _zLength + z;
}
public int[] Get3DIndexes(int idx)
{
int x = idx / (_yzLength);
idx -= (x * _yzLength);
int y = idx / _zLength;
int z = idx % _zLength;
return new[] { x, y, z };
}
public unsafe ref T ByRef(int x, int y, int z)
{
var ptr = Internal.GetUnsafePtr();
var idx = GetIndex(x, y, z);
return ref ((T*)ptr)[idx];
}
public int GetLength(int index)
{
switch (index)
{
case 0: return _xLength;
case 1: return _yLength;
case 2: return _zLength;
}
throw new ArgumentOutOfRangeException($"The dimension with Length index '{index}' doesn't exist");
}
public int Length => Internal.Length;
public void Dispose() => Internal.Dispose();
public IEnumerator<T> GetEnumerator() => Internal.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment