Praca z kinematyką odwrotną
Flash Player 10 i nowsze wersje, Adobe AIR 1.5 i nowsze wersje, wymagany program Flash CS4 lub nowszy
Kinematyka odwrotna (IK) to wspaniała technika tworzenia realistycznych ruchów.
IK umożliwia tworzenie skoordynowanych ruchów w łańcuchu połączonych części nazywanych szkieletem IK, dzięki czemu części poruszają się jak w rzeczywistości. Części szkieletu są jego kości i stawami. Na podstawie punktu końcowego szkieletu IK oblicza kąty dla stawów, które są wymagane do uzyskania konkretnego punktu końcowego.
Samodzielne obliczanie tych kątów byłoby bardzo trudne. Zaletą tej funkcji jest to, że można tworzyć szkielety interaktywnie za pomocą programu Adobe® Flash® Professional. Następnie można animować szkielety za pomocą języka ActionScript. Silnik IK zawarty w programie Flash Professional wykonuje te obliczenia w celu opisania ruchu szkieletu. Ruch można ograniczyć do pewnych parametrów w kodzie ActionScript.
Nowością wprowadzoną do mechanizmu kinematyki odwrotnej w wersji Flash Professional CS5 jest koncepcja sprężynowania kości, kojarzona zazwyczaj z aplikacjami do tworzenia zaawansowanych animacji. Dzięki nowemu mechanizmowi symulacji fizycznej dynamiki ruchu funkcja ta umożliwia tworzenie realistycznych animacji. Efekt ten jest widoczny zarówno w środowisku wykonawczym, jak i podczas tworzenia treści.
Do tworzenia szkieletów kinematyki odwrotnej wymagana jest licencja programu Flash Professional.
Podstawowe informacje o kinematyce odwrotnej
Kinematyka odwrotna (IK) umożliwia tworzenie realistycznych animacji poprzez łączenie części w taki sposób, aby poruszały się względem siebie w sposób realistyczny.
Na przykład: za pomocą IK można przesunąć nogę do określonego miejsca poprzez wykonywanie ruchów zginania w stawach nogi, która ma osiągnąć wymagane położenie. IK korzysta ze struktury kości połączonych ze sobą w strukturę o nazwie szkielet IK. Pakiet
fl.ik
ułatwia tworzenie animacji przypominających ruch naturalny. Umożliwia płynne animowanie wielu szkieletów IK bez konieczności posiadania szczegółowej wiedzy na temat zasad fizyki w algorytmach IK.
Najpierw należy utworzyć szkielet IK z pomocniczymi kośćmi i stawami w programie Flash Professional. Następnie należy uzyskać dostęp do klas kinematyki odwrotnej w celu animowania szkieletu w środowisku wykonawczym.
Szczegółowe informacje dotyczące tworzenia szkieletów kinematyki odwrotnej zawiera sekcja poświęcona korzystaniu z kinematyki odwrotnej w dokumentacji
Korzystanie z programu Flash Professional
.
Ważne pojęcia i terminy
Na poniższej liście objaśniono ważne terminy istotne w kontekście tego zagadnienia:
-
Szkielet
-
Łańcuch kinematyczny zawierający kości i stawy, używany w animacji komputerowej do symulowania realistycznych ruchów.
-
Kość
-
Sztywny segment szkieletu, analogiczny do kości w szkieletach zwierząt.
-
Kinematyka odwrotna (IK)
-
Proces określania parametrów połączonego stawami elastycznego obiektu, który jest nazywany łańcuchem kinematycznym lub szkieletem.
-
Staw
-
Miejsce, w którym łączą się dwie kości. Umożliwia ruch kości; analogiczny do stawów u zwierząt.
-
Silnik Physics
-
Pakiet algorytmów fizycznych wykorzystywanych w celu tworzenia realistycznych ruchów w animacjach.
-
Sprężyna
-
Cecha kości, która porusza się i reaguje w przypadku przesunięcia kości nadrzędnej, a następnie intensywność reakcji zmniejsza się w miarę upływu czasu.
Przegląd animacji szkieletów kinematyki odwrotnej
Po utworzeniu szkieletu IK w programie Flash Professional należy użyć klas
fl.ik
w celu ograniczenia jego ruchu, śledzenia zdarzeń i animowania szkieletu w środowisku wykonawczym.
Poniższa ilustracja prezentuje klip filmowy o nazwie
Wheel.
Oś jest instancją IKArmature o nazwie
Axle
. Klasa IKMover porusza szkieletem w synchronizacji z obrotami koła. Kość IKBone,
ikBone2
, w szkielecie jest dołączona do koła przy stawie ogonowym.
-
A.
-
Koło
-
B.
-
Oś
-
C.
-
ikBone2
W trakcie wykonywania koło obraca się zgodnie z animacją ruchu
__motion_Wheel
omówioną w sekcji
Opisywanie animacji
. Obiekt IKMover inicjuje i kontroluje ruch osi. Poniższa ilustracja prezentuje dwa zrzuty szkieletu osi dołączonego do obracającego się koła w różnych klatkach obrotu.
W czasie wykonywania następujący kod ActionScript:
-
Uzyskuje informacje o szkielecie i jego składnikach
-
Tworzy instancję obiektu IKMover
-
Porusza osią w połączeniu z obrotami koła
import fl.ik.*
var tree:IKArmature = IKManager.getArmatureByName("Axle");
var bone:IKBone = tree.getBoneByName("ikBone2");
var endEffector:IKJoint = bone.tailJoint;
var pos:Point = endEffector.position;
var ik:IKMover = new IKMover(endEffector, pos);
ik.limitByDistance = true;
ik.distanceLimit = 0.1;
ik.limitByIteration = true;
ik.iterationLimit = 10;
Wheel.addEventListener(Event.ENTER_FRAME, frameFunc);
function frameFunc(event:Event)
{
if (Wheel != null)
{
var mat:Matrix = Wheel.transform.matrix;
var pt = new Point(90, 0);
pt = mat.transformPoint(pt);
ik.moveTo(pt);
}
}
Klasy IK używane do poruszania osią:
-
IKArmature: opisuje szkielet — strukturę drzewa, która zawiera kości i stawy; należy utworzyć w programie Flash Professional
-
IKManager: zawiera klasę dla wszystkich szkieletów IK w dokumencie; należy utworzyć w programie Flash Professional
-
IKBone: segment szkieletu IK
-
IKJoint: połączenie między dwiema kośćmi IK
-
IKMover: inicjuje i kontroluje ruchy IK szkieletów
Pełny i szczegółowy opis tych klas zawiera dokumentacja
pakiet ik
.
Pobieranie informacji o szkielecie kinematyki odwrotnej
Najpierw należy zadeklarować szkielet, kość i staw, które tworzą części, jakie będą się poruszały.
W poniższym kodzie wykorzystano metodę
getArmatureByName()
klasy IKManager w celu przypisania wartości szkieletu Axle do zmiennej
tree
klasy IKArmature. Szkielet Axle został poprzednio utworzony w programie Flash Professional.
var tree:IKArmature = IKManager.getArmatureByName("Axle");
I podobnie — w poniższym kodzie wykorzystano metodę
getBoneByName()
klasy IKArmature w celu przypisania do zmiennej IKBone wartości kości
ikBone2
.
var bone:IKBone = tree.getBoneByName("ikBone2");
Staw ogonowy kości
ikBone2
jest częścią szkieletu, która jest dołączona do obracającego się koła.
Poniższa linia deklaruje zmienną
endEffector
i przypisuje ją do właściwości
tailjoint
kości
ikBone2
:
var endEffector:IKJoint = home.tailjoint;
Zmienna
pos
jest punktem, który przechowuje bieżącą pozycję stawu
endEffector
.
var pos:Point = endEffector.position;
W tym przykładzie
pos
jest pozycją stawu na końcu osi, w miejscu, w którym łączy się z kołem. Oryginalna wartość tej zmiennej jest uzyskiwana z właściwości
position
stawu IKJoint.
Tworzenie instancji klasy IK Mover i ograniczanie jej ruchu
Instancja klasy IKMover porusza osią.
W poniższej linii tworzona jest instancja obiektu IKMover
ik
, a do jego konstruktora przekazywany jest element przeznaczony do poruszenia oraz punkt początkowy ruchu:
var ik:IKMover = new IKMover(endEffector, pos);
Właściwości klasy IKMover umożliwiają ograniczanie ruchu szkieletu. Ruch można ograniczyć na podstawie odległości, iteracji oraz czasu ruchu.
Poniższe pary właściwości wymuszają te ograniczenia. Pary zawierają wartość Boolean, która wskazuje, czy ruch jest ograniczony, oraz liczbę całkowitą, która określa limit:
Właściwość typu Boolean
|
Właściwość typu Integer
|
Ustawiony limit
|
limitByDistance:Boolean
|
distanceLimit:int
|
Ustawia maksymalną odległość w pikselach, o jaką silnik IK zmieni ustawienie przy każdej iteracji.
|
limitByIteration:Boolean
|
iterationLimit:int
|
Ustawia maksymalną liczbę iteracji wykonywanych w każdym ruchu przez silnik IK.
|
limitByTime:Boolean
|
timeLimit:int
|
Ustawia maksymalny czas w sekundach przydzielony do silnika IK w celu wykonania określonego ruchu.
|
Domyślnie wszystkie wartości typu Boolean są ustawiane na
false
, a zatem ruch nie jest ograniczony, o ile wartość Boolean nie zostanie jawnie ustawiona na
true
. Aby wymusić limit, należy ustawić odpowiednią właściwość na
true
, a następnie określić wartość odpowiadającej jej właściwości typu Integer. Jeśli zostanie ustawiona wartość limitu, ale nie zostanie określona odpowiednia wartość Boolean, wówczas limit zostanie zignorowany. W takim przypadku silnik IK będzie kontynuował ruch obiektu do czasu osiągnięcia innego limitu lub pozycji docelowej klasy IKMover.
W poniższym przykładzie maksymalna odległość ruchu szkieletu jest ustawiona na 0,1 piksela na iterację. Maksymalna liczba iteracji dla każdego ruchu jest ustawiona na dziesięć.
ik.limitByDistance = true;
ik.distanceLimit = 0.1;
ik.limitByIteration = true;
ik.iterationLimit = 10;
Poruszanie szkieletem IK
Klasa IKMover porusza osią w detektorze zdarzeń koła. Przy każdym zdarzeniu enterFrame koła obliczana jest nowa pozycja docelowa dla szkieletu. Za pomocą metody
moveTo()
klasa IKMover porusza staw ogonowy do jego położenia docelowego lub na odległość zgodną z ograniczeniami określonymi przez właściwości
limitByDistance
,
limitByIteration
i
limitByTime
.
Wheel.addEventListener(Event.ENTER_FRAME, frameFunc);
function frameFunc(event:Event)
{
if (Wheel != null)
{
var mat:Matrix = Wheel.transform.matrix;
var pt = new Point(90,0);
pt = mat.transformPoint(pt);
ik.moveTo(pt);
}
}
Korzystanie ze sprężynowania
Mechanizm kinematyki odwrotnej dostępny w aplikacji Flash Professional CS5 pozwala na obsługę sprężynowania kości. Sprężynowanie kości może być ustawiane podczas tworzenia, a atrybuty sprężynowania mogą być dodawane i modyfikowane w środowisku wykonawczym. Sprężystość jest właściwością kości i jej stawów. Właściwość jest opisana dwoma atrybutami:
IKJoint.springStrength
, który określa stopień sprężynowania, oraz
IKJoint.springDamping
, który zwiększa tłumienie drgań sprężyny i wpływa na szybkość zaniku efektu sprężynowania.
Stopień sprężynowania to wartość wyrażona w procentach od 0 (domyślnie, całkowita sztywność) do 100 (elastyczność, sterowanie silnikiem Physics). Kości posiadające właściwość Spring reagują na ruch w ich stawach. Jeśli nie wystąpiła żadna zmiana (rotacja, przesunięcie x lub y), wówczas ustawienia sprężynowania nie mają wpływu na zachowanie kości.
Tłumienie sprężynowania to wartość wyrażona w procentach od 0 (brak oporu) do 100 (pełne tłumienie). Tłumienie wpływa na czas, jaki upływa między początkiem ruchu kości a jej powrotem do pozycji spoczynkowej.
Aby sprawdzić, czy sprężynowanie zostało aktywowane dla obiektu IKArmature, należy odczytać jego właściwość
IKArmature.springsEnabled
. Inne właściwości i metody Spring nalezą do poszczególnych obiektów IKJoint. Staw może umożliwiać obroty i przesunięcia wzdłuż osi x i y. Kąt sprężynowania dla stawu obrotowego można ustawić za pomocą właściwości
IKJoint.setSpringAngle
, a pozycję sprężyny dla stawu umożliwiającego przesuwanie można ustawić za pomocą właściwości
IKJoint.setSpringPt
.
Ten przykład ilustruje wybór kości wg nazwy i identyfikację jej właściwości tailJoint. Kod testuje nadrzędny szkielet w celu sprawdzenia, czy sprężynowanie zostało aktywowane, a następnie ustawia właściwości sprężynowania dla stawu.
var arm:IKArmature = IKManager.getArmatureAt(0);
var bone:IKBone = arm.getBoneByName("c");
var joint:IKJoint = bone.tailJoint;
if (arm.springsEnabled) {
joint.springStrength = 50; //medium spring strength
joint.springDamping = 10; //light damping resistance
if (joint.hasSpringAngle) {
joint.setSpringAngle(30); //set angle for rotational spring
}
}
Korzystanie ze zdarzeń kinematyki odwrotnej
Klasa IKEvent umożliwia utworzenie obiektu zdarzenia, który zawiera informacje dotyczące zdarzeń IK. Informacje w klasie IKEvent opisują ruch, który zakończył się z powodu przekroczenia limitu czasu, odległości lub iteracji.
Poniższy kod prezentuje detektor zdarzenia i moduł obsługi zdarzenia dla śledzenia zdarzeń przekroczenia limitu czasu. Ten moduł obsługi zdarzeń zgłasza właściwości dotyczące czasu, odległości, liczby iteracji i stawu biorącego udział w zdarzeniu w przypadku przekroczenia limitu czasu klasy IKMover.
var ikmover:IKMover = new IKMover(endjoint, pos);
ikMover.limitByTime = true;
ikMover.timeLimit = 1000;
ikmover.addEventListener(IKEvent.TIME_LIMIT, timeLimitFunction);
function timeLimitFunction(evt:IKEvent):void
{
trace("timeLimit hit");
trace("time is " + evt.time);
trace("distance is " + evt.distance);
trace("iterationCount is " + evt.iterationCount);
trace("IKJoint is " + evt.joint.name);
}
|
|
|
|
|