Autor Wątek: Problem z obrotem na kwaternionach  (Przeczytany 860 razy)

Offline Demon

  • Użytkownik

# Czerwiec 08, 2011, 18:46:26
Postaram się w miarę jasno opisać problem, zacznę od układu współrzędnych - oś X - w prawo wartości dodatnie, oś Y - w przód wartości dodatnie, oś Z - w górę wartości dodatnie. Mam na scenie walec, obracanie którym odbywa się za pomocą myszki (obracam nim tylko wokół osi Y). Walec ten na starcie ustawiony jest pod kątem 90 stopni do osi X.
1. W momencie wciśnięcia lewego przycisku myszki sprawdzam kolizję promienia z obiektem. Jeśli obiekt został trafiony, to w punkcie trafienia tworzę płaszczyznę.
2. Tworzę wektor od punktu kolizji do środka walca i zapamiętuję aktualną orientację obiektu w kwaternionie (qsrc).
3. Zeruję współrzędną Y utworzonego poprzednio wektora.
4. Kiedy poruszymy myszką z wciśniętym lewym przyciskiem to sprawdzam kolizję z utworzoną wcześniej płaszczyzną.
5. Tworzę drugi wektor z punktu przecięcia promienia z płaszczyzną i również ustawiam go relatywnie do środka walca.
6. Zeruję współrzędną Y tego wektora.

W tym momencie mam 2 wektory na płaszczyźnie XZ.

7. Tworzę oś obrotu poprzez iloczyn wektorowy tych dwóch wektorów. (axis)
8. Tworzę kąt obrotu między tymi wektorami poprzez iloczyn skalarny. (angle)
9. Tworzę kwaternion obrotu (qrel) z osi (axis) i kąta(angle).
10. Ustawiam rotację obiektu na qrel * qsrc.

No i tu pojawia się problem, gdyż rotacja mi się rozjeżdża (poruszam myszką, a obiekt się nie obraca, a później nagle skacze o większy kąt, czasami przeskakuje też jakby o 90 stopni).

Z tego co mi wiadomo to kwaterniony nie powinny mieć problemu z gimbal lockiem, a może jednak?
« Ostatnia zmiana: Czerwiec 08, 2011, 18:48:37 wysłana przez Demon »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline klestor

  • Użytkownik

# Czerwiec 08, 2011, 23:35:28
Mialem podobny problem w Ogre. Gdy (orbitowalem?) kamera wokol obiektu to przeskakiwala mi, z tym ze o 180 stopni. Okazalo sie ze Ogre domyslnie blokuje os Y. Wystarczylo odblokowac i juz mozna bylo bez problemu patrzec z i w kierunku Y. Ale boje sie ze ty masz nieco inny problem.

Offline Demon

  • Użytkownik

# Czerwiec 09, 2011, 07:25:54
Dzięki za odpowiedź klestor. Piszę w uniginie i póki co nie mam za bardzo jak sprawdzić co dokładnie robi ten silnik przy ustawianiu rotacji. Wczoraj napisałem sobie program symulujący to, co nie działa w unigine (c++ / gmtl) i nie zauważyłem żadnych nieprawidłowości. Możliwe więc, że problem jednak tkwi w unigine.

Quatf q1 = makeRot<Quatf, AxisAnglef>(AxisAnglef(deg2Rad(90.0f), 1.0f, 0.0f, 0.0f));
Quatf q2 = makeRot<Quatf, AxisAnglef>(AxisAnglef(deg2Rad(0.1f), 0.0f, 1.0f, 0.0f));
Quatf q3 = q1;
Vec3f v1(0.0f, 1.0f, 0.0f), v2;
v2 = q3 * v1;

for (int i=0; i<99000; i++)
{
Vec3f oldv2 = v2;
q3 = q2 * q3;
normalize(q3);
v2 = q3 * v1;
Vec3f diff = oldv2 - v2;
float lensq = lengthSquared(diff);
if (lensq > 0.1f)
{
printf("%f  %f  %f\n", oldv2[0], oldv2[1], oldv2[2]);
printf("%f  %f  %f\n", v2[0], v2[1], v2[2]);
printf("%f\n", lensq);
printf("%d\n", i);
}
}

Problem rozwiązany - ponieważ do kwaterniona potrzebny jest sin i cos połowy kąta obrotu, to robiłem coś takiego:

float angle = acos(dot(v1, v2)) * 0.5f;

Problem był spowodowany tym, że iloczyn skalarny zwracał mi 1 z bardzo małym ułamkiem i wtedy funkcja acos zwracała mi invalid number. Zapisałem wynik iloczynu do zmiennej i zamkąłem w przedziale <-1, 1>.
« Ostatnia zmiana: Czerwiec 09, 2011, 18:44:17 wysłana przez Demon »