Animate Circle Drawing

Problems with Canvas, OpenGL, etc...

Animate Circle Drawing

Postby bemipefe » Fri May 20, 2011 5:28 pm

Hi!
My goal is to use a circle like a progress bar. I mean draw the circle point to point, setting the next point when i decide to do.

I tried to do a simple View that calculate the points of the circle with the mathematic trigonometric formula (made by myself) and draw the circle setting the pixel to red color with Image.setPixel() method and then calling canvas.drawBitmap();

Image

The problem is that the method onDraw() draw all the point of the circle in one shot. I want to see the circle that appear in progression, for now is not important if CW or ACW direction. I tried to sleep the method with Thread.sleep(); but only when the program exit to onDraw() method draw the circle, and draw the whole circle of course.

I want try with AnimationDrawable class but i don't know if exist a more simple way to do this.
Any help is appreciated.
Thanks
bemipefe
Freshman
Freshman
 
Posts: 6
Joined: Fri May 20, 2011 4:55 pm

Top

Re: Animate Circle Drawing

Postby MichaelEGR » Sat May 21, 2011 1:51 am

Are you doing things with parametric equations ala:
x = a sin(t)
y = a cos(t)

a = scaling factor
t = 0 to 2PI to draw a complete circle. If you treat t as time you can animate the drawing. Without a scaling factor for time if you use t as normal time you can draw a circle in 6.28 seconds. It's advised that you manage the animation yourself. If you want to reverse the direction the circle draws in go from 0 to -2PI.

I personally wouldn't use setPixel, but for 2D / Android would simply draw into a bitmap the differential between the last and next points w/ maybe some interpolation / smaller steps depending on how far / fast t or time steps.
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Re: Animate Circle Drawing

Postby bemipefe » Mon May 23, 2011 1:12 pm

Thank you MichaelEGR !

I understand what's your idea, i have used the same formula in differet way. But the problem is not in the dependent variable t. It could be time as you say or could be simple a float value incremented manually as i do.

The problem is that i can't control directly the draw. I mean that i can't control the speed of draw and i don't know how to draw a partial circle and then re-draw the circle with one or more points. The only "refresh" method provided by View class is "invalidate()", but this method only force the onDraw method calling.

I have tried with AnimationDrawable wrapped in an ImageView object then i use "addFrame" to add a Bitmap with the circle painted on. This mean that i have to create a new bitmap for each frame, and if i have for example 628 frame the bitmaps take approximately 628x320x240 = 34 MB. Indeed i get the exception " java.lang.OutOfMemoryError: bitmap size exceeds VM budget ". If i modify only the bitmap object without recreate it, then i see only the whole circle because i give the same object for all frame so for all frame i have the last modified bitmap that is a whole circle.

i have run out my ideas :roll:
bemipefe
Freshman
Freshman
 
Posts: 6
Joined: Fri May 20, 2011 4:55 pm

Re: Animate Circle Drawing

Postby MichaelEGR » Mon May 23, 2011 9:00 pm

>
The problem is that i can't control directly the draw. I mean that i can't control the speed of draw and i don't know how to draw a partial circle and then re-draw the circle with one or more points. The only "refresh" method provided by View class is "invalidate()", but this method only force the onDraw method calling.


Yes. In my middleware / game dev library called TyphonRT I have a callback clock / scheduler that allows one to get fairly accurate callbacks at 60hz, 30hz, 20hz, 15hz, 10hz, etc. For 2D Android support there is a TyphonRuntimeView that manages the clock callback and updates any internal time tracking variables then it calls invalidate() which subsequently calls the onDraw method. So you can attach this view to any callback frequency listed above. That is how I handle things and I should release it soon, but that won't help you now.

You can try and manage this your own way whether a separate thread that manages time / clocking and provides a callback interface or a somewhat hacky way of say posting a delayed invalidate from the View itself by "postInvalidateDelayed()". There are more methods available than invalidate(). So you'd calculate each frame the approximate delay time based on current time and whatever frequency you want to hit. I'm certainly not saying this is the only or even best way of doing things, but it's quick and easy.

---------------

To the second question on how to store the previous frame. You should only create a Bitmap that is the size of the circular object you are drawing; not even full screen. Each frame you will add in another marker or continue drawing the circle. You save that bitmap between frames and keep drawing to the bitmap then draw the bitmap to the View in the onDraw method. After every cycle (revolution, etc.) you need to clear the bitmap so that what you have previously rendered into it dissapears. Again this is all highly dependent on what you are trying to draw.

---------------

In Android 3.0+ there is a new property animation system that could help, but it really doesn't because it's not backward compatible for pre Honeycomb devices. http://developer.android.com/guide/topics/graphics/animation.html
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Re: Animate Circle Drawing

Postby bemipefe » Wed May 25, 2011 2:23 pm

You can try and manage this your own way whether a separate thread that manages time / clocking and provides a callback interface or a somewhat hacky way of say posting a delayed invalidate from the View itself by "postInvalidateDelayed()"


This is what i have tried to do but without results. Then i have read this Andorid guide which has brought me light. For first i have learn that thing:

Note: In order to request an invalidate from a thread other than your main Activity's thread, you must call postInvalidate().


... not the invalidate() method i have done.
And the second thing is that when i use drawBitmap() inside onDraw i have to pass null as Paint object for some strange reason. This is the basic View that i used to test the animation:

Code: Select all
public class RenderView extends View
{
   
    SurfacePainter surfPainter;
    Bitmap frameBitmap;

    public RenderView(Context context)
    {
        super(context);

        frameBitmap = Bitmap.createBitmap(320, 240, Bitmap.Config.RGB_565);
        surfPainter = new SurfacePainter(frameBitmap);
        surfPainter.start();
    }

    @Override
    public void onDraw(Canvas canvas)
    {
        canvas.drawBitmap(frameBitmap, 0, 0, null); //Paint object is null
    }

    class SurfacePainter extends Thread
    {
        Bitmap frameBitmap;
        int i;


        public SurfacePainter(Bitmap frameBitmap)
        {
            this.frameBitmap  = frameBitmap;
        }

        @Override
        public void run()
        {
            try
            {
                 for(i = 0 ; i < 100 ; i++)
                {                   
                    frameBitmap.setPixel(50 + i, 50 + i, Color.WHITE);
                    postInvalidate();
                    sleep(40); // ~25 fps
                }

            }
            catch(Exception ex)
            {
                System.out.println(ex.toString() );
            }
        }
    } 
}
bemipefe
Freshman
Freshman
 
Posts: 6
Joined: Fri May 20, 2011 4:55 pm

Top

Return to Android 2D/3D Graphics - OpenGL Problems

Who is online

Users browsing this forum: No registered users and 3 guests