6
\$\begingroup\$

in case it matters i'm doing all this in unity with C# ...

I think I missed something or maybe don't understand the logic correctly. I have an existing voxel engine that looks very "minecrafty" at the moment, and I want to step it up a bit so it actually looks reasonably good!

So lets say I have a "chunk", and common sense says that a chunk can either be on or off in a voxel world so its basically a "point cloud" (you either render it or you dont). This means my game engine has something like this ...

public class Chunk
{
    public Block[,,] Blocks;
    ... other stuff
}

public class Block 
{
    public bool Active;
    ... other stuff
}

So bring in the marching cubes and part 1 of Paul Bourke's guide (http://paulbourke.net/geometry/polygonise/) says ....

The first part of the algorithm uses a table (edgeTable) which maps the vertices under the isosurface to the intersecting edges. An 8 bit index is formed where each bit corresponds to a vertex.

   cubeindex = 0;
   if (grid.val[0] < isolevel) cubeindex |= 1;
   if (grid.val[1] < isolevel) cubeindex |= 2;
   if (grid.val[2] < isolevel) cubeindex |= 4;
   if (grid.val[3] < isolevel) cubeindex |= 8;
   if (grid.val[4] < isolevel) cubeindex |= 16;
   if (grid.val[5] < isolevel) cubeindex |= 32;
   if (grid.val[6] < isolevel) cubeindex |= 64;
   if (grid.val[7] < isolevel) cubeindex |= 128; 

Now here's what throws me ... I'm comparing my "grid data" (so basically my block data) to some "isolevel" value. Every implementation i've seen (the easiest being here: http://nucleardevs.wordpress.com/2011/11/17/marching-cubes-sourcecode/) does exactly that but it creates a load of float values using something like simplex or perlin noise and runs through this logic.

floats? not bools?

So ...

Given a Block[,,] if i check each blocks state (Active property) and return a simple true or false ... why do i need a float / double value or should I say ... what is the purpose of the float value that requires it to be a float and not a simple boolean?

I gather they are referred to as "densities" which implies that I missed something because i've been thinking of them as the point cloud data to be evaluated and a voxel (to my knowledge) isn't a "density" value its more like a switch (on off).

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Using float values allows you to use linear interpolation to enable you to make a mesh that's more accurate to your data. With many of the blocky type terrains you see in games these days, they just decide at what density a voxel is "solid". With noise values ranging between 0 and 1, they decide a value to split the float and round to 1 or 0.

However, many of the blocky voxel games aren't using marching cubes to generate their terrain meshes. Keeping the float values allows your marching cubes more accuracy. As I'm sure you're familiar with the marching cubes algorithm, having the float values allows you to shift the vertices of your triangles along the edges of the cubes depending on the adjacent floating point values.

\$\endgroup\$
4
  • \$\begingroup\$ The common approach (which I believe this resolves) is to declare a 3D array and then "walk the array". In my situation I had something that roughly represents a shape you might associate with an asteroid (but its not space game) ... so I have either the raw data which is basically an array of bools or the first pass vertex data (not yet generated but could be) ... could you explain a bit more about which set of data I should use and how this relates to the marching cubes algorithm? \$\endgroup\$
    – War
    Apr 7, 2013 at 8:38
  • \$\begingroup\$ Hmm just re-reading this again and I'm thinking about it slightly differently now ... a float value is sort of like saying "this amount of this volumetric area is within the surface" whereas a bool is akin to saying "this volumetric area is inside the surface", thus the isolevel to determine the level of expected accuracy by "moving the verts along the edges" \$\endgroup\$
    – War
    Apr 7, 2013 at 8:50
  • \$\begingroup\$ Correct Wardy, I was trying to show that essentially, using bools is like casting all your values to ints. You loose accuracy. Many games loose that accuracy because the have now way to display it anyway, because they don't use marching cubes. However, if you were to use a single bit for each voxel to determine true/false, you could have a much higher resolution (smaller voxels). So, like many things in life, it's a balance you need to decide what works best in your situation. \$\endgroup\$
    – House
    Apr 7, 2013 at 13:47
  • \$\begingroup\$ I converted my code so it's now creating float based spacial data in the end and I think I have something working!!! Cheers @Byte56 it made a lot more sense after having you explain the gap in my knowledge. How are you with triplanar texturing? (my next challenge lol) \$\endgroup\$
    – War
    Apr 7, 2013 at 17:49
4
\$\begingroup\$

The density field is used to smooth out the curves. If you populate the field with simple true/false values you get blocky, Minecaft-like terrain. A voxel can be a floating-point value or a boolean value, just like a pixel can be a floating-point value or a boolean value (such as in masks). A pixel is a picture (2D) element; a voxel is a volume (3D) element.

Example using boolean values: Bad marching cubes

Example using floating-point values: Good marching cubes

Also, you shouldn't be representing individual voxels as classes. C# implements these as reference types, meaning a lot of overhead for something that should be plain old data, i.e. a struct.

\$\endgroup\$
5
  • \$\begingroup\$ Even with a point cloud, if one is using marching cubes, the resulting mesh won't be blocky. \$\endgroup\$
    – House
    Apr 7, 2013 at 4:51
  • \$\begingroup\$ Boreal I agree with @Byte56 on this, the whole purpose of the algorithm is to take a very course set of data and turn it in to a smooth iso surface by "adding interpolation verts" so on that basis I don't think it really matters, my problem is understanding how / why the value being a float gives a different outcome to the value being a bool when the logic goes something like "give 8 surrounding points, which are inside and which are outside, draw new verts on the lerp result", surely a bool is enough to determine that and a float is merely adding overhead? \$\endgroup\$
    – War
    Apr 7, 2013 at 8:43
  • \$\begingroup\$ @Byte64, you're right, but it's still an unacceptable result. A boolean value is too coarse. The isosurface on the boundary of 1 (ground) and 0 (air) will always lie halfway between the two grid points. This leads to what can be seen in the screenshot I've edited the post with. \$\endgroup\$
    – jmegaffin
    Apr 7, 2013 at 14:19
  • \$\begingroup\$ I've been thinking about the accuracy problem and I figured that for the cpu level calculations the load needs to be kept to a minimum so building the data "the easy way" on the cpu solves the initial pass problem, the gpu can then improve the quality with a second pass in a geometry shader if need be (i'll figure that one out later) \$\endgroup\$
    – War
    Apr 7, 2013 at 17:52
  • \$\begingroup\$ oh and i'm not using classes for the block data, it was a typo (the block object is a struct) that said, upon getting this working I basically ditched the voxel breakdown entirely and handed marching cubes the raw point cloud, although I think I may need it later so I may have to revisit my solution. +1 for the advice and I like your answer but byte gave me the advice i needed to fix my problem so i'm giving him the tick :) thanks to both of you for the help here. \$\endgroup\$
    – War
    Apr 7, 2013 at 17:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .