Processing math: 100%

úterý 27. srpna 2013


Here is my second take on explaining my multiparent script.


What it does? Standard technique in rigging is linking. You link one object A to another object B so that its position and rotation of object A is fixed if we manipulate with object B. Quite often one would like to do converse, so manipulate with A and keep position and orientation of B fixed against A. Normally you have to destroy the original link(A to B) and link B to the A. Here I propose solution where you don't have to relink those objects. But everything comes with its price, so you loose direct control of those object but to that later.

Ok we start by developing such a link constraint between two objects A and B such that you can rotate center of A around center of B and vice versa. The orientation of A and B won't be affected by such rotation, this is necessary because you need some unconstrained controls.
To achieve that we have to introduce a helper object H to which will be centers of A and B fixed and rotation of A,B will somehow affect position and orientation of H.

Next we face difficulty that position of A,B at time t does depend on rotation history of those objects. Have a look here for an example http://www.youtube.com/watch?v=lOfaFJq5Wqk as you can see rotation of A,B at time t cannot fully describe the system at time t. You have to know the rotation history of A,B to fully determine position of those objects. So we will define exact positions of A,B  at some time t0 and to find out position of A,B at time t we will march frame by frame from time the t0 to the time t.

In opposite to the previous post I won't use quaternions except when I will combine rotations but I will propose different approach with matrix exponential.

xA(t)position of object AxB(t)position of object HxH(t)position of object BRtArotation matrix of object A at time tRtBrotation matrix of object B at time tRtHrotation matrix of object H at time t

As already said position of centers of A and B are fixed against H, so
xA(t)=xH(t)+RtHpApA=(Rt0H)1(xA(t0)xH(t0))xB(t)=xH(t)+RtHpBpB=(Rt0H)1(xB(t0)xH(t0))

Now if we rotate A a little bit we want to move with B, but B is fixed against H so it is sufficient to move with H. So just for a moment forget about B and imagine that H is linked to the A. Than if we rotate with A position of H will change as
xH(t+Δt)=xH(t)+Rt+ΔtA(RtA)1(xH(t)xA(t))
and the orientation of H will change as
Rt+ΔtH=Rt+ΔtA(RtA)1RtH
Now if we take account the B's contribution we get equation

xH(t+Δt)=xH(t)+Rt+ΔtA(RtA)1(xH(t)xA(t))+Rt+ΔtB(RtB)1(xH(t)xB(t))
But there is trouble with orientation update  of H because matrix multiplication is not commutative so we don't know in which order to multiply those matrix. For now we just write something and we will  explain later what {,} means.
Rt+ΔtH={Rt+ΔtA(RtA)1,Rt+ΔtA(RtA)1}RtH

What  {,} does is that it takes two rotations and produce another new rotation, which somehow captures those two rotations. From this we require from  {,} these identities
{R1,R2}={R2,R1}{R1,I}=R1
where I is identity(ie no rotation). First says that it does not depend on the order of the matrices and the second say that if we combine some rotation with identity(ie no rotation) we should get the original rotation.

Now to define  {,}  without quaternions we need to know a little bit about rotations and matrix exponential.

If you have rotation around axis n by angle ω. Than its rotation matrix R can be expressed as
R=eω[n]×=k=0ωkk![n]k×
where [n]× is cross-product matrix .
Other way around if you have antisymmetric matrix A that eA is rotation matrix.

We are ready to define  {,}. Let's have two rotation matrices R1=eA1,R2=eA2. Than
{R1,R2}={eA1,eA2}=eA1+A2
Observe that A1+A2 is again antisymmetric matrix so eA1+A2 is rotation matrix. Next A1+A2=A2+A1 therefore  {eA1,eA2}={eA2,eA1}. Lastly I=e0 so  {eA1,e0}=eA1+0=eA1. So  {,}  satisfy all identities we wanted.

How to program this then.


What are the inputs?
We have to specify time tf at which we want to get positions and orientations of A,B,H. Next we have to know positions of A,B,H at time t0 and orientation of H at time t0. Than we have to know the whole history of rotation matrices of A,B from time t0 to time tf.
What is the output?
Position of A,B,H at time t and orientation of H.

So the code would be something like this:

1. precalculate values  pA,pB

2. then use update equations, start at time t0 and and at time tf.
xH(t+Δt)=xH(t)Rt+ΔtA(RtA)1RtHpARt+ΔtB(RtB)1RtHpBRt+ΔtH={Rt+ΔtA(RtA)1,Rt+ΔtA(RtA)1}RtH

3. from valuse xH(tf),RtfH calculate xA(tf),xB(tf)


neděle 9. června 2013


Multi-parent constraint

Ok what is the deal? For example when you animate foot sometimes you want to rotate it about forefoot and sometimes about hindfoot. Or you want to animate things like this http://www.youtube.com/watch?v=lOfaFJq5Wqk . I have simple solution.

I assume that reader is familiar with quaternions and their aplication to rotation if not than please see http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

So let's get mathematical. Beware everything is quaternion(I will try to stay consistent in notaion with wiki page on quaternion, like conjugation is denoted with star)!
ttimep0(t)position of the footq0(t)quaternion which specifies rotation of foot aroundp0now for i>0pi(t)positions of points you want to rotate aroundqi(t)quaterion which specifies rotations around corresponding point

Suppose you know p0,q0,pi at some time t0 and qi(t) for all t>t0. Than you want to find p0(t),q0(t),pi(t). But what should they satisfy??

First denote with vi relative position of pi to the p0 at time t. So:
vi(t)=pi(t)p0(t)
Points pi should stay fixed relative to foot. Therefore they have to satisfy:
pi(t)=p0(t)+R0(t)vi(t0)R0(t)

where Ri(t)=qi(t)q1i(t0) which represents change in rotation from time t0 to time t. .

Now imagine situation when you rotate only about point p1. So pi,qi  for i>1, p1 are constant in time and only q1 changes in time. What do we get? We rotate point p0 around point p1:

p0(t)=p1(t0)R1(t)v1(t0)R1(t)
q0(t)=R1(t)q0(t0)

Now replace p1(t0) with pi(t0)=p0(t0)+vi(t0) we get:

p0(t)p0(t0)=v1(t0)R1(t)v1(t0)R1(t)

So point p0 changes about vi(t0)R1(t)v1(t0)R1(t) thanks to rotation about point p1. We assumed that p1. When p1 varies in time than previous equation is "sort of OK"(it does not represents accurately the rotation of p_0 around point p_1(which varies over time)) only for small times Δt=tt0.

Now suppose that pi,qi all varies in time and Δt is small. Than we can generalize our update equation:

p0(t0+Δt)p0(t0)=ivi(t0)Ri(t0,Δt)vi(t0)Ri(t,Δt)

where R(t,Δt)=qi(t+Δt)q1i(t). But how do we update q0 ?? We could do q0(t+Δt)=R1(t,Δt)Rn(t,Δt)q0(t) But it depends on order of the Ri which is undesirable. So we do better with:
q0(t+Δt)={Ri(t,Δt)}iq0(t)

where{Ri(t,Δt)}is what I call normalized anticommutator defined by:

a1,,an are any quaternions than

{ai}i=σΠnaσ(1)aσ(n)||σΠnaσ(1)aσ(n)||

where Πn is set of all permutations of size n. I think that normalized anticommutator is the most convenient way how to combine n rotations and get again rotation. And quaternions are the good way to do it. Problem with matrices is that when you add two rotational matrices than you hardly get rotation matrix and finding closest rotation matrix to that sum is just pain. With quaternions it is easy, just add them up and normalize.

We are almost finished. We just polish those equations a little bit.

denote tn=t0+nΔt than our update equations looks like this:

vi(tn+1)=pi(tn+1)p0(tn+1)=R0(tn,Δt)vi(tn)R0(t,Δt)p0(tn+1)=p0(tn)+ivi(tn)Ri(tn,Δt)vi(tn)Ri(tn,Δt)q0(tn+1)={Ri(tn,Δt)}iq0(tn)pi(tn)=p0(tn)+R0(t0,tnt0)vi(t0)R0(t0,tnt0)

Horay! finished.

I implemented it to Autodesk Maya. You can download the plugin here:
http://uloz.to/xgp17H2G/multiparent-zip
or
http://www.4shared.com/zip/MqwiOuUt/multiParent_1.html

Watch video how to use it:
http://www.youtube.com/watch?v=5Oip-YiKuik

I hope you like it! If you find any mistakes please let me know ;)

Further investigation:

Send Δt to zero and obtain differential equations from those update equations and analyze their behavior!

úterý 14. května 2013

Takze tady jsem napsal jednu polovinu:
12