User Tools

Site Tools

Example: Bones

Querying a model's bone data is straightforward. It is not organized in a hierarchical tree as the spine data is, but as a single array.

Each bone is stored in an SSteBone structure:

struct SSteBone
    int         m_nID;              // zero-based bone ID indexes SSteGeometry::m_pBones
    int         m_nParentID;        // -1 = no parent, zero-based otherwise
    SSteVec3    m_vStart;           // position of one end
    SSteVec3    m_vEnd;             // position of other end
    float       m_fRadius;          // bone thickness
    int         m_nNumChildren;
    int*        m_pChildren;        // children stored by index into SSteGeometry::m_pBones

The structure SSteGeometry contains an array of SSteBone objects, called m_pBones. Each bone's m_nID member corresponds to its position in the array. Each parent and child value is also an index into this same array.

#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_Bones
bool Example_Bones(const char* pModelFilename)
    bool bSuccess = false;
    // register callback message functions; when api calls fail, messages will be sent here
    // 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 export options
            SSteGeometryOptions sGeometryOptions;
            SteInitGeometryOptions(pEngine, &sGeometryOptions);
            sGeometryOptions.m_eResolution = STE_RESOLUTION_HIGH;
            sGeometryOptions.m_bExport3dGeometry = false;
            sGeometryOptions.m_bExportBones = true;
            // pull over the geometry
            SSteGeometry sGeometry;
            if (SteGetGeometry(pEngine, &sGeometryOptions, &sGeometry) == STE_SUCCESS)
                // bones are always given in a single array
                for (int i = 0; i < sGeometry.m_nNumBones; ++i)
                    const SSteBone* pBone = sGeometry.m_pBones + i;
                    printf("   bone id: %d\n", pBone->m_nID);
                    printf(" parent id: %d\n", pBone->m_nParentID);
                    printf("     start: (%g, %g, %g)\n", pBone->m_vStart.x, pBone->m_vStart.y, pBone->m_vStart.z);
                    printf("       end: (%g, %g, %g)\n", pBone->m_vEnd.x, pBone->m_vEnd.y, pBone->m_vEnd.z);
                    printf("    radius: %g\n", pBone->m_fRadius);
                    if (pBone->m_nNumChildren > 0)
                        printf("  children: ");
                        for (int j = 0; j < pBone->m_nNumChildren; ++j)
                            printf("%d ", pBone->m_pChildren[j]);
                // using C, so no destructors
                bSuccess = true;
        // using C, so no destructors
    return bSuccess;