Combining UIView animation blocks and OpenGL ES rendering - iphone

I am developing an iP* game and I make use of both UIKit and OpenGL ES 2.0. The UIKit elements are rendered over the OpenGL view and occupy a significant (arbitrary) amount of screen space. I must admit that Apple has done an excellent work and the frame rate of the game is always 60 FPS.
In order to come to this conclusion I made many tests regarding the performance:
I added lots of static (not moving) UIViews over the OpenGL view -- OK!
I animated using custom code the same UIViews (modified the center property in the drawFrame method of my game) -- OK!.
I added many OpenGL ES elements under the UIViews -- OK!
I added many moving OpenGL ES elements under the UIViews -- OK!
So, now I want to make use of the Core Animation Framework in order to animate the UIKit elements. I make use of
[UIView animateWithDuration:delay:options:animations:completion:]
in oder to perform the animations (I target iOS 4 or newer).
The problem now is that the frame rate has this weird behavior: Sometimes I get 60 fps with many many UIKit animating elements (30 elements is OK for me) and some other times the frame rate is obviously under 60 fps even with a single animating UIKit element but I cannot measure it with Instruments! Let me explain more: When I open Instruments and monitor the core animation and/or OpenGL driver I get always 60 fps. But it is obvious that this is not the case, I can see with my eyes the OpenGL animations to move much slower than the corresponding UIKit animations on the top. If I remove the UIKit elements from the view the frame rate comes back to normal. A similar situation with the one I describe here happens in any OpenGL ES game when the user changes the volume of the device while playing the game. When the transparent view that shows the current volume starts fading out and until it completely fades away the frame rate drops drastically, but in the instruments (I ve made this test too) it is stuck on 60 fps!
So, to sum up: sometimes I get real 60 fps with block animations with no ups and downs for a run and some other times I get fake 60 fps with no ups and downs.
Do you have any solution to this?
All tests were performed on an iPad 2 and iPhone 3GS with iOS 5.1

I managed to solve the problem and now I can combine UIView block/core based animations in my OpenGL game without any performance drop.
The solution is quite simple:
For each UIView that you want in your OpenGL app, keep its bounds, center and transform properties in your OpenGL screen coordinate system (e.g. create the following properties: GLBounds, GLCenter, GLTranform) and update them accordingly whenever you change one of the corresponding UIView properties.
When you start the game, load the UIViews but set them to hidden. So, UIKit does not draw on top of the OpenGL view (this way the frame drop issue is completely elliminated).Instead draw the UIViews yourself using the GL* properties you created in step 1, and using the corresponding textures (the images/colors you used for every UIView).
Animate the hidden UIViews properties (bounds, center and transform) using block/core animation depending on the animation you want to achieve (which in turn updates your GL* properties) and in your OpenGL draw method use the GL* properties to draw the UIViews! To get the actual values for bounds, center and transform when a UIView is animating (and update the GL* properties) use its presentationLayer property.
Best,

Related

iOS - rotating a sphere and responding to touch

I've been tasked with creating a sphere that can be rotated by touch (or animated) along one axis, like a regular globe. I should also be able to draw animated lines on this sphere (eg. draw a line between Sydney and New York). I usually do all my animations in 2D, typically using core animation as I've never really had a need to do anything else. I have a feeling that this sort of problem though requires me to jump into OpenGL.
My question is whether it would be possible to achieve this using core animation (time is of the essence), or if I do need to quickly learn OpenGL. If so, is this a fairly simple problem to solve? I'm a pretty good programmer, but I have no OpenGL experience. Would a capable programmer be able to do this in say 2 weeks?
As a further question, supposing I do use OpenGL, if I then need to do other things in the project (eg. show different screens, or show screens over the top of the sphere), am I able to use UIKit or does the entire project need to be in OpenGL?
Core Animation is for animating views, and basically a 2D animation layer - so it's a no-go for the 3D rotating sphere.
Drawing a textured sphere is rather easy, see this sample
Mixing GL and regular UIView's is not a problem. You can overlay regular controls over the GL view.

Performance Gain Using Multiple CALayers in One UIVew

I'm in the process of writing a simple 2D game which at present does a fair bit of custom drawing for multiple sprites upon each update - i.e. I have game view that delegates to all sprites to perform quartz rendering (point/line based) upon each update.
My performance is ok upto around 50 active objects being rendered but now things are starting to slow down so I'm looking to optimize. To do so I've decided to pre-render my sprites to a CALayer then add that to the game view.
My first thought was to give each Sprite instance a CALayer which is added to the GameView's view.layer as sublayer. This would mean that I use a single UIView which has multiple CALayers - one per game sprite.
Would there be a negligible performance loss if I decided to use a UIView for each game sprite?
UIViews are part of the responder chain and will add extra overhead. I started with UIViews for sprites and found gestures became sluggish.
I would recommend sticking with CALayers
As far as I know, UIViews are pretty lightweight wrappers around CALayer, so the performance loss shouldn't be too big. But I think a sprite would simply be better represented by an instance of CALayer rather than UIView.

How to use particle effects in view based application?

How to use particle effects in view based application?
I have created a game using view based application and I want to use a particle effects in my game. But, I don't have any idea about using a particle in view based application.
Please give some/any idea.
In generally... you can't. Use fullscreen GL for regular particle effect.
Particle effect requires massive count of sprite drawing and alpha blending. You can do this with GL, however, a GL view cannot be overlay over other UIViews.
Normal UIView is implemented with backing CALayer. This is a kind of GL drawing, but optimized for smooth animation of low density UI, not for massive drawing count. So it's performance is too low and unacceptable for particle effect.
I tested CALayer based particle, and 128 particles were max fps with meaningful fps in 3GS.

OpenGL ES as a 2D Platform

I've seen a lot of bandying about what's better, Quartz or OpenGL ES for 2D gaming. Neverminding libraries like Cocos2D, I'm curious if anyone can point to resources that teach using OpenGL ES as a 2D platform. I mean, are we really stating that learning 3D programming is worth a slight speed increase...or can it be learned from a 2D perspective?
GL is likely to give you better performance, with less CPU usage, battery drain, and so on. 2D drawing with GL is just like 3D drawing with GL, you just don't change the Z coordinate.
That being said, it's easier to write 2D drawing code with Quartz, so you have to decide the trade-off.
Cribbed from a similar answer I provided here:
You probably mean Core Animation when you say Quartz. Quartz handles static 2-D drawing within views or layers. On the iPhone, all Quartz drawing for display is done to a Core Animation layer, either directly or through a layer-backed view. Each time this drawing is performed, the layer is sent to the GPU to be cached. This re-caching is an expensive operation, so attempting to animate something by redrawing it each frame using Quartz results in terrible performance.
However, if you can split your graphics into sprites whose content doesn't change frequently, you can achieve very good performance using Core Animation. Each one of those sprites would be hosted in a Core Animation CALayer or UIKit UIView, and then animated about the screen. Because the layers are cached on the GPU, basically as textures, they can be moved around very smoothly. I've been able to move 50 translucent layers simultaneously at 60 FPS (100 at 30 FPS) on the original iPhone (not 3G S).
You can even do some rudimentary 3-D layout and animation using Core Animation, as I show in this sample application. However, you are limited to working with flat, rectangular structures (the layers).
If you need to do true 3-D work, or want to squeeze the last bit of performance out of the device, you'll want to look at OpenGL ES. However, OpenGL ES is nowhere near as easy to work with as Core Animation, so my recommendation has been to try Core Animation first and switch to OpenGL ES only if you can't do what you want. I've used both in my applications, and I greatly prefer working with Core Animation.

Bad performance with core animation and view rotations: How to improve?

I have 12 views which I rotate almost similar to the icons in the home screen when going into homescreen-customization-mode by touching an icon for a few seconds.
I use a 3D transformation code to do the rotations. They have each a duration of just 0.02 seconds, and the angle and direction of rotation changes permanently upon acceleration measurements.
5 of those views are fine, but 12 have a very bad performance. Here's the rotation code:
CATransform3D rotatedTransform = CATransform3DRotate(CATransform3DIdentity, degrees * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
self.layer.transform = rotatedTransform;
there's some core animation wrapped around it. But I see a waste of CPU here, since I don't do any 3D stuff. I really only rotate 2D and nothing else. They're simple UIImageViews, but a custom class that does this rotation animations on her own.
I've heared that there are "affine" transforms which are supposed to work for the 2D space. Would you advise to change that to 2D in this case?
Must I prefer to change the transform of the layer, or of the view? which is faster?
Shark it. You must know what exactly is slow to continue.
Try increasing that update interval from 0.02s to something like 0.1s; is that acceptable?
If all of the images are being rotated together, use a sublayerTransform on the super-layer instead of transforming each individually
Try it w/o animations off, just to confirm that your callbacks are working as you expect (setDisableActions: on CATransaction). Do you see the same things as being slow in Shark when you have them off?
If you're doing this inside a scroll view, you might have other problems. You'll need to take care of things going on/off screen, etc.
3d transforms are the same speed as affine ones in core animation AFAIK. basic sin/cos stuff isn't slowing down the app
More information about the actual effect you're trying to achieve would really help to improve performance.
How big on screen are the images?
CALayer rotations are hardware accelerated, 2D and 3D transforms would be pretty similar, no redraws are happening, no need to go to opengl, no need to cache.
Shark would help, but you would need to know what you are looking for, and what you're looking for is not improving the performance of your current code, but removing your code completely.
Sounds like you are going through your own code waaay too often, for the purpose of changing the angle of each layer. You win when you let CA do the work.
So the strategy here is to find a way to have CA do the work, and call you back less than 50 times a second.
How about a CAAnimationGroup containing a few CAPropertyAnimation for each of your layers and setting up, say, one second of animation at a time?
Once you hand that off to CA, CA will playing it back in its own thread.
My advice is to go OpenGL ES.
Although Core Animation is a tad snappier than "UITransformations", the problem you're facing is a classic one: you're trying to create frame to frame based action with lots of "virtual" sprites floating around. That is not what UIKit is meant to be used for. Especially the animations you're trying to do. Rotation requires trigonometry in order to calculate pixel interpolation. That's quite an expensive procedure.
Unless there are clear restrictions to the intensitivity of the animation, the number of objects animation at the same time, and the frequency of recalculating new transformations, my only advice for you at this point is OpenGL ES.
My experience thus far with the iPhone has been quite alike. Every time we juiced up the app, the current platform could not handle it. We ended up using OpenGL ES, and it's worth the learning curve. The performance is incredible.
I'm sorry for the "bad news", but I strongly advise against using UIKit and Core Animation for frame to frame based apps.
It sounds like your redrawing your views constantly. I'm sure there is a way to disable this and only redraw at the end of the animation.