Showing posts with label Animation in Android. Show all posts
Showing posts with label Animation in Android. Show all posts

Sunday, 31 March 2013

The role of Transformation Matrices in Animation


The mechanics of animation of are quite simple. Take any scene and if you repaint it quick while some aspect of that scene is changing you get the impression that something is moving smoothly although the repaint is happening only with a certain frequency which is typically 24 or 12 frames per second.
what changes at every redraw may be color, position, orientation, or size or any combination of these. If you want to take a view or a scene or a picture and want to move that scene to the right by a few pixels, you will typically define a transformation matrix and then apply a matrix multiplication or transformation on every pixel of the scene to get the new location. So each tranformation is identified by a certain matrix.
If you start with an identity matrix and then apply each transformation to it then you will get a final matrix that you can apply just one time to transform the view. By changing these matrices in a gradual manner in a time loop you will accomplish animation. Let's spend a little bit more time and understand the matrix api before going further.
You can get an identity matrix by doing

import android.graphics.Matrix;
Matrix matrix = new Matrix();
To achieve rotation you can do

matrix.setRotate(degrees)
This method will rotate the view around origin by those many degrees in a 2D space. Some other methods are

matrix.setScale(x,y);
matrix.setTranslate(x,y);
matrix.setSkew(x,y); 
As you call these methods to arrive at a desired matrix be aware of the "set" semantics. "set" semantics works like a "setting" a variable which means "replace" the current value with the new value. All of these methods, if you follow the java source code of android eventually resolve to some c++ code from a core google graphics library called "skia". You can explore the source code online at

http://android.git.kernel.org/
"git" is a source code control system used by the android open source project. You can learn more about "git" SCM here at

http://git.or.cz/
Now back to understanding of the "set" semantics on these graphics matrices. Let us take a look at the source code for "setScale":

void SkMatrix::setScale(SkScalar sx, SkScalar sy) {
    fMat[kMScaleX] = sx;
    fMat[kMScaleY] = sy;
    fMat[kMPersp2] = kMatrix22Elem;

    fMat[kMTransX] = fMat[kMTransY] =
    fMat[kMSkewX]  = fMat[kMSkewY] = 
    fMat[kMPersp0] = fMat[kMPersp1] = 0;

    this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
}
The scale function replaces all previous scaling values and pretty much resets the matrix and sets the scale. So if you have done anything else to the matrix all that is gone. Let us take a look at the "setTranslate" to see if that is any different.

void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
    if (SkScalarAs2sCompliment(dx) | SkScalarAs2sCompliment(dy)) {
        fMat[kMTransX] = dx;
        fMat[kMTransY] = dy;

        fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
        fMat[kMSkewX]  = fMat[kMSkewY] = 
        fMat[kMPersp0] = fMat[kMPersp1] = 0;
        fMat[kMPersp2] = kMatrix22Elem;

        this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
    } else {
        this->reset();
    }
}
Basically sets the scale back to 1 and sets the translations replacing everything before.
So what do you do if you want to apply multiple transformations in a tow. Matrix class provides a set of "pre*" and "post*" functions for each of the "set*" fucnctions. Let us take a look at the source code for "preScale"

bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    SkMatrix    m;
    m.setScale(sx, sy, px, py);
    return this->preConcat(m);
}

bool SkMatrix::preConcat(const SkMatrix& mat) {
    return this->setConcat(*this, mat);
}

bool SkMatrix::postConcat(const SkMatrix& mat) {
    return this->setConcat(mat, *this);
}
Essentially "preScale" creates a brand new matrix with the given scale and then multiplies that matrix with the current matrix and replaces the current matrix with the resultant matrix. When matrices are multiplied the order is important. So if we do

m.setScale(..) = rm1
m.preScale(..) = m2 x rm1 = rm3
m.postScale(..) = rm3 x m4 = rm5
I could have acheived the same with

m1.setScale() = m1
m2.setScale() = m2
m3.setScale() = m3

m1.setConcat(m2,m1); // rm3
m1.setConcat(m1,m3); // rm5
You can concat
If "m1" was an identity matrix then the following two would be equal as well

m1.postTranslate(); // take it to the origin
m1.postScale(); //scale it
m1.postTranslate();// take it back to the center

m2.setScale();
m2.preTranslate();
m2.postTranslate();

Here is some more sample code demonstrating matrix equivalence based on the order of operations on that matrix

In summary all the "pre*" and "post*" methods are mere shortcuts to "setConcat" against itself.

preTranslate(m) -> setConcat(m x self) 
preRotate(m) -> setConcat(m x self)
preScale(m) -> setConcat(m x self)
preSkew(m) -> setConcat(m x self)

postTranslate(m) -> setConcat (self x m)
postRotate(m) -> setConcat (self x m)
postScale(m) -> setConcat (self x m)
postSkew(m) -> setConcat (self x m)

Introduction To Animation In Android

Android supports two kinds of animation. 
  • One is called "Tweened Animation". 
  • The second one is called "Frame by Frame" animation. 
"Tween" is a short for "in-between" borrowed from traditional animators. Inbetweens are drawings that simulate motion between key frames. There may be 24 inbetweens between two key frames or there could be 12 between two key frames. The former case is called "on ones" and the later ones are called "on twos".

In Android here is how "tweening" works. You start with a view. This view can be any view including a view group with any set of complex composed graphical objects. When tweening animation is attached to this view, the animation gets a call back at regular intervals to change any aspect of the tranformation matrix that would be used to render the view.

Moving an object or scaling an object, or changing the shade of an object can all be represented as a set of matrix transformations. By changing this matrix in the call back of the animation you will render the object at a different place with a different scale or a diferent color.


So at a general level, tweening animation is acomplished by changing the properties of a view at various time intervals during the alloted time of an animation.


Android supports the following types of "tween" animations

  • AlphaAnimation: Changing Transparency of an object
  • RotateAnimation: Rotating an object
  • ScaleAnimation: Scale an object
  • TranslateAnimation: Move an object


In Android frame by frame animation a series of drawable resources are loaded one after the other. The class AnimationDrawable is responsible for frame by frame animation. Each frame in this animation is a drawable resource.


As you get deeper into Android animation you will see that the distinction is not so clearcut where you can mix both concepts by essentially redrawing the canvas one way or the other.