Koduję mechanikę, która pozwala użytkownikowi poruszać się po powierzchni kuli. Pozycja na kuli jest obecnie zapisywana jako theta
i phi
, gdzie theta
jest kąt między osią z i rzutem xz bieżącej pozycji (tj. Obrót wokół osi y), i phi
jest kątem od osi y do pozycji. Wyjaśniłem, że źle, ale to jest w istocie theta = yaw
,phi = pitch
Vector3 position = new Vector3(0,0,1);
position.X = (float)Math.Sin(phi) * (float)Math.Sin(theta);
position.Y = (float)Math.Sin(phi) * (float)Math.Cos(theta);
position.Z = (float)Math.Cos(phi);
position *= r;
Uważam, że jest to poprawne, jednak mogę się mylić. Muszę być w stanie poruszać się w dowolnym, pseudo-dwuwymiarowym kierunku wokół powierzchni kuli na początku przestrzeni świata o promieniu r
. Na przykład przytrzymanie Wpowinno poruszać się po kuli w kierunku do góry w stosunku do orientacji gracza.
Uważam, że powinienem używać czwartorzędu do przedstawienia pozycji / orientacji na kuli, ale nie mogę wymyślić właściwego sposobu na zrobienie tego. Geometria sferyczna nie jest moją mocną stroną.
Zasadniczo muszę wypełnić następujący blok:
public void Move(Direction dir)
{
switch (dir)
{
case Direction.Left:
// update quaternion to rotate left
break;
case Direction.Right:
// update quaternion to rotate right
break;
case Direction.Up:
// update quaternion to rotate upward
break;
case Direction.Down:
// update quaternion to rotate downward
break;
}
}
(1,1,1)
trzymający lewy obracałby się wokół kuli, przechodząc(~1.2,0,~-1.2)
wtedy(-1,-1,-1)
, potem, potem z(~-1.2,0,~1.2)
powrotem(1,1,1)
.theta
aphi
wraz z aktualizacją pozycji, problem staje się niepotrzebnie złożony. Znacznie łatwiej jest po prostu obliczyć 2 osie obrotu każdej klatki (jedna z nich (odchylenie) nigdy się nie zmienia) iVector3.Transorm
wokół kuli. Uprości to Twój problem, ale spowoduje rozłączenie się zphi
&theta
.Odpowiedzi:
W rzeczywistości okazuje się, że nie możesz mieć tego „na dwa sposoby”: jeśli twoim celem jest brak poczucia „absolutnej orientacji” na kuli (to znaczy, jeśli gracze nie zawsze są np. Skierowani w stronę biegunów ), musisz mieć pojęcie orientacji gracza. Wynika to z tego, że wbrew intuicji, która może sugerować, ruch na kuli nie jest dokładnie taki jak ruch na płaszczyźnie, nawet lokalnie (całkiem); wewnętrzna krzywizna kuli oznacza, że gracze mogą wykonywać działania, które same się obracają!
Dla najbardziej ekstremalnego przykładu tego, o czym mówię, wyobraź sobie, że gracz zaczyna od punktu na równiku (dla wygody wyobrażamy sobie tarczę zegara odwzorowaną na równiku z góry i ustawiasz gracza na godzinie 6 ), przodem do „góry” - to znaczy w kierunku bieguna północnego. Załóżmy, że gracz idzie do bieguna północnego; wtedy będą skierowani bezpośrednio w stronę punktu o godzinie 12. Teraz pozwól graczowi przejść bezpośrednio w prawo, z Bieguna Północnego z powrotem do równika; skończą w punkcie o trzeciej godzinie - ale ponieważ ich twarze nie zmieniają się, gdy poruszą się w prawo(chodzi o to, że ich twarze nie zmieniają się bez względu na to, jak się poruszają), wciąż będą musieli stawić czoła punktowi o godzinie 12 - teraz są zwrócone wzdłuż równika! Teraz pozwól im przejść „do tyłu” z powrotem do punktu początkowego (godzina szósta); wtedy będą nadal zwrócone w kierunku równika, więc będą skierowane w stronę punktu 3-go - po prostu poruszanie się po kuli bez zmiany ich „osobistej” orientacji spowodowało, że obrócili się z kierunku w kierunku bieguna północnego, aby skierowane wzdłuż równika! W pewnym sensie jest to rozwinięcie starego żartu, „łowca porusza się milę na południe, milę na zachód, a potem milę na północ” - ale tutaj wykorzystujemy krzywiznę kuli, aby dokonać zmiany kierunku. Zauważ, że ten sam efekt nadal występuje nawet w znacznie mniejszych skalach;
Na szczęście, jak zauważyliście, czwartorzędy radzą sobie z tą sytuacją; ponieważ czwartorzęd reprezentuje dowolny obrót, skutecznie reprezentuje on dowolny „punkt plus orientacja” na kuli: wyobraź sobie, że zaczynasz od „triaxis” na początku i dajesz mu dowolny dowolny obrót, a następnie przesuwasz jedną jednostkę w dowolnym kierunku obracanych osi ” Punkty na osi Z; mała myśl przekona cię, że to prowadzi cię do punktu na sferze jednostkowej z pewną „orientacją” (tj. pewnym ułożeniem osi X i Y twojej trójosiowej) i że możesz dostać się do każdego punktu + orientacja na sferę jednostkową w ten sposób (wystarczy przypisać oś Z do punktu wzdłuż linii od początku przez punkt na kuli, a następnie przetransportować triaxy z powrotem do początku wzdłuż tej linii). Co więcej, ponieważ mnożenie czwartorzędów odpowiada składowi rotacji, każdą z opisanych operacji można przedstawić, mnożąc swoją „aktualną orientację” przez odpowiednio wybrany czwartorzędowy: konkretnie, ponieważ czwartorzędowy (jednostka) (qx, qy, qz, qw) oznacza „obracaj się wokół osi (qx, qy, qz) o arccos (qw)”, a następnie (w zależności od konkretnego wyboru układu współrzędnych i pozwalając c_a być cos (alfa) i s_a być sin (alfa)) dwa z trzy czwarte M_x = (s_a, 0, 0, c_a), M_y = (0, s_a, 0, c_a), a M_z = (0, 0, s_a, c_a) będą reprezentować „obrót (tj. ruch) w kierunku I „jestem teraz skierowany w stronę alfa” i „obracasz się w kierunku prostopadłym do tego, w którym aktualnie jestem skierowany w stronę alfa”. (Trzeci z tych czwartorzędów będzie reprezentował „obróć moją postać wokół własnej osi”
Cur_q = M_x * Cur_q
jeśli gracz naciskał, lubCur_q = M_y * Cur_q
jeśli gracz naciskał w prawo (lub coś w rodzaju,Cur_q = M_yinv * Cur_q
jeśli gracz naciskał w lewo, gdzie M_yinv jest „odwrotnością” czwartorzędu M_y, reprezentującą obrót w drugą stronę). Pamiętaj, że musisz uważać, po której „stronie” zastosujesz obrót, czy to przedwcześnie, czy później; szczerze mówiąc, najłatwiej jest to rozwiązać metodą prób i błędów, wypróbowując oba mnożenia i sprawdzając, które z nich działają.Przejście od zaktualizowanego czwartorzędu do punktu na kuli (i do orientacji twojej postaci) jest również stosunkowo proste: zgodnie z ostatnim akapitem wszystko, co musisz zrobić, to użyć czwartorzędu na podstawie wektorów bazowych (1, 0,0), (0,1,0) i (0,0,1) ramki za pomocą operacji „obróć wektor o ćwiartkę” v → qvq -1 (gdzie mnożenia są mnożnikami czwartorzędu i identyfikujemy wektor v = (x, y, z) z „zdegenerowanym czwartorzędem” (x, y, z, 0)). Na przykład pozycję na kuli jednostkowej uzyskuje się po prostu przekształcając wektor z: pos = (qx, qy, qz, qw) * (0, 0, 1, 0) * (-qx, -qy, -qz, qw) = (qx, qy, qz, qw) * (qy, -qx, qw, qz) = (2 (qy * qw + qz * qx), 2 (qz * qy-qw * qx), (qz ^ 2 + qw ^ 2) - (qx ^ 2 + qy ^ 2), 0), więc
(2(qy*qw+qz*qx), 2(qz*qy-qw*qx), (qz^2+qw^2)-(qx^2+qy^2))
byłyby to współrzędne „transformowanego” użytkownika w sferze jednostkowej (i aby uzyskać współrzędne w dowolnej sferze, po prostu pomnożymy je przez promień sfery); podobne obliczenia działają dla innych osi, aby zdefiniować np. kierunek użytkownika.źródło
Move()
procedurę, ale czy chciałbym uzyskać znormalizowaną oś (tj. Moją pozycję), czy po prostu bym wziął(sin(qx),sin(qy),sin(qw)) * r
?Myślę, że chcesz czegoś podobnego do tego http://www.youtube.com/watch?v=L2YRZbRSD1k
Opracowałem to dla 48-godzinnego gamejamu ... możesz załadować kod tutaj ... http://archive.globalgamejam.org/2011/evil-god
Użyłem czegoś podobnego do twojego kodu, aby uzyskać współrzędne 3D ... ale obróciłem planetę i gracz był w tej samej pozycji, myślę, że jesteś zainteresowany ruchem stworzenia, to:
źródło