   Physics on Tree Model
  Hi, I've written a short program that simulates a tree growing, it is based on one of Hugo Elias's tutorials (they are all amazing).http://freespace.virgin.net/hugo.elias/models/m_p_tree.htmI'm using a "tree" data structure to store all the branches (duh), and I'm using a polar coordinate system.What I want to do is add soft body physics to it, but am not sure how to do that.I want them to be droopy, blow in the wind etc...I'm using a lot of glMatrixPush and Pop functions, and when the depth of the branches gets too great funky stuff begins to happen, is there a solution to this.typedef struct sBranch{    float angleX;   // this is how much the branch angles away from the previous branch    float angleY;   // and this angle rotates the previous angle, it is between 0 and 360    float length;   // the length of the branch at the current time    float radius;   // the radius of the branch at the current time    float lengthSprout; // the lenght of the branch when it initially splits into 2    float growSpeed;    // the speed of growth of both the length and radius   struct sBranch *left, *right;   // pointers to sibling branchs} tBranch;tBranch *newBranch(float angleX, float angleY, float length, float radius, float lengthSprout, float growSpeed){    tBranch *branch;    branch = malloc(sizeof(tBranch));    if(!branch)   return NULL;    branch->angleX = angleX;    branch->angleY = angleY;   branch->length = length;    branch->radius = radius;    branch->lengthSprout = lengthSprout;    branch->growSpeed = growSpeed;    branch->left = NULL;    branch->right = NULL;    return branch;}void growBranch(tBranch *branch, float dt){    float angleXleft, angleYleft;    float angleXright, angleYright;    float growLeft, growRight;    float lengthSproutLeft, lengthSproutRight;    float radiusLeft, radiusRight;    if(branch == NULL) return;    branch->length += branch->growSpeed * dt;    branch->radius += branch->growSpeed * 0.1f * dt;    if(branch->length > branch->lengthSprout)    {   if(!branch->left)// if has no children yet, generate 2 new branchs   {  angleXleft = ((double)rand() / (double)(RAND_MAX)) * 90.0f;  angleYleft = ((double)rand() / (double)(RAND_MAX)) * 360.0f;  angleXright = angleXleft - 90;  angleYright = angleYleft - 180;  growLeft = cos(angleXleft / 57.2f) * branch->growSpeed;  growRight = cos(angleXright / 57.2f) * branch->growSpeed;    lengthSproutLeft = ((double)rand() / (double)(RAND_MAX)) * 0.1f;  lengthSproutRight = ((double)rand() / (double)(RAND_MAX)) * 0.1f;    radiusLeft = growLeft * branch->radius;  radiusRight = growRight * branch->radius;    branch->left = newBranch(angleXleft, angleYleft, 0.0f, radiusLeft, lengthSproutLeft, growLeft);  branch->right = newBranch(angleXright, angleYright, 0.0f, radiusRight, lengthSproutRight, growRight);   }    }    growBranch(branch->left, dt);    growBranch(branch->right, dt);}void renderBranch(tBranch *branch, GLUquadricObj *quad){    if(branch == NULL)   return;    glPushMatrix();    glRotatef(branch->angleX, 1.0f, 0.0f, 0.0f);    glRotatef(branch->angleY, 0.0f, 1.0f, 0.0f);    glPushMatrix();    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);   // required to orientate the cylinder along the y-axis    gluCylinder(quad, branch->radius, branch->radius, branch->length, 8, 1);    glPopMatrix();    glTranslatef(0.0f, branch->length, 0.0f);   // translate to the end of the branch, so the next ones start in the correct place */    renderBranch(branch->left, quad);    renderBranch(branch->right, quad);    glPopMatrix();}So, there is some of the source, I thought it be very cool, use it if you want, and if you have any tips/ideas on how it could be improved, much appreciated.
  I fixed the funky stuff with the matrix push and pull, all I do is reverse the rotation and translation at the end of the function. Now there is nothing limiting the size of the tree, apart from processing time, and maybe memory, but I don't think so.void renderBranch(tBranch *branch, GLUquadricObj *quad){    if(branch == NULL)   return;    glRotatef(branch->angleX, 1.0f, 0.0f, 0.0f);    glRotatef(branch->angleY, 0.0f, 1.0f, 0.0f);    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);   // required to orientate the cylinder along the y-axis    gluCylinder(quad, branch->radius, branch->radius, branch->length, 8, 1);    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);    glTranslatef(0.0f, branch->length, 0.0f);   // translate to the end of the branch, so the next ones start in the correct place */    renderBranch(branch->left, quad); // render sub branches    renderBranch(branch->right, quad);    glTranslatef(0.0f, -branch->length, 0.0f);    glRotatef(-branch->angleY, 0.0f, 1.0f, 0.0f);    glRotatef(-branch->angleX, 1.0f, 0.0f, 0.0f);};  Wow, that's amazing man. I love that.   ;  Looks great!   ;  Thanks for the encouragement.Here is the code for the whole program if anyone wants to play with it.It just needs to be linked with the OpenGL and SDL library's, should be cross platform, but haven't tested it.#include <SDL.h>#include <GL/gl.h>#include <GL/glu.h>#define SCREEN_WIDTH 800#define SCREEN_HEIGHT 600typedef struct sBranch{    float angleX;   // this is how much the branch angles away from the previous branch    float angleY;   // and this angle rotates the previous angle, it is between 0 and 360    float length;   // the length of the branch at the current time    float radius;   // the radius of the branch at the current time    float lengthSprout; // the lenght of the branch when it initially splits into 2    float growSpeed;    // the speed of growth of both the length and radius   struct sBranch *left, *right;   // pointers to sibling branchs} tBranch;int setupWindow(){    if(SDL_Init(SDL_INIT_VIDEO) < 0)    {   SDL_Quit();   return 0;    }    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);    if(!SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, SDL_OPENGL))   return 0;    return 1;}int handelEvents(){    static SDL_Event event;    while(SDL_PollEvent(&event))    {switch(event.type)   {case SDL_QUIT:return 0;break;  case SDL_KEYDOWN: if(event.key.keysym.sym == SDLK_ESCAPE)return 0; break;}}    return 1;}int setupOpenGL(){ glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity();gluPerspective(45.0f, (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.1f, 1000.0f);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glShadeModel(GL_SMOOTH);    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    glClearDepth(1.0f);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LEQUAL);    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    glEnable(GL_LIGHTING);    glEnable(GL_LIGHT0);   return 1;}tBranch *newBranch(float angleX, float angleY, float length, float radius, float lengthSprout, float growSpeed){    tBranch *branch;    branch = malloc(sizeof(tBranch));    if(!branch)   return NULL;    branch->angleX = angleX;    branch->angleY = angleY;   branch->length = length;    branch->radius = radius;    branch->lengthSprout = lengthSprout;    branch->growSpeed = growSpeed;    branch->left = NULL;    branch->right = NULL;    return branch;}void growBranch(tBranch *branch, float dt){    float angleXleft, angleYleft;    float angleXright, angleYright;    float growLeft, growRight;    float lengthSproutLeft, lengthSproutRight;    float radiusLeft, radiusRight;    if(branch == NULL) return;    branch->length += branch->growSpeed * dt;    branch->radius += branch->growSpeed * 0.1f * dt;    if(branch->length > branch->lengthSprout)    {   if(!branch->left)// if has no children yet, generate 2 new branchs   {  angleXleft = ((double)rand() / (double)(RAND_MAX)) * 90.0f;  angleYleft = ((double)rand() / (double)(RAND_MAX)) * 360.0f;  angleXright = angleXleft - 90;  angleYright = angleYleft - 180;  growLeft = cos(angleXleft / 57.2f) * branch->growSpeed;  growRight = cos(angleXright / 57.2f) * branch->growSpeed;    lengthSproutLeft = ((double)rand() / (double)(RAND_MAX)) * 0.1f;  lengthSproutRight = ((double)rand() / (double)(RAND_MAX)) * 0.1f;    radiusLeft = growLeft * branch->radius;  radiusRight = growRight * branch->radius;    branch->left = newBranch(angleXleft, angleYleft, 0.0f, radiusLeft, lengthSproutLeft, growLeft);  branch->right = newBranch(angleXright, angleYright, 0.0f, radiusRight, lengthSproutRight, growRight);   }    }    growBranch(branch->left, dt);    growBranch(branch->right, dt);}void destroyBranch(tBranch *branch){    if(branch == NULL)   return;    destroyBranch(branch->left);    destroyBranch(branch->right);    free(branch);}void renderBranch(tBranch *branch, GLUquadricObj *quad){    if(branch == NULL)   return;    glRotatef(branch->angleX, 1.0f, 0.0f, 0.0f);    glRotatef(branch->angleY, 0.0f, 1.0f, 0.0f);    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);   // required to orientate the cylinder along the y-axis    gluCylinder(quad, branch->radius, branch->radius, branch->length, 8, 1);    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);    glTranslatef(0.0f, branch->length, 0.0f);   // translate to the end of the branch, so the next ones start in the correct place */    renderBranch(branch->left, quad); // render sub branches    renderBranch(branch->right, quad);    glTranslatef(0.0f, -branch->length, 0.0f);    glRotatef(-branch->angleY, 0.0f, 1.0f, 0.0f);    glRotatef(-branch->angleX, 1.0f, 0.0f, 0.0f);}int main(int argc, char **argv){    tBranch *tree;    int running = 1;    float angle = 0.0f;    GLUquadricObj *quad;if(!setupWindow()) return 0;    if(!setupOpenGL()) return 0;    srand(time(NULL));    rand();    tree = newBranch(0.0f, 0.0f, 0.0f, 0.005f, 0.01f, 1.0f);    quad = gluNewQuadric();gluQuadricNormals(quad, GLU_SMOOTH);gluQuadricTexture(quad, GL_TRUE);while(running)    {   running = handelEvents();   growBranch(tree, 0.01f);   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   glLoadIdentity();   glTranslatef(0.0f,-16.0f,-64.0f);   glRotatef(angle, 0.0f, 1.0f, 0.0f);   renderBranch(tree, quad);   angle += 0.4f;   SDL_GL_SwapBuffers();    }    destroyBranch(tree);SDL_Quit();return 0;};  How long does it take to generate/render a tree on average?If you could extend it to three dimentions, maybe add UV coords and leaves to the mix, you could have the foundation for a nice SpeedTree competitor here.;  The time it takes to render/create a tree depends on how many branches it has. The creation of the tree happens in real time, as in the tree appears to grow from a single branch. The growing/rendering process doesn't drop below my refresh rate until there are like 2^20 branches, which if each branch is a 8 sided cylinder, makes 16.7 million polys for a single tree. :)I think that there would need to be massive optimization to compete with speed tree.And considering I've only put a few days into this project, I cant see it competing. I actually made it for a demo I have an idea of.It is 3D, and I have just added a quick and dirty texture to it.Leaves would be nice, I just need to work out the best/easiest way to do it.;  Fantastic!The point I was trying to make is SpeedTree is expensive and out of reach for us home developers, it would be nice for an open-source alternative.I've notepad'd your code and I'll have a quick play with adding leaves and things when I get a chance, I'm quite interested in seeing how this would look in a game.Can you get the same results twice, if the input variables are the same?;Quote:Can you get the same results twice, if the input variables are the same?It just uses the standard c function rand() and uses the time as a seed, but if instead you use any old number, the tree should be the same every time.I've been playing a bit with leaves, basically all that needs to be done is if the branch pointer is null, then just render a quad with some leaves on it.I don't know how to do masking yet, so it looks a bit dodgy.And I'm sure the speed of it could be increased if the trees were "pre-grown".And your not wrong about speed tree being expensive. A free alternative would be excellent.   ;  So, it turns out that blending isn't as hard as I thought.Here is a lower poly version of a tree, showing off leaves, admire my gimp skilz if you wish.And the source of the new render function.void renderBranch(tBranch *branch, GLUquadricObj *quad){    if(!branch)    {   glEnable(GL_BLEND);// Enable Blending//    glDisable(GL_DEPTH_TEST);   glBlendFunc(GL_DST_COLOR,GL_ZERO);   glBindTexture(GL_TEXTURE_2D, leafmask);   glBegin(GL_QUADS);   glTexCoord2d(0.0,0.0);   glVertex3f(-10.0f, 0.0f, 0.0f);   glTexCoord2d(0.0,1.0);   glVertex3f(-10.0f,  20.0f, 0.0f);   glTexCoord2d(1.0,1.0);   glVertex3f( 10.0f,  20.0f, 0.0f);   glTexCoord2d(1.0,0.0);   glVertex3f( 10.0f, 0.0f, 0.0f);   glEnd(); glBlendFunc(GL_ONE, GL_ONE);   glBindTexture(GL_TEXTURE_2D, leaf);   glBegin(GL_QUADS);   glTexCoord2d(0.0,0.0);   glVertex3f(-10.0f, 0.0f, 0.0f);   glTexCoord2d(0.0,1.0);   glVertex3f(-10.0f,  20.0f, 0.0f);   glTexCoord2d(1.0,1.0);   glVertex3f( 10.0f,  20.0f, 0.0f);   glTexCoord2d(1.0,0.0);   glVertex3f( 10.0f, 0.0f, 0.0f);   glEnd();//   glEnable(GL_DEPTH_TEST);// Enable Depth Testing    glDisable(GL_BLEND);   return;    }    glBindTexture(GL_TEXTURE_2D, bark);  glRotatef(branch->angleX, 1.0f, 0.0f, 0.0f);    glRotatef(branch->angleY, 0.0f, 1.0f, 0.0f);    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);   // required to orientate the cylinder along the y-axis    gluCylinder(quad, branch->radius, branch->radius, branch->length, 8, 1);    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);    glTranslatef(0.0f, branch->length, 0.0f);   // translate to the end of the branch, so the next ones start in the correct place */    renderBranch(branch->left, quad); // render sub branches    renderBranch(branch->right, quad);    glTranslatef(0.0f, -branch->length, 0.0f);    glRotatef(-branch->angleY, 0.0f, 1.0f, 0.0f);    glRotatef(-branch->angleX, 1.0f, 0.0f, 0.0f);}I'm sure this code could be made much prettier :)   