void FGLInterface::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist) { SpriteHits *spritelist = new SpriteHits[sprites.Size()]; SpriteHits **spritehitlist = new SpriteHits*[TexMan.NumTextures()]; TMap<PClassActor*, bool>::Iterator it(actorhitlist); TMap<PClassActor*, bool>::Pair *pair; BYTE *modellist = new BYTE[Models.Size()]; memset(modellist, 0, Models.Size()); memset(spritehitlist, 0, sizeof(SpriteHits**) * TexMan.NumTextures()); // this isn't done by the main code so it needs to be done here first: // check skybox textures and mark the separate faces as used for (int i = 0; i<TexMan.NumTextures(); i++) { // HIT_Wall must be checked for MBF-style sky transfers. if (texhitlist[i] & (FTextureManager::HIT_Sky | FTextureManager::HIT_Wall)) { FTexture *tex = TexMan.ByIndex(i); if (tex->gl_info.bSkybox) { FSkyBox *sb = static_cast<FSkyBox*>(tex); for (int i = 0; i<6; i++) { if (sb->faces[i]) { int index = sb->faces[i]->id.GetIndex(); texhitlist[index] |= FTextureManager::HIT_Flat; } } } } } // Check all used actors. // 1. mark all sprites associated with its states // 2. mark all model data and skins associated with its states while (it.NextPair(pair)) { PClassActor *cls = pair->Key; int gltrans = GLTranslationPalette::GetInternalTranslation(GetDefaultByType(cls)->Translation); for (int i = 0; i < cls->NumOwnedStates; i++) { spritelist[cls->OwnedStates[i].sprite].Insert(gltrans, true); FSpriteModelFrame * smf = gl_FindModelFrame(cls, cls->OwnedStates[i].sprite, cls->OwnedStates[i].Frame, false); if (smf != NULL) { for (int i = 0; i < MAX_MODELS_PER_FRAME; i++) { if (smf->skinIDs[i].isValid()) { texhitlist[smf->skinIDs[i].GetIndex()] |= FTexture::TEX_Flat; } else if (smf->modelIDs[i] != -1) { Models[smf->modelIDs[i]]->PushSpriteMDLFrame(smf, i); Models[smf->modelIDs[i]]->AddSkins(texhitlist); } if (smf->modelIDs[i] != -1) { modellist[smf->modelIDs[i]] = 1; } } } } } // mark all sprite textures belonging to the marked sprites. for (int i = (int)(sprites.Size() - 1); i >= 0; i--) { if (spritelist[i].CountUsed()) { int j, k; for (j = 0; j < sprites[i].numframes; j++) { const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j]; for (k = 0; k < 16; k++) { FTextureID pic = frame->Texture[k]; if (pic.isValid()) { spritehitlist[pic.GetIndex()] = &spritelist[i]; } } } } } // delete everything unused before creating any new resources to avoid memory usage peaks. // delete unused models for (unsigned i = 0; i < Models.Size(); i++) { if (!modellist[i]) Models[i]->DestroyVertexBuffer(); } // delete unused textures int cnt = TexMan.NumTextures(); for (int i = cnt - 1; i >= 0; i--) { FTexture *tex = TexMan.ByIndex(i); if (tex != nullptr) { if (!texhitlist[i]) { if (tex->gl_info.Material[0]) tex->gl_info.Material[0]->Clean(true); } if (spritehitlist[i] == nullptr || (*spritehitlist[i]).CountUsed() == 0) { if (tex->gl_info.Material[1]) tex->gl_info.Material[1]->Clean(true); } } } if (gl_precache) { // cache all used textures for (int i = cnt - 1; i >= 0; i--) { FTexture *tex = TexMan.ByIndex(i); if (tex != nullptr) { PrecacheTexture(tex, texhitlist[i]); if (spritehitlist[i] != nullptr && (*spritehitlist[i]).CountUsed() > 0) { PrecacheSprite(tex, *spritehitlist[i]); } } } // cache all used models for (unsigned i = 0; i < Models.Size(); i++) { if (modellist[i]) Models[i]->BuildVertexBuffer(); } } delete[] spritehitlist; delete[] spritelist; delete[] modellist; }
void CStar::Precache() { PrecacheTexture("textures/star-yellow.png"); }