GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2008-01-02 11:14:29

leif902
Member
From: Georgia, USA
Registered: 2007-10-09
Posts: 24

Grid Smoothing and Random Terrain Generation

Today I decided to take a stab at smoothing out random values in grids, useful in random terrain generation and anywhere else you need random numbers grouped in predictable ways.

Therefore I created the following script for smoothing over grids (Well, I say created, it's a commonly used algorithm):

Expand//
// ds_grid_smooth
// Smooths the randomly generated contents of a grid, useful for
// random terrain generation.
// Arguments
//    argument0 - The grid to populate
//    argument1 - The size of each sub-division (About 4 for optimal results, less than four will take longer to calculate
//                       and give you less of an effect, more than 4 will calculate faster and give you more smoothing)
//

var step, xx, yy, w, h, grid, total, y_local, x_local, average;
grid = argument0;
step = argument1;
w = ds_grid_width(grid);
h = ds_grid_height(grid);

for(yy = 0; yy < h; yy += step)
{
     for(xx = 0; xx < w; xx += step)
     {
          total = 0;
          for(y_local = yy; y_local <= yy + step; y_local += 1)
          {
               for(x_local = xx; x_local <= xx + step; x_local+= 1)
               {
                    total += ds_grid_get(grid,x_local, y_local);
               }
          }
          average = total / sqr( step );
          for(y_local = yy; y_local <= yy + step; y_local += 1)
          {
               for(x_local = xx; x_local <= xx + step; x_local += 1)
               {
                    ds_grid_set(grid, x_local, y_local, average );
               }
          }
     }
}

To test it I populated a grid randomly with values 0 - 3 (Simple enough):

Expandyy = -1;
while ( yy < h )
{
     xx = 0;
     yy += 1;
     while ( xx < w )
     {
          ds_grid_set(grid, xx, yy, floor ( random( 3 ) ) );
          xx += 1;
     }
}

and drew the results by subtracting a normalized version of each grid value from the value of the color black, this is using a step value of 4:
smoothed_grid.png

As opposed to the non-smoothed version (not the same grid):
random_grid.PNG

There are better ways to do this, but this one is easy. I found a better way and created a GML script, but I'm still toying with it as it only semi-smooths it at the moment.

Last edited by leif902 (2008-01-02 11:15:58)


Leif902

Offline

#2 2009-01-11 00:28:11

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: Grid Smoothing and Random Terrain Generation

[ MISSING ]

Offline

#3 2009-12-16 01:43:34

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: Grid Smoothing and Random Terrain Generation

I found my missing smoother method

//argument0 - grid
//argument1 - size of mean radius
//argument2 - deform factor (0-much deform, >0 less deform)
var w,h;
w = ds_grid_width(argument0)
h = ds_grid_height(argument0)
var g; g = ds_grid_create(w,h)
var xx,yy;
yy = 0;
var av;
var ct;
repeat(h)
{
    xx = 0;
    repeat(w)
    {
        av = argument2*ds_grid_get(argument0,xx,yy);
        av += ds_grid_get_disk_mean(argument0,xx,yy,argument1)
        ds_grid_set(g,xx,yy,av/(argument2+1));
        xx+=1;
    }
    yy+=1;
}

ds_grid_copy(argument0,g);
ds_grid_destroy(g);

Last edited by icuurd12b42 (2009-12-16 02:23:57)

Offline

#4 2009-12-16 05:57:04

xot
Administrator
Registered: 2007-08-18
Posts: 1,233

Re: Grid Smoothing and Random Terrain Generation

Ah, cool, thanks for posting that again.

ds_grid_get_disk_mean is definitely the way to go here. Even a chunky box-filter using ds_grid_get_mean would be much better than doing it all in GML.

In my opinion the overall construction of your version is much more appropriate for a function of this description. The original only averages in discreet blocks leading to discontinuities. It's more of a "pixelation" filter than a smoothing one. Your version appears far more continuous and should be completely smooth across all cell boundaries.


Abusing forum power since 1986.

Offline

#5 2009-12-16 06:47:30

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: Grid Smoothing and Random Terrain Generation

No prob. Make sure you backup your forum this time LOL...

Offline

#6 2009-12-19 12:12:35

xot
Administrator
Registered: 2007-08-18
Posts: 1,233

Re: Grid Smoothing and Random Terrain Generation

At the suggestion of icuurd12b42, I'll repost here what I posted in another topic.

xot wrote:

I think a faster way, again only if you are willing to use separate grids for each channel, could be like this:

Expandw = ds_grid_width(source);
h = ds_grid_height(source);
destination = ds_grid_create(w, h);
ds_grid_copy(destination, source);
ds_grid_add_grid_region(destination, source, 0, 0, w, h, -1,  0);
ds_grid_add_grid_region(destination, source, 0, 0, w, h,  1,  0);
ds_grid_add_grid_region(destination, source, 0, 0, w, h,  0, -1);
ds_grid_add_grid_region(destination, source, 0, 0, w, h,  0,  1);
ds_grid_multiply_region(destination, 0, 0, w, h, 0.2);

You could easily give the center pixel extra weight with another ds_grid_multiply_region call after the copy.

Expandw = ds_grid_width(source);
h = ds_grid_height(source);
destination = ds_grid_create(w, h);
ds_grid_copy(destination, source);
ds_grid_multiply_region(destination, 0, 0, w, h, 12);
ds_grid_add_grid_region(destination, source, 0, 0, w, h, -1,  0);
ds_grid_add_grid_region(destination, source, 0, 0, w, h,  1,  0);
ds_grid_add_grid_region(destination, source, 0, 0, w, h,  0, -1);
ds_grid_add_grid_region(destination, source, 0, 0, w, h,  0,  1);
ds_grid_multiply_region(destination, 0, 0, w, h, 0.0625);

Abusing forum power since 1986.

Offline

Board footer

Powered by FluxBB