1
\$\begingroup\$

I've been spending a lot of time over the past few days finding out information about the marching cubes algorithm and I'm pretty sure I understand it.

My game would be using chunks of land with the voxels stored in an octree in the chunk and unless it won't run with this many voxels I was going to try with .25m blocks at first.

to make the mesh I would loop through all of the blocks I would consider to be solid(above 0.5 density from 3d Perlin noise) and call the Perlin noise function for each of the blocks vertices. Depending on the combination of vertices that are within the visible density range the mesh would be one of the 256 combinations. then move the vertices of the mesh based on interpolating the density values of the corners to make a smooth surface.

Now I want to make it possible to place blocks and dig them. All placed blocks wouldn't have a smooth flag so wouldn't have the marching cubes mesh built from them so they would retain their crisp edges. How could I make it so that if you dig blocks they would look smooth? I couldn't just use perlin noise could I, because all of the dug blocks would be considered completely solid as they are in the solid area above the isovalue. However there are plenty of videos with deformable marching cubes terrain. could somebody explain how I could do this or suggest another algorithm?

\$\endgroup\$
1
\$\begingroup\$

You could add a user-defined function to the underlying perlin function.

For example, if the user adds a meta-ball function at a point x0, y0 z0 and with density d, then you add that function to your evaluation function.

It becomes (I use Java):

List<UserBallFunctions> userDefinedFunctions; // Init somewhere, let the user add members etc.
int evalFunction(x, y , z) {
    double terrainValue = perlin(x, y, z);
    double userModification = 0;
    for(UserBallFunctions func: userDefinedFunctions) {
         userModification  += func.valueAt(x, y, z);
    }
    return selectAppropriateMaterial(isovalue + userModification );
}

Where userFunction is a "ball" function added (or substracted, if value is negative) by the user:

public class UserBallFunctions{
    int x0, y0, z0;
    double ballDensity;
    // <-- Add initialisation, getters and setters)
    double valueAt(int x, int y, int z){
        return ballDensity / ( (x-x0)*(x-x0) + (y-y0)*(y-y0) + (z-z0*(z-z0) );
    }
}

When you update your topology, the world should have changed. Those changes will smoothly integrate with the existing world because we used additive mixing between terrainValue and userModification. You can force abrupt change if you instead use a max function, etc.

To make those changes persistant, you must save the metaball definitions in the same way you saved the world seeds etc. They may be saved per-chunk to speedup user function computation (fewer metaballs per-chunk), but careful with side-effects where a ball influences beyond its chunk. You may want a ball function with a bounded support to help with this.

\$\endgroup\$
  • \$\begingroup\$ So for example in the perlin noie function it could also look for the areas that were changed and if that spot was "dug" then return a low density? \$\endgroup\$ – Ben Beazley Jan 30 '17 at 19:23
  • \$\begingroup\$ Close. The perlin function cannot be altered unless you change the pseudo-random number generated sequence, but it will be disastrous on a large scale. You should return the pure Perlin result plus a lowered density. \$\endgroup\$ – MrBrushy Jan 30 '17 at 19:43
  • \$\begingroup\$ Ok, but what would happen if the perlin noise density was so high that once you subtracted some density it still was above the isovalue I believe it's called so it still looks solid? \$\endgroup\$ – Ben Beazley Jan 31 '17 at 1:59
  • \$\begingroup\$ Well since you're using the Perlin value to change between materials, the location would first change through the materials list before vanishing, there there is feedback. If this is unwanted and you want immediate disappearance, change the ball function (higher density increments + higher order powers) or change the mixing function from a '+' to a 'if' etc. \$\endgroup\$ – MrBrushy Jan 31 '17 at 7:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.