Comment dois-je implémenter une caméra à la première personne?

12

Je suis un programmeur débutant et je crée un projet qui me permet de me promener dans les pièces via une caméra à la première personne. Jusqu'à présent, j'ai dessiné les bâtiments, mais maintenant je suis coincé et je ne sais pas comment faire un appareil photo à la première personne pour me permettre de me promener.

Quelqu'un pourrait-il me diriger vers une classe d'appareil photo que je pourrais utiliser, ou un code utile?

DK10
la source
Découvrez ceci learnopengl.com/#!Getting-started/Camera
Archmede

Réponses:

7

Voici quelques conseils sur la rotation de la caméra (mouselook). Après avoir implémenté naïvement une classe de caméra à partir de zéro, j'ai trouvé que je devais faire quelques ajustements supplémentaires pour un bon comportement en rotation:

  1. Réinitialisez les coordonnées de la souris au centre de l'écran sur chaque image, afin que la souris ne se coince jamais sur les bordures de l'écran

  2. Maintenir le vecteur "up" de la caméra (interdire le roulement) et recalculer le vecteur "sideways"

  3. Interdit de regarder vers le haut au-delà de l'axe vertical + y, ou vers le bas au-delà de l'axe -y (trop haut / bas)

  4. Obtenez l'ordre des rotations correct (haut / bas d'abord, puis gauche / droite)

  5. Renormaliser les vecteurs "haut", "viser" et "latéralement" à chaque image

J'espère que vous pourrez utiliser une partie de ce code à votre avantage:

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

Notez que:

mouseAxisX et mouseAxisY sont définis comme étant +/- 1, selon que vous souhaitez inverser le regard de la souris sur les axes x ou y. Habituellement, les jeux offrent cette option au moins pour l'axe vertical.

MIN_UPWARDS_TILT_DEG est défini comme étant de 1,0 degré (de sorte que le spectateur est autorisé à regarder de -89 degrés vers le bas à +89 degrés vers le haut, ce qui ressemble de manière assez convaincante à une plage verticale complète de 180 degrés - les 2 degrés manquants aux extrêmes sont assez négligeables) .

camera.aim_, camera.right_ et camera.up_ sont bien sûr des vecteurs 3D, et la méthode rotationAboutAxis () vous permet de bricoler à partir de wikipedia et de nombreuses sources en ligne. Y_AXIS est un vecteur constant constant (0,1,0).

ASSERT_ORTHONORMAL () est une vérification d'esprit uniquement en mode débogage, qui n'est jamais compilée en mode optimisé / de libération.

Toutes mes excuses à l'avance pour le code de style C ... encore une fois, ici, vous suivez les conseils d'un gars nommé Mediocritus! ; ^)

Médiocrite
la source
Qu'est-ce que tu racontes? Le code de style C est la pierre angulaire de l'esprit des hackers! 8-)
blissfreak
5

Il y a plusieurs façons de procéder (voir les tutoriels ici , ici et ici par exemple, avec beaucoup plus disponibles sur Internet via Google). La technologie utilisée dans les ressources que vous pouvez trouver en ligne peut varier légèrement (en termes de D3D, XNA, OpenGL, et cetera), mais les principes sous-jacents seront les mêmes:

  • votre objet caméra conserve sa position et sa direction, et éventuellement une autre paire de vecteurs qui, à côté de la direction, forment une base orthogonale pour le système de coordonnées de la caméra.
  • L'API publique de votre caméra expose les méthodes de lacet, de tangage et, éventuellement, de rouler la caméra autour de ses vecteurs de base - le fait d'ajuster l'orientation de la caméra mettra à jour les vecteurs de base pour une utilisation ultérieure.

Vous pouvez choisir de stocker les vecteurs directement ou recalculer la matrice de vue sous-jacente à chaque fois, selon vos besoins et vos préférences. Il y a beaucoup de flexibilité dans la technique, donc si vous avez besoin d'aide au-delà de ces étapes générales, vous voudrez peut-être publier une nouvelle question avec une requête plus spécifique.


la source
2

Pour une référence spécifique à une implémentation d'un système de caméra utilisant Direct3D, je recommande cet article: http://www.toymaker.info/Games/html/camera.html . L'auteur décrit également d'autres méthodes et fonctionnalités qui peuvent être utilisées pour développer l'implémentation.

Thomas Anthony
la source