Rotazione videocamera 3D


9

Per favore, perdonami, ma ho bisogno di aiuto e sono bloccato su questo da alcune settimane, non sto facendo progressi e ovunque vada e vedo una risposta diversa, tutto ciò che provo non funziona. Ho avuto abbastanza suggerimenti e consigli, ora ho davvero solo bisogno di qualcuno che mi dia la risposta per farmi lavorare indietro perché non riesco a capirlo.

Ciò che ha reso questo argomento più confuso è il modo in cui ognuno usa un diverso insieme di convenzioni o regole e le loro risposte si basano sulle proprie convenzioni senza definire ciò che sono.

Quindi, ecco l'insieme di convenzioni che ho formulato sulla base di ciò che sembra essere più comune e logico:

  1. Regola della mano destra per l'asse.
  2. Il positivo Y è in alto, il positivo Z è verso lo spettatore, il positivo X è a destra.
  3. Matrici Major Row, trasposte quando inviate agli shader.
    • Passo: rotazione attorno all'asse X.
    • Yaw: rotazione attorno all'asse y
    • Rotolo: rotazione attorno all'asse z
  4. Ordine di rotazione: Roll, Pitch, Yaw (è corretto? Qualcuno può controllarmi su questo?)
  5. I valori di rotazione positivi, guardando verso il basso dall'estremità positiva di un asse, producono una rotazione in senso orario.
  6. La direzione predefinita per la rotazione 0 su tutti gli assi è un vettore che punta verso il basso su Y negativo.

.. date quelle convenzioni (sicuramente correggimi se sono sbagliate!), come si fa:

  • Scrivi una funzione LookAt? (lookAt (posizione vettoriale, eyefocus vettoriale, vector up))
  • Calcola una matrice di rotazione. (rotazione (x, y, z))

Ho provato a rispondere a queste due domande da solo almeno nelle ultime 3 settimane, ho riscritto la mia funzione LookAt & Rotation Matrix almeno 30 volte, ho testato dozzine di metodi e letto materiale che ho visto su centinaia di siti Web e leggere molte domande con risposta, copiato il codice di altre persone e nulla di ciò che ho fatto finora ha funzionato, tutto ha prodotto il risultato sbagliato. Alcuni dei quali hanno prodotto output esilaranti e bizzarri nemmeno vicini alla corretta rotazione.

Ci ho lavorato tutte le sere ad eccezione della notte scorsa perché mi sentivo così frustrato dal ripetuto fallimento che mi sono dovuto fermare e fare una pausa.

Per favore, mostrami qual è il metodo corretto in modo che io possa lavorare a ritroso da quello e capire come funziona, non sto solo ottenendo la risposta corretta e questo mi sta facendo impazzire!

Sto scrivendo in Java ma prenderò il codice scritto in qualsiasi lingua, la maggior parte del mio codice di rendering 3D in realtà funziona in modo abbastanza brillante, è solo la matematica che non riesco a capire.

AGGIORNAMENTO: RISOLTO

Grazie per l'aiuto! Ora ho una funzione LookAt funzionante che in realtà capisco e non potrei essere più felice (se qualcuno vorrebbe vederlo sicuramente chiedere).

Ho provato di nuovo a creare una matrice di rotazione basata su variabili pitch / yaw / roll e sembrava di nuovo fallire, ma ho deciso di abbandonare il tentativo di utilizzare gli angoli di eulero per la telecamera freelook in quanto sembra non essere adatto per ruolo, invece ho intenzione di creare una classe quaternione, potrebbe avere più fortuna nel percorrere quella strada, altrimenti ricorrere all'uso del pitch / yaw come coordinate sferiche e farò affidamento sulla nuova funzione LookAt funzionante per la rotazione.

Se qualcun altro si trova ad affrontare un problema simile e vuole farmi domande, sentitevi liberi di farlo.

Almeno non sono più bloccato, grazie per l'aiuto!

Risposte:


15

Quello che stai cercando può essere trovato in questa ottima spiegazione: http://www.songho.ca/opengl/gl_transform.html

Ma dal momento che l'ho trovato un po 'confuso senza tenere la mano, proverò a spiegarlo qui.

A questo punto è necessario considerare 5 sistemi di coordinate e il modo in cui si relazionano tra loro. Queste sono le coordinate della finestra, le coordinate del dispositivo normalizzate, le coordinate dell'occhio, le coordinate del mondo e le coordinate dell'oggetto.

Le coordinate della finestra possono essere viste come pixel "fisici" sullo schermo. Sono le coordinate a cui fa riferimento il sistema a finestre e se si opera nella risoluzione nativa del monitor, si tratta in realtà di singoli pixel. Il sistema di coordinate della finestra sono numeri interi 2D ed è relativo alla tua finestra. Qui x + è a sinistra e y + è in basso con l'origine nell'angolo in alto a sinistra. Li incontri quando ad esempio chiami glViewport.

Il secondo set sono le coordinate del dispositivo normalizzate. Questi si riferiscono all'impostazione dello spazio dalla porta di visualizzazione attiva. L'area visibile della porta di visualizzazione va da -1 a +1 e quindi ha l'origine al centro. La x + viene lasciata e la y + è in alto. Hai anche z + è "fuori" dalla scena. Questo è ciò che descrivi in ​​1.

Non hai alcun controllo su come ottenere dalle coordinate del dispositivo normalizzate alle coordinate della finestra, questo è implicitamente fatto per te. L'unico controllo che hai è attraverso glViewporto simile.

Quando lavori con openGL, il risultato finale sarà sempre in coordinate del dispositivo normalizzate. Di conseguenza devi preoccuparti di come rendere la tua scena resa in questi. Se si imposta la matrice di proiezione e vista modello sulla matrice identità, è possibile disegnare direttamente in queste coordinate. Questo ad esempio viene fatto quando si applicano effetti a schermo intero.

Il prossimo è le coordinate oculari. Questo è il mondo visto dalla telecamera. Di conseguenza l'origine è nella telecamera e si applicano gli stessi alimenti degli assi come le coordinate del dispositivo.

Per passare dalle coordinate oculari alle coordinate del dispositivo, costruisci la matrice di proiezione. La più semplice è la proiezione ortografica che ridimensiona i valori in modo appropriato. La proiezione prospettica è più complicata e coinvolge la prospettiva della simulazione.

Finalmente hai il sistema di coordinate mondiale. Questo è il sistema di coordinate in cui è definito il tuo mondo e la tua fotocamera fa parte di questo mondo. Qui è importante notare che gli orientamenti degli assi sono esattamente come li definisci . Se preferisci z + come sopra, va benissimo.

Per andare dalle coordinate del mondo alle coordinate dell'occhio, definisci la matrice della vista. Questo può essere fatto con qualcosa del genere lookAt. Ciò che questa matrice fa è "muovere" il mondo in modo che la telecamera sia all'origine e guardi verso il basso sull'asse z.

Per calcolare la matrice di visualizzazione è sorprendentemente semplice, è necessario per la trasformazione della fotocamera. Fondamentalmente è necessario formulare la seguente matrice:

M=X[1]y[1]z[1]-p[1]X[2]y[2]z[2]-p[2]X[3]y[3]z[3]-p[3]0001

I vettori x, ye z possono essere presi direttamente dalla fotocamera. Nel caso in cui guardassi, li deriveresti dai valori target, eye (center) e up. Così:

z=normun'lioze(eye-tun'rget)X=normun'lioze(up×z)y=zX

Ma se ti capita di avere questi valori semplicemente in giro, puoi prenderli così come sono.

Ottenere p è un po 'più complicato. Non è la posizione nelle coordinate mondiali ma la posizione nelle coordinate della telecamera. Una semplice soluzione qui è di inizializzare due matrici, una con solo x, ye z e una seconda con -eye e moltiplicarle insieme. Il risultato è la matrice di visualizzazione.

Per come questo può apparire nel codice:

mat4 lookat(vec3 eye, vec3 target, vec3 up)
{
    vec3 zaxis = normalize(eye - target);    
    vec3 xaxis = normalize(cross(up, zaxis));
    vec3 yaxis = cross(zaxis, xaxis);     

    mat4 orientation(
       xaxis[0], yaxis[0], zaxis[0], 0,
       xaxis[1], yaxis[1], zaxis[1], 0,
       xaxis[2], yaxis[2], zaxis[2], 0,
         0,       0,       0,     1);

    mat4 translation(
              1,       0,       0, 0,
              0,       1,       0, 0, 
              0,       0,       1, 0,
        -eye[0], -eye[1], -eye[2], 1);

    return orientation * translation;
}

codice completo

E infine, per completezza, hai anche il sistema di coordinate dell'oggetto. Questo è il sistema di coordinate in cui sono memorizzate le mesh. Con l'aiuto della matrice del modello, le coordinate della mesh vengono convertite nel sistema di coordinate mondiale. In pratica, le matrici modello e vista sono combinate nella cosiddetta matrice vista modello.


1
Se potessi votare questa risposta cento volte, lo farei. Grazie per una risposta completa e completa che affronta tutto ciò di cui sono stato confuso e che fornisce anche il codice e il link! Ho passato tutto il giorno a leggere libri di matematica su questo argomento e con la tua risposta, il codice di esempio e la pagina collegata, se questo non mi basta per capirlo, dovrei smettere ora. Se potessi chiedere solo un chiarimento, in quell'ultimo esempio di codice, avrei ragione nel dire che quelle matrici sono in ordine di colonna maggiore e quella sopra è in riga di maggiore?
Grado

Questo è un po 'confuso, le matrici sono la colonna maggiore, ma la colonna è nella riga. Quindi per mappare la matematica attuale al codice è necessario trasporre la matrice. Vedi github.com/rioki/glm/blob/master/src/matrix.h#l72 Questo mappa esattamente su openGL e come sarebbe se si usasse float[16].
rioki,

Ah, lo pensavo così, ma volevo solo esserne sicuro, grazie ancora! Sei stato di grande aiuto, lo apprezzo molto.
Grado
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.