CATransform3D - go back to previous state - iphone

Hi I`m working with CATransform3D.
Every time that I call the following method with the variable radian the UIImageView is rotated “radian * M_PI” from the previous angle.
I trying to go back to the original state. There is any way to do that?
I mind I want to sent a radian value i.e. 10 and that the view maintain these angle if is called more than once.
METHOD:
CATransform3D rotatedTransform = self.needleB.layer.transform;
rotatedTransform = CATransform3DRotate(rotatedTransform, radian * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
self.needleB.layer.transform = rotatedTransform;
self.needleB.layer.anchorPoint = CGPointMake(0.5, 0.9);
self.needleB.center = CGPointMake(160, 250);
Thanks !!

To undo all transforms, assign the transform property of your layer to CATransform3DIdentity.

Related

draw function causes app to lag

I'm using a draw function to highlight the score inserted into a table of highscores but i find that it makes my app lag when i try to leave the highscore layer. I'm still relatively new to cocos2d so I was wondering if there is a better way so it doesn't cause any lag. I find if i comment out this function that the isn't any lag. Heres my code:
- (void)draw {
[super draw];
if(currentScorePosition < 0 || currentScore==0) return;
float w = 320.0f;
float h = 20.0f;
float x = (320.0f - w) / 2.0f;
float y = 230.0f - currentScorePosition * h;
CGPoint vertices[4];
vertices[0] = ccp(x, y);
vertices[1] = ccp(x+w, y);
vertices[2] = ccp(x+w, y+h);
vertices[3] = ccp(x, y+h);
CCDrawNode *draw = [[[CCDrawNode alloc] init] autorelease];
[draw drawPolyWithVerts:vertices count:4 fillColor:ccc4f(0.5, 0.5, 0.8, 0.5) borderWidth:2.0 borderColor:ccc4f(0.0, 0.0, 0.0, 0.0)];
[self addChild:draw z:0 ];
}
You're creating a new CCDrawNode every frame. Over time this will slow down the game as it has to draw more and more draw nodes.
Solution: create one draw node up front and add it as child. Keep a reference to it in an ivar. Perform drawing with just this single draw node.
Note that the draw methods of CCDrawNode are still additive. If you want to draw just this one polygon and update it over time, then you'll have to call clear before drawing:
[theDrawNode clear];
[theDrawNode drawPolyWithVerts:vertices
count:4
fillColor:ccc4f(0.5, 0.5, 0.8, 0.5)
borderWidth:2.0
borderColor:ccc4f(0.0, 0.0, 0.0, 0.0)];
Another note: you can use the draw node outside the draw method. In fact if you run the code like you did, the draw node won't be drawn until the next frame and thus it'll always lag 1 frame behind. Use a scheduled update method to update the draw node.

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

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.

Rotate 3D got issue in X axis

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.

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;