Il sistema di coordinate OpenGL è mancino o destrorso?


88

Sto cercando di capire il sistema di coordinate OpenGL. Tuttavia, alcuni tutorial dicono che il sistema di coordinate predefinito è mancino (vedi http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx ) e altri dicono che è destrorso (vedi http: // www .falloutsoftware.com / tutorials / gl / gl0.htm ). Che è corretto? Capisco che possiamo trasformare l'uno nell'altro specchiandoci ma vorrei conoscere le coordinate di default.



3
Questo non dipende interamente da come scrivi le tue trasformazioni negli shader e quindi dipende interamente da te?
jcoder

Solo i miei due centesimi evl.uic.edu/ralph/508S98/coordinates.html , ha alcune immagini autoesplicative.
rraallvv

Suppongo che non prenderesti in considerazione l'aggiornamento della tua risposta accettata?
Jonathan Mee

Risposte:


133

C'è una certa confusione qui.

inserisci qui la descrizione dell'immagine

OpenGL è destrorso nello spazio degli oggetti e nello spazio del mondo.

Ma nello spazio finestra (noto anche come spazio schermo) siamo improvvisamente mancini .

Come è successo ?

Il modo in cui si passa da destrimani a mancini è una voce di ridimensionamento z negativa nelle matrici di proiezione glOrthoo glFrustum. Scalare z di -1 (lasciando xey come erano) ha l'effetto di modificare la manualità del sistema di coordinate.

Per glFrustum,

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

lontano e vicino dovrebbero essere positivi, con lontano > vicino . Dire lontano = 1000 e vicino = 1. Quindi C = - (1001) / (999) = -1,002.

Vedi qui per maggiori dettagli e diagrammi.

Da un prospettiva ortografica , glOrtho genera una matrice come questa:

inserisci qui la descrizione dell'immagine

Qui, sinistra , destra , in basso e in alto sono solo le coordinate per verticale sinistra , verticale destra , orizzontale inferiore piani di ritaglio , orizzontale superiore (risp . ) .

I piani vicini e lontani , tuttavia, sono specificati in modo diverso . Il parametro near è definito come

  • Vicino al distanza dal piano di ritaglio della profondità più vicino. Questa distanza è negativa se l'aereo deve essere dietro lo spettatore.

e lontano:

  • zFar La distanza dal piano di ritaglio della profondità più lontano. Questa distanza è negativa se l'aereo deve essere dietro lo spettatore.

Qui abbiamo un tipico volume di visualizzazione canonica

canonico

Poiché il moltiplicatore z è (-2 / (molto vicino)), il segno meno ridimensiona effettivamente z di -1 . Ciò significa che "z" è ruotata verso sinistra durante la trasformazione della visualizzazione, all'insaputa della maggior parte delle persone poiché lavorano semplicemente in OpenGL come un sistema di coordinate "destrorso".

Quindi, se chiami

glOrthof(-1, 1, -1, 1, 10, -10) ; // near=10, FAR=-10,

Quindi il NEAR PLANE è 10 unità davanti a te . Dove sei? Perché, all'origine, con l'asse x alla tua destra, l'asse y sopra la testa e il naso rivolto verso il basso l'asse z negativo (questa è l'impostazione predefinita "Per impostazione predefinita, la fotocamera si trova all'origine , punta verso il basso l'asse z negativo e ha un vettore su (0, 1, 0). " ). Quindi il piano vicino è a z = -10. Il piano lontano è di 10 unità dietro di te, in z = + 10 .


1
"il vettore forward è negato in gluLookAt" - puoi confermare che è così? Non gluPerspective o glFrustum o glOrtho?
Kos

1
Siamo improvvisamente mancini dallo spazio della clip in poi, non solo dallo spazio della finestra.
legends2k

3
+1 per l'intera risposta, -1 (aspetta, piuttosto -2) per "Il modo in cui passiamo da destrimani a mancini è perché il vettore forward è negato nell'implementazione standard di gluLookAt (), che è la funzione tutti usano per creare la matrice della vista. Quando si nega il vettore in avanti, questo ha l'effetto di cambiare la manualità del sistema di coordinate. " , che è mera spazzatura ...
Christian Rau

2
... Negare il vettore in avanti nel gluLookAtcalcolo non ha nulla a che fare con la modifica della manualità dello spazio delle coordinate, è proprio così che viene calcolata questa matrice (e infatti + z è effettivamente "indietro" nello spazio destro). gluLookAtnon fa altro che calcolare una normale trasformazione del corpo rigido (rotazione + traslazione) nello spazio destrorso. Sono le matrici di proiezione utilizzate dalla pipeline delle funzioni fisse (e di solito anche dagli shader) che eseguono l'effettiva modifica della manualità nella loro negazione del componente z, come hai già notato nella tua risposta.
Christian Rau

2
@bobobobo Il tuo detto se calcoli la tua matrice di visualizzazione usando solo le funzioni di rotazione e traduzione (che immagino non accuseresti di cambiare manualità), invece di gluLookAt, non ci sarebbe un cambio di base mentre lo gluLookAtfa? Sicuramente non (dato che probabilmente sapere che non "tutti" usi gluLookAtper view matrice di calcolo), poiché, come si dovrebbe sapere gluLookAtnon fa altro che un mucchio di chiamate rotazione e traslazione (siano essi anche mascherati come "alto livello" termine "cambiamento di base " ) senza assolutamente riflessioni coinvolte.
Christian Rau

26

Per impostazione predefinita, la coordinata del dispositivo normalizzata è mancina.

Il glDepthRange è di default [0, 1] (vicino, lontano) facendo in modo che l'asse + z punti nello schermo e con + x a destra e + y in alto è un sistema per mancini.

Cambiando l'intervallo di profondità a [1, 0] il sistema diventerà destrorso.

Citando una precedente risposta di Nicol : (il barrato è il mio lavoro, spiegato di seguito)

Sono sorpreso che nessuno abbia menzionato qualcosa: OpenGL funziona anche in un sistema di coordinate per mancini. Almeno, lo fa quando lavori con gli shader e usi l'intervallo di profondità predefinito.

Una volta eliminata la pipeline a funzione fissa, gestisci direttamente lo "spazio di clip". La specifica OpenGL definisce lo spazio di clip come un sistema di coordinate omogeneo 4D. Quando segui le trasformazioni attraverso le coordinate del dispositivo normalizzate e fino allo spazio della finestra, trovi questo.

Lo spazio della finestra è nello spazio dei pixel di una finestra. L'origine è nell'angolo inferiore sinistro, con + Y che sale e + X che va a destra. Suona molto come un sistema di coordinate destrorso. Ma per quanto riguarda Z?

L'intervallo di profondità predefinito (glDepthRange) imposta il valore Z vicino a 0 e il valore Z lontano su uno . Quindi il + Z sta andando via dallo spettatore.

Questo è un sistema di coordinate per mancini. Si, puoimodificare il test di profondità da GL_LESS a GL_GREATER emodificare glDepthRange da [0, 1] a [1, 0]. Ma lo stato predefinito di OpenGL è lavorare in un sistema di coordinate mancino . E nessuna delle trasformazioni necessarie per arrivare allo spazio della finestra dallo spazio di clip nega lo spazio Z. Quindi lo spazio di clip, l'output dello shader di vertice (o geometria) è uno spazio per mancini (un po '. È uno spazio omogeneo 4D, quindi è difficile definire la manualità).

Nella pipeline a funzione fissa, le matrici di proiezione standard (prodotte da glOrtho, glFrustum e simili) si trasformano tutte da uno spazio destrorso a uno mancino . Capovolgono il significato di Z; basta controllare le matrici che generano. Nello spazio oculare, + Z si sposta verso lo spettatore; nello spazio post-proiezione, si allontana.

Sospetto che Microsoft (e GLide) semplicemente non si siano preoccupati di eseguire la negazione nelle loro matrici di proiezione.

Ho colpito una parte poiché si discostava dalle mie scoperte.

La modifica di DepthRange o DepthFunc e l'utilizzo di ClearDepth (0) funziona, ma quando si utilizzano entrambi si annullano a vicenda in un sistema per mancini.


L'intervallo di profondità non può essere [1, -1]. Penso che intendessi [1, 0]. Inoltre, questo è stato sottolineato in precedenza .
Nicol Bolas

La tua risposta è ottima, peccato che sia a una domanda DirectX, dovresti ripubblicarla qui!
hultqvist

3
@SigTerm perché pensi che non valga la pena correggere una dichiarazione falsa? Ho passato diverse ore a risolvere i problemi relativi alle coordinate dei vertici e alla generazione della rotazione della matrice solo per scoprire che il sistema di coordinate predefinito in realtà non era destrorso.
hultqvist

1
La domanda era se fosse un sistema per mancini o destrimani. Questa risposta ha più dettagli di quella, spiegando altri due modi per farlo con la mano destra, l'aggiunta di un -1 in una trasformazione di matrice è ancora un altro modo per farlo. Ma niente di tutto ciò ha importanza se ritieni che il sistema sia destrorso per impostazione predefinita, puoi cambiare qualcosa solo se sai da cosa stai cambiando. Ancora
hultqvist

1
Ho trovato la risposta molto illuminante e mi è venuta fuori durante le ricerche, quindi per me ne è valsa la pena.
Impara OpenGL ES

13

SOLO NDC

Dovresti solo notare che OpenGL conosce solo NDC! e questo è un sistema di coordinate per mancini.

Indipendentemente dal sistema di coordinate utilizzato (sistema di coordinate asse destrorso o mancino), tutti devono essere specchiati su NDC. Se lo desideri, puoi gestire totalmente lo spazio del mondo come sistema di coordinate per mancini.

Perché di solito usiamo il sistema di coordinate della mano destra nello spazio del mondo?

Penso che sia convenzionale. Lo fa e basta. Forse vuole solo distinguersi da DirectX.


3
Penso che questo non venga ripetuto abbastanza. Tutti questi diagrammi che mostrano "trasformazione di modellazione", "trasformazione di vista", "trasformazione di prospettiva" non riescono a mostrare che non sono una parte intrinseca di OpenGL. Potresti anche fare tutte le tue trasformazioni manualmente, con o senza shader, con o senza matrici.
Tom

3
Potrebbe essere più bello se ripeterlo per includere le parole "coordinate del dispositivo normalizzate" però.
Tommy

6
OpenGL precede DirectX di alcuni anni, quindi OpenGL non stava certamente cercando di distinguersi da DirectX. Lo sviluppatore principale di DirectX, Alex St. John, ha affermato che la decisione di Microsoft di optare per un sistema di coordinate per mancini è stata "in parte per preferenza personale" e "una scelta arbitraria".
Chris Nolet

Questo non è del tutto corretto. OpenGL conosce anche il sistema di coordinate di ritaglio, poiché il ritaglio avviene in quello. Il sistema di coordinate della clip ha la stessa manualità del sistema di coordinate NDC.
plasmacel

7

Il libro "WebGl Programming Guide" di Kouichi Matsuda spende quasi dieci pagine su "WebGl / OpenGl: Left or Right Handed?"

Secondo il libro:

  • In pratica, la maggior parte delle persone usa un sistema con la mano destra

  • OpenGl in realtà è un sistema per mancini internamente

  • Internamente, più profondamente, in realtà non è né l'uno né l'altro. In fondo a OpenGl non interessa il valore z. L'ordine in cui disegni le cose determina cosa viene disegnato sopra (disegna prima un triangolo, poi un quadrilatero, il quadruplo sovrascrive il triangolo).

Non sono pienamente d'accordo con il "non è né l'uno né l'altro", ma probabilmente è comunque una questione filosofica.


7
The order in which you draw things determines what is drawn on top (draw a triangle first, then a quad, the quad overrides the triangle). Questo è vero, in assenza di test approfonditi. In presenza di test di profondità, il valore z di un frammento viene confrontato con il valore nel buffer di profondità e il frammento scartato se fallisce il test di profondità, quindi il quad può o meno sovrascrivere il triangolo a seconda della loro profondità e del funzione di profondità utilizzata.
chrisvarnz

3

Opengl è decisamente mancino. Vedi molti tutorial che affermano il contrario perché negano il valore z nella matrice di proiezione. Quando i vertici finali vengono calcolati all'interno del vertex shader, vengono convertiti i vertici che passi dal lato client (coord di destra) a quello mancino, ei vertici verranno quindi passati allo shader della geometria e allo shader dei frammenti. Se utilizzi il sistema di coordinate di destra nel lato client, Opengl non si preoccupa. Conosce solo il sistema di coordinate normalizzato, che è mancino.

Modifica: se non ti fidi di me, prova semplicemente nel tuo shader di vertici aggiungendo una matrice di traduzione e puoi facilmente vedere se Opengl è mancino o meno.


0

Utilizzando le funzioni di proiezione e trasformazione integrate di OpenGL, l'osservazione dei movimenti sullo schermo segue le regole del sistema di coordinate della mano destra . Ad esempio, se un oggetto davanti alla tua vista viene traslato nella direzione z positiva, l'oggetto si muoverà verso di te.

Il buffer di profondità è esattamente l'opposto, ed è qui che entrano in gioco le NDC (Normalized Device Coordinates). Se passare GL_LESS a glDepthFunc significa che i pixel verranno disegnati quando sono più vicini a te rispetto a ciò che è già nel buffer di profondità, allora i pixel sono considerati vivere in un sistema di coordinate mancino .

C'è un altro sistema di coordinate, e questo è il viewport! Il sistema di coordinate del viewport è tale che + x punta a destra e + y punta verso il basso. Penso che a questo punto la manualità sia discutibile poiché a questo punto abbiamo a che fare solo con x, y.

Infine, gluLookAt under the hood deve negare il vettore di look-at. Poiché la matematica presume che un vettore punti in una direzione positiva verso l'oggetto che sta guardando e una telecamera guarda in basso -z, il vettore di sguardo deve essere negato in modo che sia allineato con la telecamera.

Qualcosa da masticare. Non ha molto senso chiamare la direzione z di un sistema di coordinate destrorso un vettore in avanti :). Penso che Microsoft lo abbia capito quando ha progettato Direct3D.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.