Voxel Project: Fill those Gaps
- Kyle W

- Jul 1, 2022
- 2 min read
Updated: Jul 8, 2022
No more Gaps
Up until now the method I used to generate the mesh was complicated to say the least; each voxel shape was addressed individually in a massive switch statement, with if statements addressing possible gaps from having a slope or corner next to the current voxel. I have addressed this by adding an integer to the voxel class to use as a bitmask. A total of 18 bits is used to represent all 6 sides of the voxel (3 bits per side), and that information is used to fill gaps in the mesh. Additionally, instead of recalculating the bitmask of the entire grid, it now only does this for potentially affected voxels, which means a maximum of 9 versus checking the entire grid. The result is an easily scalable and significantly simplified method for generating the mesh.

One issue I had not anticipated while calculating the bitmasks is that even if two overlapping faces were the same type, they may not necessarily line up, since the vertex array used for generating the mesh did not originally take this into account, and adjusting them might mess up the uv mapping. As a result, I had to place if statements that check for which side of the voxel the current triangle is facing, which is not ideal.

While it took some trial and error to nail down the values for all the shapes, if in the future I add any new shapes I will only have to figure out the bitmask for that shape, whereas before I would have to add the new shape to the if statements of each shape.
Better Targeting
Back when there were only cubes, I originally decided where to place and remove blocks by raycasting from the camera and rounding the hit location up or down, depending on if I'm placing or removing a block. However, this no longer worked with slopes and corners, because the distance from the center of the voxel hit was too small. I have now added an statement that triggers if you are attempting to place a block where on elaready exists which takes into account the direction of the raycast and uses that to select an adjacent voxel. I considered several other options, as this approach may not always place the block where the user intends to, but I figured that it was the most straightforward and easiest for the user to get used to.
Next Week
With some major overall improvements in place, I feel ready to try to implement the ability to divide a grid into separate grids. This week has given me some time to plan how I want to implement this feature, and as a result I have reached two potential approaches; the first involves checking the empty spaces in the grid two confirm that the grid is seaprated into two (or three!), and the second involves checking the filled spaces in the grid to see if parts of the grid are still connected. Additionally, there is still the issue of generating a new grid with the newly separated section, as well as the potential issue of the grid splitting into more than two pieces, as in a worst case scenario the grid could separate into 5 separate pieces.



Comments