Ruota un vettore


8

Voglio che la mia fotocamera in prima persona cambi facilmente la direzione di visione dalla direzione d1 alla direzione d2. Quest'ultima direzione è indicata da una posizione target t2.

Finora ho implementato una rotazione che funziona bene ma la velocità della rotazione rallenta quanto più la direzione corrente arriva a quella desiderata. Questo è ciò che voglio evitare.

Ecco i due metodi molto semplici che ho scritto finora:

// 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;
        }
    }

Ancora una volta, la rotazione funziona bene; la fotocamera raggiunge la direzione desiderata. Ma la velocità non è uguale nel corso del movimento -> rallenta.

Come ottenere una rotazione a velocità costante?

Risposte:


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

Come Directione _desiredDirectionmodifica essere rivolto quasi nella stessa direzione (che convergono), minore è la grandezza di _rotationAxissarà. Punterà comunque nella direzione corretta per essere l'asse, ma avrà una lunghezza inferiore. Questa è la natura del calcolo incrociato.

Le viscere del CreateFromAxisAnglemetodo usano la lunghezza dell'asse come fattore della quantità di rotazione che provoca. Quando l'asse ha una lunghezza di 1, risulta la corretta quantità di rotazione.

Quindi, se dovessi normalizzare _rotationAxistra le due linee che ho citato sopra, otterrai una velocità di rotazione costante.


6

Suggerirei di lasciare che il framework faccia tutto il lavoro per te. Inizia calcolando una matrice di rotazione per gli orientamenti iniziale e finale e convertili entrambi in quaternioni. Lo fai solo una volta all'inizio del movimento e memorizzi i valori.

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

Ora interpolate tra questi due orientamenti usando l'interpolazione lineare sferica. C'è un metodo per farlo, quindi non devi implementare nulla tu stesso:

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

Infine ricalcola la tua direzione usando il quaternione sopra o convertilo nuovamente in una matrice di rotazione. Qualcosa del genere, ad esempio:

Vector3 direction = Vector3.Transform(Vector3.Forward, currentQ);

Grazie mille per i consigli dettagliati! Lo proverò dopo pranzo;)
Marc Wellman,

Quaternion.SlerpSono solo io, o suona come un nome in un romanzo fantasy davvero brutto o davvero buono? Meno il punto, ovviamente.
Finanzi la causa di Monica il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.