How to Achieve Landscape View Properly

Member
Posts: 241
Joined: 2008.07
Post: #1
Okay, I recently posted a question inquiring how to rotate the OpenGL view, it was suggested that I rotate GL_PROJECTION matrix. This works to a certain extent but when I got to trying to swap to orthographic projection and back, rotate or translate anything in space, it got really confusing because everything else's Y axis is now pointing right or somewhere other than up. (See: Horizontal view - 2008.10.26, 02:51 PM)

I found out that you can automatically make the phone rotate by going into the AppController's

Code:
- (void)applicationDidFinishLaunching:(UIApplication*)application

and add the following line of code:

Code:
    [application setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];  // or left

All this does is flip the phone for you automatically, it does nothing to the projection matrix or the view.

You can also get rid of that status bar for a more full-screen event by going into the info.plist and adding the following property:

UIStatusBarHidden

Make it a boolean type and check the checkbox. Voila.

Now for what to do to deal with the view:

1) Again, go to the app controller or wherever you have access to your OpenGL view pointer. You should see a line of code something like this:

Code:
    CGRect rect = [[UIScreen mainScreen] bounds];

It won't work like that, you'll need to add a few more lines.

Code:
    float swapTemp = rect.size.height;
    rect.size.width = rect.size.height;
    rect.size.height = swapTemp;

There may be a more appropriate way to get that data, (and if there is, please tell me), but obviously what it's doing is swapping the width and height. A few lines later, you should see a line of code that looks like:

Code:
    GLInheritedView *glView = [[GLInheritedView alloc] initWithFrame:rect];

Sometime after that line, is where you put the magic that I was looking for:

Code:
    [glView setTransform:CGAffineTransformMakeRotation(PI/2.0f)]; // This will be different if you rotate left.

Not quite done yet! Make sure anywhere you have code that asks for the perspective or view port, you change it to 480 by 320 rather than 320 by 480.

That should do it! I hope it helps. I know everyone has been very helpful to me lately and I wanted to give some back. Thanks again!!
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #2
You can also rotate to landscape using the Info.plist key UIInterfaceOrientation (instead of setStatusBarOrientationSmile. Set it to UIInterfaceOrientationLandscapeRight.

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Member
Posts: 241
Joined: 2008.07
Post: #3
Does that actually rotate the view or just the simulator?
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #4
It does the same as what calling setStatusBarOrientation does.

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Member
Posts: 87
Joined: 2006.08
Post: #5
The iPhone documentation for OpenGL specifically warns against what you're doing. You'll pay a hefty performance price for this.

Stick with modifying the projection matrix.
Quote this message in a reply
Member
Posts: 241
Joined: 2008.07
Post: #6
Frogblast Wrote:The iPhone documentation for OpenGL specifically warns against what you're doing. You'll pay a hefty performance price for this.

Stick with modifying the projection matrix.

Can you give me a reference as to where to look to read this warning?
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #7
bmantzey Wrote:Can you give me a reference as to where to look to read this warning?

It says it in the iPhone Application Programming Guide, under Drawing with OpenGL ES:

"If your application needs to present landscape content, avoid transforming the layer."

I've tested it, just for kicks, and it does indeed incur a significant performance hit if there are any transforms of the layer. You can see for yourself, if you have the layer transformed, you can do this in your EAGLView to remove the layer's transforms:

Code:
[self.layer setTransform:CATransform3DIdentity];
Quote this message in a reply
Member
Posts: 241
Joined: 2008.07
Post: #8
Ugh, so if I go back to rotating the projection, how can I make the rest of my 3D objects so that Y is up?

Maybe I don't understand the matrices very well. I know there's a local and a world matrix. Would I transform both of them or just the world or what?
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #9
Yes, it sounds like you need to study up on matrices. It'll be well worth the effort though, so spend some time on it and take it slow.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #10
*perks up and plugs own tutorial*

http://sacredsoftware.net/tutorials/Matr...ices.xhtml
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #11
I don't get what's the problem.

Say you want to draw 3d then 2d (orthografic) on top you

-setup the projection matrix for 3d perspective
-place your camera
-if you need to rotate your view you basically have to glRotate around (0,0,1) AFTER you have setup your perspective matrix and your camera (and before drawing the objects)
-translate and rotate your objects according to their position-rotation, then draw them

-setup the projection matrix for 2d (orthografic)
-rotate around (0,0,1) if needed
-draw your stuff

to avoid rotation in 2d affecting that in 3d and viceversa just glLoadIdentity() before setting up each projection matrix.

You might not have clear the thing with "projection matrix" and "modelview matrix", they're basically the same thing, they all get stacked up( i.e. multiplied) to form the actual matrix that is applied to draw your objects on screen.

You usually use the projection matrix for stuff like setting up the 3d perspective or the orthografic view, then modelview to move your camera and objects around, but you could use either indifferently.

when you call glMatrixMode(GL_PROJECTION) all matrix operations are applied to the projection matrix, until you call glMatrixMode( GL_MODELVIEW) from there on the operations are applied to the modelview matrix.

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Member
Posts: 241
Joined: 2008.07
Post: #12
awesome, awesome, awesome! Thanks for taking the time to help out everyone!
Quote this message in a reply
Nibbie
Posts: 4
Joined: 2008.11
Post: #13
AnotherJake Wrote:It says it in the iPhone Application Programming Guide, under Drawing with OpenGL ES:

"If your application needs to present landscape content, avoid transforming the layer."

I've tested it, just for kicks, and it does indeed incur a significant performance hit if there are any transforms of the layer. You can see for yourself, if you have the layer transformed, you can do this in your EAGLView to remove the layer's transforms:

Code:
[self.layer setTransform:CATransform3DIdentity];
Hi,
do you have some sample code fot the method suggested by Apple? I'm a beginner and I don't know how to do this.

Any help would be great!
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #14
I can't really think of any sample code off-hand. In OpenGL, all you'd need to do is rotate your "camera" matrix 90 degrees. Assuming you're using a default or standard y-up, looking down the negative z-axis projection, that'd be done with something like glRotatef(90.0f, 0.0f, 0.0f, 1.0f);

What you'd want to avoid is letting the iPhone rotate the view by returning YES in
Code:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOr​ientation

If you do want to let it rotate, as I sometimes do (for the effect), then what I do is let it rotate and then stabilize for a half second and then copy the layer transform for later and set the layer transform to the identity (using setTransform:CATransform3DIdentity), and then rotate the GL matrix instead. It's kind of an awkward hack, but it seems to work for me so far. I don't know that I'd recommend it, but that's what I do... I wish Apple would fix this little issue, but I'm sure they have their reasons.
Quote this message in a reply
Nibbie
Posts: 4
Joined: 2008.11
Post: #15
I can't get it working... I've been trying it for the complete last night! Wacko

this is my code where in the controller the EAGLView is set up. The test-texture is 480px in width and 320px in height. So it schould be displayes in landscape.
All I get is a totally distorted image.
I tried several combinations as you can see in my code.

Code:
- (void)loadView {
    CGRect rect = [[UIScreen mainScreen] bounds];
    
    float swapTemp = rect.size.width;
    rect.size.width = rect.size.height;
    rect.size.height = swapTemp;
    glView = [[MyEAGLView alloc] initWithFrame:rect];
    
    //Set up OpenGL projection matrix
    glMatrixMode(GL_PROJECTION);
    glRotatef(90, 0, 0, 1);
    glOrthof(0, rect.size.width, 0, rect.size.height, -1, 1);
    //glRotatef(-90.0f,0.0f,0.0f,1.0f);
    glMatrixMode(GL_MODELVIEW);
    
    //Initialize OpenGL states
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_TEXTURE_2D);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    _textures[kTexture_Test] = [[Texture2D alloc] initWithImage: [UIImage imageNamed:@"test.png"]];
    glBindTexture(GL_TEXTURE_2D, [_textures[kTexture_Test] name]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
    //Render the Title frame
    glDisable(GL_BLEND);
    [_textures[kTexture_Test] drawInRect:rect];
    glEnable(GL_BLEND);

    //Swap the framebuffer
    [glView swapBuffers];
    
    //enable landscape
    //[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
    self.view = glView;
}

I always get something like this:
http://img58.imageshack.us/my.php?image=bild1ci1.png
In this picture the phone isn't in landscape mode, but this should be no matter. I only want the X and Y axis swapped as if I had a display that has a size of 480px in its width and 320px in its height.

edit:
Got it... I don not need to swap the height and width if I'm rotating the view...
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Attempting to add landscape IB buttons to an openGL View Madrayken 1 3,764 Oct 17, 2010 07:03 AM
Last Post: iamflimflam1
  Landscape app sometimes thinks portrait bruss14 1 2,206 Dec 30, 2009 01:32 PM
Last Post: bruss14
  Chipmunk moonbuggy dynamic landscape wonza 5 3,692 Nov 6, 2009 01:08 AM
Last Post: wonza
  iPhone opengl 2d sprites landscape mode mnorton 6 5,615 Sep 9, 2009 08:27 PM
Last Post: mnorton
  How can I add autorotate (landscape, portrait) to an OpenGL ES app? riruilo 6 9,293 Feb 12, 2009 07:51 AM
Last Post: AnotherJake