// Just reuse next decal in list // A decal that spans multiple surfaces will use multiple decal_t pool entries, // as each surface needs it's own. static decal_t *R_DecalAlloc( decal_t *pdecal ) { int limit = MAX_RENDER_DECALS; if( r_decals->integer < limit ) limit = r_decals->integer; if( !limit ) return NULL; if( !pdecal ) { int count = 0; // check for the odd possiblity of infinte loop do { if( gDecalCount >= limit ) gDecalCount = 0; pdecal = &gDecalPool[gDecalCount]; // reuse next decal gDecalCount++; count++; } while(( pdecal->flags & FDECAL_PERMANENT ) && count < limit ); } // if decal is already linked to a surface, unlink it. R_DecalUnlink( pdecal ); return pdecal; }
/* =============== R_EntityRemoveDecals remove all decals from specified entity =============== */ void R_EntityRemoveDecals( model_t *mod ) { msurface_t *psurf; decal_t *p; int i; if( !mod || mod->type != mod_brush ) return; psurf = &mod->surfaces[mod->firstmodelsurface]; for( i = 0; i < mod->nummodelsurfaces; i++, psurf++ ) { for( p = psurf->pdecals; p; p = p->pnext ) R_DecalUnlink( p ); } }
/* =============== R_ClearAllDecals remove all decals from anything used for full decals restart =============== */ void R_ClearAllDecals( void ) { decal_t *pdecal; int i; // because gDecalCount may be zeroed after recach the decal limit for( i = 0; i < MAX_RENDER_DECALS; i++ ) { pdecal = &gDecalPool[i]; R_DecalUnlink( pdecal ); } if( clgame.drawFuncs.R_ClearStudioDecals ) { clgame.drawFuncs.R_ClearStudioDecals(); } }
static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, float y ) { decal_t *pdecal, *pold; int count, vertCount; if( !surf ) { MsgDev( D_ERROR, "psurface NULL in R_DecalCreate!\n" ); return; } pold = R_DecalIntersect( decalinfo, surf, &count ); if( count < MAX_OVERLAP_DECALS ) pold = NULL; pdecal = R_DecalAlloc( pold ); if( !pdecal ) return; // r_decals == 0 ??? pdecal->flags = decalinfo->m_Flags; VectorCopy( decalinfo->m_Position, pdecal->position ); if( pdecal->flags & FDECAL_USESAXIS ) VectorCopy( decalinfo->m_SAxis, pdecal->saxis ); pdecal->dx = x; pdecal->dy = y; pdecal->texture = decalinfo->m_iTexture; // set scaling pdecal->scale = decalinfo->m_scale; pdecal->entityIndex = decalinfo->m_Entity; // check to see if the decal actually intersects the surface // if not, then remove the decal R_DecalVertsClip( pdecal, surf, decalinfo->m_iTexture, &vertCount ); if( !vertCount ) { R_DecalUnlink( pdecal ); return; } // add to the surface's list R_AddDecalToSurface( pdecal, surf, decalinfo ); }
/* =============== R_DecalRemoveAll remove all decals with specified texture =============== */ void R_DecalRemoveAll( int textureIndex ) { decal_t *pdecal; int i; if( textureIndex < 0 || textureIndex >= MAX_TEXTURES ) { MsgDev( D_ERROR, "Decal has invalid texture!\n" ); return; } for( i = 0; i < gDecalCount; i++ ) { pdecal = &gDecalPool[i]; if( !textureIndex || pdecal->texture == textureIndex ) R_DecalUnlink( pdecal ); } }