Rotate 3D got issue in X axis - iphone

I have rotate3d one image.. Here is my code..
CALayer *layer = backImageView.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -300;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 15.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
As before putting background image looks like
After
But when i put one more image as a background it looks like this..
X(-ve) - axis should not be displayed..
Is there any thing wrong in code or need to add extra logic or code ?
Thanks..

I had the same problem. Its happens becouse before rotation both images lay in the same plane, but after rotation part of the image appears behind the plane and covered by another. My solution was to drag one of the images on another plane, so they do not overlap.
grayImage.layer.transform=CATransform3DMakeTranslation(0, 0, -100);
Where grayImage your second image.

Related

Rotate CGRect property of a CCSprite ?

I have a sublclass of a CCSprite that rotates throughout the game and there is a shield that has to rotate around the sprite according to the sprite's rotation. So if the sprite's rotation is 75 degrees there should be a CGRect located at 75 degrees. The dimensions of the CGRect are subordinate as it almost resembles a square.
What I did is:
I subclassed CCSprite and added a property called shieldArea.
Upon initialization I set this rect to be
self.shieldArea = CGRectMake(self.position.x-30, self.position.y, 8, 10);
Then I rotate the sprite itself, however, the rect stays at its initial position.
I hoped that the CGrect would be affected by the rotation, but I kind of expected it not to affect it, of course, why should it ? So, my question is, how do I rotate a CGRect at all ? Or do I have to add a new CGRect all the time ?
Side notes: I do not want to use Box2d or anything the like. I handle collision detection myself.
Have you tried CGAffineTransform?
Something like this:
float centerX = myOldRect.origin.x + (myOldRect.size.width / 2.0);
float centerY = myOldRect.origin.y + (myOldRect.size.height / 2.0);
CGAffineTransform rotation = CGAffineTransformMakeRotation(someAngleInRadians);
CGAffineTransform moveAnchor = CGAffineTransformMakeTranslation(centerX, centerY);
CGAffineTransform centeredRotation = CGAffineTransformConcat(moveAnchor, rotation);
CGRect rotatedRect = CGRectApplyAffineTransform(myOldRect, centeredRotation);
Note, this is NOT tested. Use at your own risk :p

apply 3d animation to view

I'm struggling with animations and can't find anything like i want. I would like to apply a 3d rotation to a view. Like a cube rotation, the view should have two images, and rotate from one to other like iphone notification animation. Animation i want is like this one here: http://www.youtube.com/watch?v=pBgVbzBJqDc
I don't think even one way of how to do this, so any help would be very appreciated!
Thanks in advance!
You can apply a 3D animation to a view by setting a CATransform3D with the transform on the views layer. The rotation will look very flat without any perspective so you should set an appropriate value for the third row and forth column of the transform matrix.
ObjC:
CATransform3D rotation = CATransform3DIdentity;
rotation.m34 = -1.0/500.0;
rotation = CATransform3DRotate(rotation, M_PI, 1.0, 0.0, 0.0);
myView.layer.transform = rotation;
Swift:
var rotation = CATransform3DMakeRotation(CGFloat(M_PI), 1.0, 0.0, 0.0);
rotation.m34 = CGFloat(-1.0/500.0)
firstView.layer.transform = rotation;
You would give the two views suitable values for the angle and position them where they should be on screen.
To make it look like a cube rotation you could also translate the layers half the width of the cubes side (so that it doesn't rotate around the center) before rotating the transform matrix.
rotation = CATransform3DTranslate(rotation, 0.0, 0.0, sideOfCube/2.0);

Applying an inverse CATransform3D to sublayers of a CALayer that has already been transformed

I'm using a CATransform3D transformation to apply a pseudo 3D perspective effect to a view.
I'm using the gyroscope in the iPhone 4 to control the parameters of the transform.
The view I'm transforming has some subviews:
The result is something like this:
My next task is to either prevent the subviews from being transformed as the main view is transformed, or to apply an inverse transform so that the subviews remain unaffected.
My aim is to have each subview perpendicular to the superview, giving the impression that they are "standing".
The code I'm using for the transform:
- (void)update:(NSTimer *)timer
{
roll = [[[_manager deviceMotion] attitude] roll];
pitch = [[[_manager deviceMotion] attitude] pitch];
yaw = [[[_manager deviceMotion] attitude] yaw];
CALayer *layer = [self.view layer];
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, -90 * M_PI / 180.0f, 0.0f, 0.0f, 1.0f); // make landscape again
rotationAndPerspectiveTransform.m34 = 1.0 / -500; // apply the perspective
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, roll, 1.0f, 0.0f, 0.0f);
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, yaw, 0.0f, 0.0f, 1.0f);
[layer setTransform:rotationAndPerspectiveTransform];
}
I have tried the following code in an attempt to invert the transform, by applying a 90 degree perspective rotation to the subview around the Y axis:
for (UIView *subview in [self.view subviews])
{
CALayer *sublayer = [subview layer];
//CATransform3D inverseTransformation = [sublayer transform];
CATransform3D inverseTransformation = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -500; // apply perspective
inverseTransformation = CATransform3DRotate(inverseTransformation, 90 * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
[sublayer setTransform:inverseTransformation];
}
but all this succeeds in doing is making the subviews disappear. If I try to use the existing transform from the layer with [sublayer transform] and apply the 3d rotation to it, then the subviews flicker, but don't rotate.
My knowledge of Matrix math isn't great, so I don't know if this is the correct approach.
How can I make the subviews sit perpendicular to the super view?
I recommend not trying to make the basic approach of calculating each individual transform work. Also, this would be easier using CALayers for each of the little sub views instead of the higher level UIView objects. The basic approach of building a 3D model, and transforming the entire model should work much better for you.
Start with the main layer, add a sublayer for each of the little squares, transform those sublayers into position, then your update: method listed in your question should work to transform everything without modification. John Blackburn has a nice little tutorial that should help greatly.

Question about rotating a slider

I am working on an application which needs to rotate the slider at one end. However, by using CGAffineTransformMakeRotation(), I can only rotate the slider at the centre.
What should I do in order to rotate the slider at the end point? If possible, please give a short paragraph of sample code. Thanks a lot.
I rotate a UIImageView by setting the anchorPoint property for the view's layer. e.g.
myView.layer.anchorPoint = CGPointMake(0.5, 1.0);
and then applying a CATransform3DRotate as the layer's transform property
CATransform3D rotationTransform = CATransform3DIdentity;
rotationTransform = CATransform3DRotate(rotationTransform, positionInRadians, 0.0, 0.0, 1.0);
myView.layer.transform = rotationTransform;
I found this from Apple's metronome example, so it's worth checking that out. Hope that helps
I second cidered's answer. To do what you want using CGAffineTransforms, you have to compose transformations until you get the effect you're looking for:
CGAffineTransform transform = CGAffineTransformMakeRotation(1.0);
transform = CGAffineTransformTranslate(transform, slider.frame.size.width / 2, 0.0);
slider.transform = transform;

How to handle a translation Matrix in an inverted Y axis point of view

My usercase is an iphone application where I do an animation on the scale, rotation and translation of an image.
So, I concat everything and feed it to the transform property, but there is one problem:
Since my images vary in size, it is a problem to position them correctly. I'm used to an inverted y axis coordinate system, so I want my image to positioned exactly at 60 pixels in the y axis.
So, how do I change from the original cartesian y axis to an inverted y axis point of view?
As smacl points out, the easiest way to do this is to shift your origin to the bottom-left of the screen by using (screenheight - viewheight - y) instead of y in the origins of your views.
However, you can flip the coordinate system of your main view's layers using a CATransform3D. I do this so that I can share the same Core Animation CALayer layout code between my iPhone application and a Mac client (the iPhone inverts the normal Quartz coordinate system for CALayers to match that of the UIViews). All you need to do to enable this is to place the line
self.layer.sublayerTransform = CATransform3DMakeScale(1.0f, -1.0f, 1.0f);
in your initialization code for your layer-hosting UIView. Remember that this will flip your CALayers, so any UIKit text rendering in those layers may also need to be flipped using code similar to the following:
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0f, self.frame.size.height);
CGContextScaleCTM(context, 1.0f, -1.0f);
UIFont *theFont = [UIFont fontWithName:#"Helvetica" size:fontSize];
[text drawAtPoint:CGPointZero withFont:theFont];
CGContextRestoreGState(context);
You can do a similar sort of inversion using a CGAffineTransform, but you will also need to apply a translation to make that work:
CGAffineTransform flipTransform = CGAffineTransformMakeTranslation(0.0f, self.frame.size.height);
flipTransform = CGAffineTransformScale(flipTransform, 1.0f, -1.0f);
You may be able to use the affine transform to convert your origin coordinates using CGPointApplyAffineTransform().
For every y ordinate, y = top-y, where top is the y ordinate of the top of the bounding box you are drawing in.