4

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

Zoltán
  • 678
  • 4
  • 15
  • 1
    *but I got stuck* - and we don't know where and on what. *a good idea to use a cylinder model* - yet your current approach uses simple lines. Do you want to rewrite that to modern OpenGL as-is, or do you want a wholly new approach? It's perfectly possible and not that hard to draw simple lines with modern OpenGL. And frankly, the first (and conceptually the most prominent) change you'd need to make would be to convert your code to use `glVertex2dv` - after that change, it's just setup and shaders :) – Bartek Banachewicz Mar 30 '16 at 14:26
  • 1
    buffer the arguments generated in your recursive `drawTree` and you'll get the vertex buffer approach – BeyelerStudios Mar 30 '16 at 14:32
  • But `glVertex2dv` used within `glBegin/glEnd` pairs, and these functions are deprecated. – Zoltán Mar 30 '16 at 14:50
  • I tried to store the generated arguments, and I managed to draw a simple fractal tree with lines, but how can I make the bole thicker and the branches thinner. Right now it looks like this: http://prntscr.com/am1ck1 – Zoltán Mar 30 '16 at 14:55
  • you'd need to buffer your arguments to `glLineWidth` and use that in your shader programme too – BeyelerStudios Mar 31 '16 at 08:55

1 Answers1

2

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;
}