====== Example: Spines ====== This example focuses on how to query only the spine data from a tree model. While this can be done with either a flat organization or hierarchically, we use hierarchical in this example because this is more commonly done with spine data. #include #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); } /////////////////////////////////////////////////////////////////////// // RecurseThroughSpines static void RecurseThroughSpines(const SSteGeometryBlock* pNode, int nLevel = 0) { if (pNode->m_nNumSpineVertices > 1) { Indent(nLevel); printf("spine at level %d:\n", nLevel); for (int i = 0; i < pNode->m_nNumSpineVertices; ++i) { // use m_vWindyPos instead of m_vBasePos if wind enabled const SSteVec3& vPos = pNode->m_pSpineVertices[i].m_vBasePos; Indent(nLevel); printf(" p%d: (%g, %g, %g)\n", i, vPos.x, vPos.y, vPos.z); } } for (int i = 0; i < pNode->m_nNumChildren; ++i) RecurseThroughSpines(pNode->m_pChildren[i], nLevel + 1); } /////////////////////////////////////////////////////////////////////// // Example_Spines bool Example_Spines(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) { if (SteLoadSpeedTreeFile(pEngine, pModelFilename) == STE_SUCCESS) { // geometry export options SSteGeometryOptions sGeometryOptions; SteInitGeometryOptions(pEngine, &sGeometryOptions); sGeometryOptions.m_bExport3dGeometry = false; sGeometryOptions.m_bExportBranchSpines = true; sGeometryOptions.m_eResolution = STE_RESOLUTION_HIGH; sGeometryOptions.m_eGroupType = STE_GROUP_BY_HIERARCHY; sGeometryOptions.m_nHierarchy = 4; // will generate many separate nodes // pull over the geometry SSteGeometry sGeometry; SteInitGeometry(&sGeometry); if (SteGetGeometry(pEngine, &sGeometryOptions, &sGeometry) == STE_SUCCESS) { // because STE_GROUP_BY_HIERARCHY is used, we need to traverse a tree RecurseThroughSpines(sGeometry.m_pGeometryRoot); // using C, so no destructors SteDeleteGeometry(&sGeometry); bSuccess = true; } } // using C, so no destructors SteDelete(pEngine); } return bSuccess; }