User Tools

Site Tools


Example: Growth

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;
}