🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Isosurface Extraction method

Started by
17 comments, last by trsh 4 years, 4 months ago

So I decided to leap into the Voxel world. I'm at the point of choosing a Isosurface Extraction extraction method. I found this list https://swiftcoder.wordpress.com/planets/isosurface-extraction/, what is pretty old, but in further searching seems like nothing much new invented in this area (or Im wrong?). So I need an advice on what method to study and start working on!

My user case is:

1) Needs to have very good performance. Work also on Mobile and consoles like NS switch. Its for gaming.

2) Possible to implement automated LOD and culling for large terrains (planet size)

3) Good visuals (sharp and round objects)

4) Editable/Destructible option (I think voxels in general are)

5) Up to date method, that elements flaws of past

4) Terrains generated from Noise on fly!

optional) Has some example code around the internet, as for me is hard to work only with Papers

For now I have been looking into "Cubical Marching Squares", but the examples found online are incomplete (even the authors lib https://graphics.cmlab.csie.ntu.edu.tw/CMS/#Download WIP since 2005, lol) and the paper seems to be a bit abstract. And "Dual Contouring" strategy, but there is so much variations that I got lost.

Please help me out there if you have some experience or have done deep research on this topic! Thanks!





Advertisement

While there is research, newer methods are generally more complex as well. Those cover the basics.

Marching cubes in its simplest form is pretty simple. You define a grid of voxel-corner points in your 3d space. This gives you a lot of voxels, each has 8 points (the corner points of the voxel).

Decide for all 8 points of a voxel whether the point is "in" or "out". For edges of the voxel where one point is "in" and the other point is "out", there has to be a surface between both points. You decide the point on the edge where the surface is crossing the edge, simplest is halfway the edge. You decide this for all 12 edges. This gives you a number of crossing points of surface within the voxel. Create a number of triangles between those crossing points that represents the surface within the voxel. (Work out what to create for each possible outcome on paper, you'll soon notice patterns there.)

You have to do that for all voxels in your 3d space. Simplest is brute-force, try everything.

Smarter is (and this is where "marching" is coming from) to only examine the neighbors of a voxel where at least one edge of the facing rectangle has a crossing point. For example, if you examined a voxel and found crossing points in its top rectangle, the voxel above must have surface too, so it should be examined as well. You 'follow' the surface from voxel to voxel.

This creates 3 problems. The first one is to find the first voxel with surface. Simplest is to start somewhere in the grid, and try every voxel while walking in one direction, until you find a voxel with surface. At that point you can switch to the marching cube idea and follow the surface.

This leads to the second problem, which is tracking which voxels you have visited and which voxels you know have surface but didn't visit yet. Easily solved with 2 sets of voxel coordinates and some book-keeping.

When you run out of unvisited voxels with surface, the marching cubes thing finishes for the surface that you found with the initial voxel (ie the voxel that was found by the solution of the first problem). The third problem is now whether there are more surfaces in your 3d space. This is simple if you know there is at most one surface in your space, else you have to continue searching until you are sure you found them all.

frob said:

While there is research, newer methods are generally more complex as well. Those cover the basics.

Can u share those newer methods u have crossed?

One of the biggest developments since I put together that list is that graphics hardware reached the point where it was feasible to directly ray-cast isosurfaces without ever converting them to polygons. For example, take a look at Lin throwing voxel worlds directly at RTX - it's near impossible to hit that kind of quality through marching-cubes style extraction and classic polygon rendering. As a result, I don't think there has been as much interest in researching polygon extraction methods over the last decade.

Since you are targeting mobile, most of those direct rendering techniques probably won't work for you (although you might be able to get Wave Surfing to work at lower resolutions even on mobile).

That leaves good old fashioned techniques. The only 100% solution to LOD seems to be marching cubes + the transvoxel algorithm to fill the gaps between LOD levels. In theory you can also get dual contouring et al to match across LOD boundaries, but my successes there have been... limited.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

swiftcoder said:

One of the biggest developments since I put together that list is that graphics hardware reached the point where it was feasible to directly ray-cast isosurfaces without ever converting them to polygons. For example, take a look at Lin throwing voxel worlds directly at RTX - it's near impossible to hit that kind of quality through marching-cubes style extraction and classic polygon rendering. As a result, I don't think there has been as much interest in researching polygon extraction methods over the last decade.

Since you are targeting mobile, most of those direct rendering techniques probably won't work for you (although you might be able to get Wave Surfing to work at lower resolutions even on mobile).

That leaves good old fashioned techniques. The only 100% solution to LOD seems to be marching cubes + the transvoxel algorithm to fill the gaps between LOD levels. In theory you can also get dual contouring et al to match across LOD boundaries, but my successes there have been... limited.


That weave surfing (no idea why you call it that) looks interesting, and has even source code available.

trsh said:
That weave surfing (no idea why you call it that) looks interesting, and has even source code available.

It started out as a very efficient method for terrain rendering. I think Ken Silverman named it "wave surfing" when he built VoxLap (i.e. you "surf" along the top of vertically RLE-encoded "waves").

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

"Wave Surfing" - never heard about that either, but i have implemented such a method using clip map heightfields on 150MHz ARM mobiles and it was cool and fast. Then mobile GPUs cam e across and made my effords obsolete :)

However, i've just finished my work on isosurface extraction, and i can share some experience. I do not target realtime, but don't see much options to make it faster, so this is what i do:

Starting from voxeloctree, i extract bricks of voxels (4x4x4), count the bits and get a scalar denisty volume, which is the regular input of iso surface extraction algorithms.

Note, traversing the octree als lets me skip empty / solid space quickly, so i do not need to brute force over the whole volume.

Unlike Marching Cubes or dual methods like Surface Nets / Dual Contouring, i then search for quads, by looking for density being above and below an both sides of such a quad face (every grid point may spawn 3 quads, for x,y,z).

Looking at the resulting quads the result looks like a Minecraft level.

To make the surface smooth, i use two methods: 1. Displace outwards along the gradient of density, 2. Displace inwards using the center of surface area (also weighted by density somehow).
This gives an acceptable result, avoiding the complexity of creating triangles at density crossed edges like Marching Cubes does. Also there is no need for fancy quadrics or such stuff dual methods often use.

The rest of my work is then about guaranteed manifolds, having full connectivity information to build half edge mesh, and stitching partial meshes to support out of core and multithreading. Nothing of this is necessary if all you want is to display on screen.

For LOD i'll use downsampled density in the octree, but i have no interest on continuous merging across LODs because i use those isosorface meshes only as input to more advanced geometry processing.

I can share some pictures and performance measure if interested, after some days...

pasting some images while working, hope this time it's visible...

So this is initial Minecraft result:

And this after the 'smoothing':

Ther is still some banding because getting density from 4x4x4 is still quantized, bu ti think with density from a noise function it would be fine.

swiftcoder said:
trsh said:
That weave surfing (no idea why you call it that) looks interesting, and has even source code available.

It started out as a very efficient method for terrain rendering. I think Ken Silverman named it "wave surfing" when he built VoxLap (i.e. you "surf" along the top of vertically RLE-encoded "waves").

But non of Sven Forstmann or Ken Silverman work does smooth isosurfaces. I checked the demos..., when you zoom into something it's just lots of tiny cubes.

This topic is closed to new replies.

Advertisement