// ----------------------------------------------------------------------------- // // Add/remove decals // ----------------------------------------------------------------------------- // DispDecalHandle_t CDispInfo::NotifyAddDecal( decal_t *pDecal ) { // FIXME: Add decal retirement... // if( m_Decals.Size() < MAX_DISP_DECALS ) // return; // Create a new decal, link it in DispDecalHandle_t h = s_DispDecals.Alloc( true ); // When linking, insert it in sorted order based on material enumeration ID // This will help us when rendering later int last = DISP_DECAL_HANDLE_INVALID; int i = m_FirstDecal; int enumerationId = pDecal->material->GetEnumerationID(); while( i != s_DispDecals.InvalidIndex() ) { int testId = s_DispDecals[i].m_pDecal->material->GetEnumerationID(); if (enumerationId <= testId) break; last = i; i = s_DispDecals.Next(i); } // NOTE: when the list is used in multimode, we can't use LinkBefore( i, INVALID_INDEX ), // since the Head and Tail of the linked list are meaningless... if ( last != DISP_DECAL_HANDLE_INVALID ) s_DispDecals.LinkAfter( last, h ); else { s_DispDecals.LinkBefore( m_FirstDecal, h ); m_FirstDecal = h; } CDispDecal *pDispDecal = &s_DispDecals[h]; pDispDecal->m_pDecal = pDecal; pDispDecal->m_FirstFragment = DISP_DECAL_FRAGMENT_HANDLE_INVALID; pDispDecal->m_nVerts = 0; pDispDecal->m_nTris = 0; // Setup a basis for it. CDecalVert *pOutVerts = NULL; R_SetupDecalClip( pOutVerts, pDispDecal->m_pDecal, MSurf_Plane( m_ParentSurfID ).normal, pDispDecal->m_pDecal->material, pDispDecal->m_TextureSpaceBasis, pDispDecal->m_DecalWorldScale ); // Recurse and precalculate which nodes this thing can touch. SetupDecalNodeIntersect( m_pPowerInfo->m_RootNode, 0, // node bit index into CDispDecal::m_NodeIntersects pDispDecal, 0 ); return h; }
//----------------------------------------------------------------------------- // Allocates fragments... //----------------------------------------------------------------------------- CDispShadowFragment* CDispInfo::AllocateShadowDecalFragment( DispShadowHandle_t h ) { DispShadowFragmentHandle_t f = s_DispShadowFragments.Alloc(true); s_DispShadowFragments.LinkBefore( s_DispShadowDecals[h].m_FirstFragment, f ); s_DispShadowDecals[h].m_FirstFragment = f; return &s_DispShadowFragments[f]; }
//----------------------------------------------------------------------------- // Adds a handle to a leaf //----------------------------------------------------------------------------- void CBSPTreeData::AddHandleToLeaf( int leaf, BSPTreeDataHandle_t handle ) { // Got to a leaf baby! Add the handle to the leaf's list of elements unsigned short leafElement = m_LeafElements.Alloc( true ); if (m_Leaf[leaf].m_FirstElement != m_LeafElements.InvalidIndex() ) m_LeafElements.LinkBefore( m_Leaf[leaf].m_FirstElement, leafElement ); m_Leaf[leaf].m_FirstElement = leafElement; m_LeafElements[leafElement] = handle; // Insert the leaf into the handles's list of leaves unsigned short handleElement = m_HandleLeafList.Alloc( true ); if (m_Handles[handle].m_LeafList != m_HandleLeafList.InvalidIndex() ) m_HandleLeafList.LinkBefore( m_Handles[handle].m_LeafList, handleElement ); m_Handles[handle].m_LeafList = handleElement; m_HandleLeafList[handleElement].m_Leaf = leaf; m_HandleLeafList[handleElement].m_LeafElementIndex = leafElement; }
// ----------------------------------------------------------------------------- // // Add/remove shadow decals // ----------------------------------------------------------------------------- // DispShadowHandle_t CDispInfo::AddShadowDecal( ShadowHandle_t shadowHandle ) { // Create a new shadow decal, link it in DispShadowHandle_t h = s_DispShadowDecals.Alloc( true ); s_DispShadowDecals.LinkBefore( m_FirstShadowDecal, h ); m_FirstShadowDecal = h; CDispShadowDecal* pShadowDecal = &s_DispShadowDecals[h]; pShadowDecal->m_nTris = 0; pShadowDecal->m_nVerts = 0; pShadowDecal->m_Shadow = shadowHandle; pShadowDecal->m_FirstFragment = DISP_SHADOW_FRAGMENT_HANDLE_INVALID; return h; }