Come animare dinamicamente una parte di un modello 3d verso qualcosa


8

Sono curioso di sapere come questo tipo di animazione viene generalmente eseguita in termini di codice.

Alcuni esempi:

  • Un personaggio prende qualcosa - solo la mano viene animata verso il bersaglio http://www.youtube.com/watch?v=rW-7uatehx4 visto dalle 4:50 quando il giocatore prende l'arma.
  • Il personaggio pende da una sporgenza - le mani sono impostate su una posizione specifica (la sporgenza) http://www.youtube.com/watch?v=SOiwArn4Bmw proprio all'inizio.
  • Il personaggio guarda qualcosa - la testa è puntata sul bersaglio (npc guarda il pc)

Risposte:


4

Questo si chiama cinematica inversa. Google è probabilmente il tuo migliore amico su questo in quanto può diventare complesso.


Ho capito, devo calcolare i movimenti necessari per raggiungere la posizione desiderata. In questo caso, calcolerei solo i movimenti per l'osso desiderato.
Gerstmann,

In effetti, la descrizione del video dice "... un sistema di animazione basato interamente sulla cinematica inversa ..."
MichaelHouse

0

Articolo originale: come codificare un sistema IK

A volte l'IK incorporato in Unity non è sufficiente. Ti mostrerò come creare il tuo script IK per Unity. Puoi applicare questo IK a qualsiasi corpo articolato - dita, mani o piedi. L'IK che sto per rivedere è attualmente utilizzato da Unity, Unreal, Panda e molti altri motori di gioco. Si chiama FABRIK.

FABRIK è un metodo iterativo. Un metodo iterativo è un metodo che non ottiene immediatamente la soluzione. Un metodo iterativo si avvicina sempre più alla soluzione corretta con più iterazioni del metodo - in altre parole, iterazioni di un ciclo.

Qualsiasi problema IK ha un determinato corpo articolato (un insieme di arti collegati con lunghezze e angoli). L'effettore finale (la posizione del punto finale dell'arto finale) ha una posizione iniziale con una posizione obiettivo. Potrebbe avere altri obiettivi, come gli angoli.

Ogni iterazione FABRIK ha due parti principali.

void FABRIK() {
    while( abs(endEffectorPosition  goalPosition) > EPS ) {
        FinalToRoot(); // PartOne
        RootToFinal(); // PartTwo
    }
}

La prima parte scorre dall'arto finale all'arto radice. Per l'arto finale, è necessario modificare l'angolazione / rotazione dell'arto in modo che punti alla posizione dell'obiettivo (mantenendo la posizione interna ancorata e lasciando che la posizione esterna sia tradotta dalla variazione dell'angolo). Successivamente, traduci l'arto finale lungo l'angolo aggiornato verso la posizione obiettivo, fino a quando la posizione esterna dell'arto è uguale alla posizione obiettivo (mantenendo l'angolo, ma lasciando che la posizione interna dell'arto cambi). È praticamente tutto per l'arto finale, tranne per il fatto che ora è necessario aggiornare la posizione attuale dell'obiettivo. La posizione attuale dell'obiettivo è ora impostata sulla posizione interna aggiornata dell'arto finale.

Per ogni arto interno consecutivo, fai la stessa cosa. Per essere chiari, lo descriverò. Per l'arto corrente, è necessario modificare l'angolazione / rotazione dell'arto in modo che punti verso la posizione attuale dell'obiettivo. Successivamente, traduci l'arto corrente lungo l'angolo aggiornato verso la posizione attuale dell'obiettivo, fino a quando la posizione esterna dell'arto è uguale alla posizione attuale dell'obiettivo. Infine, aggiorni la posizione obiettivo corrente in modo che sia uguale alla posizione interna aggiornata dell'arto corrente.

Ripeti queste operazioni fino a quando non hai completato queste operazioni sull'arto radice. Successivamente, la prima parte è stata completata.

/* Part One */
void FinalToRoot() {
    currentGoal = goalPosition;
    currentLimb = finalLimb;
    while (currentLimb != NULL) {
        currentLimb.rotation = RotFromTo(Vector.UP,
            currentGoal  currentLimb.inboardPosition);
        currentGoal = currentLimb.inboardPosition;
        currentLimb = currentLimb->inboardLimb;
    }
}

La seconda parte scorre nella direzione opposta: dall'arto della radice all'arto finale. Per l'arto radice, è necessario aggiornare la posizione interna alla posizione radice. Questo dovrebbe tradurre l'intero arto (senza allungare). È praticamente tutto per l'arto radice, tranne per il fatto che ora è necessario aggiornare la posizione interna corrente. L'attuale posizione interna è ora impostata sulla posizione esterna aggiornata dell'arto radice. Per ogni arto esterno consecutivo, fai la stessa cosa. Per essere chiari, lo descriverò. Per l'arto corrente, è necessario aggiornare la sua posizione interna alla posizione interna interna. Questo dovrebbe tradurre l'intero arto. È praticamente tutto per l'arto attuale, tranne per il fatto che ora è necessario aggiornare l'attuale posizione interna. L'attuale posizione interna è ora impostata sulla posizione esterna aggiornata dell'arto corrente.

Ripeti queste operazioni fino a quando non hai completato queste operazioni sull'arto finale. Successivamente, la seconda parte è stata completata.

/* Part Two */
void RootToFinal() {
    currentInboardPosition = rootLimb.inboardPosition;
    currentLimb = rootLimb;
    while (currentLimb != NULL) {
        currentLimb.inboardPosition = currentInboardPosition;
        currentInboardPosition = currentLimb.outboardPosition;
        currentLimb = currentLimb->inboardLimb;
    }
}

Una volta completate la prima parte e la seconda parte, è stata completata la prima iterazione del metodo FABRIK. Continua iterando sulla prima e sulla seconda parte fino a quando l'effettore finale è il più vicino necessario alla posizione obiettivo, definita da alcuni EPS (valore epsilon).

Questo è tutto! Questo è il metodo FABRIK. La prima parte scorre all'indietro dall'arto finale. La seconda parte scorre in avanti dall'arto radice. Il metodo FABRIK scorre la prima e la seconda parte fino a quando l'effettore finale è abbastanza vicino alla posizione dell'obiettivo.

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.