Back to July Calendar Previous Entry Next Entry→

July 19, 2005

 

A little explanation of yesterday’s code:

 

            v[0][0] = 0.5*(a[0] + c[0]);

            x = (float) rand()/RAND_MAX;

            v[0][1] = a[1]+x*(c[1] - a[1]);

            v[1][0] = 0.5*(b[0] + c[0]);

            x = (float) rand()/RAND_MAX;

            v[1][1] = b[1]+x*(c[1] - b[1]);

 

Let’s say the starting triangle has vertices a, b and c with a = (0,0), b = (2,0) and c = (1,1), as shown at right.  The code above is designed to locate two new 2D mountaintop points, v[0] and v[1] with the x-coordinate of v[0]  midway between the x-coordinates of a and c and the x-coordinate of v[1] midway between the x-coordinates of c and a

The y-coordinates of v[0] and v[1] are random.  The c++ function rand() returns a random integer between 0 and RAND_MAX. So x=(float)rand()/RAND_MAX is cast as a random float number between 0.0 and 1.0.   Thus, y0=a[1]+x*(c[1]–a[1]) is a random number between a[1] and c[1] (between 0 and 1, in this case.)  Similarly, y1=b[1]+x*(c[1]–b[1]) is a random number between b[1] and c[1] (again, between 0 and 1, in this case.)   
 

Trouble is, you get a different result from this code depending on whether the random point is above the current slope of that segment of the mountain, or above it.  To understand why, let’s look at the recursive calls:

divide_triangle(a, c, v[0], m-1);              

divide_triangle(b, c, v[1], m-1);

 

And if m-1=0 then the ‘else’ (base) case will be to draw the triangle’s edges according with (revised from yesterday

 

void triangle(GLfloat *a, GLfloat *b, GLfloat *c) {

      glBegin(GL_POLYGON);

         glEdgeFlag(GL_FALSE);

         glVertex2fv(a);

         glEdgeFlag(GL_TRUE);

         glVertex2fv(b);

         glVertex2fv(c);

    glEnd();

}

 

After adjusting the multiplier so the new y-coordinate (mountaintop point) can be up to 20% more than it’s neighbor ( y0=a[1]+1.2*x*(c[1]–a[1])) this leads to mountainscapes that look like this:

 

It appears that if the a new mountaintop point is below the current horizon I thought this would work without special cases, as in the sort of flagging logic required in the previous tessellations. I tried various schemes for making sure that the points were always listed in counterclockwise order, so that the “front” face (the one in edge mode) would be drawn.  Then it occurred to me that I could simply put the back face in edge mode also, like so:

 

GLfloat v[3][2] = {{0.0,0.0},{2.0,0.0},{1.0,1.0}};

void display(void) {

      glClear(GL_COLOR_BUFFER_BIT);

      glPolygonMode(GL_FRONT, GL_LINE);

      glPolygonMode(GL_BACK, GL_LINE);

      int n = 6;

      glColor3f(1.0, 0.0, 0.0);

      divide_triangle(v[0], v[1], v[2], n);    

      glFlush();

}