Procedurmodellering med MEL-skript i Maya - Dag 2

Denna handledning är en introduktion till att använda externa MEL-filer och procedurer, funktioner, loopar och skriptad interaktion inom Maya-arbetsytan. Vi ska gå över grundläggande kodningspraxis och sätta ihop ett snyggt geometriskt objekt som skulle vara mycket svårt att skapa utan att skripta.


Ytterligare filer / plugins:
  • Ladda ner Final Script

Skapa procedurer

I denna handledning skapar vi en extern scriptfil med fyra "procedurer" - fristående skript som är avsedda att uppnå specifika mål. Det första förfarandet tar ett antal objekt som valts i Maya-visningsporten och skapar en kedjad hierarki för enkla dubbeltransformationer. Det andra skriptet kommer att välja föremål som inte är förälder, och det tredje kommer att flytta pivotpunkterna för valda objekt till världsrymdens ursprung. Dessa tre skript låter dig enkelt skapa några intressanta effekter med flera objekt. Den fjärde proceduren kommer att kombinera alla de första tre för att skapa en "Fermat's Spiral", som liknar den komplexa whorl som finns på solrosor.


Steg 1

Öppna Maya. För kursen i denna handledning använder jag Maya 2010, men samma kommandon ska fungera för de flesta versioner av Maya. Börja med att skapa en kub i mitten av visningsporten.


Steg 2

Gå till "Edit> Duplicate Special" och klicka på alternativfältet för att få fram den här dialogrutan. Skapa nio kopior.


Steg 3

Gå till "Fönster> Hypergraph Hierarchy". Vi behöver nu föräldra kuberna tillsammans för att skapa en "kedja". För att göra detta, klicka först "pCube2" och skift sedan på "pCube1" och tryck på "p" på tangentbordet. Dessa föräldrar det första valda objektet (pCube2) till det andra valda (pCube1).

Fortsätt med den här processen (välj barnet, sedan föräldern och sedan slå "p" för att kedja ihop dem) för var och en av våra kuber. När det är klart att varje objekt i mitten av hierarkin ska ha en förälder och en barnkub och den övergripande hierarkin ska se ut så här:


Steg 4

Stäng fönstret "Hypergraph Hierarchy". Markera alla objekt genom markering - dra över kuberna mitt i visningsporten. Sedan håller du alla kubor som valts, försök flytta och rotera dem.

Eftersom varje kubs transformationer nu ligger i förhållande till kuben ett steg ovanför i kedjan, ger den resulterande dubbeltransformationen dig möjlighet att flytta kuberna på ett mycket unikt sätt - små översättningar blir snabbt stora förändringar.


Steg 5

Med alla de kuber som fortfarande valts, slår du "Shift-P" på ditt tangentbord till un-parent kuberna. Vi har nu gått igenom alla de stora stegen som vi vill automatisera med vårt manus. Så starta en ny Maya-fil och öppna en textredigerare. Min personliga favorit är Notepad ++, som till och med har ett MEL-språk plugin tillgängligt. Använd gärna vad som helst textredigerare du föredrar, men för närvarande använder jag bra, gammal Microsoft Notepad. Anteckningsblocket är enkelt, men det blir jobbet gjort.


Steg 6

Fortsätt och spara din fil. När du lagrar ett MEL-dokument, se till att du väljer "Alla filer" under "Spara som typ". Spara dokumentet som en .mel-fil i mappen Maya-skript. Jag använder EdW_DoubleTransform.mel som mitt filnamn.


Steg 7

För att skapa ett förfarande måste du veta ett par saker på förhand. Först måste du definiera en "räckvidd" för proceduren. Omfattning fastställs där ett förfarande kan nås från. En "lokal" räckvidd innebär att koden endast är tillgänglig för andra procedurer inom samma .mel-fil. "Global" betyder att förfarandet är tillgängligt för andra skriptfiler och användaren, och laddas också i minnet. I allmänhet använder jag många globala förfaranden. Detta är inte den absoluta bästa kodningspraxis, men jag gillar att få mina procedurer tillgängliga över flera skript. För det andra måste du välja ett namn för ditt förfarande. I allmänhet försöker du välja något unikt och beskrivande - om proceduren är global vill du inte att namnet står i konflikt med något annat förfarande i något annat skript. Jag brukar jobba med några typ av initialer i namnet, och eftersom skriptet vi skriver kallas "DoubleTransform", kommer jag att gå med "dt" i det här fallet. Vid det mest grundläggande är detta det förfarande vi bygger:

 global proc dt_makeParentChain () // handlingar av manuset;

Steg 8

Det första vi gör med vårt förfarande är att definiera en variabel som så småningom kommer att innehålla en lista över objektnamn. I MEL anges variabler med ett dollar-tecken ($) före variabelnamnet. Det finns flera olika typer av data som en variabel kan innehålla - strängar av text, heltal som heter heltal, flytande punkts decimaler, vektorvärden etc. Syntaxen för att deklarera en variabel är följande:

 dataType $ variableName;

För närvarande gör vi en tom strängvariabel:

 sträng $ selectedObjects;

Om vi ​​vill kan vi också tilldela data till variabeln i samma kodlinje. Dubbel citat används för att definiera textsträngar.

 sträng $ selectedObjects = "detta är en textsträng";

ett enda lika tecken betyder "ställa in variabeln till". Ett dubbelt lika tecken betyder "är lika med" och används vid jämförelse av variabler.


Steg 9

För att testa vår nya variabel behöver vi lägga till en utskriftskommando. Detta kommer att mata ut en sträng till Script Editor när man kör skriptet. I det här fallet skriver vi helt enkelt innehållet i variabeln '$ selectedObjects'.

 skriv ut $ selectedObjects;

Steg 10

Lägg till en kommentar till ditt nya förfarande. Jag brukar lägga till en kommentar före varje förfarande så att jag snabbt kan hitta dem senare. Några av mina skript har dussintals procedurer, och kommentarer gör processen med att felsöka och ändra kod mycket enklare. Den fullständiga koden ska nu se ut så här:

 // Gör moderkedjan global proc dt_makeParentChain () string $ selectedObjects = "detta är en textsträng"; skriv ut $ selectedObjects; ;

Steg 11

Spara filen och gå tillbaka till Maya. När Maya först startar, skannar det skriptkatalogen och laddar en lista över alla filer där. Om du har lagt till ett skript i katalogen medan Maya redan är öppet, vet systemet inte att filen finns. I det här fallet har du två alternativ, antingen starta om Maya eller du kan använda kommandot "rehash" för att tvinga Maya att uppdatera den lista med filer. Vi använder den andra metoden, så gå till "Window> General Editors> Script Editor", skriv följande:

 uppkok;

Klicka nu på 'Ctrl-Enter' för att köra kommandot.


Steg 12

För att testa ditt skript måste du "initialisera" det i Maya. Kommandot "rehash" berättar för Maya att filen existerar, och kommandot "Source" berättar för Maya att ladda skriptet i minnet. Skriv följande i skriptredigeraren:

 källan EdW_DoubleTransform.mel;

Skriv sedan kommandot för proceduren som vi skapade i skriptet:

 dt_makeParentChain;

Det här är vad du ska få i manusredigeraren efter att ha kört proceduren:


Steg 13

Nu när vi har sammanställt ett fungerande förfarande, låt oss räkna ut pseudokoden för vad vi vill ha den proceduren att göra i vårt sista skript:

  • skriv en lista med valda objekt till en variabel
  • få antalet valda objekt
  • förälder varje objekt till föregående i listan

Steg 14

För att få en lista över objekten som valts i Maya-visningsporten, använd kommandot "ls". Listan brukar användas med en flagga som berättar kommandot att ta tag i vad som för närvarande är valt i Maya-visningsporten, -sl. Prova att välja några objekt i maya viewporten och skriv hela kommandot (visas nedan) i skriptredigeraren, kom ihåg att slå 'Ctrl-Enter' för att köra kommandot.

 ls -sl;

Steg 15

Listkommandot matar ut ett gäng strängar som representerar den fullständiga listan över valda objekt. För att göra denna information användbar för oss, måste vi skriva resultatet av "list" -kommandot till en variabel. För att göra detta, lägg in listkommandot i kryssmarkeringar (Obs, kryssmarkeringen, även kallad backquote, ligger vanligen ovanför flikknappen på tangentbordet ... var noga med att inte använda single-quote-markeringen bredvid Enter-tangent). Wrapping ett kommando i tick-markeringar översätts som "utgången från". Vårt befäl bör nu se ut så här:

 sträng $ selectedObjects = 'ls -sl';

Steg 16

Variabeln $ selectedObjects är en enda textsträng. Vad vi verkligen behöver är något som kallas en strängmatris - en ordnad lista över strängar som finns i en enda variabel. För att göra strängen till en strängmatris, använd fyrkantiga parenteser när deklarerar variabeln:

 sträng $ selectedObjects [] = 'ls -sl';

Nu, när vi hänvisar till variabeln, kan vi antingen använda hela arrayen:

 $ selectedObjects // alla strängarna i arrayen

... Eller en enskild sträng inuti matrisen genom att tillhandahålla ett index - positionen för strängen vi vill ha inom själva matrisen. Indexvärdena i MEL börjar alltid vid noll som visas nedan:

 skriv ut $ selectedObjects [0]; // returnerar den första strängen i arrayutskriften $ selectedObjects [2]; // returnerar den tredje strängen i arrayen

Steg 17

Vi behöver också ett sätt att räkna ut hur många objekt som finns i matrisen. Du kan använda kommandot "size" för att göra just det. Låt oss skapa en ny variabel för att lagra den här informationen. Ett heltal representeras av ett heltal, vilket alltid refereras till i MEL som en "int":

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

Steg 18

Nu behöver vi ett sätt att förälska varje objekt enligt dess plats i matrisen. Det finns en handfull sätt att göra detta, men för närvarande använder vi en grundläggande "för" -slinga. För-loopar är vanliga vid programmering som ett sätt att göra en åtgärd ett antal gånger. Syntaxen för en för-loop som körs tio gånger är detta:

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

Slingstrukturen har tre delar. $ i = 0 definierar en heltal variabel, $ i

 för ($ i = 0; $ i < $numSelectedObjects; $i++)  //action to be performed ;

Steg 19

Vi behöver nu använda kommandot "förälder" för att skapa hierarkikedjan. Syntaxen för det här kommandot är som följer:

 föräldrabarnObject parentObject;

Så i vårt fall skulle moderkommandot vara:

 för ($ i = 1; $ i < $numSelectedObjects; $i++)  parent $selectedObjects[(i-1)] $selectedObjects[i]; ;

Steg 20

Med vår slinga klar måste vi avmarkera det sista objektet i urvalet, med kommandot "select" med "avmarkera" flaggan. För att beräkna indexet för det sista objektet som valts tar vi det totala antalet objekt, och eftersom indexet för valfri array i Maya börjar vid 0, subtraherar 1.

 välj -markera $ selectedObjects [($ numSelectedObjects - 1)];

Steg 21

Och med det är vår första procedur nu klar:

 // Gör moderkedjan global proc dt_makeParentChain () string $ selectedObjects [] = 'ls -sl'; int $ numSelectedObjects = 'size ($ selectedObjects)'; för ($ i = 1; $ i < $numSelectedObjects; $i++)  parent $selectedObjects[($i - 1)] $selectedObjects[$i]; ; select -deselect $selectedObjects[($numSelectedObjects - 1)]; ;

Steg 22

Under 'dt_makeParentChain', skapa ett nytt förfarande för att inte använda de valda objekten. Koden nedan föräldrar de markerade objekten till världen, vilket är detsamma som att de inte föräldrar dem.

 global proc dt_unParentSelected () parent -w; ;

Steg 23

Vår tredje procedur automatiserar processen för att flytta ett objekts pivotpunkt till ursprunget. Precis som tidigare börjar vi med att skapa rutinerna:

 global proc dt_pivotToOrigin () // proceduråtgärder;

Steg 24

Vi använder sedan samma teknik som i det första förfarandet för att skriva en lista över de valda objekten till en variabel:

 sträng $ selectedObjects [] = 'ls -sl';

Steg 25

Vi behöver nu lägga till en slinga. Medan vi kunde använda samma sorts för-loop som i det första skriptet, låt oss använda en för-varje sling istället. En "för-varje" -slinga är en specialiserad version av för-loop som exekverar en gång för varje värde i en array. Det låter dig också skriva en variabel som representerar det aktuella indexvärdet. Syntaxen ser ut så här:

 för ($ vardera i $ arrayVariable) // gör denna åtgärd med $ each;

$ Varje variabel innehåller värdet av det aktuella indexet för matrisen. För vårt skript är det här koden ska se ut:

 för ($ thisObj i $ selectedObjects) // flytta pivot av $ thisObj;

Samma teknik kan användas för att automatisera eventuella maya-kommandon för valfritt antal utvalda objekt.


Steg 26

Med hjälp av variabel $ thisObj kan vi nu välja det objekt som för närvarande tittas på genom slingan:

 välj -r $ thisObj;

Steg 27

För att flytta pivoten till ursprunget kan vi använda kommandot "xform" och återställa flaggan -rp (rotatePivot) och -sp (scalePivot) till 0 på X, Y och Z-axeln:

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

Steg 28

Huvudkomponenterna i skriptet är nu färdiga, och din kod, som innehåller alla tre procedurer, ska se ut så här:

 // Gör moderkedjan global proc dt_makeParentChain () string $ selectedObjects [] = 'ls -sl'; int $ numSelectedObjects = 'size ($ selectedObjects)'; för ($ 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; ; ;

Steg 29

Vi kommer nu att skapa en fjärde procedur som kommer att använda de föregående tre för att skapa en intressant geometrisk progression som heter "Fermat's Spiral", som bygger på vinkelförhållandet mellan Golden Ratio, phi. Det är en form som vanligen finns i naturen, och det följer alla typer av intressanta geometriska regler. Låt oss börja med att skriva ut pseudokoden:

  • skapa en sfär
  • skapa 1000 kopior
  • föräldrakedja alla sfärer
  • flytta objekten i x-axeln
  • flytta alla sfärens svängpunkter till ursprunget
  • rotera sfärer i Y 137,5 grader (Golden Angle)

Steg 30

Så, till att börja med, låt oss skapa en ny rutinbeskrivning:

 global proc dt_fermatSpiral () 

Steg 31

Nu ska vi skapa en sfär med 8 radial och 8 höjdavdelningar, och skriv de resulterande transformations- och formnodderna till en strängmatris så att vi kan hålla reda på dem. De flesta kommandon som skapar geometri matar ut två strängar - namnet på transformationsnoden, och namnet på formnoden. För det mesta vill du arbeta med transkriptionssträngen, som kommer att lagras i [0] -indexet i variabeln $ seedSphere array som skapas nedan:

 sträng $ seedSphere [] = 'polySphere -x 8 -sy 8';

Steg 32

Vi ska nu skapa en tom stränggruppsvariabel:

 sträng $ allSpheres [];

Steg 33

Öppna sedan en för-loop som kör 1000 gånger:

 för ($ i = 1; $ i<1000; $i++)

Steg 34

Vi behöver nu duplicera vår nyskapade sfär och skriv de resulterande transformations- och formnodarna till en variabel:

 sträng $ duplicatedSphere [] = 'duplicate';

Steg 35

Här lägger vi namnet på vår duplicerade transformationsnod till slutet av $ allSpheres-arrayen. Du kan använda kommandot "storlek" för att bestämma hur många objekt som redan finns i matrisen och använd resultatet som index för vårt nya värde.

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

Steg 36

Här väljer vi alla de skapade sfärerna och kör kommandot för föräldrakedjan som vi tidigare skapat:

 välj -r $ allSpheres; dt_makeParentChain;

Steg 37

Efter att du har föräldra samman sfärerna, väljer vi dem igen och flyttar dem alla .05 i X med "move" -kommandot:

 välj -r $ allSpheres; flytta 0,05 0 0;

Steg 38

När vi har återställt ursprungspositionen med vårt tidigare skapade "pivotToOrigin" -procedur väljer vi sfärerna en sista gång och roterar dem 137,5 grader i Y. Med det gjort, kör vårt otillgängliga script:

 dt_pivotToOrigin; välj -r $ allSpheres; rotera 0 137,5 0; dt_unParentSelected;

Steg 39

Och det avslutar vårt slutförfarande. Så, vårt fullständiga skript borde se ut så här:

 // Gör moderkedjan global proc dt_makeParentChain () string $ selectedObjects [] = 'ls -sl'; int $ numSelectedObjects = 'size ($ selectedObjects)'; för ($ 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; ;

Steg 40

Och med det är vi färdiga! Spara skriptet och kör igen processen "rehash" / "source" som beskrivs ovan. Skriv sedan in följande kommando i Mayas scriptredigerare, tryck 'Ctrl-Enter' och vänta några sekunder:

 dt_fermatSpiral ();

Och där har du Fermats spiral, konstruerad helt och hållet med MEL. Prova att spela med olika vinklar, former och transformationer i slutproceduren - du kan få alla typer av intressanta mönster!


Denna handledning är dag 2 i en serie - Gå till dag 1.