CAKeyframeAnimation different on device / simulator - ios

So I am using a CAKeyframeAnimation to spin a layer 360*s. It works as intended on iPhone 6 and iOS Simulator:
http://www.goloskok.com/u/cap_2016-12-02_12-51-28_pm.mov
but looks different on iPad mini 1st Gen:
http://goloskok.com/u/ipad-C97WYOhVhj.mov
I suspect that this has something to do with iPad mini being 32bit?
The code I'm using is:
[NSValue valueWithCATransform3D:RTSpinKit3DRotationWithPerspective(1.0/120.0, 0.0, 0.0, 0.0, 0.0)],
[NSValue valueWithCATransform3D:RTSpinKit3DRotationWithPerspective(1.0/120.0, 0.5 * M_PI, 0.0, 1.0, 0.0)],
[NSValue valueWithCATransform3D:RTSpinKit3DRotationWithPerspective(1.0/120.0, M_PI, 0.0, 1.0, 0.0)],
[NSValue valueWithCATransform3D:RTSpinKit3DRotationWithPerspective(1.0/120.0, 2 * M_PI, 0.0, 1.0, 0.0)],
[NSValue valueWithCATransform3D:RTSpinKit3DRotationWithPerspective(1.0/120.0, 0.0, 0.0, 0.0, 0.0)]
With the used function being:
CATransform3D RTSpinKit3DRotationWithPerspective(CGFloat perspective, CGFloat angle, CGFloat x, CGFloat y, CGFloat z) {
CATransform3D transform = CATransform3DIdentity;
transform.m34 = perspective;
return CATransform3DRotate(transform, angle, x, y, z);
}

Related

CATransform3DMakeRotation how to stop going off the screen

I am rotating a layer using CATransform3DMakeRotation. I am having two issues:
a) Sometimes going out of the screen
b) Sometimes positioning on top of other layer.
int randrotate=arc4random()%3+1;
CATransform3D trans5=CATransform3DMakeRotation(M_PI*randrotate , 1.0, 0.0, 0.0);
randrotate=arc4random()%4+1;
CATransform3D trans6=CATransform3DRotate(trans5,M_PI*randrotate, 0.0, 0.0, 1.0);
randrotate=arc4random()%3+1;
CATransform3D trans7=CATransform3DRotate(trans5,M_PI_2*randrotate, 0.0, 1.0, 0.0);
CATransform3D trans=CATransform3DRotate(trans7,M_PI*45/180, 0.0, 1.0, 0.0);
CATransform3D trans8=CATransform3DRotate(trans,DEGREES_TO_RADIANS(-45), 1.0, 0.0, 0.0);
CABasicAnimation *ganimation = [CABasicAnimation animationWithKeyPath: #"transform"];
ganimation.beginTime=CACurrentMediaTime();
ganimation.toValue = [NSValue valueWithCATransform3D: trans];
ganimation.duration = 0;
ganimation.cumulative = NO;
ganimation.repeatCount = 0;
ganimation.removedOnCompletion = NO;
ganimation.fillMode = kCAFillModeForwards;
ganimation.delegate=self;
[correctbase addAnimation:ganimation forKey:#"green"];
after animation correct base is changing his position.
Now after animation, I want to put the correctbase in it's original position back, correctbase is a CATransformLayer.
if i try to access presentation layer it's always nil
CATransformLayer *layer=(CATransformLayer*)correctbase.presentationLayer;
Can someone help me?
Thanks in advance.

OpenGL What need to reconfig when rotate screen

I have to make a lib for iOS. There is one UIView class which must support rotation. This class currently using OpenGL ES 1.0 to draw everything. There no problem when the view is in portrait orientation. But when i rotate device / emulator, everything i draw become blurry, not much. I check but they didn't seem like they got stretched. So i thing the reason is that i need to reconfig something in OpenGL like my render buffer after it got rotation. But i'm don't know exactly which one. I'm rather new to OpenGL, because i'm work mostly with Web / Core function.
So if anyone can give me any advice about this matter, please. Which normally should i do when i rotate screen when using OpenGL?
Also please tell me if i need to provide any code for this case.
Thank you
I don't know if this solves your problem or not, but at least it solved mine, so I'll share what I found. My code is in C# via OpenTK, but the OpenGLES interfaces are the same, so I'm pretty sure you can do the same thing in your code.
The thing is that when the device is rotated, the renderbuffer has to be recreated with the landscape dimensions. If you don't do this, the EAGL context will stretch your renderbuffer and make it fit the screen. You will then have squished pixels in the vertical axis, and stretched pixels in the horizontal axis.
This is how I recreate my renderbuffer (in C#) when I detect a rotation (WillRotate)
public void ResizeFrameBuffer(int newWidth, int newHeight)
{
DeviceWidth = newWidth;
DeviceHeight = newHeight;
Size = new System.Drawing.Size(DeviceWidth, DeviceHeight);
Bounds = new System.Drawing.RectangleF(0, 0, DeviceWidth, DeviceHeight);
MakeCurrent();
GL.DeleteRenderbuffers(1, ref renderbuffer);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Framebuffer);
GL.GenRenderbuffers(1, out renderbuffer);
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, renderbuffer);
EAGLContext.RenderBufferStorage((uint)RenderbufferTarget.Renderbuffer, (CAEAGLLayer)Layer);
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, RenderbufferTarget.Renderbuffer, renderbuffer);
GL.Viewport(0, 0, DeviceWidth, DeviceHeight);
GL.Scissor(0, 0, DeviceWidth, DeviceHeight);
Frame = new System.Drawing.RectangleF(0, 0, DeviceWidth, DeviceHeight);
}
There is a bit more information in the question I posted on the Game Development SE, so you may want to check that one out as well.
You can rotate the OpenGL output in the vertex shader as follows:
#version 300 es
in vec4 position;
in mediump vec4 texturecoordinate;
in vec4 color;
uniform float preferredRotation;
out mediump vec2 coordinate;
void main()
{
//const float pi = 4.0 * atan(1.0);
//float radians = (( -90.0 ) / 180.0 * pi );
// Preferred rotation of video acquired, for example, by:
// AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
// CGAffineTransform preferredTransform = [videoTrack preferredTransform];
// self.glKitView.preferredRotation = -1 * atan2(preferredTransform.b, preferredTransform.a);
// Preferred rotation for both portrait and landscape
mat4 rotationMatrix = mat4( cos(preferredRotation), -sin(preferredRotation), 0.0, 0.0,
sin(preferredRotation), cos(preferredRotation), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
// Mirror vertical (portrait only)
mat4 rotationMatrix = mat4( cos(preferredRotation), sin(preferredRotation), 0.0, 0.0,
-sin(preferredRotation), cos(preferredRotation), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
// Mirror horizontal (landscape only)
mat4 rotationMatrix = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, cos(preferredRotation), -sin(preferredRotation), 0.0,
0.0, sin(preferredRotation), cos(preferredRotation), 0.0,
0.0, 0.0, 0.0, 1.0);
// Mirror vertical (landscape only)
mat4 rotationMatrix = mat4( cos(preferredRotation), 0.0, sin(preferredRotation), 0.0,
0.0, 1.0, 0.0, 0.0,
-sin(preferredRotation), 0.0, cos(preferredRotation), 0.0,
0.0, 0.0, 0.0, 1.0);
gl_Position = position * rotationMatrix;
coordinate = texturecoordinate.xy;
}
Obviously, you choose only one matrix4, depending on the orientation of the video, and then its rotation. Each matrix4 flips the video window -- not rotates it. For rotation, you have to first pick the matrix4 based on the orientation, and then substitute the preferredRotation variable with the number of degrees (in radians, the formula for which is also provided).
There are a lot of ways to rotate a view, layer, object, etc.; but, if you're rendering an image via OpenGL, then you should choose this method, and only this method.

Can't assign BoundingVolume for CC3MeshNode

I want to create a CC3MeshNode with boundingvolume in cocos3d. I have created a CC3MeshNode with a pod file. I want to get notification on collision .
-(void) initializeScene
{
[self addContentFromPODFile: #"hello-world.pod" withName:#"pod1"];
CC3MeshNode *object1 = (CC3MeshNode*)[self getNodeNamed: #"pod1"];
CC3MeshNod *object2=[[object1 copyWithName:#"pod1"]autorelease];
[object1 populateAsSolidBox:CC3BoundingBoxMake(9.5, 5.0, 4.0, 0.0, 0.0, 0.0)]; object1.location=cc3v(-5.0, 0.0, 0.0); object2.location=cc3v(5.0, 0.0, 0.0);
[self addChild:object2];
CCActionInterval *move1=[CC3MoveTo actionWithDuration:3.0 moveTo:cc3v(-1.0, 0.0, 0.0)]; CCActionInterval *move2=[CC3MoveTo actionWithDuration:3.0 moveTo:cc3v(1.0, 0.0, 0.0)]; [object1 runAction:move1];
[object2 runAction:move2];
}
-(void) updateAfterTransform: (CC3NodeUpdatingVisitor*) visitor
{
if([object1 doesIntersectNode:object2])
NSLog(#"Collision !!!!!!!!!!!!!!!!!!!!!!");
}
I tried to assign boundingvolume but didnt work. Actually i am confused in implementing boundingvolume for cc3MeshNode
Your comment above says:
I get error in [object1 populateAsSolidBox:CC3BoundingBoxMake(9.5, 5.0, 4.0, 0.0, 0.0, 0.0)];
Here's why you have the error. From the CC3Foundation documentation it looks like you are setting the max values in CC3BoundingboxMake to a value lower than the mins (they are all zero), in the call
CC3BoundingBoxMake(9.5, 5.0, 4.0, 0.0, 0.0, 0.0)];
That is, from the link above, the signature of CC3BoundingBoxMake() is
CC3BoundingBoxMake ( GLfloat minX,
GLfloat minY,
GLfloat minZ,
GLfloat maxX,
GLfloat maxY,
GLfloat maxZ
)
where your minX is 9.5 and your maxX is 0.0, your minY is 5.0 and your maxY is 0.0, and your minZ is 4.0 and your maxZ is 0.0.

Actual landscape OpenGL View on iOS

I'm porting a C++-based engine from Android to iOS and I have some questions on how landscape mode on iOS devices work.
I can successfully start my device on landscape mode but my framebuffer stays on portrait mode no matter how I rotate it (or force its rotation). For instance, I would expect a 960x640 resolution instead of the default 320x480.
I've been researching about it and I saw some people doing this but explicitly rotating the scene using OpenGL, which means the actual axis were not in landscape mode, which for me is an ugly workaround.
Make sure your OpenGL UIView is attached to a UIViewController and not inserted directly into the UIWindow. To do that, create a custom view controller:
#interface MyViewController : UIViewController
#end
#implementation MyViewController
- (void)loadView {
// Create your EAGL view
MyEAGLView *eaglView = [[MyEAGLView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
self.view = eaglView;
[eaglView release];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#end
Then add it to your app's window via the AppDelegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
MyViewController *viewController = [[MyViewController alloc] init];
[self.window setRootViewController:viewController];
[viewController release];
[self.window makeKeyAndVisible];
}
self.window is just the app's UIWindow, you may have to change that if you store the window somewhere else.
After that, the UIViewController takes care of rotations and resizing your view when the device is turned and you can override the layoutSubviews method in your MyEAGLView object to handle resizing the OpenGL context. You may also want to look at Apple's sample code for OpenGL apps since it correctly handles this stuff.
You can rotate the OpenGL output in the vertex shader as follows:
#version 300 es
in vec4 position;
in mediump vec4 texturecoordinate;
in vec4 color;
uniform float preferredRotation;
out mediump vec2 coordinate;
void main()
{
//const float pi = 4.0 * atan(1.0);
//float radians = (( -90.0 ) / 180.0 * pi );
// Preferred rotation of video acquired, for example, by:
// AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
// CGAffineTransform preferredTransform = [videoTrack preferredTransform];
// self.glKitView.preferredRotation = -1 * atan2(preferredTransform.b, preferredTransform.a);
// Preferred rotation for both portrait and landscape
mat4 rotationMatrix = mat4( cos(preferredRotation), -sin(preferredRotation), 0.0, 0.0,
sin(preferredRotation), cos(preferredRotation), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
// Mirror vertical (portrait only)
mat4 rotationMatrix = mat4( cos(preferredRotation), sin(preferredRotation), 0.0, 0.0,
-sin(preferredRotation), cos(preferredRotation), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
// Mirror horizontal (landscape only)
mat4 rotationMatrix = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, cos(preferredRotation), -sin(preferredRotation), 0.0,
0.0, sin(preferredRotation), cos(preferredRotation), 0.0,
0.0, 0.0, 0.0, 1.0);
// Mirror vertical (landscape only)
mat4 rotationMatrix = mat4( cos(preferredRotation), 0.0, sin(preferredRotation), 0.0,
0.0, 1.0, 0.0, 0.0,
-sin(preferredRotation), 0.0, cos(preferredRotation), 0.0,
0.0, 0.0, 0.0, 1.0);
gl_Position = position * rotationMatrix;
coordinate = texturecoordinate.xy;
}
Obviously, you choose only one matrix4, depending on the orientation
of the video, and then its rotation. Each matrix4 flips the video
window -- not rotates it. For rotation, you have to first pick the
matrix4 based on the orientation, and then substitute the
preferredRotation variable with the number of degrees (in radians, the
formula for which is also provided).
There are a lot of ways to rotate a view, layer, object, etc.; but, if
you're rendering an image via OpenGL, then you should choose this
method, and only this method.

How to use CGAffineTransformMakeRotation?

I want to draw text use Quartz 2D. The "menu" direction is wrong. I want "Menu" still readable and have 45 degree with X-axis. Below is my code:
CGContextSelectFont(context, "Arial", 12, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);
CGContextSetRGBFillColor(context, 0, 0, 0, 1); // 6
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
CGContextSetTextMatrix(context, CGAffineTransformMake(1.0,0.0, 0.0, -1.0, 0.0, 0.0));
CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(45));
CGContextShowTextAtPoint(context,10, 10, "Menu", 4);
CGAffineTransformMakeRotation expects angle in radians, not in degrees.
#define DEGREES_TO_RADIANS(x) (M_PI * (x) / 180.0)
...
CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));
[view setTransform:CGAffineTransformMakeRotation(M_PI / 2)];

Resources