From: Frogblast, an Apple developer:
“Asking CA (CoreAnimation) to apply rotations to your content is often slower than doing the work yourself within your own drawing with glRotate. glRotate is effectively free, while CA might have to do more compositing work to get your image into an orientation that'll fit on the display. The significance of that performance cost varies across devices, with the newer hardware being much less sensitive to this (but it still isn't free).
Going down the glRotate path does (as you observed) make it more difficult to gracefully handle UIKit views at the same time. The iPhone, iPhone 3G, and 1st Gen iPod touch will pay the most severe performance penalty.
Getting autorotation to work should be straightforward, so you should try it first and see if that meets your performance needs on your target devices (everything? recent devices? ipad only?), and then start looking into glRotate if needed.”
UIViewControllershouldAutorotateToInterfaceOrientation: should return YES for the supported orientationswillRotateToInterfaceOrientation:duration: should resize the EAGLView if it supports both portrait and landscape orientationsCCDirector should set the orientation to Portrait. DON'T modify the orientation using CCDirector in this method.Features and limitations:
EAGLView will be always in the “correct” orientationUIKit objects will auto rotate if the EAGLView is rotated.Full working sample:
Sample:
// App Delegate - (void) applicationDidFinishLaunching:(UIApplication*)application { window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; CCDirector *director = [CCDirector sharedDirector]; // // Init the UI View Controller // viewController = [[rootViewController alloc] initWithNibName:nil bundle:nil]; viewController.wantsFullScreenLayout = YES; EAGLView *glView = [EAGLView viewWithFrame:[window bounds] pixelFormat:kEAGLColorFormatRGBA8 depthFormat:GL_DEPTH_COMPONENT24_OES preserveBackbuffer:NO]; // // attach the openglView to the director // [director setOpenGLView:glView]; // // VERY IMPORTANT: // If the rotation is going to be controlled by a UIViewController // then the device orientation should be "Portrait". Default orientation is Portrait // [director setDeviceOrientation:kCCDeviceOrientationPortrait]; // // make the OpenGLView a child of the view controller // [viewController setView:glView]; // // make the View Controller a child of the main window // [window addSubview: viewController.view]; [window makeKeyAndVisible]; // Run the intro Scene [[CCDirector sharedDirector] runWithScene: [HelloWorld scene]]; }
// // UIViewController // // Override to allow orientations other than the default portrait orientation. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations // eg: Only support landscape orientations ? // return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || // interfaceOrientation == UIInterfaceOrientationLandscapeRight ); // eg: Support 4 orientations return YES; } // // The EAGLView MUST be resized manually // -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { CGRect rect; if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) rect = CGRectMake(0, 0, 768, 1024); else rect = CGRectMake(0, 0, 320, 480 ); } else if(UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) rect = CGRectMake(0, 0, 1024, 768); else rect = CGRectMake(0, 0, 480, 320 ); } EAGLView *glView = [[CCDirector sharedDirector] openGLView]; glView.frame = rect; }
CCDirector. The EAGLView object won't be rotated, but the glRotatef() command will rotate all the rendered objects.shouldAutorotateToInterfaceOrientation: should return NO. But it should rotate the interface using CCDirectorFeatures and limitations:
glRotatef() commandUIKit objects won't rotate automatically. You'll have to rotate them manually.Sample:
// // App Delegate: Very similar to the previous sample // - (void) applicationDidFinishLaunching:(UIApplication*)application { window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; CCDirector *director = [CCDirector sharedDirector]; // // Init the UI View Controller // viewController = [[rootViewController alloc] initWithNibName:nil bundle:nil]; viewController.wantsFullScreenLayout = YES; EAGLView *glView = [EAGLView viewWithFrame:[window bounds] pixelFormat:kEAGLColorFormatRGBA8 depthFormat:GL_DEPTH_COMPONENT24_OES preserveBackbuffer:NO]; // // attach the openglView to the director // [director setOpenGLView:glView]; // // Set the initial orientation. eg: Landscape Left // [director setDeviceOrientation:kCCDeviceOrientationLandscapeLeft]; // // make the OpenGLView a child of the view controller // [viewController setView:glView]; // // make the View Controller a child of the main window // [window addSubview: viewController.view]; [window makeKeyAndVisible]; // Run the intro Scene [[CCDirector sharedDirector] runWithScene: [HelloWorld scene]]; }
// // UIViewController // // // Rotate manually using CCDirector // - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // // IMPORTANT: // InterfaceOrientation is the opposite of DeviceOrientation // if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) { [[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeRight]; } else if( interfaceOrientation == UIInterfaceOrientationLandscapeRight) { [[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeLeft]; } // // MUST return NO. // return NO; }
UIViewControllerFeatures and limitations:
Sample:
- (void) applicationDidFinishLaunching:(UIApplication*)application { // CC_DIRECTOR_INIT() // // 1. Initializes an EAGLView with 0-bit depth format, and RGB565 render buffer // 2. EAGLView multiple touches: disabled // 3. creates a UIWindow, and assign it to the "window" var (it must already be declared) // 4. Parents EAGLView to the newly created window // 5. Creates Display Link Director // 5a. If it fails, it will use an NSTimer director // 6. It will try to run at 60 FPS // 7. Display FPS: NO // 8. Device orientation: Portrait // 9. Connects the director to the EAGLView // CC_DIRECTOR_INIT(); // Obtain the shared director in order to... CCDirector *director = [CCDirector sharedDirector]; // Sets landscape mode [director setDeviceOrientation:kCCDeviceOrientationLandscapeLeft]; CCScene *scene = [CCScene node]; [scene addChild: [nextAction() node]]; [director runWithScene: scene]; }
Don't forget to update your accelerometer code.
You should also test that your accelerometer code also works with different orientations!