Kicsit gondban voltam a forgatások animációjával, ugyanis mindenki azt írja, hogy hát azt bizony csakis kvaternióval szabad blablabla. Mivel a dolog k*rvára nem működik a gyakorlatban, áttekintettem, hogy miért nincs szükség kvaterniókra.
Gimbal lock: mindenki tudja mi az a gimbal, ha nem akkor megnézed wikipédián. A lényeg, hogy az FPS, TPS vagy csak egy sima modelviewer kamera is gimbal lockos szándékosan. A hatása az, hogy ha pont fel vagy le nézel, akkor a kamera a view space beli z tengely körül forog, azaz valóban elvesztettél egy szabadságfokot (yaw helyett is rollol).
Kvaternió: egy ilyen állat csak olyan elforgatást tud reprezentálni, ami nem gimbal lock-os. Azaz ha kvaternióval próbálod interpolálni az amúgy gimbal lock-os kamerád szögeit, akkor eszméletlenül idióta eredményeket fogsz kapni (pl. elkezd sinus görbéket bejárni). Egy kvaternióval implementált kamera mindig úgy fordul, ahogy alapesetben: ha felfele nézel, akkor is a yaw jobbra-balra fog fordulni. Ami egy FPS-ben nagyon hülyén néz ki, azt hinnéd hogy elrontottál valamit, pedig nem.
Mátrix: forgatási mátrixot nem lehet, illetve nem úgy kell interpolálni, hogy komponensenként interpolálsz (más mátrixokkal működhet a dolog). De ez az ami abszolút nem éri meg, még ha jól is csinálod.
Euler szögek: bármily meglepő, ez a legjobb megoldás, némi meggondolással. Általában a legrövidebb úton akarsz eljutni a másik pontba. Kis számolás után erre az alábbi függvényt firkáltam:
float CurveAngle(float current, float dest, float step)
{
if (dest - current > _Q_PI)
dest = dest - _Q_2PI;
else if (current - dest > _Q_PI)
current = current - _Q_2PI;
current += (dest - current) * step;
return current;
}
Elég ezt meghívni mindhárom szögre és vidáman interpolál, úgy ahogy szeretnéd. Egy kisebb meggondolás az, hogy ha már összegányoltad kvaternióval a dolgot, mint én (amit most egyébként ki is gyomláltam), akkor sürgősen írd át, mert kvaternióból visszaszámolva pontatlan lehet (nekem speciel az invSqrt() miatt volt az).