Uso dei quaternioni: cosa posso fare con loro? (senza la matematica)


24

Sono uno sviluppatore di giochi e non ho studiato matematica. Quindi voglio usare solo Quaternions come strumento. E per essere in grado di lavorare con la rotazione 3D, è necessario utilizzare Quaternions (o Matrixes, ma restiamo a Quaternions qui in questa domanda). Penso che sia importante per molti sviluppatori usarli. Ecco perché voglio condividere le mie conoscenze e spero di riempire i buchi che ho. Adesso....

Per quanto ho capito:

Un Quaternion può descrivere 2 cose:

  1. L'attuale orientamento di un oggetto 3d.
  2. La trasformazione di rotazione che un oggetto potrebbe fare. (RotationChange)

Puoi fare con un Quaternion:

moltiplicazioni:

  1. Quaternion endOrientation = Quaternion rotationChange * Quaternion currentOrientation;

    Quindi, per esempio: il mio oggetto 3D viene ruotato di 90 ° a sinistra - e la mia rotazione che moltiplico è una rotazione di 180 ° a destra, alla fine il mio oggetto 3D di 90 ° viene ruotato a destra.

  2. Quaternion rotationChange = Quaternion endRotation * Quaternion.Inverse (startRotation);

    Con questo si ottiene un cambio di rotazione, che può essere applicato a un altro orientamento.

  3. Vector3 endPostion = Quaternion rotationChange * Vector3 currentPosition;

    Quindi, per esempio: il mio oggetto 3D è in posizione (0,0,0) e la mia rotazione che moltiplico è una rotazione di 180 ° a destra, la mia posizione finale è simile a (0, -50,0). All'interno di quel Quaternione c'è un asse - e una rotazione attorno a quell'asse. Ruoti il ​​tuo punto attorno a quell'asse Y Gradi.

  4. Vector3 rotatedOffsetVector = Rotazione quaternioneCambia * Vector3 currentOffsetVector;

    Ad esempio: La mia direzione di inizio sta mostrando SU - (0,1,0), e la mia rotazione che moltiplico è una rotazione di 180 ° a destra, la mia direzione finale è mostrata in basso. (0, -1,0)

Miscelazione (Lerp e Slerp):

  1. Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, interpolator)

    se l'interpolatore è 1: currentOrientation = endOrientation

    se l'interpolatore è 0: currentOrientation = startOrientation

    Slerp interpola più preciso, Lerp interpola più performante.

Le mie domande):

Tutto ciò che ho spiegato fino ad ora è corretto?

È "tutto" quello che puoi fare con i Quaternioni? (ovvio no)

Cos'altro puoi fare con loro?

A cosa servono il prodotto Dot e il prodotto Cross tra 2 Quaternioni?

Modificare:

Domanda aggiornata con alcune risposte


Supponi di non avere 2, ma norientamenti diversi (atteggiamenti, pose, ecc.). Quindi puoi mediarli usando i pesi, generalizzando efficacemente slerp / lerp. Puoi anche convertire un quaternione in un rotore, il che equivale ad applicare una velocità angolare per un certo periodo di tempo a un corpo rigido. Quindi puoi descrivere l'integrazione della velocità angolare anche con i quaternioni. Puoi anche stimare quanto siano diversi i due orientamenti (calcola la lunghezza dell'arco attraversato dai due quaternioni nell'ipersfera).
Teodron,

E sì, a prima vista, la tua logica è corretta (la tua comprensione dei quaternioni è abbastanza buona per una persona non tecnica). Questo non è appropriato per un commento, ma complimenti! Nemmeno i tecnicamente dotati conoscono tutti gli usi del quaternione, anche se li usano proprio come strumenti di ingegneria del software per uno scopo.
teodron,

4
"E per poter lavorare con la rotazione 3D, è necessario usare i Quaternioni" Non posso sottolineare abbastanza quanto sia falsa questa frase. Puoi usare gli angoli di Eulero o Tait-Bryan per lo sviluppo del gioco, l'unico problema è il gimbal lock. Se vuoi diventare uno sviluppatore di giochi, a un certo punto avrai bisogno di matematica, imparalo.
Bálint,

1
"sviluppatore di giochi" e "non studiare matematica" è un ossimoro.
Margaret Bloom,

2
Apprezzo quello che stai cercando di fare con la domanda, ma le risposte dovrebbero essere in una risposta, non nella domanda. Fai una risposta "sommaria" se pensi che valga la pena metterli insieme.
Base

Risposte:


23

Moltiplicazione

Almeno in termini di implementazione dei Quaternioni da parte di Unity, l'ordine di moltiplicazione descritto nella domanda non è corretto. Questo è importante perché la rotazione 3D non è commutativa .

Quindi, se voglio ruotare un oggetto rotationChangepartendo dal suo, currentOrientationlo scriverei in questo modo:

Quaternion newOrientation = rotationChange * currentOrientation;

(ad es. le trasformazioni si accumulano verso sinistra - lo stesso della convenzione di matrice di Unity. La rotazione più a destra viene applicata prima / all'estremità "più locale")

E se volessi trasformare una direzione o un offset vettore con una rotazione, lo scriverei in questo modo:

Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;

(Unity genererà un errore di compilazione se si fa il contrario)

mescolanza

Nella maggior parte dei casi puoi cavartela con le rotazioni di Lerping. Questo perché l'angolo usato "sotto il cofano" in un quaternione è metà dell'angolo di rotazione, rendendolo sostanzialmente più vicino all'approssimazione lineare di Lerp rispetto a qualcosa come una Matrix (che in generale non Lerp bene!). Guarda circa 40 minuti in questo video per ulteriori spiegazioni .

L'unico caso in cui hai davvero bisogno di Slerp è quando hai bisogno di una velocità costante nel tempo, come l'interpolazione tra i fotogrammi chiave su una sequenza temporale di animazione. Per i casi in cui ti interessa solo che un'uscita sia intermedia tra due ingressi (come la fusione di livelli di un'animazione), di solito Lerp serve abbastanza bene.

Cos'altro?

Il prodotto punto di due quaternioni unità fornisce il coseno dell'angolo tra di loro, quindi è possibile utilizzare il prodotto punto come misura di somiglianza se è necessario confrontare le rotazioni. Questo è un po 'oscuro, quindi per codice più leggibile userei spesso Quaternion.Angle (a, b) , che invece esprime più chiaramente che stiamo confrontando gli angoli, in unità familiari (gradi).

Questi tipi di metodi di convenienza forniti da Unity per i Quaternioni sono super utili. In quasi tutti i progetti ne uso almeno uno alcune volte :

Quaternion.LookRotation(Vector3 forward, Vector3 up)

Questo crea un quaternione che:

  • ruota l'asse z + locale per puntare esattamente lungo l' forwardargomento vettoriale
  • ruota l'asse y + locale per puntare il più vicino possibile upall'argomento vettoriale, se fornito, o (0, 1, 0)se omesso

Il motivo per cui "su" diventa "il più vicino possibile" è che il sistema è troppo determinato. Affrontare z + per forwardutilizzare fino a due gradi di libertà (ad es. Imbardata e beccheggio), quindi rimane solo un grado di libertà (rollio).

Trovo abbastanza spesso che voglio qualcosa con le proprietà di esattezza opposte: voglio che y + locale punti esattamente lungo up, e z + locale si avvicini il più possibile alla forwardlibertà rimanente.

Questo viene ad esempio quando provo a formare un riquadro di coordinate relativo alla telecamera per l'input di movimento: voglio che la mia direzione verso l'alto locale rimanga perpendicolare al pavimento o alla superficie inclinata normale, quindi il mio input non tenta di scavare il personaggio nel terreno o levitarli fuori di esso.

Potresti anche ottenere questo se vuoi che l'alloggiamento della torretta di un carro armato sia rivolto verso un bersaglio, senza staccarsi dal corpo del carro armato quando miri su / giù.

Possiamo realizzare la nostra funzione di convenienza per farlo, usando LookRotationper il sollevamento pesante:

Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
    Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
    Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);

    return rotateZToUp * rotateYToZ;
}

Qui prima ruotiamo y + locale su + z, e z + locale su y-.

Quindi ruotiamo il nuovo z + nella nostra direzione verso l'alto (quindi il risultato netto è y + locale direttamente lungo exactUp) e il nuovo y + il più vicino possibile alla direzione in avanti negata (quindi il risultato netto è z + punti locale il più vicino possibile lungo lungo approximateForward)

Un altro pratico metodo di praticità è Quaternion.RotateTowards, che uso spesso così:

Quaternion newRotation = Quaternion.RotateTowards(
                             oldRotation, 
                             targetRotation,
                             maxDegreesPerSecond * Time.deltaTime
                         );

Questo ci consente di avvicinarci targetRotationa una velocità costante e controllabile indipendentemente dal framerate, importante per le rotazioni che influenzano il risultato / la correttezza delle meccaniche di gioco (come girare il movimento di un personaggio o avere una torretta da rintracciare sul giocatore). Lerping / Slerping ingenui in questa situazione possono facilmente portare a casi in cui il movimento diventa più scattante ad alti framerate, influenzando l'equilibrio del gioco. (Questo non vuol dire che questi metodi sono sbagliati: ci sono modi per usarli correttamente senza cambiare equità, richiede solo cura. RotateTowardsFornisce una scorciatoia conveniente che si prende cura di questo per noi)


Suggerimento: aggiungi & t = 40m alla fine dell'URL del video in modo che salti direttamente lì (facoltativamente, ad esempio 40m5s). I prodotti a punti Quaternion sono utili anche quando si tratta di mondi di gioco sferici, o più in generale quando si orientano pezzi di sfere rotanti.
Luke Briggs,

@Luke Briggs: il punto di vista del mondo di gioco sferico sembra che valga la pena di approfondirlo nella sua risposta (specialmente con i diagrammi) se lo desideri. :)
DMGregory

Ottima idea - sono le 3 del mattino qui (quindi penso che sarebbe uscito un po 'incomprensibile!) Ma sarei felice di mettere insieme qualcosa domani (se ricordo!)
Luke Briggs

1
Modifica: mi sono lasciato un po 'trasportare pensando a una risposta, quindi la sfida è stata accettata! Almeno lo segnerò come un taglio approssimativo in modo che la gente possa essere consapevole dell'ustione a tarda notte che è andata in esso: P
Luke Briggs

Eccoci! Ho cercato di coprirlo in senso grafico, basandomi sul fatto che la tua risposta copre già molto bene le funzioni sottostanti. Tempo per dormire un po 'penso!
Luke Briggs,

14

Dov'è utilizzato il prodotto punto?

In Unity, uno degli utenti più comuni del prodotto punto è ogni volta che si controlla se due quaternioni sono uguali tramite ==o !=. Unity calcola il prodotto punto per verificare la somiglianza piuttosto che confrontare direttamente i valori interni x, y, z, w. Vale la pena tenerlo presente perché rende la chiamata più costosa di quanto ci si possa aspettare.

Lo usiamo anche in un caso d'uso interessante ..

Divertimento con i prodotti a punti di quaternione: mondi e orbitali sferici

Le simulazioni di interi pianeti e persino di interi sistemi solari stanno diventando sempre più comuni. Per farcela in tempo reale, abbiamo bisogno anche del prodotto punto quaternione. Molti di loro. Il prodotto punto quaternione è molto sottoutilizzato ma sicuramente ha i suoi usi - Diamo un'occhiata!

Innanzitutto, dobbiamo considerare tutta una serie di rotazioni:

  1. (Opzionalmente) La stella attorno al centro galattico
  2. Il pianeta intorno alla stella
  3. L'inclinazione del pianeta
  4. La rotazione del pianeta
  5. La posizione delle celle della griglia vicine (ruotate attorno al nucleo dei pianeti) *
  6. Piani orbitali multipli

Combinali tutti insieme e finisci con molta complessità (e molti numeri enormi!). Quando lo spettatore è in piedi sulla superficie del pianeta, non vogliamo che sfrecciano a una velocità folle attraverso il nostro spazio del mondo di gioco. In realtà preferiremmo che fossero fermi e da qualche parte vicino all'origine - spostiamo invece l'universo attorno al giocatore.

Pianeta rotante

È importante sottolineare che, al fine di essere in grado di ottenere la rotazione e l'inclinazione del pianeta corrette in questo scenario, dobbiamo bloccare l'asse in modo che possa solo oscillare su / giù sull'immagine sopra (cioè oscillare "su" mentre il giocatore viaggia nord). È qui che entra in gioco un prodotto a punti quaternione. Se qui non avessimo usato un prodotto a punti e invece solo moltiplicato l'inclinazione, ciò accadrebbe:

"Pianeti" erroneamente inclinati

Nota come i poli dei nostri "pianeti" in orbita si inclinano sempre verso la stella. Questo non è ciò che accade nella realtà: l'inclinazione è in una direzione fissa .

Senza andare troppo lontano dall'argomento, ecco un breve riassunto:

  • Su una sfera, un orientamento descrive anche una posizione della superficie.
  • Abbiamo molte rotazioni da combinare insieme.
  • Descrivi tutto come rotazione; anche la posizione dello spettatore. Questo aiuta ad aumentare le prestazioni poiché alla fine finiamo per fare meno operazioni.
  • L'angolo tra le rotazioni (il nostro prodotto a punti) aiuta quindi a misurare la longitudine e funziona particolarmente bene nel gestire le inclinazioni.

Ottenendo solo l'angolo, lasciamo cadere una parte di quella rotazione indesiderata . Allo stesso tempo abbiamo anche finito con una misurazione della longitudine che è utile per la navigazione e il clima locale.

* I pianeti sono costruiti da molte celle della griglia . Vengono visualizzati solo quelli vicini.


2
Questo fa un ottimo lavoro preparando la scena e motivando il problema, ma sono ancora un po 'confuso su come la matematica del prodotto punto quaternione (cioè il prodotto scalare dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.wrispetto alla composizione quaternione che useremmo per concatenare rotazioni) ci aiuterebbe a risolvere questo problema. Gradirei volentieri se potessi approfondire un po 'più tardi (non intendo trattenerti dal tuo slerp ... intendo dormire!)
DMGregory

@DmGregory la risposta breve è tilt è quella dispari; tutto si compone bene tranne quello (altrimenti il ​​pianeta sembrerebbe oscillare attorno alla sua stella). Domani (si spera!) Aggiungerò qualche altro contesto!
Luke Briggs,

@DMGregory Ho aggiunto alcune informazioni aggiuntive (non riuscivo a dormire!) - si spera che lo renda più chiaro.
Luke Briggs il

1
Scusami se sono un po 'denso, ma dopo aver riletto più volte non so ancora come utilizzare il prodotto punto in una formula per ottenere la trasformazione che stai descrivendo. Saresti in grado di aggiungere un piccolo pseudocodice che espone esplicitamente le operazioni che esegui?
DMGregory

@DMGregory Non ho familiarità con i quaternioni, ma se si tratta di rotazioni su una sfera, allora non si tratta di composizioni di rotazione. Questo sta usando la geometria sferica con i vettori per calcolare il vettore normale per una "linea" sulla superficie di una sfera AKA qualsiasi circonferenza. Ancora una volta, la risposta non ha molto senso né questa domanda, ma credo che stiano usando la geometria sferica.
The Great Duck il
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.