====== Geometry Structures ====== While the vertex declarations of SpeedTree geometry may vary from model to model and even within a single SpeedTree model or a single LOD, the hierarchical organization of the geometry structures remain otherwise rigid. ---- ===== SGeometry Structure ===== Each tree model contains one SGeometry object that encapsulates all of its 3d, billboard geometry, and render states. Render state objects contain material colors, lighting model data, shader names, and many other states. SGeometry also contains data for vertical and horizontal billboards, with details [[accessing_billboard_geometry|here]]. struct SGeometry { // render states st_int32 m_nNum3dRenderStates; st_bool m_bDepthOnlyIncluded; st_bool m_bShadowCastIncluded; SRenderState* m_p3dRenderStates[SHADER_PASS_COUNT]; SRenderState m_aBillboardRenderStates[SHADER_PASS_COUNT]; // LODs st_int32 m_nNumLods; CLodPointer m_pLods; // typecast to SLod // billboards SVerticalBillboards m_sVertBBs; SHorizontalBillboard m_sHorzBB; }; ---- ===== SLod Structure ===== Each tree model consists of one or more LOD levels, as defined by the //SLod// structure below. It contains all of the geometries associated with its LOD level, and may optionally have bone data (an option on the Compiler's SRT exporter). If no bones are present, //m_pBones// is NULL and// m_nNumBones// is zero. struct SLod { st_int32 m_nNumDrawCalls; CDrawCallPointer m_pDrawCalls; // typecast to SDrawCall* st_int32 m_nNumBones; CBonePointer m_pBones; // typecast to SBone* }; ---- ===== SDrawCall Structure ===== While dubbed //SDrawCall//, this structure holds a group of geometries that can be rendered in a single draw under a shared render state (e.g. all have backfacing culling active, the same diffuse lighting model, etc). Note the vertex data-accessing functions named //GetProperty().// Index data is also available in this structure. Think of //m_pIndexData// as an st_byte pointer that can be typecast into either an st_uint32* or st_uint16*, depending on the value of //m_b32BitIndices//. /////////////////////////////////////////////////////////////////////// // Structure SDrawCall // structure is serialized in Parser.cpp struct SDrawCall { // render state CRenderStatePointer m_pRenderState; // typecast to SRenderState* st_int32 m_nRenderStateIndex; // vertices st_int32 m_nNumVertices; CBytePointer m_pVertexData; // mixed types, but can typecast to st_byte* // vertex data access helper functions; if you know exacly how the vertex attributes are // packed in m_pVertexData, you can skip using these functions and access m_pVertexData directly. st_bool GetProperty(EVertexProperty eProperty, st_int32 nVertex, st_float32 afValues[4]) const; st_bool GetProperty(EVertexProperty eProperty, st_int32 nVertex, st_float16 ahfValues[4]) const; st_bool GetProperty(EVertexProperty eProperty, st_int32 nVertex, st_byte abValues[4]) const; // indices st_int32 m_nNumIndices; st_bool m_b32BitIndices; CBytePointer m_pIndexData; // can typecast to st_byte*, then to st_uint32* or st_uint16*, // depending on m_b32BitIndices }; ---- ===== Bringing It All Together ===== The following code example shows how to load an SRT file, access the SGeometry pointer and run through its LODs, draw calls, and access the raw vertex and index data. using namespace SpeedTree; /////////////////////////////////////////////////////////////////////// // Geometry_Structures void Geometry_Structures(void) { const char* pFilename = "example.srt"; // load SRT file CCore* pTree = Internal_LoadSrtFile(pFilename); if (pTree) { // access tree's geometry const SGeometry* pGeometry = pTree->GetGeometry( ); // each tree may have multiple LOD levels for (int i = 0; i < pGeometry->m_nNumLods; ++i) { const SLod& sLod = pGeometry->m_pLods[i]; // each LOD has a number of "draw calls" which is simply a set // of geometries that share the same material/render state for (int j = 0; j < sLod.m_nNumDrawCalls; ++j) { const SDrawCall& sDrawCall = sLod.m_pDrawCalls[j]; // each "draw call" has a vertex declaration const SVertexDecl& sVertexDecl = sDrawCall.m_pRenderState->m_sVertexDecl; // each draw call also contains a vertex buffer block, accessible // with the SDrawCall::GetProperty() functions, or raw access as: const st_byte* pRawVertexBuffer = sDrawCall.m_pVertexData; // each draw call is organized as a indexed triangle list, where indices // may be 16- or 32-bit; access as follows: const st_byte* pRawIndexBuffer = sDrawCall.m_pIndexData; if (sDrawCall.m_b32BitIndices) { // 32-bit indices const st_uint32* pIndices32 = (const st_uint32*) pRawIndexBuffer; // access with 32-bit indices... } else { // 16-bit indices const st_uint16* pIndices16 = (const st_uint16*) pRawIndexBuffer; // access with 16-bit indices... } } } st_delete(pTree); } }