Autor Wątek: Radar - czyli rzutowanie 3d->2d  (Przeczytany 1236 razy)

Offline Chimerian

  • Użytkownik
    • Profil na Warsztat.GD

# Lipiec 29, 2013, 12:33:10
Programując natrafiłem ostatnio na problem związany z obsługą radaru. Sprawa jest niezwykle prosta w przypadku FPSów - w takich grach poruszamy się po płaszczyźnie X i Z, więc na dobrą sprawę pozycje przeciwników na radarze mamy jawnie podane (wystarczy sprawdzić odległości między mną a obiektem, wykonać odpowiedni obrót i przeskalować odległości tak aby odpowiadały skali radaru).

Problem zaczyna się w przypadku, gdy mogę obracać się w dowolnym kierunku. Taki problem występuje w grach space-sim. Szukałem informacji na ten temat i dowiedziałem się że wygodnie jest to zrobić na plane. Napisałem poniższy kod:

for (int i = 0; i < ships.Units.Count; i++)
            {
                if (ships.Units[i].Enable == true)
                {
                    Vector2 position = new Vector2(radarCenter.X, radarCenter.Y);

                    Plane planeOne = new Plane(player.Ship.ForwardVector, player.Ship.UpVector, player.Ship.Position);
                    Plane planeTwo = new Plane(player.Ship.LeftVector, 0);

                    float distance = Vector3.Distance(planeOne.Normal, ships.Units[i].Position);
                    float distance2 = Vector3.Distance(planeTwo.Normal, ships.Units[i].Position);

                    position.X += distance;
                    position.Y += distance2;


                    spriteBatch.Draw(blank, position, new Rectangle(0, 0, blank.Width, blank.Height),
                                         Color.Red, 0.0f, new Vector2(blank.Width / 2, blank.Height / 2),
                                         0.25f, SpriteEffects.None, 1.0f);
                }
            }

Niestety nie działa on prawidłowo. Wektory Forward, Up i Left z tego co widzę wyliczane są prawidłowo (dla każdego obiektu znajdującego się w grze). Być może źle wyznaczam plane ? Byłbym wdzięczny za pomoc przy rozwiązaniu tego problemu.

Środowisko: VisualStudio 2008 + XNA 3.1 + C#

Offline Mr. Spam

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

Offline Xender

  • Użytkownik

  • +1
# Lipiec 29, 2013, 13:32:30
Chyba trzeba zrzutować pozycje na płaszczyznę, w której porusza się statek (czyli zawierającą pozycję statku i zawierającą wektory forward i left).

Zauważ też, że ignorujesz początek układu współrzędnych, bo korzystasz tylko z normalnych. Nie mam też pojęcia, czym jest distance - jeśli liczy różnicę wektorów i zwraca jej długość, to na pewno nie tego chcesz. To czego tu potrzebujesz, to iloczyn skalarny.

Spróbuj (pseudokod):relative_position = ship.position - player.position;
radar_position.x = Vector3.dot(relative_position, player.right);
radar_position.y = Vector3.dot(relative_position, player.forward);

Offline koirat

  • Użytkownik

# Lipiec 29, 2013, 13:44:15
W pierwszej kolejności powinieneś znaleźć pozycje obiektu relatywną do statku:

Możesz to zrobić poprzez wyliczenie macierzy A będącą wynikową macierzą transformacji statku.
Następnie jej inwersja A^-1 i przemnożenie pozycji obiektu w świecie przez tą odwróconą macierz.

Offline Chimerian

  • Użytkownik
    • Profil na Warsztat.GD

# Lipiec 30, 2013, 23:41:10
Chyba trzeba zrzutować pozycje na płaszczyznę, w której porusza się statek (czyli zawierającą pozycję statku i zawierającą wektory forward i left).

Tak, też tak uważałem - tylko chciałem to zrobić przez płaszczyzny.

Zauważ też, że ignorujesz początek układu współrzędnych, bo korzystasz tylko z normalnych. Nie mam też pojęcia, czym jest distance - jeśli liczy różnicę wektorów i zwraca jej długość, to na pewno nie tego chcesz. To czego tu potrzebujesz, to iloczyn skalarny.

relative_position = ship.position - player.position;
radar_position.x = Vector3.dot(relative_position, player.right);
radar_position.y = Vector3.dot(relative_position, player.forward);

Skorzystałem z Twojego rozwiązania i działa ! Dodałem jeszcze do tego obsługę wysokości względem gracza:
radar_position.z = Vector3.dot(relative_position, player.up);
Wielkie dzięki dla was obu za szybką odpowiedź :)
« Ostatnia zmiana: Lipiec 31, 2013, 00:08:52 wysłana przez Chimerian »