Diamond Square Algorithm Implementation Problem

Posted on 2008-11-20
Last Modified: 2013-12-21
Im working on an implementation of the Diamon Square algortihm, and I can't quite seem to get it to look right.

I'm working off this tutorial which might help explain some of my code.

The function that I know I need to change somehow is below.

It simply takes the min and max X/Z coordinates for the current square being subdivided (which index into an array of Y-Values where these min's and max's already have a Y value computed) and a displacement.

I'm pretty sure the step where I calculate a new midpoint is correct (setting E) but the part that I know is wrong is where I set the midpoint of each side (F G H I)

The forumla seems like it should work, but on high levels of recursion I see almost veritcal drops instead of a smoother transition:

An alternate approach I tried that -almost- worked was just doing:

   yMap[xMin][zMidpnt] = (A + C ) / 2;  // F
   yMap[xMidpnt][zMin] = (A + B) / 2 ;  // G
   yMap[xMax][zMidpnt] = (B + D)/ 2;  // H
   yMap[xMidpnt][zMax] = (C + D) / 2 ;  // I

Which produces a more better landscape but isn't really performing the square step of the algorithm correctly (I think) because it does not add any random displacement to these midpoints.

Any help on how to fix this would be appreciated.

void genLandscapeRec(int xMin, int xMax, int zMin, int zMax, float disp) {


   float nDisp =  (float)(disp * (float)pow(2, -(double)roughnes)); // New displacement


   int xMidpnt = (xMin+xMax) / 2;

   int zMidpnt = (zMin+zMax) / 2;


   GLfloat A = yMap[xMin][zMin];

   GLfloat B = yMap[xMax][zMin];

   GLfloat C = yMap[xMin][zMax];

   GLfloat D = yMap[xMax][zMax];


   GLfloat E = (A + B + C + D) / 4 + randDisp(disp); // Midpoint height


   yMap[xMidpnt][zMidpnt] = E; // Set E


   yMap[xMin][zMidpnt] = (A + C + E) / 3 + randDisp(disp);  // F

   yMap[xMidpnt][zMin] = (A + B + E) / 3 + randDisp(disp);  // G

   yMap[xMax][zMidpnt] = (B + D + E) / 3 + randDisp(disp);  // H

   yMap[xMidpnt][zMax] = (C + D + E) / 3 + randDisp(disp);  // I


   if ((xMidpnt - xMin) > 1) { // Subdivide if new midpoint length will be > 1


      genLandscapeRec(xMin, xMidpnt, zMin, zMidpnt, nDisp);

      genLandscapeRec(xMidpnt, xMax, zMin, zMidpnt, nDisp);

      genLandscapeRec(xMin, xMidpnt, zMidpnt, zMax, nDisp);

      genLandscapeRec(xMidpnt, xMax, zMidpnt, zMax, nDisp);



float randDisp(float disp) {

    return (((float)rand()) / ((float)RAND_MAX)) * (disp + (disp/3)) - disp/3;


Open in new window

Question by:iMr_Ki
    LVL 1

    Author Comment

    The following globals and initialization function may also be helpful:
    // fractal landscape globals
    static GLfloat recDepth = 9;
    static GLfloat roughnes = 1;
    static GLfloat yMap[1025][1025];
    void genLandscape(void) {
       int dMax = (int)pow(2, recDepth);
       int dMin = 0;
       float disp = 3;
       yMap[dMin][dMax] = 0.0;
       yMap[dMin][dMax] = 0.0;
       yMap[dMax][dMin] = 0.0;
       yMap[dMax][dMax] = 0.0;
       genLandscapeRec(dMin, dMax, dMin, dMax, disp);

    Open in new window

    LVL 20

    Expert Comment

    hey iMr_Ki,

    probably the randDisp-function is returning wrong (too high) values. check the values it is returning with an assert-ation

    LVL 1

    Author Comment

    randDisp works fine, its at the bottom of the code snippet, simply returns floats in the range of the parameter passed (with a preference on positive values).
    LVL 11

    Expert Comment

    I sort of got this working better....

    The issue was the test for "doneness"....

    this test
       if ((xMidpnt - xMin) > 1) { // Subdivide if new midpoint length will be > 1

    didn't return values in the expected range

    it returned large intervals.... and it was never less than zero.


    LVL 11

    Expert Comment

    ie, xMin was always positive.. and so was xMidpiont....

    the sides of the square were monotonically increasing... so in the interval 1 to 10 for instnace... xMid is 5, xMin is 1....

    but midpoint never crosses 1.. so interval is big...


    LVL 1

    Accepted Solution

    Jaggedness was being caused by overwriting edge midpoints that had already been computed.

    Solution would be to code snippet to something like:

       yMap[xMin][zMidpnt] = (A + C + E) / 3 + randDisp(disp);  // F
       yMap[xMidpnt][zMin] = (A + B + E) / 3 + randDisp(disp);  // G
       yMap[xMax][zMidpnt] = (B + D + E) / 3 + randDisp(disp);  // H
       yMap[xMidpnt][zMax] = (C + D + E) / 3 + randDisp(disp);  // I

    Checking to see if midpoints had been previously set.

    Featured Post

    Find Ransomware Secrets With All-Source Analysis

    Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

    Join & Write a Comment

    Artificial Intelligence comes in many forms, and for game developers, Path-Finding is an important ability for making an NPC (Non-Playable Character) maneuver through terrain.  A* is a particularly easy way to approach it.  I’ll start with the algor…
    As game developers, we quickly learn that Artificial Intelligence (AI) doesn’t need to be so tough.  To reference Space Ghost: “Moltar, I have a giant brain that is able to reduce any complex machine into a simple yes or no answer. (http://www.youtu…
    THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
    The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.

    732 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    23 Experts available now in Live!

    Get 1:1 Help Now