title: How to rotate a flat object around its center in perspective view?
body: <p>What I'm trying to do seems like it should be easy enough: I created a 2D top-down view of an old phonograph record.  I want to rotate it (lay it back) in its X axis and then spin it around its Z axis.</p>
  
  <p>I've read every question here that has CATransform3D in the body, I've read Steve Baker's <a href="http://www.sjbaker.org/steve/omniv/matrices_can_be_your_friends.html" rel="noreferrer">"Matrices can be your friends"</a> article as well as Bill Dudney's book "Core Animation for Mac OS X and the iPhone"  I think Brad Larson's <a href="http://www.sunsetlakesoftware.com/2008/10/22/3-d-rotation-without-trackball" rel="noreferrer">"3-D Rotation without a trackball"</a> has all the right code, but since he's permitting the user to adjust all three axis, I'm having a hard time shrinking his code into what I perceive to be just one dimension (a rotated z axis).</p>
  
  <p>Here's the image I'm testing with, not that the particulars are important to the problem:</p>
  
  <p><img src="https://i.stack.imgur.com/EXhku.png" alt="Gold Record"></p>
  
  <p>I bring that onscreen the usual way: (in a subclass of UIView)</p>
  
  <pre><code>- (void)awakeFromNib
  {
      UIImage *recordImage = [UIImage imageNamed:@"3DgoldRecord"];
      if (recordImage) {
          recordLayer = [CALayer layer];
          [recordLayer setFrame:CGRectMake(0.0, 0.0, 1024, 1024)];
          [recordLayer setContents:(id)[[UIImage imageNamed:@"3DgoldRecord"] CGImage]];
          [self.layer addSublayer:recordLayer];
      }
  }
  </code></pre>
  
  <p>That's the first test, just getting it on the screen ;-)</p>
  
  <p>Then, to "lay it back" I apply a transform to rotate about the layer's X axis, inserting this code after setting the contents of the layer to the image and before adding the sublayer:</p>
  
  <pre><code>    CATransform3D myRotationTransform = 
                      CATransform3DRotate(recordLayer.transform,
                                          (M_PI_2 * 0.85), //experiment with flatness
                                          1.0, // rotate only across the x-axis
                                          0.0, // no y-axis transform
                                          0.0); //  no z-axis transform
      recordLayer.transform = myRotationTransform;        
  </code></pre>
  
  <p>That worked as expected: The record is laying back nicely.</p>
  
  <p>And for the next step, causing the record to spin, I tied this animation to the touchesEnded event, although once out of the testing/learning phase this rotation won't be under user control:</p>
  
  <pre><code>CATransform3D currentTransform = recordLayer.transform; // to come back to at the end
  CATransform3D myRotationTransform = 
                  CATransform3DRotate(currentTransform,
                                      1.0, // go all the way around once
                                      (M_PI_2 * 0.85),    // x-axis change
                                      1.00,    // y-axis change ?
                                      0.0);   // z-axis change ?
  recordLayer.transform = myRotationTransform;        
  CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
  myAnimation.duration = 5.0;
  myAnimation.fromValue = [NSNumber numberWithFloat:0.0];
  myAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2.0];
  myAnimation.delegate = self;
  [recordLayer addAnimation:myAnimation forKey:@"transform.rotation"];
  </code></pre>
  
  <p>So I'm pretty sure what I'm hung up on is the vector in the CATransform3DRotate call (trust me: I've been trying simple changes in that vector to watch the change... what's listed there now is simply the last change I tried).  As I understand it, the values for x, y, and z in the transform are, in essence, the percentage of the value passed in during the animation ranging from fromValue to toValue.</p>
  
  <p>If I'm on the right track understanding this, is it possible to express this in a single transform?  Or must I, for each effective frame of animation, rotate the original upright image slightly around the z axis and then lay the result down with an x axis rotation?  I saw a question/answer that talked about combining transforms, but that was a scale transform followed by a rotation transform.  I have messed around with transforming the transform, but isn't doing what I think I should be getting (i.e. passing the result of one transform into the transform argument of the next seemed to just execute one completely and then animate the other).</p>