1

Picture an OpenGL ES 1.1 rendering surface with a transparent CALayer of the same frame and bounds directly above it. Objects in the OpenGL scene are transformed (translated and rotated) using a 4x4 matrix. The overlayed CALayer transforms sublayers with a CATransform3D (which happens to be a 4x4 matrix, identical to ones used for OpenGL transforms).

The OpenGL matrices transform the scene objects in exactly the manner I would like them to. I would then like to take the same matrix transform used on the scene object and have the CALayer apply it to a sublayer such that the sublayer is in the exact same position and orientation as the scene object.

The problem is (I think) that my OpenGL scene and the "scene" of the CALayer don't agree on definition of the arbitrary "scene-unit", and this disagreement manifests itself as discrepancies in the translation of the sub-layer vs. the translation of the scene object (The rotations are fine). Specifically, the CALayer seems to operate with the understanding that a scene unit corresponds very closely to a screen pixel, whereas my OpenGL scene uses much larger units, meaning the CALayer translates only a small fraction of what a scene object does.

So what I'm looking for is a way to mathematically convert a matrix transform specified in my OpenGL scene-units to a functionally equivalent matrix transform specified in the CALayer-scene-unit. I need to be able to define a CALayer-scene-unit in terms of my OpenGL scene unit, but I have no idea how the CALayer is interfacing with OpenGL behind the scenes.

Is it possible to calculate the conversion in such a way? If not, are there other approaches that may help?

NOTE: I've been able to remedy the issue with a purely empirical approach that basically comes down to noting what adjustment needs to be made to the CATransform3D to make it work in a couple positions, and extrapolating. I'm hoping for something more precise.

Matt Wilding
  • 20,115
  • 3
  • 67
  • 95
  • What do you use for `glOrtho()` for your OpenGL ES scene? By adjusting the orthographic matrix, could you bring OpenGL ES coordinate system in line with the CALayer one? – Brad Larson May 04 '11 at 21:59
  • @Brad: I'm not actually using orthographic projection in the OpenGL scene. It's a perspective scene, where the perspective frustum is calculated from the camera parameters of the device on which the app is running. Perspective transforms on CALayers seem like deep magic to me, so I'm unsure of the correlation between the two. – Matt Wilding May 04 '11 at 22:17
  • Do you use `glFrustum()` then? If so, you may need to multiply your model view matrix by the perspective matrix from the `glFrustum()` to get what to use for your CATransform3D, as David suggests. – Brad Larson May 04 '11 at 22:32
  • @Brad, no, I compute a frustum by hand, then just call `glMultMatrixf()` in projection mode. But I see your (and David's) point, nonetheless. Also applying the projection matrix to the CATransform3D does seem to get the transforms into the same coordinate space, which is really what I was going for. Now there are just some smaller kinks (y and z translations are backward, as is rotation around y and z). Thanks for the help. – Matt Wilding May 05 '11 at 16:14

1 Answers1

4

I’m guessing the problems is caused by the OpenGL view’s projection matrix. Remember that the transformation from world to view is view_point = projection x modelview x world_point.

David Cairns
  • 603
  • 5
  • 18
  • The projection matrix, by itself, is fine. The OpenGL scene is rendering correctly, I just need a way to convert OpenGL's modelview / projection matrix for use in the CALayer's coordinate space (which is very, very, very poorly documented). – Matt Wilding May 04 '11 at 19:48
  • I stand corrected. Multiplying the scene's CATransform3D by the projection matrix does indeed (mostly) do the trick. I misunderstood the answer originally. Cheers =). – Matt Wilding May 05 '11 at 16:15
  • @Matt can you write how have you concatenated projection and modelView matrices? I have the same problem, but when I call CATransform3DConcat(modelViewMatrix, _projectionMatrix) the result is quite odd. My transformed CALayer is too far and looks like small dot on the screen. – Zapko May 18 '11 at 07:44
  • 1
    @Zapko: I actually concatenate the modelView and projection matrices with my own C Matrix utilities before making the conversion to a CATransform3D. One thing to note, Open GL ignores the entries corresponding to m14, m24, and m34, but Core Animation uses them for some arcane purpose that only it knows. I explicitly set those entries to 0, and m44 to 1, when making the conversion. – Matt Wilding May 18 '11 at 17:38
  • @Matt-Wilding would you be willing to share your C-based matrix utilities? I'm facing the same issues as in this post, but have had no luck using the `CATransform3DConcat()` function (which should be functionally equivalent, shouldn't it?). – Tony Arnold Aug 07 '11 at 03:49
  • @Tony, I would think `CATransform3DConcat()` should be functionally equivalent to matrix multiplication. My matrix utility code is your standard matrix multiplication that you could find in a simple Google search. I had issues with the way perspective is handled in the CATransform3D. – Matt Wilding Aug 07 '11 at 22:47
  • @Matt, this is the reversal of the translations applied to y and z, as well as the rotations applied to y and z? Was this a flip of the components (y = invert value of y) or swapping y and z? Sorry, I'm not great at matrix maths, but it seems like your findings might get me 99% of the way to where I need to be. – Tony Arnold Aug 08 '11 at 00:52
  • 1
    @Tony, the code I was using to apply the OpenGL matrix stack to the CATransform3D is no longer with me. I didn't like having magic numbers in the 4th column, and the way a layer's perspective is handled is VERY poorly documented. As such, I could never, (even with the correct conversion and some really good magic number guesses) get the layer as tightly integrated as I would have liked. I ended up rendering the layer to a texture and displaying it on a quad in the scene. – Matt Wilding Aug 10 '11 at 16:25
  • Thanks, Matt. That's the method I've chosen as well. I appreciate your advice :) – Tony Arnold Aug 11 '11 at 01:30