Pivot point dinamico






Molte volte può capitare di dover far ruotare tutto il nostro personaggio intorno ad un punto, e, magari poi farlo ruotare di nuovo intorno ad un altro centro di rotazione, prendiamo l'esempio di un cilindro che si muove in questa maniera:


Image00

E quindi parta da qui(Il locator indica il punto di rotazione):

Image01

Ruoti...

Image02

arrivato qui il suo centro di rotazione si sposti

Image03

ruoti

Image04

cambio

Image05

rotazione

Image06

Naturalmente tutto questo all'interno di una animazione...come fare per modificare il pivot point di un oggetto dinamicamente?

Questa è la semplice costruzione della scena:

Un oggetto(il cilindro), un gruppo parent dell'oggetto, ed un locator(che può essere creato in qualsiasi momento ed in qualsiasi momento eliminato, non è importante che esista sempre, come non è importante che sia un locator, potrebbe essere anche un qualsiasi oggetto della scena).

Il gruppo rappresenta il nostro pivot point animabile, mentre il nostro cilindro avrà il suo pivot point fisso, dove serve a noi per la nostra scena ma sempre fisso.

Ora faremo il tutto in maniera manuale, per capire la tecnica...

Nascondiamo il nostro locator e selezioniamo il gruppo...la posizione del gizmo di rotazione rappresenta il nostro PP(Pivot Point).

Image07

ora ruotiamo

Image08

Benissimo...ora vogliamo spostare il nostro PP, quindi spostiamo il nostro gruppo, naturalmente spostandolo si muoverà anche il cilindro...allora, per avere un punto di riferimento preciso duplico il cilindro, gli applico un materiale trasparente e lo stacco dal gruppo.

Image09

Ora selezioniamo il cilindro e riportiamolo nella posizione che aveva prima

Image10

riselezioniamo il gruppo

Image11

e ruotiamo

Image12

Vi risparmio il seguito...è uguale...sposto il gruppo, rimetto a posto il cilindro, ruoto il gruppo...ecc....

Ho creato un piccolo e semplice script che fa tutto questo per me...devo solo selezionare il parent(cioè il gruppo che faccio ruotare), il o i figli(in questo caso il cilindro) e l'obiettivo(il locator)...

Lo script crea tutti locators che si snappano alle posizioni dei figli, poi muove il gruppo sull'obiettivo e riporta i figli nei punti indicati dai locators creati, cancellandoli subito dopo(i locators, non i figli... :) ).

La procedura di snap funziona in questo modo:

Abbiamo un parallelepipedo (A) e un cilindro ( B ), in posizioni diverse, vogliamo snappare A su B,

Image13

selezioniamo B (quello fisso) e shift+selezione A (quello che si deve muovere)

Image14

Eseguiamo un point constraint con il flag Mantain Offset DESELEZIONATO, ed ecco che il tutto avviene

Image15

Ora nell'outliner basterà selezionare e cancellare il point constraint appena creato

Image16

Un problema sorge quando il nostro oggetto che si deve spostare ha delle keyframes nei campi translate...una volta eliminato il point constraint lui ritorna nella posizione che aveva prima, rendendo inutile il procedimento...allora lo script cosa fa...una volta creato il point constraint, legge i valori nei campi di translate, elimina il point constraint e poi ce li rimette.

In questa maniera anche se l'oggetto è già stato animato e ha delle keyframes, rimane nella posizione che gli abbiamo assegnato.

Vediamo lo script:

/*

    SELEZIONA PARENT, FIGLI, OBIETTIVO

    MUOVE IL PARENT SULL ' OBIETTIVO

    E TUTTI I FIGLI

    IN MODO CHE LA LORO POSIZIONE RIMANGA LA STESSA

*/

prendiamo la selezione corrente, usiamo il flag -l (i nomi lunghi, perchè non so se nella scena ci sono oggetti con lo stesso nome e parent diversi

string $allobjs[] = `ls -sl -l`;

mettiamo in $sz il numero degli elementi selezionati

int $sz = size($allobjs);

string $children[];

il primo è il nostro oggetto che deve snapparsi

string $master = $allobjs[0];

l'ultimo è l'obiettivo

string $moveto = $allobjs[$sz - 1];

tutti gli altri li mettiamo nell'array $children

int $i;

for($i = 0; $i < ($sz - 2); $i++) {

    $children[$i] = $allobjs[$i + 1];

}

creiamo un locator per ogni figlio, e snappiamolo, gli diamo il nome "dummyloc" + il nome del figlio

for($i = 0; $i < ($sz - 2); $i++) {

    string $dummyloc = ("dummyloc_" + $i);

la procedura verrà spiegata in seguito

    LocatorTo($dummyloc,$children[$i]);

}

ora snappiamo il nostro gruppo principale all'obiettivo(spiegazione della procedura in seguito)

PCandDelete($moveto,$master);

snappiamo tutti i figli che presumibilmente si saranno mossi ed eliminiamo uno ad uno tutti i locators creati

for($i = 0; $i < ($sz - 2); $i++) {

    string $dummyloc = ("dummyloc_" + $i);

    PCandDelete($dummyloc,$children[$i]);

    delete $dummyloc;

}

questa procedura crea un locator, lo snappa al figlio e gli da' il nome

proc LocatorTo(string $locName,string $toObj) {

creo un locator all'origine degli assi

    string $loc[] = `spaceLocator -p 0 0 0`;

lo snappo

    PCandDelete($toObj,$loc[0]);

lo rinomino

    rename $loc[0] $locName;

}

Questa è la procedura di snap:

proc PCandDelete(string $master,string $slave) {

creo un point constraint e mi segno il nome

    string $pc[] = `pointConstraint -offset 0 0 0 -weight 1 $master $slave`;

metto in $px, $py e $pz i nuovi valori di translate presi dall'oggetto mosso

    float $px = `getAttr ($slave + ".translateX")`;

    float $py = `getAttr ($slave + ".translateY")`;

    float $pz = `getAttr ($slave + ".translateZ")`;

elimino il point constraint

    delete $pc;

rimetto nell'oggetto mosso i valori che avevo registrato prima, nel caso l'oggetto stesso abbia keyframes e quindi sia ritornato alla sua posizione precedente non appena eliminato il point constraint

    setAttr ($slave + ".translateX") $px;

    setAttr ($slave + ".translateY") $py;

    setAttr ($slave + ".translateZ") $pz;

}



Lo stesso metodo si può utilizzare con l'orient constraint, e tutti e due insieme per un object snap sia della posizione che dell'orientamento, ad esempio quando un personaggio deve prendere un oggetto...cosa che spiegherò in un prossimo tutorial.



Ora un breve esempio di applicazione in una animazione...la stessa iniziale

Cilindro...gruppo...locator...

Image17

settiamo una keyframe a 1 per il gruppo e il cilindro(IMPORTANTE...tutti e due)

spostiamo la timeline su 6 e ruotiamo il gruppo di 90°

Image18

Ora portiamo il locator nella nuova posizione del nostro PP e selezioniamo in quest'ordine: GRUPPO + CILINDRO + LOCATOR

Image19

eseguiamo lo script...niente sembra essere successo, ma se selezioniamo il gruppo, vediamo che il suo PP si è spostato

Image20

settiamo un'altra keyframe a 6 per il gruppo e il cilindro(IMPORTANTE...tutti e due)

spostiamo la timeline su 12 e ruotiamo il gruppo di altri 90° (180°)

settiamo un'altra keyframe a 12 per il gruppo e il cilindro(IMPORTANTE...tutti e due).

Con ancora la selezione dei due oggetti attiva apriamo il graph editor e selezioniamo i valori di traslate poi premiamo il tasto A (che ci renderà visibili tutte le chiavi per quei valori)

Image21

selezioniamo tutto

Image22

e cambiamo le tangenti in 'stepped'

Image23
Image24

questo perchè i cambi di posizione del pivot point devono essere eseguiti in un frame, per rendere invisibile il procedimento

Premiamo play e divertiamoci.

---
Questo articolo è stato importato automaticamente dal forum il 31/lug/2014
Per vedere il post originale e/o i commenti sul forum prima di quella data clicca qui