Landreth’s FK Spine

Anatomisch correcte spine

Op de DVD “The making of Ryan” vertelt Chris Landreth ons persoonlijk aan de hand van een skelet hoe het anatomisch gesteld is met onze spine.

Van belang zijn de drie zones van de spine; het lage gedeelte (lumbar-spine), het middelste gedeelte (thoracle-spine) en het bovenste gedeelte, de nek (cervical-spine). Dan de hoeveelheid wervels, de lumbar-spine telt er 5 (L1 t/m L5),de thoracle-spine 12 (T1 t/m T12) en de cervical-spine 7 (C1 t/m C7).

Om geheel anatomisch te werken wordt elke wervel een joint, dus als ik de nek even niet meereken kom ik op 17 joints.  Ik kom in de praktijk op 18 omdat de eerste joint het heiligbeen is, wat statisch is.

Chris Landreth

Chris Landreth was ten tijde van de 1e release van Maya (1998) in dienst bij Alias|Wavefront met de opdracht een filmpje te maken, wat een goed idee zou geven van de nieuwe software. Dat filmpje werd “Bingo” (the clowno), de opvolger van “The End”, eveneens een promotiefilm voor software. De short “Ryan” (2004) is in eigen beheer gemaakt, hij won er de Oscar voor best animated short mee.

Bewegingsanalyse

  • Als we naar voren buigen (rotate Z), buigt het lumbar-gedeelte van de wervelkolom evenveel als het thoracle gedeelte. De bewegingsvrijhijd vooruit is circa 60 graden, naar achteren circa 30 graden, verdeeld  fifty-fifty over lumbar en thoracle.
  • Proberen we te twisten (rotate X), dan is zowel de lumbar als de thoracle vrij stijf. Het lage gedeelte van de thoracle heeft de meeste bewegingsvrijheid, wervels T10, T11 en T12 nemen het grootste gedeelte van de beweging voor hun rekening.
  • Lateral flexion, opzij buigen (rotate Y) geeft een meer gelijk verdeelde beweging, hoewel er in T10 t/m 12 iets meer beweging zit.

Setup

  • Gebruik de Joint Tool en teken de spinejoints tot aan het nekgedeelte. Gebruik een side-view en gebruik het plaatje als Image Plane. Positioneer de rug zo dat de positieve Z naar voren wijst. Zet de eerste joint op het bot onder de L5-wervel opde plaats van het heiligbeen, dit wordt de root-joint, die traditioneel ongemoeid gelaten wordt.

Overbodig zo langzamerhand te noemen, is het geven van de correcte namen;

spineJoint1, spineJoint2 etc. Hoewel er ook iets voor te zeggen is om de echte namen te gebruiken, L1_Joint, L2_Joint.. is dat niet helemaal praktisch, vooral omdat de nummering precies tegengesteld is aan onze nummering. In het voorbeeld laat ik deze stap achterwege, zodat de namen beginnen bij joint1 (root)en eindigen bij joint18.

Om deze rig te maken, is spline-IK niet zo geschikt, het geeft te weinig precisie. In plaats daarvan gebruiken we een methode die ik de “gewogen rotatie” noem. Deze methode gebruik ik bijvoorbeeld ook voor vingers en tentakels.

Oriëntatie van de joints


  • Daarvoor gaan we naar component-mode en klikken op het vraagtekentje bij selectie-types. Nu worden de local axis van de joints zichtbaar. Voor de rig is het belangrijk dat ze allemaal hetzelfde staan, en om verdere verwarrring te voorkomen, zetten we de assen  zo neer dat X naar boven wijst en  Y naar de voorkant van de spine en de Z allemaal naar 1 zijkant.
  • In de toolbar rechtsboven is een invoerveld, zet deze van selection naar relative input. Selecteer met de Rotatetool een van de local axises die niet goed staat.
  • Voer nu getallen in als 180 0 0 om de as 90 graden over X te draaien, of 0 -90 om -90 graden over Y te draaien.
  • Werk steeds in eenheden van 90 graden, zodat de globale oriëntatie van de joint goed blijft.Zorg dat alle joints goed staan.

Tip:

In plaats van 180 0 0 mag je ook alleen 180 invullen, bij een rotatie 0 90 0 mag je volstaan met 0 90

Primary control

De volgende stap is aanbrengen en plaatsen van een control-object.

  • Een curve van de letter S voldoet  prima. Plaats deze aan de bovenkant achter de spine. Clean het object door een center pivot , overbodige groepen eruit te gooien, delete historyen als laatste een freeze transform. Noem deze control spineCTRL.
  • We gebruiken alleen de rotaties, daarom gaan we naar Channel Control en halen alles weg behalve de rotaties.

Oriëntatie van de spineCTRL

Hier zit een gemeen addertje onder het gras. Het jointsysteem  van Maya laat elke joint met x-as naar de volgende wijzen. In het geval van de spine wijzen ze allemaal naar boven. In het worldsysteem wijst de Y-as naar boven. Wanneer ik een logische rig wil bouwen zal ik of de joints Y-up moeten maken, of mijn controlobject X-up. Ooit koos ik voor het eerste, maar dat had wel als consequentie, dat ik altijd en overal de oriëntatie van de joints moest veranderen. Het controlobject X-up maken lijkt toch eenvoudiger.

Maar nu het volgende probleem: wanneer ik de local axis verander zodat x omhoog wijst, krijg ik rotatiewaarden in de transformnode.  Het is absoluut van belang dat de beginwaarden 0 zijn van de rotaties, de rig moet ten allen tijde naar  defaultwaarden te resetten zijn, bij voorkeur 0 met rotaties.

Oplossing:

  • Groep spineCTRL, center pivot en noem deze spineCTRLgrp.
  • Geef spineCTRLGrp rotateX=90 en rotateZ=90
  • Nu staat de S verkeerd, roteer de CV’s naar de gewenste stand

Eigenlijk hadden we al een groep nodig voor het vastmaken van het controlobject aan de spine. Dat wordt nu een groep boven spineCTRLgrp:

  • Het is de bedoeling dat hetcontrol-object steeds mee beweegt met de spine. Groep spineCTRLgrp in zichzelf (ctrl-g), en doe een center pivot. Noem deze groep spineCTRLconstrain.
  • Selecteer de onderste joint en selecteer spineCTRLconstrain erbij.
  • Doe nu Animation->Constraints-> Parent Constrain.

Secondary control

We hebben een tweede control-object  nodig. Hierin komen de rotatie-gewichten in  te staan. Deze control wordt vantevoren ingesteld en hoeft normaal gesproken niet meer getweaked te worden tijdens de animatie. De control is daarom onzichtbaar en niet voor de animator bedoeld.

  • We maken een Null-transform met Create-> empty group. Rename deze naar spineWeight.
  • Ga naar Channel Control en haal alle keyable attributes weg.
  • We maken nieuwe attributes met Modify->Add Attribute. Het type zetten we op vector. Vul bij name weight2 in en druk op add. In de channelbox verschijnen Weight2 X, Weight2 Y en Weight2 Z.
  • Maak nu voor elke joint een weight-attribute, behalve voor de eerste, deze joint doet niet mee, vandaar dat mijn telling bij weight2 begint.

Connectie

Nu kunnen we de boel aan elkaar vastmaken. De rotaties van de joints moeten gestuurd worden door spineCTRL en de mate waarin ze bewegen wordt bepaald in spineWeight.

Voor dit alles volstaat een simpele expressie:

joint2.rotateX = spineWeight.weight2X * spineCTRL.rotateX;
joint2.rotateY = spineWeight.weight2Y * spineCTRL.rotateY;
joint2.rotateZ = spineWeight.weight2Z * spineCTRL.rotateZ;

Open de Expression – Editor en maak voor elke joint deze expressie. Hiermee is de rig voor 90 % klaar.

Je kunt de onderstaande tekst copy-pasten, wanneer je naamgeving hetzelfde is gebleven als dit voorbeeld:

joint2.rotateX = spineWeight.weight2X * spineCTRL.rotateX;
joint2.rotateY = spineWeight.weight2Y * spineCTRL.rotateY;
joint2.rotateZ = spineWeight.weight2Z * spineCTRL.rotateZ;
joint3.rotateX = spineWeight.weight3X * spineCTRL.rotateX;
joint3.rotateY = spineWeight.weight3Y * spineCTRL.rotateY;
joint3.rotateZ = spineWeight.weight3Z * spineCTRL.rotateZ;
joint4.rotateX = spineWeight.weight4X * spineCTRL.rotateX;
joint4.rotateY = spineWeight.weight4Y * spineCTRL.rotateY;
joint4.rotateZ = spineWeight.weight4Z * spineCTRL.rotateZ;
joint5.rotateX = spineWeight.weight5X * spineCTRL.rotateX;
joint5.rotateY = spineWeight.weight5Y * spineCTRL.rotateY;
joint5.rotateZ = spineWeight.weight5Z * spineCTRL.rotateZ;
joint6.rotateX = spineWeight.weight6X * spineCTRL.rotateX;
joint6.rotateY = spineWeight.weight6Y * spineCTRL.rotateY;
joint6.rotateZ = spineWeight.weight6Z * spineCTRL.rotateZ;
joint7.rotateX = spineWeight.weight7X * spineCTRL.rotateX;
joint7.rotateY = spineWeight.weight7Y * spineCTRL.rotateY;
joint7.rotateZ = spineWeight.weight7Z * spineCTRL.rotateZ;
joint8.rotateX = spineWeight.weight8X * spineCTRL.rotateX;
joint8.rotateY = spineWeight.weight8Y * spineCTRL.rotateY;
joint8.rotateZ = spineWeight.weight8Z * spineCTRL.rotateZ;
joint9.rotateX = spineWeight.weight9X * spineCTRL.rotateX;
joint9.rotateY = spineWeight.weight9Y * spineCTRL.rotateY;
joint9.rotateZ = spineWeight.weight9Z * spineCTRL.rotateZ;
joint10.rotateX = spineWeight.weight10X * spineCTRL.rotateX;
joint10.rotateY = spineWeight.weight10Y * spineCTRL.rotateY;
joint10.rotateZ = spineWeight.weight10Z * spineCTRL.rotateZ;
joint11.rotateX = spineWeight.weight11X * spineCTRL.rotateX;
joint11.rotateY = spineWeight.weight11Y * spineCTRL.rotateY;
joint11.rotateZ = spineWeight.weight11Z * spineCTRL.rotateZ;
joint12.rotateX = spineWeight.weight12X * spineCTRL.rotateX;
joint12.rotateY = spineWeight.weight12Y * spineCTRL.rotateY;
joint12.rotateZ = spineWeight.weight12Z * spineCTRL.rotateZ;
joint13.rotateX = spineWeight.weight13X * spineCTRL.rotateX;
joint13.rotateY = spineWeight.weight13Y * spineCTRL.rotateY;
joint13.rotateZ = spineWeight.weight13Z * spineCTRL.rotateZ;
joint14.rotateX = spineWeight.weight14X * spineCTRL.rotateX;
joint14.rotateY = spineWeight.weight14Y * spineCTRL.rotateY;
joint14.rotateZ = spineWeight.weight14Z * spineCTRL.rotateZ;
joint15.rotateX = spineWeight.weight15X * spineCTRL.rotateX;
joint15.rotateY = spineWeight.weight15Y * spineCTRL.rotateY;
joint15.rotateZ = spineWeight.weight15Z * spineCTRL.rotateZ;
joint16.rotateX = spineWeight.weight16X * spineCTRL.rotateX;
joint16.rotateY = spineWeight.weight16Y * spineCTRL.rotateY;
joint16.rotateZ = spineWeight.weight16Z * spineCTRL.rotateZ;
joint17.rotateX = spineWeight.weight17X * spineCTRL.rotateX;
joint17.rotateY = spineWeight.weight17Y * spineCTRL.rotateY;
joint17.rotateZ = spineWeight.weight17Z * spineCTRL.rotateZ;
joint18.rotateX = spineWeight.weight18X * spineCTRL.rotateX;
joint18.rotateY = spineWeight.weight18Y * spineCTRL.rotateY;
joint18.rotateZ = spineWeight.weight18Z * spineCTRL.rotateZ;

Naar voren en achteren buigen RotateZ

Nu nog even de juiste gewichten invullen bij spineWeight, en de job is gedaan. Als we nog even kijken bij de bewegingsanalyse is er bij het naar voor- en achterbuigen 50% van de beweging lumbar; spineJoint2 t/m 6 en de andere 50% komt van de thoracle; spineJoint7 t/m 18.

  • Bij de Lumbarjoints (joint2 t/m 6) komt dat neer om 0.5 te verdelen over 5 joints =0.1.
  • Bij de Thoraclejoints (joint7 t/m 18) wordt deze 0.5 verdeeld over 12 joints=0.042.

Draaien om de eigen as RotateX

De twist vindt plaats vooral bij L10-11-12, (joint7,8 en 9).

  • Laten we zeggen die doen 60%, dat is 0.6/3 joints=0.2 per joint.
  • De Lumbar (joint 2 t/m 6) doet 15%, dat is 0.15/5 joints = 0.03 per joint
  • De rest van de Thoracle (joint 7 t/m 18) doet 25%, dat is 0.25/12 joints =  0.021 per joint.

Opzij buigen RotateY

Deze beweging is redelijk verdeeld over alle joints, bij L10-11-12 (joint7,8 en 9) iets meer.
De gewichten worden voor de L10-11-12: 0.06
Voor de andere joints : 0.058.

Rotatielimiet voor het controlobject

Het mooie is dat je makkelijk kunt variëren in de waarden. Een ballerina zal leniger zijn dan een bouwvakker.

Tot slot, kunnen we rotatie-limieten zetten in het control-object, ook hier weer verschillende lenigheden mogelijk.

Selecteer spineCTRL en ga naar de Attribute Editor en probeer de volgende waarden bij limit information

Draaien om eigen as                  Rot limit X max = 80

Rot limit X min = -80

Opzij buigen                                          Rot limit Y max = 50

Rot limit Y min = -50

Voorover buigen ca 60 graden     Rot limit Z max = 60

Achterover buigen ca 15 graden   Rot limit Z min = -30

Het beste van 2 werelden

Beperkingen

De Landreth-spine,  met de gewogen rotatie-methode heeft als grootste nadeel, vind ik, dat een beweging vanuit de heup de beweging van de schouder teveel bepaalt. De Schleiffer-spine deukt simpelweg in, en laat de schouderpartij redelijk ongemoeid. Bewegingen met de Schleifer-spine lijken daardoor ook veel soepeler en natuurlijker. Anderzijds,  het buigen en twisten van de Landreth-spine zijn gewoon goed en accuraat.  Het mooiste zou zijn deze twee technieken te combineren, vraag is hoe je dat zou doen.

Het antwoord is weer eens simpel: Landreth is FK en Schleiffer is IK. Hoera, we kunnen ze gewoon door elkaar gebruiken. Met de IKBlend –attribute kunnene we switchen tussen beide methoden. Voor bewegingen vanuit de benen of heup, zoals lopen of dansen, lijkt IK het  beste, en voor bewegingen vanuit het bovenlichaam, zoals buigen en draaien is FK weer geschikter.

Geef een reactie

Vul je gegevens in of klik op een icoon om in te loggen.

WordPress.com logo

Je reageert onder je WordPress.com account. Log uit / Bijwerken )

Twitter-afbeelding

Je reageert onder je Twitter account. Log uit / Bijwerken )

Facebook foto

Je reageert onder je Facebook account. Log uit / Bijwerken )

Google+ photo

Je reageert onder je Google+ account. Log uit / Bijwerken )

Verbinden met %s