Elements/Wired Style 3D Animation - iphone

I am trying to implement the style of 3D rotational animation you see in the Elements and the Wired iPad applications. The animation has the UIScrollView style acceleration so it looks like they have connected a UIScrollView to a sequence of images.
I have tried implementing it in UIKit, using an "empty" UIScrollView to increment through an array of images and set the contents of a UIImageView, based on the content offset. This works but even with scaled down images on the simulator, it is very sluggish. I am not sure how I could optimise it to make it run faster.
Source Code on GitHub
I have also tried doing something similar in Cocos2D. Cocos could animate the sequence very smoothly but I couldn't control the animation. I tried using a scroll view and setDisplayFrame to step through an animation but it didn't work.
Any help or suggestions on either option would be greatly appreciated.

I'm not 100% sure I understand the effect you're trying to achieve, but if you're referring to the images in "The Elements" app which you can spin around, then yeah, you probably don't want to be doing that with an UIScrollView.
You can control the animation of content in Cocos2d. While you can set an animation to "just run", you can also manually set frames directly out of an animation, so if you can get smooth animation out of Cocos, you should be able to do it interactively. Look at the atlas sprite object - you can set the rect of an animation frame directly.
However, again, I'm not sure this is the best approach, either, since that's a lot of frames for a texture. If you're going to be doing a lot of 3D photographic objects, you might consider looking into the video codecs and scrubbing along a video instead of trying to pack all the frames of a rotation animation into a series of textures.
Just so you know, the guy who made "The Elements" wrote an article about the development of the app, and here's what he had to say about the 3D rotatable objects:
"Creating fluidly spinning objects with the level of crystal clear photographic quality I demanded is actually harder than it might seem. A number of the obvious things the more technical of you might think of turn out not to work for reasons too complicated to get into here. Suffice to say that John designed a brilliant solution that uses the iPad's excellent graphics subsystem to lend a hand in ways it's not normally intended to."
I don't know how exactly they achieved the 3D objects, but perhaps that "uses the iPad's excellent graphics subsystem" mention gives you a clue where to head from here...

Related

What is the exact performance cost when mixing OpenGL with UIKit in iPhone?

I need to make a design decision of how to approach an app which needs to render few 3D objects on top of an image texture.
Result needs to be rendered and saved as an UIImage.
Graphical design (client) expects standard UIKit controls to manipulate 3D world.
OpenGL view (CAEAGLLayer layer) needs to be inside UIScrollView for cheap and natural scroll and zooming implementation.
There are just few extra controls to manipulate rotation scale and transition of the few 3D objects.
There is not many triangles expected (100-200 at most) and 2-3 textures (1 mask). It does not even have to be refreshed constantly, just when some transformations and zoom changes.
CAEAGLLayer does not need to be opaque.
I would go with Core Animation solution but rendering 3D transformed CALayers to CGContextRef is not supported (neither is masking).
What is real performance cost when putting CAEAGLLayer inside UIScrollView and mixing it with few UIKit views?
How much triangles per second can I expect to be rendered with smooth frame rate (30fps will do), so I can make the best decision possible?
I know there are similar questions out there already, but none of the answers provides specific numbers, which could help with estimating expected rendering results.
Per Allan Schaffer, who gives the WWDC and WWDC on tour OpenGL speeches, OpenGL itself is not so much a special case — it's that anything that changes will cause everything on top of it to be recomposited. I spoke to him specifically about an app with a live updating video view underneath a live updating OpenGL view and he said that sort of thing is the pathological worst case. It's generally not that expensive to throw a few quite static views on top, such as using a UILabel to display the current score over an OpenGL game.
In your case, I think you can probably largely avoid the problem. Don't put the GL view inside the scroll view, but rather make the scroll view non-opaque and put the GL view behind it. Catch scrollViewDidScroll: (and the corresponding zoom messages) and make related OpenGL adjustments. I can speak from experience and say I've done exactly that on an iPad 1 with no performance issues. Particularly for the sort of model you're talking about I don't imagine a problem.

Can it be done using UIAnimation?

I am developing a game for iPhone and I came across a question whether this can be done using UIAnimation or I have to switch to OpenGL.
If you see the picture above, you can realize there is a rectangle (it will have background image) having many holes in it. User is supposed to touch on holes and initiate the animation. The holes are actually on the image and are not some view. Do you know any article or tutorial I need to read in order to understand this can be done using UIAnimation?
It's more like chess. When you tap a hole, there is a view placed and moved at z-axis and then when you press the other hole, the view is moved to that hole and so on.
I believe it can be done with UIViews too. The holes can be made by using an image with "transparent" holes in it. You can place this UIView on top of a background image(if required). When touches are detected, you can animate another view on top of this view using addSubview:. You can keep this other view outside the screen bounds initially so that the animation seems like a sliding animation.
yes UIView is also an option in your case. if you feel that you will use high quality lots of graphic and will do lots of animation stuff at once on the screen, openGL will be the best or perhaps the gane you are making is a 2d game so you must consider COCOS2D "http://www.cocos2d-iphone.org/" for kick starting your game you'll surely get many effects and other glittering stuff with it. and bes of all it is openGL based..!! Performance will be too high for you..!!
Best of luck..!!

How do I create a custom page curl Core Animation?

I'm trying to create a "page curl" animation of an image in my iPhone application. I t UIViewAnimationTransitionCurlUp, and it's undocumented Core Animation siblings, however the image I need to animate is a transparent PNG, with "uneven" (some alpha pixels) outlines. When using the aforementioned pre-made transition, those alpha pixels are painted black as soon as the animation starts, which looks terribly ugly.
Therefore, I seek to create a Core Animation of my own. I have tried to research the subject, but have been unable to find a good overview of the techniques involved. The implementation would of course have to be more complex than a single property change, I get the feeling that even CATransform3D would be to limited for this purpose, as the image needs to have different 3D transformations applied in different parts of it - changing over time. How would one then go about this subject? I'm very grateful for any thoughts or ideas!
Best,
Eli
As Corey points out, you'll probably need to go with OpenGL ES for this one. Core Animation exposes the ability to work with layers, even in 3-D, but all layers are just rectangles and they are manipulated as such. You can animate the flipping of a layer about an axis, even with a perspective distortion, but the kind of curving you want to do is more complex than you can manage using the Core Animation APIs.
You might be able to split your image up into a mesh of tiny layers and manipulate each using a CATransform3D to create this curving effect, but at that point you might as well be using OpenGL ES to create the same effect.
The book Core Animation for Mac OS X and the iPhone: Creating Compelling Dynamic User Interfaces from Pragmatic Programmer may help you write custom Core Animation animations.

Need help optimizing my 2d drawing on iPhone

I'm writing a game that displays 56 hexagon pieces filling the screen in the shape of a board. I'm currently drawing each piece using a singleton rendering class that when called to draw a piece, creates a path from 6 points based of the coordinate passed in. This path is filled with a solid color and then a 59x59 png with an alpha to white gradient is overlayed over the drawing to give the piece a shiny look. Note I'm currently doing this in Core Graphics.
My first thought is that creating a path everytime I draw is costly and seems like I can somehow do this once and then reuse it, but I'm not sure of the best approach for this. When I look at the bottlenecks with Shark, it looks like the drawing of the png is the most taxing part of the process. I've tried just rendering the png overlay or just rendering the path without the overlay and both give me some frame gains, although removing the png overlay yields the most frames.
My current thought is that at startup, I should render 6 paths (1 for each color piece I have) and overlay them with the png and then store an image of these pieces and then just redraw the pieces each time I need them. Is there an effecient machanism for storing something you've drawn once and redrawing it? It kinda just sounds like I'd be running into the whole drawing pngs too often thing again, but maybe there's a less taxing method that does a similar thing...
Any suggestions are much appreciated.
Thanks!
You might try CGLayer or CALayer.
General thoughts:
Game programming on iPhone usually necessitates OpenGL. Core Graphics is a bit easier to work with, but OpenGL is optimized for speed.
Prerender this "shiny look" into the textures as much as is possible (as in: do it in Photoshop before you even insert them into your project). Alpha blending is hell on performance.
Maybe try PVRTC (also this tutorial) as it's a format used by iPhone's GPU's manufacturer. Then again, this could make things worse depending on where your bottleneck is.
If you really need speed you have to go the OpenGL route. Be careful if you want to mix OpenGL and Core Animation, they can conflict.
OpenGL is a pain if you haven't done much with it. It sounds like you could use Core Animation and make each tile a layer. CA doesn't call the redraw again unless you change something, so you should be able to just move that layer around without taking a big hit. Also note that CA stores the layer in the texture memory so it should be much faster.
Some others have mentioned that you should use OpenGL. Here's a nice introduction specifically for the iPhone: OpenGL ES from the Ground Up: Table of Contents
You might also want to look at cocos2d. It seems to be significantly faster than using CoreAnimation in my tests, and provides lots of useful stuff for games.

Performance and background images for OpenGL ES/iPhone

I'm developing a 2D game for the iPhone using OpenGL ES and I'd like to use a 320x480 bitmapped image as a persistent background.
My first thought was to create a 320x480 quad and then map a texture onto it that represents the background. So... I created a 512x512 texture with a 320x480 image on it. Then I mapped that to the 320x480 quad.
I draw this background every frame and then draw animated sprites on top of it. This works fine except that the drawing of all of these objects (background + sprites) is too slow.
I did some testing and discovered that my slowdown is in the pixel pipeline. Not surprisingly, the large background image is the main culprit. To prove this, I removed the background draw and everything else rendered very fast.
I am looking for advice on how to keep my background and also improve performance.
Here's some more info:
1) I am currently testing on the Simulator (still waiting on Apple for the license)
2) The background is a PVR texture squeezed down to 128k
3) I had hoped that there might be a way to cache this background into a color buffer but haven't had any luck with that. that may be due to my inexperience with OpenGL ES or it just might be a stupid idea that won't work :)
4) I realize that the entire background does not always have to refresh, just the parts that have been drawn over by the moving sprites. I started to look into techniques for refreshing (as necessary) parts of the the background either as separate textures or with a scissor box, however this seems less than elegant.
Any tips/advice would be greatly appreciated...
Thank you.
Do not do performance testing on the simulator. Ever!
The differences to the real hardware are huge. In both directions.
If you draw the background every frame:
Do not clear the framebuffer. The background will overdraw the whole thing anyway.
Do you really need a background texture ?
What about using a color gradient via vertex colors ?
Try using the 2bit mode for the texture.
Turn of all render steps that you do not need for the background.
E.g.: Lighting, Blending, Depth-Test, ...
If you could post some of your drawing code it would be a lot easier to help you.
If you're making a 2D game, is there any reason you aren't using an existing library? Specifically, the cocos2d for iPhone may be worth your time. I can't answer your question about how to fix the issue doing it all yourself, but I can say that I've done exactly what you're talking about (having one full screen background with sprites on top) with cocos2d and it works great. (Assuming 60 fps is fast enough for you.) You may have your reasons for doing it yourself, but if you can, I would highly suggest at least doing a quick prototype with cocos2d and seeing if that doesn't help you along. (Details and source for the iPhone version are here: http://code.google.com/p/cocos2d-iphone/)
Thanks to everyone who provided info on this. All of the advice helped out in one way or another.
However, I wanted to make it clear that the main issue here turned out to be the behavior of simulator itself (as implied by Andreas in his response). Once I was able to get the application on the device, it performed much, much better. I mention this because, prior to developing my game, I had seen a lot of posts that indicated that the device was much slower than the simulator. This might be true in some instances (e.g. general application logic) but in my experience, animation (particularly 3d transformations) are much faster on the device.
I dont have much experience with OpenGL ES, but this problem occurs generally.
Your idea about the 'color buffer' is good intuition, essentially you want to be storing your background as a frame buffer and loading it directly onto your rendering buffer before drawing the foreground.
In OpenGL this is fairly straight forward with Frame Buffer Objects (FBO's). Unfortunatly I dont think OpenGL ES supports them, but it might give you somewhere to start looking.
you may want to try using VBOs (Vertex Buffer Objects) and see if that speeds up things. Tutorial is here
In addition, I just saw, that since OpenGL ES v1.1, there is a function called glDrawTex (Draw Texture) that is designed for
fast rendering of background paintings, bitmapped font glyphs, and 2D framing elements in games
You could use frame buffer objects similar to the GLPaint example from Apple.
Use a texture atlas to minimize the number of draw calls you make. You can use glTexCoordPointer for setting your texture coordinates that maps each image to its correct position. Remember to set your vertex buffer too. Ideally one draw call will render your entire 2D scene.
Avoid enabling/disabling states where possible.