Example: Materials Only

This is a straightforward example that focuses on pulling material definitions only. It does not query any geometry. Most queries are set up similarly to this example. The general set up is:

  1. Make sure the callbacks are set (done once per application lifetime).
  2. Allocate a new SSteEngine object.
  3. Load the SpeedTree Model file (STE or SPM).
  4. Create, init, and set the query options using SSteGeometryOptions.
  5. Create and init the SSteGeometry object to hold the data.
  6. Call SteGetGeometry to force a compute and population of the SSteGeometry object.
  7. Pull needed data from SSteGeometry object.
  8. Clean up by deleting the SSteGeometry and SSteEngine objects.
#include <cstdio>
#include "speedtree_engine.h"
 
///////////////////////////////////////////////////////////////////////
//  SpeedTree Engine API error callback
 
static void MyEngineApiErrorCallback(const char* pError)
{
    fprintf(stderr, "    **[Error Report from SpeedTree Engine API]**: %s\n", pError);
}
 
 
///////////////////////////////////////////////////////////////////////
//  SpeedTree Engine API message callback
 
static void MyEngineApiMessageCallback(const char* pMessage)
{
    fprintf(stderr, "    [Message from SpeedTree Engine API]: %s\n", pMessage);
}
 
 
///////////////////////////////////////////////////////////////////////
//  Example_MaterialsOnly
 
bool Example_MaterialsOnly(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)
        {
            // 'geometry' is used in a lot of these function names, but the materials are
            // the only part we're interested in in this example
 
            // use SSteGeometryOptions to isolate just materials
            SSteGeometryOptions sQueryOptions;
            SteInitGeometryOptions(pEngine, &sQueryOptions);
 
            // rely on mostly default values, but let's set a few specific to our needs
            sQueryOptions.m_bExport3dGeometry = false;
            sQueryOptions.m_eResolution = STE_RESOLUTION_DRAFT; // don't need detail
 
            // init structure to hold the materials
            SSteGeometry sGeometry;
            SteInitGeometry(&sGeometry);
 
            // causes a tree compute to make the data avaialble
            if (SteGetGeometry(pEngine, &sQueryOptions, &sGeometry) == STE_SUCCESS)
            {
                // report a few things about the materials now that have them
                printf("# of material: %d\n\n", sGeometry.m_nNumMaterials);
 
                for (int i = 0; i < sGeometry.m_nNumMaterials; ++i)
                {
                    printf("material %d is called '%s' and has normal texture: [%s]\n", i,
                           sGeometry.m_pMaterials[i].m_szName,
                           sGeometry.m_pMaterials[i].m_aMaps[STE_MAP_NORMAL].m_szFilename);
                }
 
                // using C, so no destructors
                SteDeleteGeometry(&sGeometry);
 
                bSuccess = true;
            }
            else
            {
                // if there's a failure, a message will be sent via the callback
            }
        }
        else
        {
            // if there's a failure, a message will be sent via the callback
        }
 
        // using C, so no destructors
        SteDelete(pEngine);
    }
 
    return bSuccess;
}