Wie soll ich eine First-Person-Kamera implementieren?

12

Ich bin ein Anfängerprogrammierer und erstelle ein Projekt, mit dem ich mit einer First-Person-Kamera durch Räume laufen kann. Bisher habe ich die Gebäude gezeichnet, aber jetzt stecke ich fest und weiß nicht, wie ich eine Ego-Kamera machen soll, damit ich herumlaufen kann.

Könnte mich jemand auf eine Kameraklasse hinweisen, die ich verwenden könnte, oder auf einen nützlichen Code?

DK10
quelle
Sehen
Archmede

Antworten:

7

Hier sind einige Tipps zum Drehen der Kamera (Mausblick). Nachdem ich eine Kameraklasse von Grund auf neu implementiert hatte, musste ich ein paar zusätzliche Änderungen vornehmen, um ein gutes Drehverhalten zu erzielen:

  1. Setzen Sie die Mauskoordinaten in jedem Frame auf die Bildschirmmitte zurück, damit die Maus nicht an den Bildschirmrändern hängen bleibt

  2. Behalten Sie den Aufwärtsvektor der Kamera bei (Rollverbot) und berechnen Sie den Seitwärtsvektor neu

  3. Blick nach oben über die vertikale + y-Achse oder nach unten über die -y-Achse nicht zulassen (zu weit oben / unten)

  4. Richtige Reihenfolge der Umdrehungen (zuerst hoch / runter, dann links / rechts)

  5. Renormieren Sie die Vektoren "up", "aim" und "sideways" für jeden Frame

Hoffentlich können Sie einen Teil dieses Codes zu Ihrem Vorteil nutzen:

    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();

Beachten Sie, dass:

mouseAxisX und mouseAxisY sind mit +/- 1 definiert, abhängig davon, ob die X- oder Y-Achse des Mauszeigers invertiert werden soll. Normalerweise bieten Spiele diese Option zumindest für die vertikale Achse an.

MIN_UPWARDS_TILT_DEG ist mit 1,0 Grad definiert (der Betrachter darf also von -89 Grad nach unten bis +89 Grad nach oben schauen, was ziemlich überzeugend wie ein voller vertikaler 180-Grad-Bereich aussieht - die fehlenden 2 Grad an den Extremen sind vernachlässigbar). .

camera.aim_, camera.right_ und camera.up_ sind natürlich 3D-Vektoren und die rotateAboutAxis () -Methode, die Sie aus Wikipedia und einer beliebigen Anzahl von Online-Quellen zusammenfügen können. Y_AXIS ist ein Vektor mit fester Konstante (0,1,0).

ASSERT_ORTHONORMAL () ist eine reine Fehlerprüfung im Debug-Modus, die niemals im optimierten / Release-Modus kompiliert wird.

Entschuldigen Sie sich im Voraus für den C-Style-Code ... aber auch hier werden Sie von einem Typen namens Mediocritus beraten! ; ^)

Mediocritus
quelle
Worüber redest du? C-Style-Code ist der Eckpfeiler des Hackergeistes! 8-)
blissfreak
5

Es gibt verschiedene Möglichkeiten, dies zu tun (siehe Tutorials hier , hier und hier, zum Beispiel mit vielen weiteren Möglichkeiten, die über Google im Internet verfügbar sind). Die in den online verfügbaren Ressourcen verwendete Technologie kann geringfügig variieren (in Bezug auf D3D, XNA, OpenGL usw.), die zugrunde liegenden Prinzipien werden jedoch dieselben sein:

  • Ihr Kameraobjekt behält seine Position und seine Richtung sowie optional ein weiteres Vektorpaar bei, das neben der Richtung eine orthogonale Basis für das Koordinatensystem der Kamera bildet.
  • Die öffentliche API Ihrer Kamera zeigt Methoden zum Gieren, Neigen und optionalem Rollen der Kamera um ihre Basisvektoren an. Durch Anpassen der Kameraausrichtung werden die Basisvektoren für die spätere Verwendung aktualisiert.

Sie können die Vektoren entweder direkt speichern oder die zugrunde liegende Ansichtsmatrix bei Bedarf und nach Belieben neu berechnen. Die Technik ist sehr flexibel. Wenn Sie also Hilfe benötigen, die über diese allgemeinen Schritte hinausgeht, möchten Sie möglicherweise eine neue Frage mit einer genaueren Abfrage stellen.


quelle
2

Für einen konkreten Verweis auf eine Implementierung eines Kamerasystems mit Direct3D empfehle ich diesen Artikel: http://www.toymaker.info/Games/html/camera.html . Der Autor beschreibt auch andere Methoden und Funktionen, die zur Erweiterung der Implementierung verwendet werden können.

Thomas Anthony
quelle