c++openglfractalsglm-mathl-systems

Fractal tree in modern OpenGL (OpenGL 3.3 and above)


I need an approach to draw a 3D fractal tree with modern OpenGL. Any suggestions?

I don’t necessarily require full source code, just an idea how to do it.

What I'm trying to do is to make a 3D tree. In fixed-function OpenGL it's not so difficult to draw a good looking realistic tree, but I don't know how to do it in modern Opengl.

I thought it would be a good idea to use a cylinder model for every branch and use glm to transform it in the right place and size because in this case I could use the texture coordinates and normals of the model, but I got stuck and I don't know how to do it.

Here is fractal 2D tree made in fixed function OpenGL with recursion. If anyone interested I can send the entire source code.

void drawTree(int currentDepth, int maxDepth)
{
    if (currentDepth > maxDepth)
        return;

    if (currentDepth <= maxDepth - 2)
    {
        glColor3d(0.45, 0.2, 0.05);
        glLineWidth(10 * static_cast<GLfloat>(pow(TREE_FACTOR, currentDepth)));
    }
    else
    {
        glColor3d(0, 0.5, 0);
        glLineWidth(30 * static_cast<GLfloat>(pow(TREE_FACTOR, currentDepth)));
    }

    double lineLen = TREE_LINE_BASE_LEN * pow(TREE_FACTOR, currentDepth);
    glBegin(GL_LINES);
    glVertex2d(0, 0);
    glVertex2d(0, lineLen);
    glEnd();

    int angle1 = 10 + rand() % 40;
    int angle2 = 10 + rand() % 40;

    glTranslated(0, lineLen, 0);
    glRotated(-angle1, 0, 0, 1);
    drawTree(currentDepth + 1, maxDepth);
    glRotated(angle1 + angle2, 0, 0, 1);
    drawTree(currentDepth + 1, maxDepth);
    glRotated(-angle2, 0, 0, 1);
    glTranslated(0, -lineLen, 0);
}

How can I make something like this in modern OpenGL with VAOs and VBOs and shaders?

enter image description here


Solution

  • Quick idea.

    void SudoCreateChild(const mat4x4& m2w_noscale, const int depth)
    {
        if(depth>=MAX_DEPTH){
            return;
        }
        /// Creates the M2W matrix
        mat4x4 m2w=m2w_noscale * mat4x4::identity*(1/depth);
        /// Draw the branch
        DrawCylinder(m2w);
        /// Create the children branches
        for(int i=0; i<CHILDREN_NUMBER; ++i){
            float angle=(2.0f*PI/CHILDREN_NUMBER)*i;
            /// Initial rotation of PI/4 plus equal rotation between siblins
            mat4x4 rotation=mat4x4::rotate(angle, vector3(0,1,0))*mat4x4::rotate(PI*0.25, vector3(1,0,0))
            /// Size of the branch is 1/depth
            mat4x4 translation=mat4x4::translate(vector3(vector3(0,1,0)*(1/(depth+1))));
            /// Recursively create the branches
            SudoCreateChild(m2w_noscale*translation*rotation, depth+1);
        }
    }
    
    int main(void)
    {
        SudoCreateChild(mat4x4::identity, 1);
        return 0;
    }