Modellazione procedurale con MEL Scripts in Maya - Day 2

Questo tutorial è un'introduzione all'utilizzo di file MEL esterni e procedure, funzioni, loop e interazione con script all'interno dell'area di lavoro di Maya. Esamineremo le pratiche di codifica di base e metteremo insieme un oggetto geometrico elegante che sarebbe molto difficile da creare senza scripting.


File / plugin aggiuntivi:
  • Scarica lo script finale

Creazione di procedure

In questo tutorial, creeremo un file di script esterno con quattro "procedure": script autosufficienti pensati per raggiungere obiettivi specifici. La prima procedura richiederà un numero qualsiasi di oggetti selezionati nella vista Maya e creerà una gerarchia concatenata per facili trasformazioni doppie. Il secondo script separerà gli oggetti selezionati e il terzo sposterà i punti di rotazione degli oggetti selezionati sull'origine dello spazio del mondo. Questi tre script ti permetteranno di creare facilmente alcuni effetti interessanti con più oggetti. La quarta procedura combinerà tutti i primi tre per creare una 'Spirale di Fermat', simile alla spirale complessa trovata sulle teste di girasole.


Passo 1

Apri Maya. Per il corso di questo tutorial, userò Maya 2010, ma gli stessi comandi dovrebbero funzionare per la maggior parte delle versioni di Maya. Inizia creando un cubo al centro della finestra.


Passo 2

Vai su "Modifica> Duplica speciale" e fai clic sulla casella di opzione per visualizzare questa finestra di dialogo. Crea nove copie.


Passaggio 3

Vai a 'Finestra> Gerarchia Hypergraph'. Ora dobbiamo raggruppare i cubi per creare una "catena". Per fare ciò, prima fai clic su "pCube2", quindi fai clic su "pCube1" e premi "p" sulla tastiera. Genera il primo oggetto selezionato (pCube2) al secondo selezionato (pCube1).

Continua questo processo (selezionando il bambino, poi il genitore e poi colpendo "p" per incatenarli insieme) per ciascuno dei nostri cubi. Una volta completato, ogni oggetto nel mezzo della gerarchia dovrebbe avere un genitore e un cubo figlio e la gerarchia complessiva dovrebbe assomigliare a questa:


Passaggio 4

Chiudere la finestra 'Gerarchia Hypergraph'. Seleziona tutti gli oggetti per selezione trascinando sopra i cubi nel mezzo del viewport. Quindi, mantenendo tutti i cubetti selezionati, prova a muoverli ea ruotarli.

Poiché le trasformazioni di ogni cubo sono ora relative al cubo di un gradino sopra la catena, la doppia trasformazione risultante consente di spostare i cubi in un modo molto particolare - le piccole traduzioni diventano rapidamente grandi cambiamenti.


Passaggio 5

Con tutti i cubi ancora selezionati, premi "Maiusc-P" sulla tastiera per separare i cubi. Ora abbiamo analizzato tutti i principali passaggi che vogliamo automatizzare con il nostro script. Quindi avvia un nuovo file Maya e apri un editor di testo. Il mio preferito è Notepad ++, che ha anche un plugin per la lingua MEL disponibile. Sentiti libero di usare qualsiasi editor di testo che preferisci, ma per ora userò il buon vecchio Blocco note di Microsoft. Blocco note è semplice, ma ottiene il lavoro svolto.


Passaggio 6

Vai avanti e salva il tuo file. Quando si salva un documento MEL, assicurarsi di selezionare "Tutti i file" sotto "salva come tipo". Salva il documento come file .mel nella directory degli script Maya. Userò EdW_DoubleTransform.mel come nome del mio file.


Passaggio 7

Per creare una procedura, devi conoscere un paio di cose in anticipo. Innanzitutto, è necessario definire un "ambito" per la procedura. Scope stabilisce da dove è possibile accedere a una procedura. Un ambito "locale" significa che il codice è accessibile solo ad altre procedure all'interno dello stesso file .mel. "Globale" significa che la procedura è disponibile per altri file di script e per l'utente e viene anche caricata in memoria. In generale, utilizzo molte procedure globali. Questa non è la migliore pratica di codifica in assoluto, ma mi piace avere le mie procedure disponibili su più script. Secondo, devi scegliere un nome per la tua procedura. In generale, prova a scegliere qualcosa di unico e descrittivo: se la procedura è globale, non vuoi che il nome sia in conflitto con altre procedure in qualsiasi altro script. Solitamente inserisco alcune iniziali nel nome e poiché lo script che stiamo scrivendo si chiama "DoubleTransform", in questo caso andrò con "dt". Al suo livello più semplice, questa è la procedura che stiamo costruendo:

 global proc dt_makeParentChain () // azioni dello script;

Passaggio 8

La prima cosa che faremo con la nostra procedura è definire una variabile che alla fine ospiterà un elenco di nomi di oggetti. In MEL, le variabili sono denotate da un segno di dollaro ($) prima del nome della variabile. Esistono diversi tipi di dati che una variabile può contenere: stringhe di testo, numeri interi chiamati numeri interi, numeri decimali in virgola mobile, valori vettoriali, ecc. La sintassi per la dichiarazione di una variabile è la seguente:

 dataType $ variableName;

Per ora, creeremo una variabile stringa vuota:

 stringa $ selectedObjects;

Se vogliamo, possiamo anche assegnare dati alla variabile nella stessa riga di codice. Le virgolette sono usate per definire stringhe di testo.

 string $ selectedObjects = "questa è una stringa di testo";

un singolo segno di uguale significa "imposta la variabile su". Un doppio segno di uguale significa "è uguale a" e viene utilizzato quando si confrontano le variabili.


Passaggio 9

Per testare la nostra nuova variabile, dobbiamo aggiungere un comando di stampa. Ciò produrrà una stringa allo Script Editor quando viene eseguito lo script. In questo caso, stiamo semplicemente stampando il contenuto della variabile '$ selectedObjects'.

 stampa $ selectedObjects;

Passaggio 10

Aggiungi un commento alla tua nuova procedura. Tendo ad aggiungere un commento prima di ogni procedura, in modo che possa trovarli rapidamente in seguito. Alcuni dei miei script hanno dozzine di procedure e commenti rendono molto più facile il processo di debugging e modifica del codice. Il codice completo dovrebbe ora apparire come questo:

 // Crea catena globale proc dt_makeParentChain () string $ selectedObjects = "questa è una stringa di testo"; stampa $ selectedObjects; ;

Passaggio 11

Salva il file e torna a Maya. Ogni volta che Maya si avvia per la prima volta, analizza la directory degli script e carica un elenco di tutti i file presenti. Se hai aggiunto uno script alla directory mentre Maya è già aperto, il sistema non sa che il file esiste. In questo caso hai due opzioni, riavvia Maya, oppure puoi usare il comando "rehash" per forzare Maya ad aggiornare quell'elenco di file. Useremo il secondo metodo, quindi vai a 'Finestra> General Editors> Script Editor', digita quanto segue:

 rimaneggiamento;

Ora premi "Ctrl-Invio" per eseguire il comando.


Passaggio 12

Per testare il tuo script, dovrai "inizializzarlo" in Maya. Il comando "rehash" dice a maya che il file esiste, e il comando "source" dice a Maya di caricare lo script in memoria. Digitare quanto segue nell'editor di script:

 fonte EdW_DoubleTransform.mel;

Quindi, digita il comando per la procedura che abbiamo creato all'interno dello script:

 dt_makeParentChain;

Questo è ciò che dovresti ottenere nell'editor di script dopo aver eseguito la procedura:


Passaggio 13

Ora che abbiamo messo insieme una procedura funzionante, vediamo lo pseudocodice per ciò che vogliamo che la procedura faccia nel nostro script finale:

  • scrivere una lista di oggetti selezionati su una variabile
  • ottieni il numero di oggetti selezionati
  • genitore ogni oggetto al precedente nell'elenco

Passaggio 14

Per ottenere un elenco degli oggetti selezionati nella vista Maya, utilizzare il comando list, "ls". L'elenco viene in genere utilizzato con un flag che indica al comando di catturare qualsiasi cosa sia attualmente selezionata nella vista di maya, -sl. Prova a selezionare alcuni oggetti nella finestra di maya e digita il comando completo (mostrato sotto) nell'editor di script, ricorda di premere 'Ctrl-Invio' per eseguire il comando.

 ls -sl;

Passaggio 15

Il comando list genera un gruppo di stringhe che rappresentano l'elenco completo degli oggetti selezionati. Per rendere queste informazioni utili a noi, dobbiamo scrivere il risultato del comando "lista" su una variabile. Per fare ciò, racchiudi il comando list in tick-marks (Nota, il segno di spunta, chiamato anche backquote, si trova di solito sopra il tasto tab sulla tastiera ... assicurati di non usare il segno di virgoletta singolo accanto al tasto Invio). Il wrapping di un comando in tick-marks si traduce come "l'output di". Il nostro comando dovrebbe ora assomigliare a questo:

 string $ selectedObjects = 'ls -sl';

Passaggio 16

La variabile $ selectedObjects è una singola stringa di testo. Ciò di cui abbiamo veramente bisogno è qualcosa chiamato string array: un elenco ordinato di stringhe contenute in una singola variabile. Per rendere la nostra stringa in una matrice di stringhe, utilizzare le parentesi quadre quando si dichiara la variabile:

 string $ selectedObjects [] = 'ls -sl';

Ora, ogni volta che ci riferiamo alla variabile, possiamo usare l'intero array:

 $ selectedObjects // tutte le stringhe nella matrice

... O una singola stringa all'interno della matrice, fornendo un indice - la posizione della stringa che vogliamo all'interno della matrice stessa. I valori dell'indice in MEL iniziano sempre da zero come mostrato di seguito:

 stampa $ selectedObjects [0]; // restituisce la prima stringa nell'array print $ selectedObjects [2]; // restituisce la terza stringa nell'array

Passaggio 17

Avremo anche bisogno di un modo per capire quanti oggetti ci sono nell'array. Puoi usare il comando "size" per fare proprio questo. Creiamo una nuova variabile per memorizzare queste informazioni. Un numero intero è rappresentato da un numero intero, a cui si fa sempre riferimento in MEL come "int":

 int $ numSelectedObjects = 'size ($ selectedObjects)';

Passaggio 18

Ora abbiamo bisogno di un modo per genificare ciascun oggetto in base alla sua posizione nell'array. Ci sono alcuni modi per farlo, ma per ora useremo un ciclo "for" di base. I loop for-end sono comuni nella programmazione come un modo per fare un'azione un certo numero di volte. La sintassi di un ciclo for che viene eseguito dieci volte è questa:

 for (int $ i = 0; $ i < 9; $i++) //action to be done ;

La struttura del ciclo ha tre parti. $ i = 0 definisce una variabile intera, $ i

 per ($ i = 0; $ i < $numSelectedObjects; $i++)  //action to be performed ;

Passaggio 19

Ora dobbiamo usare un comando "genitore" per creare la catena gerarchica. La sintassi per questo comando è la seguente:

 genitore childObject parentObject;

Quindi nel nostro caso, il comando genitore sarebbe:

 per ($ i = 1; $ i < $numSelectedObjects; $i++)  parent $selectedObjects[(i-1)] $selectedObjects[i]; ;

Passaggio 20

Con il nostro ciclo completato, ora dobbiamo deselezionare l'ultimo oggetto nella selezione, usando il comando "seleziona" con il flag "deseleziona". Per calcolare l'indice dell'ultimo oggetto selezionato, prendiamo il numero totale di oggetti, e quindi, poiché l'indice di qualsiasi matrice in Maya inizia da 0, sottrai 1.

 select -deselect $ selectedObjects [($ numSelectedObjects - 1)];

Passaggio 21

E con questo, la nostra prima procedura è ora completa:

 // Crea catena globale proc dt_makeParentChain () string $ selectedObjects [] = 'ls -sl'; int $ numSelectedObjects = 'size ($ selectedObjects)'; per ($ i = 1; $ i < $numSelectedObjects; $i++)  parent $selectedObjects[($i - 1)] $selectedObjects[$i]; ; select -deselect $selectedObjects[($numSelectedObjects - 1)]; ;

Passaggio 22

Sotto "dt_makeParentChain", crea una nuova procedura per annullare la selezione degli oggetti selezionati. Il codice seguente raggruppa gli oggetti selezionati nel mondo, che è lo stesso di quelli non parentali.

 global proc dt_unParentSelected () parent -w; ;

Passaggio 23

La nostra terza procedura automatizzerà il processo di spostamento del punto di rotazione di un oggetto all'origine. Proprio come prima, iniziamo creando il profilo della procedura:

 global proc dt_pivotToOrigin () // procedure actions;

Passaggio 24

Quindi usiamo la stessa tecnica della prima procedura per scrivere una lista degli oggetti selezionati su una variabile:

 string $ selectedObjects [] = 'ls -sl';

Passaggio 25

Ora dobbiamo aggiungere un ciclo. Mentre potremmo usare lo stesso tipo di ciclo for nel primo script, usiamo invece un ciclo for-each. Un ciclo "for-each" è una versione specializzata del ciclo for che viene eseguita una volta per ciascun valore in un array. Permette anche di scrivere una variabile che rappresenti il ​​valore dell'indice corrente. La sintassi ha questo aspetto:

 for ($ each in $ arrayVariable) // fai questa azione con $ each;

$ Ogni variabile contiene il valore dell'indice corrente dell'array. Per il nostro script, questo è come dovrebbe apparire il codice:

 for ($ thisObj in $ selectedObjects) // sposta il pivot di $ thisObj;

Questa stessa tecnica può essere utilizzata per automatizzare qualsiasi comando maya per qualsiasi numero di oggetti selezionati.


Passaggio 26

Usando la variabile $ thisObj possiamo ora selezionare l'oggetto che si sta attualmente cercando dal loop:

 seleziona -r $ thisObj;

Passo 27

Per spostare il pivot all'origine, possiamo usare il comando "xform" e ripristinare i flag -rp (rotatePivot) e -sp (scalePivot) su 0 sull'asse X, Y e Z:

 xform -ws -rp 0 0 0 -sp 0 0 0;

Passaggio 28

I componenti principali dello script sono ora finiti e il tuo codice, che contiene tutte e tre le procedure, dovrebbe apparire come questo:

 // Crea catena globale proc dt_makeParentChain () string $ selectedObjects [] = 'ls -sl'; int $ numSelectedObjects = 'size ($ selectedObjects)'; per ($ i = 1; $ i < $numSelectedObjects; $i++)  parent $selectedObjects[($i - 1)] $selectedObjects[$i]; ; select -deselect $selectedObjects[($numSelectedObjects - 1)]; ; // Un-Parent Objects global proc dt_unParentSelected() parent -w; ; // Move Pivot to Origin global proc dt_pivotToOrigin() string $selectedObjects[] = 'ls -sl'; for($thisObj in $selectedObjects) select -r $thisObj; xform -ws -rp 0 0 0 -sp 0 0 0; ; ;

Passaggio 29

Ora creeremo una quarta procedura che userà le tre precedenti per creare un'interessante progressione geometrica chiamata "Fermat's Spiral", che si basa sulla relazione angolare del Golden Ratio, phi. È una forma che si trova comunemente in natura e segue tutti i tipi di regole geometriche interessanti. Iniziamo scrivendo lo pseudocodice:

  • creare una sfera
  • creare 1.000 copie
  • parent-chain tutte le sfere
  • sposta gli oggetti sull'asse x
  • sposta i punti di rotazione di tutte le sfere sull'origine
  • ruotare le sfere in Y 137,5 gradi (l'angolo d'oro)

Passaggio 30

Quindi, per cominciare, creiamo un nuovo schema di procedura:

 global proc dt_fermatSpiral () 

Passaggio 31

Ora creeremo una sfera con 8 divisioni radiali e 8 di altezza e scriveremo i nodi di trasformazione e forma risultanti in un array di stringhe in modo che possiamo tenerne traccia. La maggior parte dei comandi che creano geometrie emettono due stringhe: il nome del nodo di trasformazione e il nome del nodo di forma. Per la maggior parte, si desidera lavorare con la stringa del nodo di trasformazione, che verrà memorizzata nell'indice [0] nella variabile di matrice $ seedSphere creata di seguito:

 string $ seedSphere [] = 'polySphere -sx 8 -sy 8';

Passo 32

Ora creeremo una variabile di stringa vuota:

 string $ allSpheres [];

Passaggio 33

Quindi apri un ciclo for che viene eseguito 1.000 volte:

 per ($ i = 1; $ i<1000; $i++)

Passaggio 34

Ora dobbiamo duplicare la nostra sfera appena creata e scrivere i nodi di trasformazione e forma risultanti in una variabile:

 string $ duplicatedSphere [] = 'duplicate';

Passaggio 35

Qui, aggiungiamo il nome del nostro nodo di trasformazione duplicato alla fine dell'array $ allSpheres. È possibile utilizzare il comando "size" per determinare quanti oggetti ci sono già nell'array e utilizzare il risultato come indice per il nostro nuovo valore.

 $ allSpheres [size ($ allSpheres)] = $ duplicatedSphere [0];

Passaggio 36

Qui selezioniamo tutte le sfere create ed eseguiamo il comando parent chain creato in precedenza:

 seleziona -r $ allSpheres; dt_makeParentChain;

Passaggio 37

Dopo aver unito le sfere insieme, le selezioniamo nuovamente e le spostiamo tutte a 0,05 in X usando il comando "sposta":

 seleziona -r $ allSpheres; sposta 0.05 0 0;

Passaggio 38

Dopo aver ripristinato la posizione di origine usando la nostra procedura "pivotToOrigin" creata in precedenza, selezioniamo le sfere un'ultima volta, e le ruotiamo di 137,5 gradi in Y. A tale scopo, esegui il nostro script unparent:

 dt_pivotToOrigin; seleziona -r $ allSpheres; ruota 0 137,5 0; dt_unParentSelected;

Passaggio 39

E questo completa la nostra procedura finale. Quindi, il nostro script completo dovrebbe assomigliare a questo:

 // Crea catena globale proc dt_makeParentChain () string $ selectedObjects [] = 'ls -sl'; int $ numSelectedObjects = 'size ($ selectedObjects)'; per ($ i = 1; $ i < $numSelectedObjects; $i++)  parent $selectedObjects[($i - 1)] $selectedObjects[$i]; ; select -deselect $selectedObjects[($numSelectedObjects - 1)]; ; // Un-Parent Objects global proc dt_unParentSelected() parent -w; ; // Move Pivot to Origin global proc dt_pivotToOrigin() string $selectedObjects[] = 'ls -sl'; for($thisObj in $selectedObjects) select -r $thisObj; xform -ws -rotatePivot 0 0 0 -scalePivot 0 0 0; ; ; //Create Fermat's Spiral of Spheres global proc dt_fermatSpiral() string $seedSphere[] = 'polySphere -sx 8 -sy 8'; string $allSpheres[]; for ($i=1; $i<1000; $i++) string $duplicatedSphere[] = 'duplicate'; $allSpheres[size($allSpheres)] = $duplicatedSphere[0]; ; select -r $allSpheres; dt_makeParentChain; select -r $allSpheres; move 0.05 0 0; dt_pivotToOrigin; select -r $allSpheres; rotate 0 137.5 0; dt_unParentSelected; ;

Passaggio 40

E con quello abbiamo finito! Salvare lo script ed eseguire nuovamente il processo 'rehash' / 'source' come descritto sopra. Quindi inserisci il seguente comando nell'editor di script di Maya, premi "Ctrl-Invio" e attendi qualche secondo:

 dt_fermatSpiral ();

Ed ecco la Fermat's Spiral, costruita interamente con MEL. Prova a giocare con diversi angoli, forme e trasformazioni nella procedura finale: puoi ottenere tutti i tipi di modelli interessanti!


Questo tutorial è il giorno 2 di una serie: vai al giorno 1.