poniedziałek, Listopad 23rd, 2009

XNA: Detekcja stromych zboczy terenu

xna-zbocza-terenuW wielu aplikacjach, gdzie napotyka się na problem generowania terenu, pojawia się problem detekcji, aby np. postać, którą stworzymy, nie mogła wychodzić na zbyt strome zbocza. Metod na rozwiązanie tego problemu jest kilka, ja postaram się tutaj przedstawić prostą i skuteczną, a przede wszystkim dość uniwersalną metodę, która w małych projektach powinna się doskonale sprawdzić.Postawione przed nami zadanie, to na wygenerowanym z heightmap’y terenie, wykryć kiedy kolejny ruch naszego aktora (postaci, pojazdu itp.), nie będzie możliwy właśnie ze względu na przekroczenie stromości vertexa, w którego kierunku chcemy zmierzać. Do wygenerowania terrenu, wykorzystamy sample przygotowany przez twórców XNA: Heightmap Collision with Normals, który pozwoli wygenerować nam stosowny model terenu i wyliczy normal’e dla wszystkich vertexów.

Koncepcję, która przyjąłem, jest sprawdzanie, czy vertex w konkretnym punkcie, a właściwie normal do niego przypisany, jest nachylony do płaszczyzny pod odpowiednim kątem, który dobrany został eksperymentalnie (określony jest przez współczynnik i zależy od wielkości wygenerowanych vertexów i skali terenu).

Kluczem do wyliczania stromości, jest metoda, która jest składową klasy terrain (w moim przypadku dziedziczy po DrawableGameComponent i posiada jako składową, klasę HeightMapInfo z ww. przykładu), która to z kolei w zależności od spełnienia warunku stromości wyliczonego w ww. sposób, zwraca bool.

Jej postać jest następująca:

public bool bluff(Vector3 position)
        {
            Vector3 normal;
            heightMapInfo.GetHeightAndNormal(position, out position.Y, out normal);
            Vector3 angle;
            Vector3 plane = new Vector3(1, 0, 1);
            normal.Normalize();
            Vector3.Cross(ref plane, ref normal, out angle);
            angle.Normalize();

            if (Math.Abs(angle.Y) < 0.45f) 
                return true;
            else
                return false;
        }

Użycie:

// metoda update, reakcja na klawisz
if (terrain.heightMapInfo.IsOnHeightmap(newSpherePosition) && terrain.bluff(newSpherePosition))
{
      // zmień pozycje i wykonaj opcjonalnie jakieś akcje
}
else
{
      // nie zmieniaj pozycji
}

Innymi metodami, które można zastosować w tym przypadku to mapa kolizji (rejonów po których można się poruszać bądź też nie), czy też np. podpięcie systemu fizyki, który wykonał by "brudną robotę" za nas. Zaletą tego rozwiązania oprócz prostoty, jest jego automatyka - raz zaimplemetowany, działa zawsze. Jestem pewien, że można by jeszcze udoskonalić zaprezentowaną metodę, zatem zainteresowanych zachęcam do przedstawienia swoich metod rozwiązania tego problemu, w komentarzach.

Fotografia: [ Link ]

Be Sociable, Share!

Kategorie: .net / c# / xna
Możesz śledzić komentarze do tego wpisu poprzez kanał RSS 2.0. Możesz również napisać własny komentarz, lub umieścić odnośnik do tego wpisu, na swojej stronie.

2 komentarze/y

Kwiecień 27, 2010

Hello !!
I see that you are using my licensed photo in your website , however I don’t see any credits to my name , I am glad you liked my photo but I request to be credited for my name in your blog
thank you .

ilker ender.


Kwiecień 28, 2010
Dawid Pośliński

Ofcourse I did – check link at the end of post after „Fotografia” with direct to flickr page, where user can find information about You.


  • *

    Spam Protection by WP-SpamFree