I'm trying to perform a 3D rotation on a UIView layer using CATransform3DMakeRotation. I'm confused as to why this simple example doesn't show the perspective, but looks squished instead. I can get the rotation to work when using CATransform3DRotate, but I don't want to rotate by, I want to rotate to. Thanks.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    [newView setBackgroundColor:[UIColor orangeColor]];
    UILabel *newLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 50, 20)];
    [newLabel setText:@"Hello"];
    [newView addSubview:newLabel];
    [self.window addSubview:newView];

    CALayer *layer = newView.layer;

    CATransform3D perspective = CATransform3DMakeRotation(1.0, 0, 1, 0);
    perspective.m34 = -1 / 500;

    layer.anchorPoint = CGPointMake(1.0, 0.5);
    layer.zPosition = 99;
    layer.transform = perspective;

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

Here is a screenshot of what it looks like:

Screenshot

UPDATE after David's Answer:

Just to strengthen David's point that order matters, I wanted to see the difference in the matrices and coded this up:

CATransform3D transform1 = CATransform3DMakeRotation(-1, 0, 1, 0);
transform1.m34 = -1.0 / 500.0;

NSLog(@"%f %f %f %f", transform1.m11, transform1.m12, transform1.m13, transform1.m14);
NSLog(@"%f %f %f %f", transform1.m21, transform1.m22, transform1.m23, transform1.m24);
NSLog(@"%f %f %f %f", transform1.m31, transform1.m32, transform1.m33, transform1.m34);
NSLog(@"%f %f %f %f", transform1.m41, transform1.m42, transform1.m43, transform1.m44);

NSLog(@"==============================");

CATransform3D transform2 = CATransform3DIdentity;
transform2.m34 = -1.0 / 500.0;
transform2 = CATransform3DRotate(transform2, -1, 0, 1, 0);

NSLog(@"%f %f %f %f", transform2.m11, transform2.m12, transform2.m13, transform2.m14);
NSLog(@"%f %f %f %f", transform2.m21, transform2.m22, transform2.m23, transform2.m24);
NSLog(@"%f %f %f %f", transform2.m31, transform2.m32, transform2.m33, transform2.m34);
NSLog(@"%f %f %f %f", transform2.m41, transform2.m42, transform2.m43, transform2.m44);

NSLog(@"==============================");

CATransform3D transform3 = CATransform3DIdentity;
transform3 = CATransform3DRotate(transform3, -1, 0, 1, 0);
transform3.m34 = -1.0 / 500.0;

NSLog(@"%f %f %f %f", transform3.m11, transform3.m12, transform3.m13, transform3.m14);
NSLog(@"%f %f %f %f", transform3.m21, transform3.m22, transform3.m23, transform3.m24);
NSLog(@"%f %f %f %f", transform3.m31, transform3.m32, transform3.m33, transform3.m34);
NSLog(@"%f %f %f %f", transform3.m41, transform3.m42, transform3.m43, transform3.m44);

Which produces this output:

0.540302 0.000000 0.841471 0.000000
0.000000 1.000000 0.000000 0.000000
-0.841471 0.000000 0.540302 -0.002000
0.000000 0.000000 0.000000 1.000000
==============================
0.540302 0.000000 0.841471 -0.001683
0.000000 1.000000 0.000000 0.000000
-0.841471 0.000000 0.540302 -0.001081
0.000000 0.000000 0.000000 1.000000
==============================
0.540302 0.000000 0.841471 0.000000
0.000000 1.000000 0.000000 0.000000
-0.841471 0.000000 0.540302 -0.002000
0.000000 0.000000 0.000000 1.000000
有帮助吗?

解决方案

Setting the m34 value doesn't give you perspective for all transforms by magic (unfortunately). Since the rotation changes many different values of the transform you need to set the perspective on an identity message and then rotate that transform.

CATransform3D rotationWithPerspective = CATransform3DIdentity;
rotationWithPerspective.m34 = -1.0/500.0;
rotationWithPerspective = CATransform3DRotate(rotationWithPerspective, angle, 0, 1, 0);

The difference here from what you are doing is that you create an identity matrix and set perspective on that, then you rotate that matrix. The problem is that order matters.


If you know matrix math then you can verify the difference between the two transforms and see why yours does not give you any perspective. If you are interested in learning about the math behind transforms I wrote a blog post about just that (warning: it's quite long and contains only math).

其他提示

I've always found the m34 property to be finicky, try this:

CATransform3D transform = CATransform3DIdentity;

instead of CATransform3DMakeRotation(1.0, 0, 1, 0);

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top