Jak powinienem wdrożyć kamerę pierwszoosobową?

12

Jestem początkującym programistą i tworzę projekt, który pozwala mi chodzić po pokojach za pomocą kamery z perspektywy pierwszej osoby. Do tej pory rysowałem i włączałem budynki, ale teraz utknąłem i nie wiem, jak zrobić aparat z perspektywy pierwszej osoby, aby pozwolić mi chodzić.

Czy ktoś mógłby skierować mnie w stronę kamery, której mógłbym użyć, lub jakiegoś przydatnego kodu?

DK10
źródło

Odpowiedzi:

7

Oto kilka wskazówek na temat obracania aparatu (podgląd myszy). Po naiwnym wdrożeniu klasy kamery od zera stwierdziłem, że muszę zrobić kilka dodatkowych poprawek, aby uzyskać dobre zachowanie obrotowe:

  1. Zresetuj współrzędne myszy do środka ekranu na każdej klatce, aby mysz nigdy nie została złapana na granicach ekranu

  2. Utrzymaj wektor „w górę” aparatu (nie zezwalaj na przewracanie) i ponownie oblicz wektor „na boki”

  3. Nie zezwalaj na patrzenie w górę poza osią pionową + y lub w dół za osią -y (zbyt daleko w górę / w dół)

  4. Uzyskaj prawidłową kolejność obrotów (najpierw góra / dół, potem lewo / prawo)

  5. Ponownie znormalizuj wektory „góra”, „cel” i „na boki” w każdej ramce

Mamy nadzieję, że wykorzystasz ten kod na swoją korzyść:

    const int mouseDeltaX = mouseAxisX * (input.GetMouseX() - int(app.GetWidth()/2));
    const int mouseDeltaY = -mouseAxisY * (input.GetMouseY() - int(app.GetHeight()/2));  // mouse y-offsets are upside-down!

    // HACK:  reset the cursor pos.:
    app.SetCursorPosition(app.GetWidth()/2, app.GetHeight()/2);

    float lookRightRads = mouseDeltaX * CAMERA_ANGULAR_SPEED_DEG * DEG_TO_RAD;
    float lookUpRads    = mouseDeltaY * CAMERA_ANGULAR_SPEED_DEG * DEG_TO_RAD;

    // Limit the aim vector in such a way that the 'up' vector never drops below the horizon:
    static const float zenithMinDeclination = DEG_TO_RAD * MIN_UPWARDS_TILT_DEG;
    static const float zenithMaxDeclination = DEG_TO_RAD * (180.0f - MIN_UPWARDS_TILT_DEG);

    const float currentDeclination = std::acosf(camera.aim_.y_);  ///< declination from vertical y-axis
    const float requestedDeclination = currentDeclination - lookUpRads;

    // Clamp the up/down rotation to at most the min/max zenith:
    if(requestedDeclination < zenithMinDeclination)
        lookUpRads = currentDeclination - zenithMinDeclination;
    else if(requestedDeclination > zenithMaxDeclination)
        lookUpRads = currentDeclination - zenithMaxDeclination;

    // Rotate both the "aim" vector and the "up" vector ccw by 
    // lookUpRads radians within their common plane -- which should 
    // also contain the y-axis:  (i.e. no diagonal tilt allowed!)
    camera.aim_.rotateAboutAxis(camera.right_, lookUpRads);
    camera.up_.rotateAboutAxis(camera.right_, lookUpRads);
    ASSERT_ORTHONORMAL(camera.aim_, camera.up_, camera.right_);

    // Rotate both the "aim" and the "up" vector ccw about the vertical y-axis:
    // (again, this keeps the y-axis in their common plane, and disallows diagonal tilt)
    camera.aim_.rotateAboutAxis(Y_AXIS, -lookRightRads);
    camera.up_.rotateAboutAxis(Y_AXIS, -lookRightRads);
    camera.updateRightAxis();

Uwaga:

mouseAxisX i mouseAxisY są zdefiniowane jako +/- 1, w zależności od tego, czy chcesz odwrócić widok myszy osi X lub Y. Zwykle gry oferują tę opcję przynajmniej dla osi pionowej.

MIN_UPWARDS_TILT_DEG jest zdefiniowany jako 1,0 stopnia (więc widz może patrzeć od -89 stopni w dół do +89 stopni w górę, co wygląda całkiem przekonująco jak pełny zakres 180 stopni w pionie - brakujące 2 stopnie na krańcach są dość nieistotne) .

camera.aim_, camera.right_ i camera.up_ to oczywiście wektory 3D, a metodę rotateAboutAxis () można łączyć ze sobą z wikipedii i dowolnej liczby źródeł online. Y_AXIS jest wektorem o stałej stałej (0,1,0).

ASSERT_ORTHONORMAL () to sprawdzanie poprawności wyłącznie w trybie debugowania, które nigdy nie jest kompilowane w trybie zoptymalizowanym / zwolnionym.

Z góry przepraszam za kod w stylu C ... z drugiej strony, tutaj otrzymujesz porady od faceta o imieniu Mediocritus! ; ^)

Mediokryt
źródło
O czym mówisz? Kod w stylu C jest kamieniem węgielnym ducha hakera! 8-)
blissfreak,
5

Jest na to kilka sposobów (zobacz tutoriale tutaj , tutaj i tutaj, na przykład, a wiele innych jest dostępnych w Internecie za pośrednictwem Google). Technologia zastosowana w zasobach, które można znaleźć w Internecie, może się nieznacznie różnić (pod względem D3D, XNA, OpenGL itp.), Ale podstawowe zasady będą takie same:

  • obiekt kamery zachowuje swoją pozycję i kierunek oraz opcjonalnie inną parę wektorów, które wraz z kierunkiem tworzą ortogonalną podstawę układu współrzędnych kamery.
  • publiczny interfejs API kamery ujawnia metody ziewania, pochylania i opcjonalnego obracania kamery wokół jej wektorów podstawowych - czynność dostosowania orientacji kamery spowoduje aktualizację wektorów podstawowych do późniejszego użycia.

Możesz wybrać przechowywanie wektorów bezpośrednio lub ponowne obliczenie podstawowej macierzy widoku za każdym razem, gdy potrzebujesz i wolisz. Ta technika jest bardzo elastyczna, więc jeśli potrzebujesz pomocy poza tymi ogólnymi krokami, możesz opublikować nowe pytanie z bardziej szczegółowym zapytaniem.


źródło
2

Aby uzyskać szczegółowe odniesienie do implementacji systemu kamer wykorzystującego Direct3D, polecam ten artykuł: http://www.toymaker.info/Games/html/camera.html . Autor opisuje także inne metody i funkcje, które można wykorzystać do rozszerzenia implementacji.

Thomas Anthony
źródło