Jump to content


Photo

Midpoint Displacement and Diamond Square


  • This topic is locked This topic is locked
4 replies to this topic

#1 lethman427

lethman427

    GMC Member

  • New Member
  • 58 posts

Posted 03 May 2012 - 10:56 PM

Hey forum. I recently went to port my Midpoint displacement and Diamond Square algorithms to use grids instead of arrays, but when I did, all my images have a solid square in the top left corner.
Here's my MD code:
//argument0 = heightmap's ID
//argument1 = the width/height of the heightmap (must be a power of 2) 
//argument2 = the initial height-change variable. reccomended to by max height/4
//argument3 = the seed for the heightmap

var iid, width, h, seed, starttime, endtime, rep, i, b, x1, x2, y1, y2;
//define variables
iid=argument0
width=argument1
h=argument2
seed=argument3

//create Array
global.terrains[MD,iid]=ds_grid_create(width,width)

//define start points
ds_grid_set(global.terrains[MD,iid],0,0,128);
ds_grid_set(global.terrains[MD,iid],0,width,128);
ds_grid_set(global.terrains[MD,iid],width,0,128);
ds_grid_set(global.terrains[MD,iid],width,width,128);

//fetch the start time
starttime=current_time

//execute Midpoint Displacement code
for(rep = 2; rep < width; rep *= 2) 
{ 
    for(i = 1; i <= rep; i += 1)
    {
     for(b = 1; b <= rep; b += 1)
      {
      //get corner points
      x1 = (width / rep) * (i-1); 
      x2 = (width / rep) * i;
      y1 = (width / rep) * (b-1); 
      y2 = (width / rep) * b;
      
      //right side 
      randomize()      
      avg = (ds_grid_get(global.terrains[MD,iid],x2,y1) + ds_grid_get(global.terrains[MD,iid],x2,y2)) / 2; 
      ds_grid_set(global.terrains[MD,iid],x2,(y1 + y2) / 2,avg + random_range(-h,h));
      
      //left side
      randomize() 
      avg = (ds_grid_get(global.terrains[MD,iid],x1,y1) + ds_grid_get(global.terrains[MD,iid],x1,y2)) / 2; 
      ds_grid_set(global.terrains[MD,iid],x1,(y1 + y2) / 2,avg + random_range(-h,h));
      
      //top
      randomize() 
      avg = (ds_grid_get(global.terrains[MD,iid],x1,y1) + ds_grid_get(global.terrains[MD,iid],x2,y1)) / 2;
      ds_grid_set(global.terrains[MD,iid],(x1 + x2) / 2,y1,avg + random_range(-h,h)); 
      
      //bottom
      randomize() 
      avg = (ds_grid_get(global.terrains[MD,iid],x1,y2) + ds_grid_get(global.terrains[MD,iid],x2,y2)) / 2; 
      ds_grid_set(global.terrains[MD,iid],(x1 + x2) / 2,y2,avg + random_range(-h,h));           
      
      //center
      randomize() 
      avg = (ds_grid_get(global.terrains[MD,iid],x1,y1) + ds_grid_get(global.terrains[MD,iid],x2,y1) + ds_grid_get(global.terrains[MD,iid],x1,y2) + ds_grid_get(global.terrains[MD,iid],x2,y2)) / 4;
      ds_grid_set(global.terrains[MD,iid],(x1 + x2) / 2,(y1 + y2) / 2,avg + random_range(-h,h)); 
     }
    }
    //divide height change variable by 2
    h/=2
}
//fetch when code execution time ended
endtime=current_time

//return the time it took to excecute the code
return(endtime-starttime)
and Here's the Diamond Square
//argument0 = heightmap's ID
//argument1 = the width/height of the heightmap (must be a power of 2) 
//argument2 = the initial height-change variable. reccomended to by max height/4
//argument3 = the seed for the heightmap

var iid, width, h, seed, starttime, endtime, rep, i, b, x1, x2, y1, y2;

//define variables
iid=argument0
width=argument1
h=argument2
seed=argument3

//create Array
global.terrains[DS,iid]=ds_grid_create(width,width)

//define start points
ds_grid_set(global.terrains[DS,iid],0,0,128);
ds_grid_set(global.terrains[DS,iid],0,width,128);
ds_grid_set(global.terrains[DS,iid],width,0,128);
ds_grid_set(global.terrains[DS,iid],width,width,128);

//set the random number generator's seed
random_set_seed(seed)

//fetch the start time
starttime=current_time

//execute Midpoint Displacement code
for(rep = 2; rep < width; rep *= 2) 
{ 
    for(i = 1; i <= rep; i += 1)
    {
     for(b = 1; b <= rep; b += 1)
      {
      //get corner points
      randomize()
      x1 = (width / rep) * (i-1); 
      x2 = (width / rep) * i;
      y1 = (width / rep) * (b-1); 
      y2 = (width / rep) * b;
  
      //center
      randomize()
      avg = (ds_grid_get(global.terrains[DS,iid],x1,y1) + ds_grid_get(global.terrains[DS,iid],x2,y1) + ds_grid_get(global.terrains[DS,iid],x1,y2) + ds_grid_get(global.terrains[DS,iid],x2,y2)) / 4;
      ds_grid_set(global.terrains[DS,iid],(x1 + x2) / 2,(y1 + y2) / 2,avg + random_range(-h,h));      
      
      //right side
      randomize()       
      avg = (ds_grid_get(global.terrains[DS,iid],x2,y1) + ds_grid_get(global.terrains[DS,iid],x2,y2) + ds_grid_get(global.terrains[DS,iid],(x1 + x2) / 2,(y1 + y2) / 2)) / 3; 
      ds_grid_set(global.terrains[DS,iid],x2,(y1 + y2) / 2,avg + random_range(-h,h));
      
      //left side
      randomize()
      avg = (ds_grid_get(global.terrains[DS,iid],x1,y1) + ds_grid_get(global.terrains[DS,iid],x1,y2) + ds_grid_get(global.terrains[DS,iid],(x1 + x2) / 2,(y1 + y2) / 2)) / 3; 
      ds_grid_set(global.terrains[DS,iid],x1,(y1 + y2) / 2,avg + random_range(-h,h));
      
      //top
      randomize()
      avg = (ds_grid_get(global.terrains[DS,iid],x1,y1) + ds_grid_get(global.terrains[DS,iid],x2,y1) + ds_grid_get(global.terrains[DS,iid],(x1 + x2) / 2,(y1 + y2) / 2)) / 3;
      ds_grid_set(global.terrains[DS,iid],(x1 + x2) / 2,y1,avg + random_range(-h,h)); 
      
      //bottom
      randomize()
      avg = (ds_grid_get(global.terrains[DS,iid],x1,y2) + ds_grid_get(global.terrains[DS,iid],x2,y2) + ds_grid_get(global.terrains[DS,iid],(x1 + x2) / 2,(y1 + y2) / 2)) / 3; 
      ds_grid_set(global.terrains[DS,iid],(x1 + x2) / 2,y2,avg + random_range(-h,h));           
      

     }
    }
    //divide height change variable by 2
    h/=2
}
//fetch when code execution time ended
endtime=current_time

//return the time it took to excecute the code
return(endtime-starttime)
Any help is greatly appreciated.
Thanks,
~Lethman~
  • 0

#2 torigara

torigara

    GMC Member

  • GMC Member
  • 6483 posts

Posted 07 May 2012 - 07:06 AM

//create Array
global.terrains[MD,iid]=ds_grid_create(width,width)

//define start points
ds_grid_set(global.terrains[MD,iid],0,0,128);
ds_grid_set(global.terrains[MD,iid],0,width,128);
ds_grid_set(global.terrains[MD,iid],width,0,128);
ds_grid_set(global.terrains[MD,iid],width,width,128);

You had to make the grid larger by 1.
ds_grid_create(width + 1, width + 1);
Alternatively, you could subtract 1 from the bottom and right coordinates. But you may also have to modify other calculations to take that -1 into account.
ds_grid_set(global.terrains[MD,iid], width - 1, width - 1, 128);

There is a common off-by-one mistake caused by mixing up the data size and the last index. In general, when the first index is 0, the last index is less by one than the number of data. For simplicity, suppose that you have created a 4x4 grid:
ds_grid_create(4, 4);
It has four columns and four rows, each numbered as 0, 1, 2 and 3.
      0       1       2       3    <- column no.
  +-------+-------+-------+-------+
0 | (0,0) | (1,0) | (2,0) | (3,0) |
  +-------+-------+-------+-------+
1 | (0,1) | (1,1) | (2,1) | (3,1) |
  +-------+-------+-------+-------+
2 | (0,2) | (1,2) | (2,2) | (3,2) |
  +-------+-------+-------+-------+
3 | (0,3) | (1,3) | (2,3) | (3,3) |
  +-------+-------+-------+-------+
^
|
row no.
You can't set or get values at column/row 4 that doesn't exist. (In practice, it will just return 0 when you try to get a value outside the grid.) To use columns/rows from 0 to 4, the size of grid must be 4+1.

Edited by torigara, 07 May 2012 - 10:51 AM.

  • 0

#3 lethman427

lethman427

    GMC Member

  • New Member
  • 58 posts

Posted 08 May 2012 - 02:28 AM

Oh, I get it now. Stupid of me to forget that the data starts at 0 instead of 1... Thanks!
  • 0

#4 xot

xot

    media multimixer

  • Global Moderators
  • 4653 posts
  • Version:GM:Studio

Posted 09 May 2012 - 02:07 PM

If your intention is to use 'seeds' to reliably reproduce a 'random' height-map, you should remove all instances of randomize() in your code.
  • 0

#5 lethman427

lethman427

    GMC Member

  • New Member
  • 58 posts

Posted 10 May 2012 - 02:43 AM

If your intention is to use 'seeds' to reliably reproduce a 'random' height-map, you should remove all instances of randomize() in your code.

That was my original idea, but then I didn't need the functionality of seeds and wanted things as random as possible so I got rid of it. I simply forgot to remove the seed initialization code. Sorry.
Cheers,
~Lethman~
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users