Original Post
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.htm I'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. 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.
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();
}

