You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The simplest way to store voxels is to define a three-dimensional array of elements (be it `struct`s or `integer`s), where each element represents a single voxel:
11
-
12
-
```c#
13
-
intwidth=...;
14
-
intheight=...;
15
-
intdepth=...;
16
-
varvoxels=newVOXEL[width][height][depth];
17
-
18
-
// Set a voxel:
19
-
voxels[x][y][z] =voxel;
20
-
21
-
// Get a voxel:
22
-
varvoxel=voxels[x][y][z];
23
-
```
24
-
25
-
However, because storing *arrays within arrays* often means having *pointers pointing at pointers* (which ain't good for [various reasons](/wiki/optimization) we won't get into here), it is generally recommended to use a one-dimensional array with a clearly defined *spatial indexing scheme*.
26
-
27
-
Here's an example:
28
-
29
-
```c#
30
-
--snip--
31
-
// Spatial Indexing Scheme is: Y-height, Z-depth, X-width
32
-
// The arrays size is just all axes multiplied together:
33
-
varvoxels=newVOXEL[height*depth*width];
34
-
35
-
// Our Indexing Formula is the indexing scheme in reverse,
36
-
// with the components being multiplied subsequently:
37
-
// x + z*width + y*width*depth
38
-
39
-
// So let's define a function (here a lambda) for it:
// ^ NOTE: You may want to throw an error right here
42
-
// if either the coordinate components
43
-
// or the resulting index are out of bounds.
44
-
45
-
// Set a voxel:
46
-
voxels[idx(x,y,z)] =voxel;
47
-
48
-
// Get a voxel:
49
-
varvoxel=voxels[idx(x,y,z)];
50
-
```
51
-
52
-
Now, storing voxels in a plain array like this is perfectly fine for small scenes...
53
-
54
-
However, for larger scenes, we'll have to use a data-structure that allows both loading and purging *parts of our volume* (called [Chunks](/wiki/chunking) or Bricks) from memory, nearly in realtime, without slowing down the *access times* of our voxel data too much.
10
+
Storing voxels in a plain array is perfectly fine for small scenes,
11
+
but as we increase the size (and thus volume) of our scene,
12
+
we will inevitably run into various limits, like the *size of our RAM*...
13
+
14
+
As such, we'll have to use a data-structure that allows both
15
+
loading and purging *parts of our volume* (called [Chunks](/wiki/chunking) or Bricks)
16
+
from memory, nearly in realtime, without slowing down the *access times* of our voxel data,
17
+
or the performance of world generation, *too* much.
55
18
56
19
> **Note:** These techniques can often be combined.
Alas, this shows us one of three annoyances with using 3D arrays:
90
-
91
-
- Accessing elements always requires us to 'jump' trough two levels of indirection.
92
-
- Iterating/looping over our voxels requires *three* nested loops, which is a pain to write.
93
-
- Creating and filling a 3D array is, unsurprisingly, quite messy.
85
+
{% info_notice() %}
86
+
**Note on 3D arrays:**
87
+
In the vast majority of languages, 3D arrays are implemented as *"arrays of pointers to arrays of pointers to arrays of values"* (sometimes referred to as "jagged arrays"), which has a few downsides:
88
+
89
+
- If the memory allocator doesn't play nice,
90
+
our innermost arrays may be spread all over the place (i.e.: fragmentation).
91
+
- Accessing any value requires dereferencing three-ish pointers,
92
+
which can and will trash the cache and thus access speed.
93
+
- Iterating/looping over them *always* requires three nested loops.
94
+
- Creating and (de)serializing 3d arrays tends to be a messy affair.
95
+
{% end %}
94
96
95
-
As such, we will now go ahead and make our array *flat*, turning it one-dimensional!
97
+
For a variety of reasons (see note above) and reasons yet to be revealed,
98
+
we will now go ahead and *flatten* our array, turning it one-dimensional!
0 commit comments