Drehen Sie einen Vektor

8

Ich möchte, dass meine First-Person-Kamera ihre Blickrichtung reibungslos von Richtung d1 in Richtung d2 ändert. Die letztere Richtung wird durch eine Zielposition t2 angezeigt.

Bisher habe ich eine Drehung implementiert, die gut funktioniert, aber die Geschwindigkeit der Drehung verlangsamt sich, je näher die aktuelle Richtung der gewünschten kommt. Das möchte ich vermeiden.

Hier sind die zwei sehr einfachen Methoden, die ich bisher geschrieben habe:

// this method initiates the direction change and sets the parameter
public void LookAt(Vector3 target) {

        _desiredDirection = target - _cameraPosition;
        _desiredDirection.Normalize();

        _rotation = new Matrix();

        _rotationAxis = Vector3.Cross(Direction, _desiredDirection);

        _isLooking = true;
    }


// this method gets execute by the Update()-method if _isLooking flag is up.
private void _lookingAt() {

        dist = Vector3.Distance(Direction, _desiredDirection);

        // check whether the current direction has reached the desired one.
        if (dist >= 0.00001f) {

            _rotationAxis = Vector3.Cross(Direction, _desiredDirection);
            _rotation = Matrix.CreateFromAxisAngle(_rotationAxis, MathHelper.ToRadians(1));


            Direction = Vector3.TransformNormal(Direction, _rotation);
        } else {

            _onDirectionReached();
            _isLooking = false;
        }
    }

Auch hier funktioniert die Rotation einwandfrei. Kamera erreicht die gewünschte Richtung. Aber die Geschwindigkeit ist im Laufe der Bewegung nicht gleich -> sie verlangsamt sich.

Wie erreicht man eine Rotation mit konstanter Geschwindigkeit?

Marc Wellman
quelle

Antworten:

3
_rotationAxis = Vector3.Cross(Direction, _desiredDirection);
_rotation = Matrix.CreateFromAxisAngle(_rotationAxis, MathHelper.ToRadians(1));

Als Direction& _desiredDirectionWechsel (wie sie konvergieren), Je kleiner die Größe der in fast die gleiche Richtung werden _rotationAxiswird. Es zeigt immer noch in die richtige Richtung, um die Achse zu sein, hat aber eine kürzere Länge. Das ist die Art der Kreuzberechnung.

Die Eingeweide der CreateFromAxisAngleMethode verwenden die Länge der Achse als Faktor für den Rotationsbetrag, zu dem sie führt. Wenn die Achse eine Länge von 1 hat, ergibt sich der richtige Rotationsbetrag.

Wenn Sie also _rotationAxiszwischen den beiden oben zitierten Linien normalisieren würden, würden Sie eine konstante Rotationsrate erhalten.

Steve H.
quelle
6

Ich würde vorschlagen, dass das Framework die gesamte Arbeit für Sie erledigt. Berechnen Sie zunächst eine Rotationsmatrix für Ihre Start- und Endausrichtung und konvertieren Sie beide in Quaternionen. Sie tun dies nur einmal zu Beginn der Bewegung und speichern die Werte.

Matrix start = /* calculate current rotation matrix */;
Matrix end = /* calculate desired rotation matrix */;
Quaternion startQ = Quaternion.CreateFromRotationMatrix(start);
Quaternion endQ = Quaternion.CreateFromRotationMatrix(end);

Interpolieren Sie nun zwischen diesen beiden Orientierungen mithilfe der sphärischen linearen Interpolation. Es gibt eine Methode dafür, damit Sie nichts selbst implementieren müssen:

// Animate the progress parameter between 0 and 1
Quaternion currentQ = Quaternion.Slerp(startQ, endQ, progress);

Berechnen Sie abschließend Ihre Richtung mit dem obigen Quaternion neu oder konvertieren Sie sie zurück in eine Rotationsmatrix. So etwas zum Beispiel:

Vector3 direction = Vector3.Transform(Vector3.Forward, currentQ);
David Gouveia
quelle
Vielen Dank für Ihre ausführliche Beratung! Ich werde das nach dem Mittagessen versuchen;)
Marc Wellman
Quaternion.SlerpIst es nur ich oder klingt das wie ein Name in einem wirklich schlechten oder wirklich guten Fantasy-Roman? Abzüglich des Punktes natürlich.
Fund Monica Klage