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:
Zresetuj współrzędne myszy do środka ekranu na każdej klatce, aby mysz nigdy nie została złapana na granicach ekranu
Utrzymaj wektor „w górę” aparatu (nie zezwalaj na przewracanie) i ponownie oblicz wektor „na boki”
Nie zezwalaj na patrzenie w górę poza osią pionową + y lub w dół za osią -y (zbyt daleko w górę / w dół)
Uzyskaj prawidłową kolejność obrotów (najpierw góra / dół, potem lewo / prawo)
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! ; ^)