iPhone HUD / GUI Newbie

Member
Posts: 31
Joined: 2009.01
Post: #1
Hey Everyone,

I'm a big newb when it comes to the iphone, so please help me out Smile

I'm trying to create a HUD for my game, but am having problems drawing it. I've been looking at this for a couple hours read a bunch of posts and still can't figure out what I'm doing wrong...

Here is the important parts of my code, I've condensed everything into one function so it's easy to follow.

Code:
void CC_UIWindow::Draw()
{
    SetupOrtho();
    
    glDisable(GL_DEPTH_TEST);
    
    //enable vertex arrays
    glEnableClientState(GL_VERTEX_ARRAY);
    
    //enable color blending
    glEnableClientState (GL_COLOR_ARRAY);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, mQuad.mVertColors);
    
    //enable texture mapping
    glEnable(GL_TEXTURE_2D);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    //bind the appropriate texture
    glBindTexture(GL_TEXTURE_2D, mQuad.mTexture[0]);
    
    
    mQuad.mVertices[0] = 0; mQuad.mVertices[1] = 0; mQuad.mVertices[2] = 0;
    mQuad.mVertices[3] = 100; mQuad.mVertices[4] = 0; mQuad.mVertices[5] = 0;
    mQuad.mVertices[6] = 100; mQuad.mVertices[7] = 100; mQuad.mVertices[8] = 0;
    mQuad.mVertices[9] = 0; mQuad.mVertices[10] = 100; mQuad.mVertices[11] = 0;
    
     mQuad.mVertIndicies[0] = 3; mQuad.mVertIndicies[1] = 2; mQuad.mVertIndicies[2] = 1;
    mQuad.mVertIndicies[3] = 0; mQuad.mVertIndicies[4] = 3; mQuad.mVertIndicies[5] = 1;
    
    
    mQuad.mTextureCoords[0] = 0.0f; mQuad.mTextureCoords[1] = 0.0f;
    mQuad.mTextureCoords[2] = 1.0f; mQuad.mTextureCoords[3] = 0.0f;
    mQuad.mTextureCoords[4] = 1.0f; mQuad.mTextureCoords[5] = 1.0f;
    mQuad.mTextureCoords[6] = 0.0f; mQuad.mTextureCoords[7] = 1.0f;
  
    //grab pointers so we can draw
    glVertexPointer(3, GL_FLOAT, 0, mQuad.mVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, mQuad.mTextureCoords);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, mQuad.mVertIndicies);
    
    //restore our texture states
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_TEXTURE_2D);
    
    glEnable(GL_DEPTH_TEST);
    SetupPerspective();
}


void CC_UIWindow::SetupOrtho(void)            // Set Up An Ortho View
{
    glMatrixMode(GL_PROJECTION);            // Select Projection
    glPushMatrix();                            // Push The Matrix
    glLoadIdentity();                        // Reset The Matrix
    glOrthox( 0, 320, 480, 0, -1, 1 );        // Select Ortho Mode
    glMatrixMode(GL_MODELVIEW);                // Select Modelview Matrix
    glPushMatrix();                            // Push The Matrix
    glLoadIdentity();                        // Reset The Matrix
  
}

void CC_UIWindow::SetupPerspective(void)                            // Set Up A Perspective View
{
    glMatrixMode( GL_PROJECTION );                    // Select Projection
    glPopMatrix();                            // Pop The Matrix
    glMatrixMode( GL_MODELVIEW );                    // Select Modelview
    glPopMatrix();                            // Pop The Matrix
}

Now I would expect this code to draw my window at the top left corner of the screen with a 100X100 dimension, utilizing the full texture. Instead the entire screen is filled with a piece of my texture.

Thanks in advance
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #2
It's because of:

Code:
glOrthox( 0, 320, 480, 0, -1, 1 );        // Select Ortho Mode

"320" is a very small number when it is interpreted as 16.16 fixed point.

There are various other inefficiencies with your code, would you like them all pointed out?
Quote this message in a reply
Member
Posts: 31
Joined: 2009.01
Post: #3
Thanks for replying arekkusu,

I don't understand what you mean by 16.16 fixed point...

Please point out the inefficiencies in my code, that's the only way I'll learn.

Thanks so much.
Quote this message in a reply
Member
Posts: 31
Joined: 2009.01
Post: #4
I should also note:

besides

Code:
mQuad.mVertIndicies[0] = 3; mQuad.mVertIndicies[1] = 2; mQuad.mVertIndicies[2] = 1;
    mQuad.mVertIndicies[3] = 0; mQuad.mVertIndicies[4] = 3; mQuad.mVertIndicies[5] = 1;
    
    
    mQuad.mTextureCoords[0] = 0.0f; mQuad.mTextureCoords[1] = 0.0f;
    mQuad.mTextureCoords[2] = 1.0f; mQuad.mTextureCoords[3] = 0.0f;
    mQuad.mTextureCoords[4] = 1.0f; mQuad.mTextureCoords[5] = 1.0f;
    mQuad.mTextureCoords[6] = 0.0f; mQuad.mTextureCoords[7] = 1.0f;

I'm not sure what the pieces are that are inefficent.
Quote this message in a reply
Member
Posts: 249
Joined: 2008.10
Post: #5
arekkusu Wrote:It's because of:

Code:
glOrthox( 0, 320, 480, 0, -1, 1 );        // Select Ortho Mode

"320" is a very small number when it is interpreted as 16.16 fixed point.

There are various other inefficiencies with your code, would you like them all pointed out?

Do it as I'm doing something similar.
Why do you say 320 is a small number? What do you suggest? Can you explain that?

Thanks a lot for your help.
Quote this message in a reply
Member
Posts: 269
Joined: 2005.04
Post: #6
glOrthox uses fixed point numbers. You probably want glOrthof instead.

http://www.khronos.org/opengles/document...Ortho.html
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #7
All of the "x" entry points in ES (like glOrthox) expect 16.16 fixed point numbers. "320" in 16.16 fixed point = 320/65536, or about 0.005, which is going to clip your scene to a small corner of the content you're drawing. That content will then be stretched by your glViewport scale to fill the entire window.

If this doesn't make sense yet, you should read section 2.10 "Coordinate transformations" in the spec to understand how the vertex positions and matrices you set up are used.

The short answer to this problem is-- you really didn't mean to use glOrthox. You should use glOrthof instead. Or, you could pass in fixed point data, but there's really no reason to ever do that on the iPhone where the CPU natively supports floats.

As for the other inefficiencies, let me comment a couple areas in your code:
Code:
//enable vertex arrays
    glEnableClientState(GL_VERTEX_ARRAY);
...
    glDisableClientState(GL_VERTEX_ARRAY);

In OpenGL ES1.1, there's no reason to ever disable the vertex array. So you might as well enable it once in your initialization and leave it that way forever. Just call glVertexPointer, and enable/disable the other arrays when needed.

Code:
//enable color blending
    glEnableClientState (GL_COLOR_ARRAY);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, mQuad.mVertColors);

Actually, this is just enabling an array of vertex colors. It doesn't have anything to do with blending. Whether the colors are used or not depends on your current TexEnv state-- the default state is MODULATE, so the interpolated colors will be multiplied by the texture color. This is fine if you want to tint your HUD different colors, but is inefficient otherwise.

Code:
mQuad.mVertices[0] = 0; mQuad.mVertices[1] = 0; mQuad.mVertices[2] = 0;
...
    glVertexPointer(3, GL_FLOAT, 0, mQuad.mVertices);

Your HUD is 2D, and all of the geometry has a Z coordinate of zero. So don't bother passing that in; use glVertexPointer(2, ...) instead, and Z will automatically default to zero.

Code:
mQuad.mVertIndicies[0] = 3; mQuad.mVertIndicies[1] = 2; mQuad.mVertIndicies[2] = 1;
...
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, mQuad.mVertIndicies);

For drawing one quad, it's overkill to set up indices. Just set up four vertices and use glDrawArrays(GL_TRIANGLE_STRIP, ...) instead, submitting 4 vertices instead of 6. If you're going to draw many quads (like a string of text) then indexed triangles is fine.
Quote this message in a reply
Member
Posts: 31
Joined: 2009.01
Post: #8
Oh wow thanks Arekkusu! I made that one change and it worked "perfectly" I really appreciate all the other information you provided me. You've exposed how little I truly know about Open GL.

Question. Is triangle strips "always" better? Under what scenarios would you want to use one versus the other?
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #9
Triangle strips are better if you're drawing connected chunks of geometry, like a typical 3D model. There are various algorithms to convert arbitrary 3D geometry into triangles trips, and this is generally a win.

If you need to draw disconnected pieces of geometry (for example, one quad per glyph in a font, where the texture coordinates can't be shared between two adjacent glyphs) then you can't use triangle strips. This also applies to 3D models where the geometry may be connected, but some attribute is not continuous across the connected faces (for example, take a 3D cube where you want to light each face with the vertex normal. You need different normals per face, so you have to break the geometry apart and can't share vertices between faces.)
Quote this message in a reply
Member
Posts: 215
Joined: 2008.06
Post: #10
haudio Wrote:Oh wow thanks Arekkusu! I made that one change and it worked "perfectly" I really appreciate all the other information you provided me. You've exposed how little I truly know about Open GL.

Question. Is triangle strips "always" better? Under what scenarios would you want to use one versus the other?

Hate to pry, but what file format are you using for your textures and how do you load them as GLuint textures? I've been struggling with this for a while now. I have .bmp files working great, but I would really like to get .png files working. Thanks.

Mac users swear by their computers, PC users swear at their computers. ~Unknown

iSayz
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #11
Quote:I've been struggling with this for a while now.
Sheesh, man, no kidding! I can't believe you haven't got it working for you yet, after all this time. What is the problem? We gotta get to the bottom of this, because it really isn't hard.
Quote this message in a reply
Member
Posts: 31
Joined: 2009.01
Post: #12
I'm using pvrtc which is a compressed version of png. Although I think the loading code is the same for both... I think the only difference is you should use

glTexImage2D rather than glCompressedTexImage2D

Basically here is the loading code
Code:
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
    // Most likely for PNG you should use: of glTexImage2D,
    glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, mPower2Width, mPower2Height, 0, (mPower2Width * mPower2Height) / 2, [texData bytes]);


Let me know if you need more guidance.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #13
The "loading code" will be quite different.

When you use one of the TexImage APIs, OpenGL just reads bytes from the pointer you hand it, and interprets the data according to the parameters (like format) you specified.

Loading the image off disk (perhaps decompressing it in the process) has nothing to do with OpenGL, so it belongs in another thread. But briefly-- loading a .png needs to decompress the image into an array of pixels before you pass the address of those pixels to GL. That requires an image decompressor like ImageIO or libpng, and with the API that Apple provided, perhaps rendering the image to a CoreGraphics context to get the pixels. On the other hand, loading a compressed texture like DXT or PVRTC is just a matter of reading bytes off disk, like with NSData.
Quote this message in a reply
Post Reply