User Tools

Site Tools


Accessing 3D Geometry

Geometry access in the SDK isn't as straightforward as declaring a structure and typecasting a vertex data pointer to it, as each draw call for each LOD of a tree model may have a different vertex declaration as decribed by the associated render state's SVertexDecl. However, the SDK does provide a few overloaded functions in SDrawCall to facilitate quick vertex property access. Specifically:

  • void SDrawCall::GetProperty(EVertexProperty eProperty, st_int32 nVertex, st_float32 afValues[4]) const;
  • void SDrawCall::GetProperty(EVertexProperty eProperty, st_int32 nVertex, st_float16 ahfValues[4]) const;
  • void SDrawCall::GetProperty(EVertexProperty eProperty, st_int32 nVertex, st_byte abValues[4]) const;

Where eProperty is one of the sixteen pre-defined vertex properties (e.g. VERTEX_PROPERTY_POSITION, VERTEX_PROPERTY_NORMAL, etc), nVertex is which vertex index in the buffer to be retrieved, and finally the last parameter will contain the returned value, padded with zeroes if necessary.

The following code loads a tree and prints the position property for every draw call of each LOD. Position is always present in every vertex. When checking for other properties, consider using SVertexDecl::m_asProperties[X].IsPresent() (where X is any EVertexProperty value) to determine if that property is in the vertex data.

///////////////////////////////////////////////////////////////////////  
//  Geometry_AccessVertexPosition
 
void Geometry_AccessVertexPosition(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( );
 
        // run through every LOD in the tree
        for (int i = 0; i < pGeometry->m_nNumLods; ++i)
        {
            const SLod& sLod = pGeometry->m_pLods[i];
 
            // each LOD has a number of draw calls
            for (int j = 0; j < sLod.m_nNumDrawCalls; ++j)
            {
                const SDrawCall& sDrawCall = sLod.m_pDrawCalls[j];
                const SVertexDecl& sVertexDecl = sDrawCall.m_pRenderState->m_sVertexDecl;
 
                // each draw call contains its own logical vertex buffer
                for (int k = 0; k < sDrawCall.m_nNumVertices; ++k)
                {
                    EVertexFormat ePosFormat = sVertexDecl.m_asProperties[VERTEX_PROPERTY_POSITION].m_eFormat;
                    if (ePosFormat == VERTEX_FORMAT_HALF_FLOAT)
                    {
                        st_float16 afProperty[4]; // GetProperty() always takes four-float array
                        sDrawCall.GetProperty(VERTEX_PROPERTY_POSITION, k, afProperty);
 
                        printf("pos[%d] = (%g, %g, %g)\n", k,
                            float(afProperty[0]), float(afProperty[1]), float(afProperty[2]));
                    }
                    else if (ePosFormat == VERTEX_FORMAT_FULL_FLOAT)
                    {
                        st_float32 afProperty[4]; // GetProperty() always takes four-float array
                        sDrawCall.GetProperty(VERTEX_PROPERTY_POSITION, k, afProperty);
 
                        printf("pos[%d] = (%g, %g, %g)\n", k,
                            afProperty[0], afProperty[1], afProperty[2]);
                    }
                    // positions cannot be stored as VERTEX_FORMAT_BYTE
                }
            }
        }
 
        st_delete(pTree);
    }
}