Animacja - przechowywanie zmiennych - 2006-10-26
Przy zapisywaniu wartości do pliku nie zapomnij wstawić na końcu przecinka
wiecej >>

Szukaj: 
Logowanie
Login
Hasło   
Pamiętaj mnie na tej stronie
 Zarejestruj się...




Najnowsza grafika
maxmoon
2012-04-24


Najnowsza tapeta
Nunas
2011-09-15
Tutorial - Budujemy szkielet - podstawy IK

Jak przy każdym tutorialu, który piszę tak i przy tym nie wiem jak zacząć, bo w zasadzie po co piszę taki tutorial? Mógłbym zrobić coś innego, pograć, napisać dokumentacje dla klienta, czy też może posprzątać w mieszkaniu. A jednak poświęcam wieczór na napisanie tej małej pomocy. Myślę, że pisaniu czegoś takiego należy sobie odpowiedzieć na pytanie co chcemy osiągnąć pisząc coś takiego. Odpowiedź na to pytanie postaram się podać pod koniec tego artykułu czy jak to tam nazwać.

Dobrze zacznijmy od stworzenia prostej sceny, małego świata w którym będziemy umieszczać nasze dzieło. A naszym dziełem będzie szkielet, podstawa do animacji i może w przyszłości do kinematyki odwrotnej.

Kod sceny
  
  #version 3.5;
  global_settings  {  assumed_gamma 1.0 }
  
  #include "colors.inc"
  
  camera  { angle 15
                              location  <0.0 , 20.0 ,-40.0>
                              right     x*image_width/image_height
                              look_at   <0.0 , 1.0 , 0.0>}
  
  
  
  // SŁOŃCE 
  light_source {<1500,2500,-2500> color White}
  
  sky_sphere { pigment { gradient <0,1,0>
                       color_map { [0   color rgb<1,1,1>         ]
                                  [0.4 color rgb<0.14,0.14,0.56>]
                                  [0.6 color rgb<0.14,0.14,0.56>]
                                  [1.0 color rgb<1,1,1>         ]
                                }
                       scale 2 }
             } 
  
  plane  { <0,1,0>, 0 texture  { pigment {color White} }  }
  //--------------------------------------------------------------------------
  //---------------------------- OBIEKTY W SCENIE ----------------------------
  //--------------------------------------------------------------------------
  


Skoro mamy scenę to teraz słów klika o obiekcie, który będziemy tworzyć. Szkielet w ogólnym zarysie będzie wyglądał tak.

Zdaję sobie sprawę, że nie jest to arcydzieło rysunku i szkicu, ale do naszych potrzeb wystarczy.
od samego początku będziemy ludka tworzyć jako obekt powstały w wyniku działania macra. Podstawy tworzenia macra można znaleźć tu dla przypomnienia. Macro jest to swego rodzaju funkcja, procedura która odpowiednio wywołana wykonuje jakąś czynność, od obliczania, poprzez tworzenie jakiś zaawansowanych obiektów.

Do dzieła, definiujemy macro.
  
  #macro mc_szkielet(_tObr)
      // terść macra
  #end
  
W pierwszej linijce deklarujemy macro (słowo kluczowe macro poprzedzone hashem #). W nawiasach okrągłych określamy ile parametrów będziemy przekazywać do naszego macra. Zaś w trzeciej określamy koniec macra (słowo kluczowe end poprzedzne #).
_tObr - jest to parametr, który będziemy przekazywać do naszego macra, tak naprawdę będzie to tablica wetorów. Wektory te będą nam sterować obrotem poszczególnych części ciała, ale wszystko po kolei.

Każdy obiekt prosty czy też masakrycznie złożony ma swój środek ciężkości tzn punkt obrotu, domyślnie wszystkie tworzone obiekty w povray;u mają ten punkt w <0,0,0>. Masz ludek swój punkt obrotu będzie miał w miednicy. Na początek stwórzmy miednicę.

  
  #macro mc_szkielet(_tObr)
  1.    #local __miednica=box  { <-4,-1.5,-1>,<4,1.5,1> }
  2.    object  { __miednica}
  #end
  
Miednica jest to zwyczajny sześcian o wymiarach 8x3x2 (SxWxG). Ważny jest w nim punkt obrotu, w tym wypadku jest to środek tego sześcianu. Teraz jeszcze tylko uruchomienie naszego macra...
  
  #macro mc_szkielet(_tObr)
      #local __miednica=box  { <-4,-1.5,-1>,<4,1.5,1> }
      object  { __miednica}
  #end
  
   
  1. #declare tabObr=array[17];
  2. object  { mc_szkielet(tabObr) pigment  { color Red }}
  
Doszły nowe dwie linijki, w pierwszej linicje deklarujemy tablice, która będzie zawierała 17 wektorów. w drugiej linicje wywołujemy to macro i przypisujemy mu kolor Czerwony.

No i nasz pierwszy render.


Kod programu

Teraz może wykorzystamy naszą tablicę i przekarzemy w niej wektor obrotu dla naszej miednicy. W tym celu musimy dokonać dwóch zmian.
a) Zdeklarować jako pierwszy element tablicy wektor #declare tabObr[0]=<0,0,0>;
b) W deklaracji naszej miednicy obrócić ją o ten właśnie wektor. #local __miednica=box { <-4,-1.5,-1>,<4,1.5,1> rotate _tObr[0] }

Całość wygląda tak.

  
  #macro mc_szkielet(_tObr)
      #local __miednica=box  { <-4,-1.5,-1>,<4,1.5,1> rotate _tObr[0] }
      object  { __miednica}
  #end
  
   
  #declare tabObr=array[1];
  #declare tabObr[0]=<0,0,0>;
  
  object  { mc_szkielet(tabObr) pigment  { color Red }}
  
Okej teraz jeżeli ten wektor zdeklarujemy tak: #declare tabObr[0]=<0,45,0>; i wyrenderujemy to nasza miednica wygląda tak. Ja wiem, że to co zrobiliśmy wydawało by się, że można to zrobić łatwiej ale myślę, że później się wyjaśni dlaczego tak to zrobiłem.

Rendering:

Kod programu

(Zielony cylinder dodałem aby zobrazować w którym miejscu, się obraca nasza miednica).

Dobrze teraz zdeklarujmy nogę a dokładnie udo prawe.
  
  #local __udo_praw=union  { 
          sphere { <0,0,0>,1 }
          cylinder  { <0,0,0>,<0,-12,0>, .7 }
          rotate _tObr[1]
      } 
  
Udo prawe jest to obiekt złożony z dwóch prymitywów: kuli i walca. Proszę zwrócić uwagę na punkt obrotu, który został ustawiony w środku kuli, natomiast walec początek ma w tym samym punkcie co kula ma swój środek.
Teraz nasze udo umieszczamy w odpowiednim miejsc miednicy w tym celu trochę zmieniamy deklarację miednicy
  
  #local __miednica=union {
          box  { <-4,-1.5,-.5>,<4,1.5,.5>  }
          object  { __udo_praw translate <-3,-1.5,0> }
          rotate _tObr[0]
      }
  
Teraz nasza miednica jest to obiekt typu UNION składający się z box'a czyli tej miednicy, co do tej pory i naszego uda prawego. Proszę zauważyć, że nasze udo zostało przesunięte na pozycję. 3, 15, 0 Ze względu na to aby czytelniej się to nam renderowało zmieniłem trochę ustawienia sceny. (oddaliłem kamerę i cały obiekt szkielet przesunąłem do góry)

A tak wygląda nasz render

Kod programu

Dobrze, reasumując mamy dwa obiekty miednice (którą obracamy wektorem (zerowy element tablicy)) i udo prawe które obracamy wektorem (pierwszym elementem tablicy). Teraz np. obracając udo w x o -45 mamy takie coś:


Ale jeżeli obrócimy dodatkowo miednice w x o -45 to będziemy mieli coś takiego:

Proszę zwrócić uwagę, że mimo, że miednica została przekręcona o 45 stopni, to udo pozostało tak samo obrócone..

Dobrze ale zdeklarujmy łydkę, to się jeszcze wyjaśni.
  
      #local __lydka_praw=union  { 
          sphere { <0,0,0>,1 }
          cylinder  { <0,0,0>,<0,-11,0>, .6 }
          rotate _tObr[2]
      }
  
Dobrze skoro mamy łydkę to teraz ją powinniśmy jakoś dodać. I teraz niespodzianka łydkę dodajemy do uda :-) kod wygląda tak
  
  #macro mc_szkielet(_tObr)
      #local __lydka_praw=union  { 
          sphere { <0,0,0>,1 }
          cylinder  { <0,0,0>,<0,-11,0>, .6 }
          rotate _tObr[2]
      }
      #local __udo_praw=union  { 
          sphere { <0,0,0>,1 }
          cylinder  { <0,0,0>,<0,-12,0>, .7 } 
          object  { __lydka_praw translate <0,-12,0> }
          rotate _tObr[1]
      }
       
      #local __miednica=union {
          box  { <-4,-1.5,-.5>,<4,1.5,.5>  }
          object  { __udo_praw translate <-3,-1.5,0> }
          rotate _tObr[0]
      }
      
      object  { __miednica}
  #end
  
   
  #declare tabObr=array[17];
  #declare tabObr[0]=<0,0,0>;
  #declare tabObr[1]=<0,0,0>;
  #declare tabObr[2]=<0,0,0>;
  
Niemal, że dodaliśmy łydkę do uda to jeszcze ją przesuneliśmy w Y o -12, ale proszę zwrócić uwagę, że mimo tego jak będziemy łydką obracać to nadal ona się zgina w kolanie...

Kod programu



Dobrze teraz skoro mamy już trzy punkty obrotu to zademonstrujemy jakie ma to zalety.


Jest to animacja, gdzie obracamy tylko lydkę. Kod tego wygląda tak,
  
  #declare tabObr=array[17];
  #declare tabObr[0]=<0,0,0>;
  #declare tabObr[1]=<0,0,0>;
  #declare tabObr[2]=<-75*clock,0,0>;
  


Zauważyć można, że obracamy tylko wektor znajdujący się w drugim elemencie tablicy.

Kod programu



A teraz jak dodamy obrót w udzie wyjdze coś takiego.

Kod programu



  
  #declare tabObr=array[17];
  #declare tabObr[0]=<0,0,0>;
  #declare tabObr[1]=<-(75 - 150*clock),0,0>;
  #if(clock<.5)
      #declare tabObr[2]=<-150*clock,0,0>;
  #else                              
      #declare tabObr[2]=<-(150-150*clock),0,0>;
  #end
  
W linijce 3 deklarujemy wektor obrotu dla uda, uzależniamy kąt obrotu X od zmiennej clock, która to zmienia się z zakresu 0 - 1 czyli kąt zmienia się z zakresu -75 do 75. Od linijki 4 do 8 jest zdeklarowany warunek, króty określa że jeżeli zmienna clock jest mniejsza od 0.5 to wykonywana jest linijka 5 czyli obracamy łydkę w osi X od 0 -75 następnie jeżeli zmienna clock jest większa od .5 wykonujemy linijkę 7 czyli obracamy łydkę w osi X od -75 - 0.

Co nam to daje takie ustawienie wektorów obrotów i przekazywanie do macra? pozwala nam obracać poszczególne elementy w ich własnym lokalnym punkcie <0,0,0> dopiero po obrocie przenosimy je do wybranego punktu i obracamy, ale wektorem obrotu rodzica.

Dobrze pokazałem jak wygląda i co nam daje takie ustawienie i taki model przekazywania kątów obrotu, teraz szybko stwórzmy prawą stopę i całą lewą nowy zrobimy na zasadzie kopiuj wklej :-)

Tak wygląda deklaracja stopy
  
  #local __stopa_prawa=union  { 
          sphere { <0,0,0>,1 }
          box  { <-1,0,-1>,<1,-2,1> }
          box  { <-1,-1,-4>,<1,-2,1> }
          rotate _tObr[3]
      }
  


Dobrze po zdeklarowaniu lewej nogi i przypisaniu jej odpowiednich wektorów obrotów otrzymujemy coś takiego..

Kod programu

Teraz szybko stworzę tłów ręce szyję i głowę, technika i metoda jest taka sama jak przy tworzeniu nóg. Pominę szczegółowe opisywanie poszczególnych etapów tworzenia tych obiektów, nie jest to istotne na treść tego tutoriala, po stworzeniu tych elementów przejdziemy do tworzenia macr które ułatwią zarządzanie ludkiem. Opiszę tylko hierarichę.

    Tłów
      Reką prawa
        Ramię prawe
          Przedramie prawe
            Nadgarstek prawy
              Dłoń prawa
      Reką lewa
        Ramię lewe
          Przedramie lewe
            Nadgarstek lewy
              Dłoń lewa
      Szyja
        Głowa


Tak wygląda nasz model, dodałem wszystkie elementy teraz przejdziemy do tworzenia macr pomocniczych


Kod programu

  
  object  { mc_szkielet(tabObr) pigment  { color Red } translate <0,26.5,0> }   
  
Proszę zwrócić uwagę na to, aby nasz obiekt stał na ziemi musimy przesunąć go o 26.5 do góry. Taką wysokość mają nogi ludka. Dlatego wstawimy to translate do naszego macra.
Teraz podciągniemy kolana do góry

  
  #declare tabObr[1]=<45,0,0>;   // Udo prawe
  #declare tabObr[2]=<-90,0,0>;   // Łydka prawa
  #declare tabObr[3]=<45,0,0>;   // stopa prawa 
  
  #declare tabObr[4]=<45,0,0>;   // udo lewe
  #declare tabObr[5]=<-90,0,0>;   // Łydka lewa
  #declare tabObr[6]=<45,0,0>;   // Stopa lewa
  
a rendering wygląda tak



Proszę zwrócić uwagę, że podciąganięcie kolan do góry osiągneliśmy zmienijąc kąty ud, łydkek i stóp, jednocześnie stopy uniosły się od poziomu ) o jakąś tam odległość, teraz aby nasz ludek stał na ziemi musimy znowu go przesunąć o jakąś tam odległość. Oczywiście są tacy co trafiają i próbują aż w końcu udam się przestawić ludka na odpowiednią wysokość :-) oczywiście szanujemy ich. My stworzymy macro i użyjemy do tego transform i vtransform... Ogólnie rzecz ujmując musimy znaleźć punkt na którmy znajduje się dół stopy i przesunąć cały obiekt o tą wartość.
Transform - jest to swego rodzaju grupowanie poszczególnych operacji przekształcania, rotate, translate scale, który można później użyć do każdego rodzaju obiektu, np
  
  #local _trMoj=transform
   {
  translate <12,0,0>
  rotate x*12
  translate <0,-1,0>
  scale <1,.4,1>
  }
  sphere  { <0,0,0>, 2 transform _trMoj }
  
Tworzymy obiekt przekształcenia, a następnie przekształcamy sferę.

Natomiast
vtransform(p, tra) - jest to macro które punkt (p) poddaje transformacji (tra) i zwraca położenie tego punktu.

No to mamy wszystkie już potrzebne narzędzie, tak więc tworzymy macro które obliczy nam punkt gdzie znajduje się stopa
  
  #macro obliczY(tO)
  #local _trStopaPrawa=transform
   { 
  translate <0,-2,0>      // punkt od dołu stopy do poczatku stopy tam gdzie jest to sphere
  rotate tO[3]            // kąt obrotu stopy   
  
  translate <0,-11,0>     // przesunięcie lydki
  rotate tO[2]            // kąt obroty łydki
  
  translate <0,-12,0>     // przesuniecie uda
  rotate tO[1]            // obrot uda
  
  translate <0,-1.5,0>    // przesuniecie biodra
  rotate tO[0]            // obrot całego biodra
  
  translate <0,26.5,0>
  }
  -vtransform(<0,0,0>,  _trStopaPrawa).y
  #end
  
W pierwszej linijce tworzymy macro do którego przekazujemy tablice wektorów, w drugijej linijce zaś tworzym transform takie jakie jest uzywane w ludku. W 18 linijce obliczamy punkt i zwracamy tylko wartość y z tego punktu.

Macra używamy tak,
  
  object  { mc_szkielet(tabObr) pigment  { color Red } translate  y*obliczY(tabObr) }   
  
A oto Efekt..

Kod programu

Takie rozwiązanie ma swoje wady ponieważ bierzemy pod uwagę tylko jedną nogę, jeżeli np noga lewa jest bardziej wyprostowana to nie do końca działa... oto przykład


Jednak jak przerobimy nasze macro o tak
  
  #macro obliczY(tO)
  
  #local _trStopaPrawa=transform
   { 
      translate <0,-2,0>      // punkt od dołu stopy do poczatku stopy tam gdzie jest to sphere
      rotate tO[3]            // kąt obrotu stopy   
      
      translate <0,-11,0>     // przesunięcie lydki
      rotate tO[2]            // kąt obroty łydki
      
      translate <0,-12,0>     // przesuniecie uda
      rotate tO[1]            // obrot uda
      
      translate <-3,-1.5,0>    // przesuniecie biodra
      rotate tO[0]            // obrot całego biodra
      
      translate <0,26.5,0>
  }
  #local _trStopaLewa=transform
   { 
      translate <0,-2,0>      // punkt od dołu stopy do poczatku stopy tam gdzie jest to sphere
      rotate tO[6]            // kąt obrotu stopy   
      
      translate <0,-11,0>     // przesunięcie lydki
      rotate tO[5]            // kąt obroty łydki
      
      translate <0,-12,0>     // przesuniecie uda
      rotate tO[4]            // obrot uda
      
      translate <3,-1.5,0>    // przesuniecie biodra
      rotate tO[0]            // obrot całego biodra
      
      translate <0,26.5,0>
  }
  max(-vtransform(<0,0,0>,  _trStopaPrawa).y,-vtransform(<0,0,0>,  _trStopaPrawa).y)
  #end
  

Wtedy już będziemy potrafili określić ile trzeba przesunąć do poziomu;
A oto gotowy render...

Kod programu



I sam koniec przykład zastosowania, obrazujący jak to co stworzylismy działa:


Kod programu
Kod pliku z animacją

Można dopisać jeszcze macro które będzie ustawiało stopy równolegle do podłoża... ale to już w innym tutorialu,
© druidy.pl

Korzystając z witryny bez zmiany ustawień przeglądarki wyrażasz zgodę na użycie plików cookies. W każdej chwili możesz swobodnie zmienić ustawienia przeglądarki decydujące o ich zapisywaniu.