Barnsley fern fractal to generate a 3D model of a fern leaf, Recursion Sample

Started by Theo Gottwald, April 13, 2024, 09:32:30 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

Here's an example program that uses the Barnsley fern fractal to generate a 3D model of a fern leaf. The Barnsley fern is a fractal that is generated using an iterated function system (IFS), which is a set of affine transformations that are applied repeatedly to generate a complex shape.

' Barnsley Fern Fractal in 3D
' Oxygen Basic, ConsoleG, OpenGL

#compact
%filename "barnsley_fern.exe"
'uses RTL64
% Title "Barnsley Fern Fractal in 3D"

'% WindowStyle WS_OVERLAPPEDWINDOW
'% Animated
'% ScaleUp
% PlaceCentral
% AnchorCentral

% shaders

uses consoleG

BeginScript

const int MAX_ITER = 100000
const int MAX_POINTS = 10000

struct Point {
    float x, y, z;
};

Point points[MAX_POINTS];
int numPoints = 0;

procedure applyTransform(Point *p, float a, float b, float c, float d, float e, float f) {
    float x = p->x;
    float y = p->y;
    float z = p->z;
    p->x = a*x + b*y + c*z + d;
    p->y = e*x + f*y + z + 1;
}

procedure drawFern() {
    if (numPoints <= 0) {
        return;
    }

    glBegin(GL_LINES);
    for (int i = 0; i < numPoints-1; i++) {
        glVertex3f(points[i].x, points[i].y, points[i].z);
        glVertex3f(points[i+1].x, points[i+1].y, points[i+1].z);
    }
    glEnd();
}

procedure generateFern() {
    Point p;
    p.x = 0;
    p.y = 0;
    p.z = 0;

    for (int i = 0; i < MAX_ITER; i++) {
        int transform = int(rnd*100);
        if (transform < 1) {
            applyTransform(&p, 0, 0, 0, 0, 0, 0.16);
        } else if (transform < 8) {
            applyTransform(&p, 0.85, 0.04, -0.04, 0, -0.85, 1.6);
        } else if (transform < 15) {
            applyTransform(&p, 0.2, -0.26, 0.23, 0, 0.22, 1.6);
        } else if (transform < 85) {
            applyTransform(&p, -0.15, 0.28, 0.26, 0, 0.24, 0.44);
        } else {
            applyTransform(&p, 0, 0, 0, 0, 0, 1.6);
        }

        if (numPoints < MAX_POINTS) {
            points[numPoints++] = p;
        }
    }
}

procedure main() {
    cls();
    shading();

    generateFern();

    while (not key[KB_ESC]) {
        drawFern();
        wait(0.01);
    }
}

EndScript
```
In this program, we define a `Point` struct to represent a 3D point in space. We also define a `MAX_ITER` constant to control the number of iterations used to generate the fern, and a `MAX_POINTS` constant to limit the number of points stored in memory.

The `applyTransform` procedure takes a `Point` pointer and six coefficients that define an affine transformation, and applies the transformation to the point. The `drawFern` procedure draws lines between adjacent points in the `points` array to create the 3D model of the fern.

The `generateFern` procedure generates the Barnsley fern fractal by repeatedly applying a set of four affine transformations to an initial point, and storing the resulting points in the `points` array. The probability of each transformation being applied is controlled by a random number generator.

Finally, the `main` procedure generates the fern using `generateFern`, and then enters a loop that repeatedly calls `drawFern` to display the 3D model of the fern. The loop continues until the user presses the Escape key.

When you run this program, you should see a 3D model of a fern leaf that is generated using the Barnsley fern fractal. You can experiment with different coefficients and probabilities for the affine transformations to create different variations of the fern.