Vai al contenuto
chick

Mel Tutorial

Recommended Posts

In questa parte analizzeremo 4 script MEL un po' più complessi di quelli visti fino ad ora, e sicuramente più utili. Questi script possono essere usati come base per crearne di ancora più complessi, ovviamente!!!

INSTANCER

Questo primo script genera un certo numero di istanze di un qualsiasi oggetto e le posiziona su di una superficie NURBS.

$numDuplicati = 100;

$nomeSuperf = "Superficie";

$nomeOggetto = "Template";

$prefissoIstanza = "Istanza";

$nomeGruppo = "Istanze";


group -n $nomeGruppo -empty;


for ($i=0; $i<$numDuplicati; $i++)

	{

	$UPos = rand(0,1);

	$VPos = rand(0,1);

	$pos = `pointOnSurface -u $UPos -v $VPos -p $nomeSuperf`;

	instance -n ($prefissoIstanza + $i) $nomeOggetto;

	move $pos[0] $pos[1] $pos[2] ($prefissoIstanza + $i);

	rotate 0 (rand(0, 360)) 0 ($prefissoIstanza + $i); 

	parent ($prefissoIstanza + $i) $nomeGruppo;

	}
Le prime righe dello script definiscono semplicemente il numero di istanze, il nome della superficie NURBS su cui verranno posizionate, il nome dell'oggetto da istanziare e il prefisso che avranno le istanze. Le istanze verranno poi messe tutte in un gruppo, di cui possiamo cambiare il nome. Il resto dello script è abbastanza semplice: come prima cosa creiamo un gruppo vuoto (-empty) con il nome scelto. Poi abbiamo un ciclo for che ripete le operazioni per $numDuplicati volte. Come prima cosa prendiamo due numeri random tra 0 e 1. A questo punto usiamo pointOnSurface, un'utilissima funzione che ci può dare informazioni su di un punto di una superficie NURBS. In questo caso diciamo di restituirci la posizione del punto usando –p. Per identificare il punto passiamo, con –u e –v, le sue coordinate U e V che sono i due numeri random che abbiamo trovato prima. Quindi in pratica con queste tre righe troviamo le coordinate di un punto a caso sulla superficie. NOTA: questo script funziona solo se le coordinate UV della superficie vanno da 0 a 1. In caso contrario basta usare rebuild surface con Keep NumSpans attivato e Parameter Range : 0 to 1. Usiamo quindi il comando instance per creare un istanza del nostro oggetto e con move la spostiamo sulla superficie. pointOnSurface restituisce un array di 3 elementi quindi useremo [] per accedere alle tre coordinate del punto. Quindi ruotiamo il punto sull'asse y di un numero a caso di gradi. Ovviamente si potrebbe fare lo stesso per gli altri due assi. Infine spostiamo l'istanza appena creata nel gruppo, usando il comando parent (che si usa con questa sintassi: parent nomeoggetto nomegruppo). Ecco un paio di immagini fatte con questo script. Un paesaggio con alberi colline.jpg Una sfera ricoperta di sfere sfere.jpgNOISE Questo script sposta casualmente i punti di un oggetto poligonale, dando un'effetto di "noise" sulla forma dell'oggetto stesso.
string $sel[] = `ls -selection`;

string $obj;

float	 $minX = 0.0, $maxX = 0.1,

	$minY = 0.0, $maxY = 0.1,

	$minZ = 0.0, $maxZ = 0.1;


for ($obj in $sel)

	{

	$numVert = `polyEvaluate -vertex $obj`;


	for ($v=0; $v<$numVert[0]; $v++)

		{

		$movX = rand($minX, $maxX);

		$movY = rand($minY, $maxY);		

		$movZ = rand($minZ, $maxZ);	


		$vertex = $obj + ".vtx[" + $v + "]";

		move -r $movX $movY $movZ $vertex;

		}

	}
Questo script agisce sugli oggetti selezionati, quindi come prima cosa andiamo a mettere nell'array $sel i nomi degli oggetti nella selezione che otteniamo con il comando ls. A questo punto usiamo un ciclo for…in per guardare uno a uno gli oggetti della selezione: per ogni oggetto troviamo il numero di vertici usando polyEvaluate. Questa funzione può essere usata per avere molte informazioni su di un oggetto poligonale. Anche se in questo caso chiediamo solo un'informazione (il numero di vertici) la funzione restituisce comunque un array, perché in teoria potremmo richiedere anche altre cose nella stessa chiamata, quindi poi dovremo usare $numVert[0] per sapere l'attuale numero di vertici. A questo punto, per ogni vertice generiamo tre numeri casuali, entro i limiti che abbiamo stabilito sopra, che saranno gli spostamenti sui tre assi. Infine usiamo il comando move per muovere il vertice. Quando vogliamo accedere ad un componente di un oggetto, dobbiamo usare l'operatore punto. Ad esempio, per accedere ad un vertice scriviamo: nomeoggetto.vtx[numero del vertice] La riga :
vertex = $obj + ".vtx[" + $v + "]";
crea una stringa fatta in quel modo: mette il nome dell'oggetto, poi un punto, poi vtx, e tra parentesi quadre il numero del vertice che stiamo spostando. Questa stringa viene "data in pasto" a move per muovere i vertici. Ecco un esempio di oggetto processato con questo script (con qualche altra piccola modifica successiva ;) ) donut.jpgROPE Questo script crea una corda che segue il percorso di una curva. Qui andiamo un po' più sul difficile… ma don't worry! Vi spiego tutto qui sotto!!!
$numTurns = 30;

$numPointsPerTurn = 4;

$nomeCurva = "curva";

$numFili = 3;

$raggioFilo = 0.2;


$turnStep = 1.0/$numPointsPerTurn;


for ($f=0; $f<$numFili; $f++)

	{

	float $t = (float)$numPointsPerTurn/(float)$numFili*$f;


	$cmd = "curve -d 3";


	for ($i=0.0; $i<=1.0; $i+=(1.0/($numPointsPerTurn*$numTurns)))

		{

		$pos = `pointOnCurve -pr $i -top 1 -position $nomeCurva`;

		$tan = `pointOnCurve -pr $i -top 1 -tangent $nomeCurva`;	

		circle -nr $tan[0] $tan[1] $tan[2] -c $pos[0] $pos[1] $pos[2] -r 0.5 -n TempCircle;


		$cp =  `pointOnCurve -pr ($turnStep*$t) -top 1 -position TempCircle`;

		delete TempCircle;


		$cmd += " -p " + $cp[0] + " " + $cp[1] + " " + $cp[2];


		$t+=(float)$numPointsPerTurn/(float)$numFili;


		if ($t == $numPointsPerTurn)

			$t = 0;

		}


	$cmd += " -n path" + $f;


	eval $cmd;


	circle -n ("profilo" + $f) -r $raggioFilo;


	extrude -et 2 -upn 1 -fpt 1 -ucp 1 ("profilo" + $f) ("path" + $f);

	}
La corda viene generata creando un certo numero di curve che "girano" attorno alla curva profilo e poi estrudendo un cerchio su queste curve. Come al solito all'inizio abbiamo i parametri: il numero di giri della corda, il numero di punti che le varie curve avranno per ogni giro, il nome della curva-profilo, il numero dei fili e il loro raggio. E adesso arriva il bello… tutto il processo è rinchiuso in un ciclo for che ripete il processo di creazione di un filo $numFili volte. Il comando importante di questo script è pointOnCurve, che è molto simile a pointOnSurface che abbiamo visto nello script Instancer. Usiamo questo comando varie volte per trovare informazioni sulle varie curve. Per pointOnSurface passavamo le coordinate UV del punto sulla superficie, mentre qui passiamo un parametro che va da 0 a 1 e identifica i punti dall'inizio alla fine della curva. È importante usare il parametro –top 1 (cioè turnOnPercentage) che normalizza i parametri della curva e quindi ci permette di usare numeri da 0 a 1. Quindi ad esempio con:
pointOnCurve -top 1 -pr 0.6 -position
troveremo la posizione del punto al 60% della curva (notare che la curva deve avere i CV equispaziati perché questo funzioni correttamente). Per trovare i punti delle curve-profilo dei fili potremmo usare strane formule matematiche… ma useremo invece un trucchetto: per ogni punto creeremo un cerchio attorno alla nostra curva principale, orientato come la normale in quel punto, e useremo pointOnCurve per trovare la posizione di un punto attorno a questa curva. Ad ogni passaggio useremo un punto più in là nel cerchio, in modo da "girare" attorno alla curva. Queste due righe trovano la posizione e la tangente di un punto sulla curva principale
$pos = `pointOnCurve -pr $i -top 1 -position $nomeCurva`;

$tan = `pointOnCurve -pr $i -top 1 -tangent $nomeCurva`;
Il parametro del punto ($i) è un valore che va da 0 a 1 e viene incrementato dal ciclo for di 1/numero di punti ad ogni ciclo. In questo modo arriveremo alla fine della curva in un numero di cicli uguale al numero di punti (e quindi le curve dei fili avranno il corretto numero di punti). Il numero di punti è uguale al numero di giri moltiplicato per il numero di punti per ogni giro. Dopo aver trovato la tangente e la posizione del punto, creiamo in quel punto un cerchio orientato secondo la tangente della curva. Poi usiamo nuovamente pointOnCurve per trovare un punto su questo cerchio:
$cp =  `pointOnCurve -pr ($turnStep*$t) -top 1 -position TempCircle`;
In questo caso il parametro è uguale a $turnStep * $t. $turnStep è uguale a 1 / numero di punti per giro, mentre $t è una variabile che viene aumentata di numero di punti per giro / numero di fili. In questo modo i nostri fili saranno equispaziati sul cerchio e ad ogni giro ci sposteremo di un angolo opportuno a seconda del numero di punti per ogni giro. Per creare la curva usiamo:
curve -d 3 -p x1 y1 z1 -p x2 y2 z2 … -p xN yN zN  -n nome
il parametro -d definisce il grado della curva, e i vari -p sono le coordinate dei punti. Costruiamo questo comando aggiungendo un pezzo alla volta alla variabile $cmd. Notare che $cmd è semplicemente una stringa che contiene questo comando, quindi NON viene eseguita! Per eseguirla usiamo un utilissimo comando che è eval. Questo "valuta" ed esegue una stringa che contenga istruzioni MEL. Infine creiamo un cerchio e lo estrudiamo sulla curva creata:
extrude -et 2 -upn 1 -fpt 1 -ucp 1 ("profilo" + $f) ("path" + $f);
I parametri sono: -et 2 : extrude type, 2 sta per tube -upn 1 : use profile normal, in modo che la superficie segua la normale del profilo -fpt 1 : fixed path, in modo che la superficie sia messa sulla curva -ucp 1 : use component pivot Questo è un esempio del risultato rope.jpgLIGHT DOME Uno script che crea una light dome attorno alla scena.
$pi = 3.1415;

$complexity = 10;

$domeRad = 20.0;

$intensity = 0.02;

float $colorStart[3] = {0.2, 0.8, 0.8};

float $colorEnd[3] = {0.8, 0.2, 0.2};


group -empty -n dome;

$num = 0;

for ($y=0; $y<$complexity; $y++)

	{

	$perc = (float)$y/(float)$complexity;


	$rad = $domeRad * cos(($pi/2)*$perc);

	for ($x=0.0; $x<2*$pi; $x+=(2*$pi/$complexity))

		{

		pointLight -pos ($rad*sin($x)) ($y*($domeRad/$complexity)) ($rad*cos($x))

			-i $intensity -rgb ($colorStart[0] * (1.0-$perc) + $colorEnd[0] * $perc)

			($colorStart[1] * (1.0-$perc) + $colorEnd[1] * $perc)

			 ($colorStart[2] * (1.0-$perc) + $colorEnd[2] * $perc) -n ("point"+$num);

		parent ("point"+$num) dome;

		$num++;

		}

	}

Lo script è piuttosto semplice a patto di ricordarsi un po' di trigonometria.

Al solito, definiamo un po' di parametri:

$pi è semplicemente pi greco, $complexity è il numero di luci per ogni "cerchio" della dome, $domeRad è il raggio, $intensity è l'intensità della singola point e colorStart e colorEnd sono i colori delle luci in basso (colorStart) e in cima alla dome (colorEnd).

In pratica creiamo un numero (uguale a $complexity) di livelli con un cerchio di luci.

Il ciclo for con $x aumenta $x di 2*pi (=360 gradi) / numero di luci per cerchio.

Le coordinate delle luci saranno sin(x) e cos(x) per quanto riguarda x e z, mentre per y andiamo a calcolare la percentuale dell'altezza a cui siamo (nella variabile $perc) e ci alziamo della stessa % del raggio. Il raggio dei cerchi va inoltre mano a mano diminuendo.

NOTA: sin e cos vogliono l'angolo in radianti, non in gradi! È per questo che bisogna usare pi greco.

Per quanto riguarda il colore delle luci facciamo semplicemente un'interpolazione lineare con la coordinata y. Se quindi siamo al 60% dell'altezza il colore sarà 40% del colore iniziale + 60% di quello finale.

Ed ecco il risultato in Maya…

dome.JPG

… e in render

sfere2.jpg

E questo è tutto anche per questa parte del tutorial!

Nella prossima parte analizzeremo le espressioni.

Alla prossima!!!

post-1-1146237454.jpg

Condividi questo messaggio


Link al messaggio
Condividi su altri siti

Grazie dei complimenti, fanno sempre piacere! :)

@mapomac: Il MEL l'ho imparato completamente da autodidatta... pero' c'e' da dire che sapendo usare C/C++ la cosa e' mooolto piu' facile. Certo, se alla Alias (anzi ormai Autodesk) si decidessero a fare una documentazione un pochino piu' umana...

@Shinji: il tutorial sulle espressioni e' gia' tutto nella mia mente... devo solo scriverlo! LOL

Condividi questo messaggio


Link al messaggio
Condividi su altri siti

Chick, sono shockato...e mi pento sempre di non capire una mazza di programmazione e scripts in generale.

Complimenti e grazie. Stai rendendo un servizio davvero molto utile.

Condividi questo messaggio


Link al messaggio
Condividi su altri siti

Bel tutorial, inoltre il primo script è proprio quello che serve a me.

Ho un bicchiere e voglio realizzarci sopra le goccioline d'acqua (brina).

Il problema è che il bicchiere è una mesh poligonale ...... come faccio?

Mi date una mano.

Premetto che di programmazione ne capisco abbastanza conoscendo PHP, Sql, VB, Javascript ........ mi manca il mel ma da una prima occhiata come sintassi è molto simile al php.

Condividi questo messaggio


Link al messaggio
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora


  • Navigazione recente   0 utenti

    Non ci sono utenti registrati da visualizzare in questa pagina.

×