I worked on C25K again today. This post is detail about developing using CALayer in the iPhone SDK.
I want C25K to have a 3d feel to it. Most of this is going to be faked up with static, hand drawn art work, but part of the 3D display needs to interactively slide in and out of the screen. This really needs actual 3d rendering.
Apple’s iPhone OS (and OS X) supports a relatively light weight scene graph style of programming in the form of the CALayer class hierarchy. What seems to be happening in the background is that CALayers are rendered in to openGL textures and composited on to the screen as textured rectangles. This makes CALayers extremely quick to render because all modern machines can do this with eye watering speed using their 3d rendering hardware.
The cool thing is that although it pretends to be 2D most of the time, the CALayer scene graph actually tracks all the CALayer objects using homogenous 3D co-ordinates. By making a tweak (that is barely documented by Apple), it is possible to make your scene spring dramatically in to the third dimension.
Apple show how to unleash the feature in Listing 2 of their Core Animation Programming Guide. To find out how to actually use this, take a look at the Core Animation: 3D Perspective article in Watching Apple. It could also be useful to have Wikipedia’s Perspective Projection article to hand.
The attraction of this over diving down in to openGLes for rendering is that that I’m pretty rusty with openGL. Hey! It’s been a while, okay?! I’m finding that this developing software for your self is quit a big deal, and I want to minimise my risks at the moment by removing chunks of unknown. So – using Apple’s finely crafted work is attractive.
But is it finely crafted? Well, it does seem to actually work pretty well. I’ve found a few wrinkles, but I’d expect a little bit of faffing.
Here’re some troubleshooting points…
I found that CASrollLayer defaults to clipping its sub layers. I didn’t originally want to bother setting the scroll layer’s bounds, and thought it wouldn’t clip them. That’s easy to fix up though.
There seems to be something a bit strange with the 3d culling of sub layers. I found that my sub layers would clip while still visible. I managed to fix this by giving their parent view a bounds that included its children.
Things didn’t work well when I set up a perspective transform matrix for the “transform” property of the layer of the containing view. I think others I have found this. I rectified this by setting up the layer’s “sublayerTransform” as a perspective transform instead.
The main issue I’ve found is that I’m looking at my CALayer from the side. This means that over its surface, the texture is at several different resolutions. What ever rendering Apple have put in place isn’t dealing well with this. Maybe I need to explicitly set up mipmaps somehow, but I think I would need anisotropic filtering anyway, and I’m not sure the hardware even supports that. I’ve worked round this by limiting the high frequency content of the layer to prevent it jittering too badly, but it’s not an ideal solution. For background on what I’m gassing about here, the Wikipedia Anisotropic Filtering entry gives the gist.