Contenitore texture globale

4

Per il mio primo endevor di grandi dimensioni in Open-GL sto facendo un simulatore di sorta. Ho funzionato molte delle funzionalità di base, ma di recente ho riscontrato un problema. Come da allora ho realizzato, inizialmente ho progettato il programma in modo che ogni oggetto nel simulatore avesse una sua classe che ne memorizzasse la posizione, la trama, il codice di disegno, ecc. Questo divenne un problema, tuttavia, quando cominciai a creare molti oggetti di lo stesso tipo, come ho capito rapidamente che ho scritto le classi per ricaricare una nuova istanza dei dati di texture per ogni istanza di un oggetto. Per risolvere questo problema ho preso in considerazione l'idea di creare una classe di ordinamento del database di texture semplice che conterrebbe un puntatore a una singola istanza di ciascun dato di texture dell'oggetto che ogni istanza dell'oggetto copierà al momento della sua creazione.

Il problema qui è che molte classi diverse nel simulatore creano oggetti e io sono titubante nel memorizzare semplicemente la classe del database delle texture nella parte superiore della gerarchia del programma e passarla a tutte le funzioni che creano un oggetto, come ritengo che questo diventerà molto complesso molto velocemente. Invece, ritengo sarebbe meglio avere una classe contenitore globale che tenga traccia dei puntatori di trama, ma non sono sicuro di come potrei memorizzare i puntatori senza istanziare un'istanza del contenitore che richiederebbe di passarla dappertutto . Spero che ci sia una soluzione più elegante e semplice che sto trascurando, altrimenti proverò come ho descritto. In alternativa, se sembra che una ristrutturazione del simulatore sia la migliore, non è fuori discussione, ma gradirei qualsiasi consiglio.

    
posta fedora 13.05.2012 - 18:57
fonte

3 risposte

2

Modifica: soluzione singleton rimossa a favore di static std :: map più semplice che utilizza la funzione buildTex esistente. Nota che non è thread-safe come implementato.

GLuint buildTex(string strFileName)
{
    static map<string, GLuint> s_Textures;

    if (s_Textures.find(strFileName) == s_Textures.end())
    {
        GLuint hTexture;
        // TODO: load hTexture from file

        s_Textures[strFileName] = hTexture;
    }

    return s_Textures[strFileName];
}

// Tree.cpp
void Tree::Draw()
{
    GLuint hTex = buildTex("Tree.tex");
    ...
}
    
risposta data 13.05.2012 - 19:17
fonte
0

Che ne dici di una texture fabbrica ?

Questo approccio potrebbe richiedere un po 'di riorganizzazione della gerarchia degli oggetti, ma ecco il succo in un pseudocodice c ++ approssimativo:

class World
{
    void createVisibleObject(objProps) // objProps -> object properties
    {
        Texture myTex;

        if(textureCache.contains(objProps.textureName))
        {
            myTex = textureCache.find(objProps.textureName);
        }
        else
        {
            myTex = textureFactory.create(textureName);
            textureCache.add(objProps.textureName, myTex);
        }

        VisibleObject visObj(myTex);
        // add visObj to your visible object collection
    }

    TextureCache textureCache;
    TextureFactory textureFactory;
};

I tuoi singoli oggetti visibili non hanno (e non dovrebbero) bisogno di sapere come vengono caricate le trame. Passa loro una texture precostruita. Qualunque cosa sia responsabile per la creazione di questi oggetti è quella che si preoccupa di quei dettagli. La TextureCache / Factory è tenuta nell'unico posto che deve sapere su di loro. La cache può essere fantasiosa con le mappe e i puntatori intelligenti.

I vantaggi di questo approccio sono vari:

  • Chiara separazione delle preoccupazioni
  • La cache funziona 'globalmente', senza essere globale
  • La creazione della risorsa avviene in un unico punto
  • Nessuna dipendenza da singleton
risposta data 14.05.2012 - 17:28
fonte
0

Quello che ho fatto è stato creare un oggetto risorsa, che quindi crea oggetti che hanno bisogno di detta risorsa, quindi in questo caso std::shared_ptr<Texture> (dove Texture è un'interfaccia e l'implementazione contiene i dati reali della trama) e quindi si chiama tex_ptr->CreateSprite(); per creare uno sprite che usa quella texture.

The problem here is that lots of different classes in the simulator create objects

C'è il tuo problema. Niente a che vedere con le trame. Il tuo codice è un pasticcio di spaghetti. Devi centralizzare le tue dipendenze. Crea una classe che si occupa della simulazione e una classe che si occupa di OpenGL.

Se "passare un riferimento" è troppo arduo per te, rifatta il codice quindi non lo è. Un simulatore non dovrebbe sapere nulla di OpenGL o di trame.

    
risposta data 14.05.2012 - 19:11
fonte

Leggi altre domande sui tag