如何用我的代码控制我的L-System模式?

时间:2009-12-11 23:21:22

标签: c++ opengl

我正在开展一个项目来展示和生长树木的动画。我在这个项目上使用C ++和OpenGL。树长到一定数量的树枝,停止,然后树的叶子落到地上。我已决定使用Lidenmayer系统以图形方式描绘这一点,因为它似乎更容易替代创建结构和定义树的每个元素。到目前为止,我可以显示树和天空的树干,但我迷失了如何实际让树生长新的树枝。我考虑过做一个for循环来控制它,但我不知道如何完成它。处理这个问题的好方法是什么?

我的L系统规则:

推导长度:10 公理:F F - > G [-F] [+ F] GF G - > GG

旋转角度= 15.0度(.2618弧度)

更新:这是我到目前为止所做的。

#include <math.h>
#include <windows.h>
#include <GL/gl.h>
#include <glut.h>

int treeSeed = 0;
float branchAngle = .2618;

/*
    Controls the growth of the tree. Factor
    of growth is inverse to that of the ShrinkTree
    method

*/

//void GrowTree()
//{
    /*Tree grows in a direction depending
    on the L-System rules */
//
//      int i;
//      for(i = 0; i <=10 ; i++)
//      {
//          
//          //grow tree
//
//      }

//}

/*
Tree shrinks in a direction depending
on the L-System rules. Factor of shrinkage is 
inverse to that of the GrowTree method.*/

void ShrinkTree()
{
    /*int j;
    for (j = -; j <=10 ; j++)
    {

    }*/

}

//void treeAninmation()
//{
//
//  glutPostRedisplay();
//}


/*
    Draws a leaf on the branch.
    If the seed axiom is at zero,
    a new leaf is drawn. Otherwise,
    the branch shrinks to accomodate
    existing leaves.


*/

void DrawLeaf()
{


    if(treeSeed==0)
    {
        glBegin(GL_QUADS);
        glColor3f(0.0f,1.0f,0.0f);

        glVertex2f(-0.05, -40.5);
        glVertex2f(-0.05, -20.5);
        glVertex2f(-0.02, -40.5); 
        glVertex2f(-0.02,-20.5);

        glEnd();

    }
    /*else
    {

        GrowTree();
        DrawTwig(treeSeed-1);
        glPushMatrix();
                glRotate(branchAngle,1.0f,0.0f,0.0f);
                DrawLeaf(treeSeed-1);
        glPopMatrix();
        glPushMatrix();
                glRotate(branchAngle, );
                DrawLeaf(treeSeed-1);
        glPopMatrix();
    }*/

}


void DrawTwig()
{

    /*

        Draws trunk of tree
        Represents base scenario of
        recursion

    */
    if(treeSeed==0)
    {

        glLineWidth(5.0);

        glBegin(GL_LINE_STRIP);

        glColor3f(0.60f,0.40f,0.12f);

        glVertex2f(-0.10, -80.5);
        glVertex2f(-0.10, -100.5);

        glEnd();

    }

    /*else
    {
        ShrinkTree();
        DrawTwig(treeSeed-1);

    }*/
}



/* Draws the tree with leaves *
    Uses recursion to draw tree structure
    Relies on L-System formula in order
    to produce a tree 

*/

void DrawTree()
{

    DrawTwig(treeSeed);
    //DrawLeaf(treeSeed);


}




/* Draws the horizon, the sky, and the ground*/

void RenderScene(void)
{
    // clears color buffer
    glClear(GL_COLOR_BUFFER_BIT);

    /*
    //GLfloat y;
    GLfloat fSizes[2]; // Store supported line width range
    GLfloat size;  // Store supported line width increments
    */

    //The horizon lies in the xy plane

    glBegin(GL_LINE_STRIP);

    glColor3f(0.0f,0.0f,0.0f); //sets color of horizon to black
    glVertex2f(-135.0,0.0);
    glVertex2f(135.0,0.0);

    glEnd();

    //The sky lies in the xy plane
    //Starts at horizon line,
    //goes upwards to height edge of screen,
    //and goes rightwards to width edge of screen.


    glBegin(GL_QUADS);

    glColor3f(0.0f,0.0f,1.0f);

    glVertex2f(135.0, 0.0);
    glVertex2f(-135.0, 0.0);
    glVertex2f(-135.0, 100.0); 
    glVertex2f(135.0,100.0);


    glEnd();

    DrawTree();

    glFlush();

}


void SetupRC(void)
{

    glClearColor(1.0f,1.0f,1.0f,1.0f);

}


void ChangeSize(GLsizei w, GLsizei h)
{
    GLfloat aspectRatio;

    //prevents divison by zero
    if(h ==0)
        h = 1;

    //set Viewport to window dimensions
    glViewport(0,0,w,h);

    // Reset coordinate system
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Establish clipping volume (left, right,bottom,top,near,far

    aspectRatio = (GLfloat)w/(GLfloat)h;

    if (w <= h)
        glOrtho (-100.0, 100.0, -100/aspectRatio, 100/aspectRatio,1.0,-1.0);
    else
        glOrtho (-100.0 * aspectRatio, 100.0 * aspectRatio, -100.0, 100.0, 1.0, -1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void main(int argc, char **argv)
{
    glutInit(&argc, argv);

/* Testing basic display functions for now */

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(1000, 1000);
    glutCreateWindow("falling leaves");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    //glutIdleFunc(treeAnimation);
    //glutDisplayFunc(DrawTree);
    SetupRC();   
    glutMainLoop();
}

2 个答案:

答案 0 :(得分:1)

我认为你试图一次解决太多事情。你正试图:

  • 构建用于评估递归树结构的形式语言。
  • 构建一个方法,用于指定在“age”上参数化的树规则。
  • 呈现给定的树规则。

在你最普遍地解决这个问题之前,我会解决一个特例。

  1. 使用硬编码组件渲染树
  2. 向树中添加参数以控制这些组件(分支长度,分支数等)
  3. 编写一个由“age”参数化的函数,用于控制低级树组件。
  4. 将L系统规则中的转换函数写入低级树参数

答案 1 :(得分:1)

正如Jonathan所说,看起来你正试图同时做太多事情。通常使用L系统,树生成与渲染分开。

如果我理解你的规则:

Axiom: F
F --> G[-F][+F]GF
G --> GG

然后你的起始树是:

tree(0): F

即行李箱。通过在树中应用一个规则来增长树,在这种情况下会产生以下结果:

tree(1): G[-F][+F]GF

另一次迭代会进一步增长并产生:

tree(2): GG[-G[-F][+F]GF][+G[-F][+F]GF]GGG[-F][+F]GF

等等。

通常,您可以通过逐字符遍历字符串来实现此功能,并且对于匹配规则的每个字符,将规则rhs附加到目标字符串,否则只需附加字符。

通过迭代树字符串再次完成树的渲染,这次将其解释为一组渲染指令,即F将光标移动一个单位向前绘制一条线,+作为旋转光标向左移动等。

如果您通过一次迭代交替生长树然后渲染它,那么树似乎会增长。

因此,从概念上讲,您可能希望从一个Tree类开始,该类封装了公理,规则等和当前树字符串。这个类将知道如何生长树而不是如何渲染它。所以你也会有一个渲染器类OpenGLRenderer来处理它。然后你就像这样循环:

while (someFlag)
{
    tree->grow ();
    renderer->render (tree.stringRep ());
}

大多数只是L系统的基础知识,你可能已经知道了,在这种情况下,我仍然不明白你究竟是在问什么。