Conversione di tipo primitivo in computer grafica

2

Mi è stato ripetutamente detto che le conversioni di tipo esplicito sono un indicatore di codice errato e dovrebbero essere evitate.

Ora, in tutta onestà, sono stato un po 'infastidito da queste affermazioni a causa della natura del mio lavoro che sembra richiedere un sacco di conversione di tipo primitivo. Quindi voglio sapere se c'è un modo migliore per strutturare il mio codice, o se la grafica è un'eccezione a questa euristica "codice errato".

Nella grafica lavori al 50% con uno spazio continuo e il 50% con uno spazio discreto, che si traducono rispettivamente in float e inte.

Uno degli esempi più comuni sarebbe, calcolare una posizione 3D utilizzando una funzione continua e quindi troncare i 3 valori di quella posizione per indicizzare una matrice multidimensionale.

Come organizzerei il mio codice in modo tale da non effettuare alcuna conversione di tipo? i float sono necessari per calcolare la funzione continua, ma non possono essere usati direttamente come indici di array, in quanto il compilatore rifiuterà le istruzioni nella forma array[float] anche se il float rappresenta un intero.

    
posta Makogan 04.12.2018 - 20:59
fonte

2 risposte

6

La cosa che devi ricordare è che ogni float -to-% conversione diint e viceversa potenzialmente perde informazioni . Sulla maggior parte delle implementazioni, int può memorizzare un numero intero più grande con precisione completa rispetto a float , mentre i valori decimali di float vengono tagliati durante la conversione in int e che float può memorizzare numeri più grandi di entra in un int .

Ora, per il tuo caso d'uso specifico, potrebbe essere perfetto o più esattamente è esattamente ciò che desideri. Ma in generale , non si dovrebbero prendere queste conversioni alla leggera.

Considera solo l'esempio dalla tua domanda SO , che non include nemmeno la conversione di float :

int size = vector.size(); // Throws an implicit conversion warning
int size = (int)vector.size(); // C like typecasting is discouraged and forbidden in many code standards
int size = static_cast<int>vector.size(); // This makes me want to gauge my eyes out (it's ugly)

Ciascuno di questi casi ha un bug sottile: se la dimensione di vector è maggiore di numeric_limits<int>::max() (in genere 2 ^ 31 - 1), non si ottiene la dimensione effettiva. Quindi qualsiasi cosa tu stia facendo con size non funzionerà.

Ora puoi affermare che non avrai un vector così grande. E questo potrebbe essere vero ... oggi . Quanti buchi / bug di sicurezza sono stati aperti perché un'applicazione è stata ridimensionata al punto in cui alcuni valori hanno superato il tipo previsto? E quanti bug esistono che sono là fuori, in agguato, in attesa di balzare una volta superata la dimensione arbitraria?

Ecco perché ricevi un avviso quando non lo converti in modo esplicito. Ecco perché C ++ usa la sintassi che "mi fa venir voglia di valutare i miei occhi". È perché quello che stai facendo potrebbe non essere sicuro . Quindi dovresti considerare attentamente se dovresti farlo.

Ed è qui che arriviamo:

3D voxelization of geometry; 3D reconstruction of 2D textures and subsequent UV mapping onto the original texture to store values; Conversion of float coordinates to grid cells for the cached version of perlin noise...

Ognuna di queste cose dovrebbe essere nascosta dietro qualche interfaccia che esegue internamente la conversione richiesta. E non una semplicistica funzione convert_int ; Intendo uno specifico per l'attività in questione. Se stai convertendo normalizzati [0, 1] in virgola mobile in coordinate di pixel di una certa dimensione, hai una funzione per fare esattamente questo. Verrebbero fornite le coordinate e la dimensione della trama e restituirebbero coordinate intere.

Il punto del consiglio è che il tuo codice non dovrebbe essere sparpagliato con tali conversioni nude.

    
risposta data 04.12.2018 - 21:52
fonte
3

Stai confondendo casting e conversioni .

La conversione tra i tipi è perfetta. Ad esempio, troncare un float su un int, o convertirlo in un float o analizzare un int da una stringa. Stai effettivamente chiamando un tipo di costruttore che sta eseguendo questa conversione, anche se alcune conversioni potrebbero essere implicite. Non è possibile evitare le conversioni. Tuttavia, tali conversioni potrebbero presentare comportamenti non definiti se il valore non può essere rappresentato nel tipo di destinazione.

La trasmissione tra tipi è un'indicazione che stai sovvertendo il sistema dei tipi della lingua e di solito non è sicuro. Ci sono alcuni cast sicuri come gli upcast, le conversioni const o std::move() . E a volte i cast sono inevitabili in un programma molto dinamico. Soprattutto in C, spesso si esegue il cast da e verso void* per aggirare la mancanza di generici. Tuttavia, un programma C ++ moderno richiede cast molto raramente.

  • Un reinterpret_cast<T>(value) reinterpreta un modello di bit di qualche oggetto come oggetto di un tipo diverso. Ad esempio, potremmo reinterpretare un puntatore mobile come puntatore int. Questo non converte correttamente il valore puntato, ci ritroviamo con un int che ha lo stesso schema di bit. Tali lanci tendono quindi a dipendere dal comportamento definito dall'implementazione o non definito, e sono inappropriati nella maggior parte dei casi (possibili contro-esempi: serializzazione zero-overhead, o ABI cross-language).

  • Un dynamic_cast<T>(value) esegue un downcast sicuro di un oggetto polimorfico. L'esistenza di tali tipi di cast è talvolta necessaria se il sistema di tipi non è in grado di descrivere alcune informazioni di tipo, ma di solito indica che una gerarchia di classi è stata erroneamente designata: un utente di un'interfaccia non dovrebbe dover downcastare un oggetto a un tipo specifico, ma dovrebbe essere in grado di eseguire tutte le operazioni necessarie attraverso tale interfaccia. Un cast dinamico può anche generare un'eccezione e può essere relativamente lento. Sono inoltre disponibili modelli di progettazione che possono evitare la necessità di cast espliciti, ad esempio l'idioma del costruttore di copie virtuali o il pattern visitor.

Nel tuo lavoro di grafica, è improbabile che si verifichi la necessità di questi cast problematici.

    
risposta data 04.12.2018 - 21:58
fonte

Leggi altre domande sui tag