Sebagaimana Nathan Reed dan teodron terpapar, resep untuk memutar vektor v oleh q angka empat satuan panjang adalah:
1) Buat p angka empat murni dari v . Ini berarti menambahkan koordinat keempat dari 0:
p = ( vx, vy, vz, 0 ) ⇔ p = ( v , 0 )
2) Pra-gandakan dengan q dan gandakan dengan konjugat q * :
hal′= q× p × q∗
3) Ini akan menghasilkan angka empat murni lain yang dapat dikembalikan ke vektor:
v′= ( hal′x,p′y,p′z)
Vektor ini adalah diputar oleh .v′vq
Ini bekerja tetapi jauh dari optimal . Penggandaan Quaternion berarti berton-ton operasi. Saya ingin tahu tentang berbagai implementasi seperti ini , dan memutuskan untuk mencari dari mana mereka datang. Inilah temuan saya.
Kami juga bisa menggambarkan q sebagai kombinasi dari vektor 3-dimensi u dan skalar s :
q=(ux,uy,uz,s)⇔q= ( kamu , s )
Dengan aturan perkalian angka empat , dan sebagai konjugasi dari angka empat satuan hanya kebalikannya, kita mendapatkan:
hal′= qp q∗= ( u , s ) ( v , 0 ) ( - u , s )= ( s v + u × v , - u ⋅ v ) ( - u , s )= ( ( - u ⋅ v ) ( - u ) + s ( s v + u × v ) + ( s v + u × v ) × ( - u ) , ... ) = ( ( u ⋅ v ) u + s2v + s ( u × v ) + s v × ( - u ) + ( u × v ) × ( - u ) , ... )
Bagian skalar (elips) menghasilkan nol, seperti yang dijelaskan di sini . Yang menarik adalah bagian vektor, AKA vektor diputar kami v ' . Ini dapat disederhanakan menggunakan beberapa identitas vektor dasar :
v′= ( u ⋅ v ) u + s2v + s ( u × v ) + s ( u × v ) + u × ( u × v )= ( u ⋅ v ) u + s2v + 2 s ( u × v ) + ( u ⋅ v ) u - ( u ⋅ u ) v= 2 ( u ⋅ v ) u + ( s2- u ⋅ u ) v + 2 s ( u × v )
Ini sekarang jauh lebih optimal ; produk dua titik, produk silang dan beberapa tambahan: sekitar setengah operasi. Yang akan memberikan sesuatu seperti itu dalam kode sumber (dengan asumsi beberapa perpustakaan matematika vektor generik):
void rotate_vector_by_quaternion(const Vector3& v, const Quaternion& q, Vector3& vprime)
{
// Extract the vector part of the quaternion
Vector3 u(q.x, q.y, q.z);
// Extract the scalar part of the quaternion
float s = q.w;
// Do the math
vprime = 2.0f * dot(u, v) * u
+ (s*s - dot(u, u)) * v
+ 2.0f * s * cross(u, v);
}