Animating tree growth is about as straightforward as a typical geometry query. The only difference is that SteGetGeometry must be called per frame of animation with a new value for SSteGeometryOptions::m_fTimeInSecs at each frame and SSteGeometryOptions::m_bGrowthActive must be set to true.
This growth example is nearly identical to the wind example.
/////////////////////////////////////////////////////////////////////// // Example_Growth bool Example_Growth(const char* pModelFilename) { bool bSuccess = false; // register callback message functions; when api calls fail, messages will be sent here SteSetErrorFunction(MyEngineApiErrorCallback); SteSetMessageFunction(MyEngineApiMessageCallback); // uses a C interface -- objects are created and initialized through function calls SSteEngine* pEngine = SteNew( ); if (pEngine) { // this causes the model file to be loaded and parsed, but nothing is computed yet if (SteLoadSpeedTreeFile(pEngine, pModelFilename) == STE_SUCCESS) { bSuccess = true; // geometry export options SSteGeometryOptions sGeometryOptions; SteInitGeometryOptions(pEngine, &sGeometryOptions); sGeometryOptions.m_eGroupType = STE_GROUP_BY_MATERIAL; sGeometryOptions.m_fFramesPerSec = 30.0f; sGeometryOptions.m_bGrowthActive = true; // this is a key flag // set up time loop const float c_fExampleTime = 15.0f; // seconds const float c_fFrameTime = 1.0f / sGeometryOptions.m_fFramesPerSec; for (float fTime = 0.0f; fTime < c_fExampleTime; fTime +=c_fFrameTime) { sGeometryOptions.m_fTimeInSecs = fTime; // SteGetGeometry() is called for each frame. Note that the tree computes internally only // once. After the first query/compute, the time taken by this function is almost entirely // from the wind computation. SSteGeometry sGeometry; SteInitGeometry(&sGeometry); if (SteGetGeometry(pEngine, &sGeometryOptions, &sGeometry) == STE_SUCCESS) { // each of these children will have new, wind-affected data for (int i = 0; i < sGeometry.m_pGeometryRoot->m_nNumChildren; ++i) { const SSteGeometryBlock* pChild = sGeometry.m_pGeometryRoot->m_pChildren[i]; // process the wind-updated data } // using C, so no destructors SteDeleteGeometry(&sGeometry); } else bSuccess = false; } } // using C, so no destructors SteDelete(pEngine); } return bSuccess; }