Re: Smooth animation
Re: Smooth animation
- Subject: Re: Smooth animation
- From: arekkusu <email@hidden>
- Date: Wed, 11 Dec 2002 12:10:26 -0800
On Tuesday, December 10, 2002, at 11:03 AM, <email@hidden>
wrote:
>
I am working on a quite simple screen saver which print a text on the
>
screen and translate it in the limits os the screen. The process used
>
to move it is very simple: every 1/50 of a second, I redraw the text
>
one pixel on the left of its previous position. The problem is that
>
this kind of animation is choppy. What could I do to make it smoother?
Arthur,
I have similar problems. The solution here is to make sure you update
your
image at the same rate as your display device. For example, if your
monitor
is set to i.e. 60Hz or 75Hz, you will need to update the image exactly
60 or 75 times a second
in order to make the animation perfectly smooth. If you only do it 59
or 74 times a second,
you will notice that is it choppy (there is a certain limit that the
human eye can perceive
rapid updates at, but you will still notice the dropped frames with
something like a slowly moving rectangle.)
Unfortunately, there does not appear to be any good way to do this in
Cocoa.
There are two problems: you need to a) figure out what the refresh rate
of the display device is,
and b) make sure your update method is called at that frequency.
You can try to do a) via CoreGraphics, something like:
NSDictionary *screen_props = (NSDictionary
*)CGDisplayCurrentMode(CGMainDisplayID());
NSString *refresh = [screen_props objectForKey: (NSString
*)kCGDisplayRefreshRate];
This works fine for CRT monitors, but it will always return "0" for
LCDs, which is wrong. And since almost all
of Apple's current products are sold with LCD displays, it is nearly
useless.
You can try to do b) via NSTimer, something like:
NSTimer *timer = [[NSTimer scheduledTimerWithTimeInterval:
refresh_rate target: self
selector:@selector(update) userInfo:self
repeats:true] retain];
In my testing, there are some problems with this, though. Firstly, I am
unsure how accurate NSTimer really is. The
documentation states: "Because of the various input sources a typical
run loop manages, the effective resolution of the time interval for an
NSTimer is limited to on the order of 50-100 milliseconds." 50-100
milliseconds translates to 10-20 Hz, which is much too slow
to use for anything related to video updates. If you try setting an
NSTimer with a fast rate, like 100Hz, it does seem to
fire that quickly though, so perhaps the documentation is wrong here.
However, I cannot determine if NSTimer is "drift-free",
that is, will it reliably fire at 100Hz, or is it perhaps 100Hz and
then 102Hz and then 98Hz. In my testing it does appear
to drift by (complexity_of_update_method + some_random_factor) and this
makes it ill-suited for getting reliable video updates.
Secondly, OS X is a preemptive multitasking OS. This means that,
depending what other applications are running, your graphic update
may or may not be able to get some CPU time when the timer fires. The
suggested solution to this is to make your application use
a real-time thread, which goes a bit beyond Cocoa, into the mach
kernel. Due to the above problems, particularly a), I haven't tried
this yet.
So, this mail is getting a bit long, but let me say that the proper way
to do this would be to for the display device to generate
a hardware interrupt after every update, which your update method could
be notified by. In OS 9, this was known as a VBLTask.
There does not appear to be any (public) way to do it under OS X. (I'd
love to be proven wrong about this.)
Lacking a proper way to do it, there _is_ a hackish kludgy way, if you
are using OpenGL. Basically, you set an NSTimer to fire at 1000Hz,
much faster than you need it to, and use a double-buffered OpenGL
context set to sync to VBL. When your update method is called,
the graphics hardware will pause for you at VBL which has the effect of
slowing down the actual rate to whatever the display refresh rate is.
This is what much of the Apple sample code does. Of course, if you want
to know what that rate is (for instance, to adjust your animation
speed) you'll have to measure it empirically since there is still no
API to get it programmatically.
HTH,
-alex
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.