views:

883

answers:

4

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?

+1  A: 

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.

Kriem
Basically: Can I put an "OpenGL ES view" inside a UIScrollView? Then that would be cool.
Thanks
I'm afraid not. It's OpenGL all the way or not. I know it sounds a bit frustrating or dissapointing. But rest assure, 20 days of learning and you're creating an above expectation performing OpenGL ES app.
Kriem
I don't think OpenGL is an obvious fit here. You can get good performance with CALayers; you just have to be judicious about the number of transactions you commit for instance.
Andrew Pouliot
User "Thanks" says: "5 of those views are fine, but 12 have a very bad performance.". The number of transactions seem to be the bottleneck.
Kriem
A: 

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.

Georg
I agree. It's more or less my point. If user "Thanks" doesn't require a frame to frame based recalculation of transformation, he should be golden. I'm afraid thought that he surpassed that simplicity and is trying to create a more active app.
Kriem
well, while the views rotate (animated), the user must see that changes, otherwise it wouldn't be a "real" animation ;) ...things would just change from state A to B, but not "smoothly". However, for testing: How could I switch off that there happens a frame to frame recalculation?
Thanks
Turning off animations: [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; or animation.duration=0.f;
Kriem
Isn't there a way to cache the view and rotate/scale the cached image?
Georg
The iPhone already does that for you. No need for cashing.
Kriem
+2  A: 
  1. Shark it. You must know what exactly is slow to continue.

  2. Try increasing that update interval from 0.02s to something like 0.1s; is that acceptable?

  3. If all of the images are being rotated together, use a sublayerTransform on the super-layer instead of transforming each individually

  4. 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?

  5. 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.

  6. 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?

Andrew Pouliot
+1  A: 

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.

duncanwilcox