// This gets an AABB for the renderable, but it doesn't cause a parent's bones to be setup. // This is used for placement in the leaves, but the more expensive version is used for culling. void CalcRenderableWorldSpaceAABB_Fast( IClientRenderable *pRenderable, Vector &absMin, Vector &absMax ) { C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity(); if ( pEnt && pEnt->IsFollowingEntity() ) { C_BaseEntity *pParent = pEnt->GetMoveParent(); Assert( pParent ); // Get the parent's abs space world bounds. CalcRenderableWorldSpaceAABB_Fast( pParent, absMin, absMax ); // Add the maximum of our local render bounds. This is making the assumption that we can be at any // point and at any angle within the parent's world space bounds. Vector vAddMins, vAddMaxs; pEnt->GetRenderBounds( vAddMins, vAddMaxs ); // if our origin is actually farther away than that, expand again float radius = pEnt->GetLocalOrigin().Length(); float flBloatSize = max( vAddMins.Length(), vAddMaxs.Length() ); flBloatSize = max(flBloatSize, radius); absMin -= Vector( flBloatSize, flBloatSize, flBloatSize ); absMax += Vector( flBloatSize, flBloatSize, flBloatSize ); } else { // Start out with our own render bounds. Since we don't have a parent, this won't incur any nasty CalcRenderableWorldSpaceAABB( pRenderable, absMin, absMax ); } }
//----------------------------------------------------------------------------- // Add entity to frame think list //----------------------------------------------------------------------------- void CClientThinkList::AddEntityToFrameThinkList( ThinkEntry_t *pEntry, bool bAlwaysChain, int &nCount, ThinkEntry_t **ppFrameThinkList ) { // We may already have processed this owing to hierarchy rules if ( pEntry->m_nIterEnum == m_nIterEnum ) return; // If we're not thinking this frame, we don't have to worry about thinking after our parents bool bThinkThisInterval = ( pEntry->m_flNextClientThink == CLIENT_THINK_ALWAYS ) || ( pEntry->m_flNextClientThink <= gpGlobals->curtime ); // This logic makes it so that if a child thinks, // *all* hierarchical parents + grandparents will think first, even if some // of the parents don't need to think this frame if ( !bThinkThisInterval && !bAlwaysChain ) return; // Respect hierarchy C_BaseEntity *pEntity = ClientEntityList().GetBaseEntityFromHandle( pEntry->m_hEnt ); if ( pEntity ) { C_BaseEntity *pParent = pEntity->GetMoveParent(); if ( pParent && (pParent->GetThinkHandle() != INVALID_THINK_HANDLE) ) { ThinkEntry_t *pParentEntry = GetThinkEntry( pParent->GetThinkHandle() ); AddEntityToFrameThinkList( pParentEntry, true, nCount, ppFrameThinkList ); } } if ( !bThinkThisInterval ) return; // Add the entry into the list pEntry->m_nIterEnum = m_nIterEnum; ppFrameThinkList[nCount++] = pEntry; }
void CGlowObjectManager::GlowObjectDefinition_t::DrawModel() { C_BaseEntity *pEntity = m_hEntity.Get(); if ( !pEntity ) return; if ( pEntity->GetMoveParent() != NULL ) { C_BaseAnimating *pBaseAnimating = pEntity->GetBaseAnimating(); if ( pBaseAnimating ) { pBaseAnimating->InvalidateBoneCache(); } } pEntity->DrawModel( STUDIO_RENDER ); C_BaseEntity *pAttachment = pEntity->FirstMoveChild(); while ( pAttachment != NULL ) { if ( !g_GlowObjectManager.HasGlowEffect( pAttachment ) && pAttachment->ShouldDraw() ) { C_BaseAnimating *pBaseAnimating = pAttachment->GetBaseAnimating(); if ( pBaseAnimating ) { pBaseAnimating->InvalidateBoneCache(); } pAttachment->DrawModel( STUDIO_RENDER ); } pAttachment = pAttachment->NextMovePeer(); } }