Saturday, June 20, 2015

Subvoxel Terrain

Range of subvoxels I currently have implemented
In my first pass at subvoxel terrain, I'm trying to shoehorn a random Perlin Noise field into a bunch of subvoxels. Instead of a single integer height value, I could use of the subvoxels pictured at right.

For now I'm sticking to just eleven possibilities: the solid voxel (duh), the half-slab, and the nine sloped options at the bottom-left of the picture. In other words, I can now support elevations at the corners -- that is, four elevation values go into deciding what to draw at each voxel.

There's some tricks here. What if the highest elevation is in a different voxel? Before I get into that, let me describe how I'm thinking about the problem.

First I pick a lowest integer voxel value; one that's at or below the lowest corner. This value I call "0", duh. Then the corners are numbered according to how many half-voxels they are above that voxel. The lowest corner could actually be a 1, or even a 2 -- the latter case if the lowest corner is 0.75 units above the floor.

The set of options I have to work with are things like 0011 or 0222 or 2202, etc. There's three ways to consider the numbers: as they are, with the northwest corner first; rotated, such that the lowest corner is first; or as a generic set of corner values. There's 15 possibilities in that set, btw, which I'll leave as an exercise for the reader.

15 possibilities -- if each corner is 0, 1, or 2. But what if I have a voxel where my corner values want to be 0, 1, 2, and 3? Or 1, 3, 5, and 9? That I'm just punting for now, actually. I've got some shapes that I could rotate such that I could handle a combination (clockwise) like 0044, and I'm planning on adding a couple shapes that would handle 0033 or 1144 or 1133. Maybe I need to add something for 1333? And I could do a two-voxel stack that would handle 0242.

I think options like 0244 is just right out; that would require a radically different way of handling voxels. Converting corner elevations to subvoxels is a bit of a "hack" -- taking what I have in the engine, and trying to find a simple way to generate undulating terrain with something other than plain stairsteps.

OK, so what DO we have? Let's take 0000, 1111, and 2222 first. In this cases, I have no voxel, a half-slab, and a solid voxel. Simple enough.

Next comes combinations of two height-values. The nine angled shapes in the front-left of the image represent the (clockwise) combinations 2211, 1211, 2221; 1100, 0100, 1110; and 2220, 0200, plus 2200. Note that I haven't implemented 2121, 1010, or 2020. With rotation, these shapes can handle all of the possibilities of two numbers (again, minus the 2121 1010 and 2020 cases).

There's also the problem of voxels like 1133. What do I do with that? If I'm not going to do two voxels (and I don't have the shapes for that yet), do I force that to 1122, or 2233 (and raise the surface voxel up one unit)? For now, I've got some simple logic that decides; I don't know that there's a one-size solution, so I went with "close enough" and we'll see where that gets me.

subvoxel terrain test world
So that's what I do. Simple pattern-matching. Here's what it looks like now, and it makes plain -- I need to fix subvoxel lighting! Guess what I work on next? :)

No comments:

Post a Comment