Sample of recursive scene graph

I just wanted to share an example of my new research. It is a technique to define fractal and recursive contents in a scene graph.

My example shows a mathematical tree affected by a smooth wind. Look at http://www.tooltech-software.com

Any doc/sample for us on non-win32 platforms?

Julien.

I can compile it for Linux, Irix, Mac OS X and Linux. What would you prefer ?

You can find the source code in the source directory…

Here is the source code for the tree demo that builds the actual tree

// A displacement function for a branch segment
gzRealXY xyfunk1(gzReal in)
{
return gzRealXY(in*(1-in)sin(inGZ_PI3)5,in(1-in)sin(3inGZ_PI)*5);
}

// A second displacement function for a branch segment
gzRealXY xyfunk2(gzReal in)
{
return gzRealXY(in*(1-in)sin(2inGZ_PI)5,in(1-in)sin(5inGZ_PI));
}

// A method that creates a leaf geometry ( A quad texture )
gzGeometry *leaf()
{
gzGeometry *leaf=new gzGeometry;

gzArray &coordinates=leaf->getCoordinateArray();
gzArray &tex=leaf->getTexCoordinateArray();
gzArray &norm=leaf->getNormalArray();

coordinates+= gzVec3(-80,0,0);
coordinates+= gzVec3(80,0,0);
coordinates+= gzVec3(80,160,0);
coordinates+= gzVec3(-80,160,0);

tex+= gzVec2(0,0);
tex+= gzVec2(1,0);
tex+= gzVec2(1,1);
tex+= gzVec2(0,1);

norm+=gzVec3(0,0,1);

leaf->setTexBind(GZ_BIND_ON);
leaf->setNormalBind(GZ_BIND_PER_PRIM);
leaf->setGeoPrimType(GZ_PRIM_QUADS);

// Fix state on leaf

gzMaterial *material=new gzMaterial;
gzState *state=new gzState;

state->setMaterial(material);
//state->setBackMaterial(material);
state->setMode(GZ_STATE_MATERIAL,GZ_STATE_ON);

gzTexture *texture=new gzTexture;

texture->setImage(gzImageManager::loadImage(“leaf.png”));
texture->setComponents(4);
texture->setWrapS(GZ_REPEAT);
texture->setWrapT(GZ_REPEAT);
texture->useMipMaps(TRUE);
texture->setMagFilter(GZ_LINEAR);
texture->setMinFilter(GZ_LINEAR_MIPMAP_LINEAR);

// Make the leaf texture transparent ourside leaf
state->setMode(GZ_STATE_ALPHA_FUNC,GZ_STATE_ON);
state->setAlphaFunc(GZ_ALPHA_FUNC_GREATER,0.5f);

state->setTexture(texture);
state->setMode(GZ_STATE_TEXTURE,GZ_STATE_ON);

state->setMode(GZ_STATE_POLYGON_MODE,GZ_STATE_ON);
state->setBackPolygonMode(GZ_POLYGON_MODE_FILL);
state->setFrontPolygonMode(GZ_POLYGON_MODE_FILL);

leaf->setState(state);

return leaf;
}

// Builds the recursive tree geometry
gzNode *buildTree()
{

// Create two potential selections of a branch
gzGeometry *base_1=new gzGeometryTube(50,5,11,6,GZ_TUBE_CONE,xyfunk1,5,5);

gzGeometry *base_2=new gzGeometryTube(50,5,11,6,GZ_TUBE_CONE,xyfunk2,5,5);

// Base branch

gzSeedSwitch *base=new gzSeedSwitch;

base->addNode(base_1);
base->addNode(base_2);

// The max recursion depth
gzULong depth=13;

// Build tree

gzRecursive *tree=new gzRecursive;

tree->setMaxDepth(depth);

// Experimental stuff
//tree->useDistanceDepth(TRUE);
//tree->setDistanceDepthEquation(1000,1);

// The recusrsive tree algo
// tree=(base+T1R1S1tree+T2R2S2tree))

// tree=base
tree->addNode(base);

// When max recusrion is reached, use this coupling to next set
tree->setMaxDepthNode(leaf());

// Some paramenters
gzFloat rotation=180;
gzFloat balance=0.6;
gzFloat spread=50;
gzFloat offset=0;
gzFloat add_rotation=108;

// TRS1 - top striving high
gzSeedTransform pSeedTransform_1=new gzSeedTransform();
pSeedTransform_1->setTranslation(0,48.5,0);
pSeedTransform_1->setScale(0.85,balance
1.5,0.85);
pSeedTransform_1->setHPRSeedValue(TRUE,gzVec3(rotation+add_rotation,(1-balance)*spread,0),gzVec3(rotation+add_rotation,(1-balance)*spread,0));

pSeedTransform_1->setStriveDirection(gzVec3(1,0,0));
pSeedTransform_1->setStriveFactors(0.1,0.1,2);

pSeedTransform_1->addNode(tree);
pSeedTransform_1->setRecursiveDepthScaleFactor(1);

// tree=base+T1R1S1*tree
tree->addNode(pSeedTransform_1);

// TRS2 - side winder
gzSeedTransform *pSeedTransform_2=new gzSeedTransform();
pSeedTransform_2->setTranslation(0,48,0);
pSeedTransform_2->setScale((1-balance)*1.7,(1-balance)1.7,(1-balance)1.7);
pSeedTransform_2->setHPRSeedValue(TRUE,gzVec3(rotation+add_rotation,-(offset+balance
spread),0),gzVec3(rotation+add_rotation,-(offset+balance
spread),0));

pSeedTransform_2->setStriveDirection(gzVec3(1,-1,0));
pSeedTransform_2->setStriveFactors(0.5);

pSeedTransform_2->addNode(tree);
pSeedTransform_2->setRecursiveDepthScaleFactor(1.1);

tree->addNode(pSeedTransform_2);

// Fix state on overall tree

gzMaterial *material=new gzMaterial;
gzState *state=new gzState;

state->setMaterial(material);
state->setMode(GZ_STATE_MATERIAL,GZ_STATE_ON);

gzTexture *tex=new gzTexture;

tex->setImage(gzImageManager::loadImage(“bark.png”));
tex->setWrapS(GZ_REPEAT);
tex->setWrapT(GZ_REPEAT);
tex->useMipMaps(TRUE);
tex->setMagFilter(GZ_LINEAR);
tex->setMinFilter(GZ_LINEAR_MIPMAP_LINEAR);

state->setTexture(tex);
state->setMode(GZ_STATE_TEXTURE,GZ_STATE_ON);

// Seed starter
gzSeedControl *topNode=new gzSeedControl;
//topNode->setSeedControlType(GZ_SEED_FROM_TIME);

base->setState(state);

// Add recursive tree

topNode->addNode(tree);

return topNode;
}

wow this is really cool. I’m really impressed I’ve been planning on doing somthing similar to this for a couple months but school has had me all tied up.

does your algorithm use Hofmeisters rules?

is there a higher-level interface for defining different types of plants?

can you grow the tree from a seed?

which variables determine the shape of the tree?

The system can be used to implement hoffmeister rules. The demo is just one simple rule. More complex rule can be cascaded.

I am planning to add some kind of language that can build the scene structure, but for know I am working on performance on the implementation. The demo is about 160.000 polys each frame and thats too much…

I can grow the plant from a seed. The gzSeedControl can take a position or time etc to start a new sequence.

The shapes are really determined by the scaling and rotation. Right now I am experimenting with classes that adds/removes contents based on weights so e.g. I can design a library of 10 branch types and let the algo select beteen them…