PDA

View Full Version : The Sturpor of OpenGL Lists



Atomic_Sheep
12th January 2013, 09:43
Hi guys, trying to create texture font. Have the texture ready and have made a display list which has different parts of the texture mapped onto a GL Quad. I also have a 'Print' function that then prints this text to the screen. I got most of the code from NeHe, question is, how on earth do I get the correct text to display? i.e. say I do Print("abcdef", 3, 2) or whatever the function is, the text that shows up random gibberish that doesn't correlate to the string that I type. In fact, when I go to re-size the window, the text actually changes. Yes it's pointers that are used to point to the string of text which means that whatever it's pointing to is incorrect or at the very least it's pointing to some part of the memory that is dynamic/changing and not the string text pointer variable that I created. But this isn't the problem.

My question is: if I create a list, how do I then pick out specific things from it to print out specific letters? i.e. when I want an A, how do I pick out the right quad? I've looked everywhere on the internet and can't seem to find the answer. NeHe's perspective doesn't answer my question.

wysota
12th January 2013, 12:03
I don't know how you expect us to help you without telling us what you actually do. If you want to print "abcdef" then "a" is the first item so if you're keeping a list of some objects representing your data, it will be the first item.

Atomic_Sheep
13th January 2013, 00:51
Ok no probs, I have the following code:


for(loop=1;loop<183; loop++)
{
cx = float(loop%26)/26.0f;
cy = float(loop/7)/7.0f;
glNewList(m_iDisplaySquare+loop, GL_COMPILE);

glBegin(GL_QUADS);

//Bottom Left
glTexCoord2f(cx,1-cy-0.1f); // Texture Coord (Bottom Left)
glVertex2i(-15.3f,-25.6f); // Vertex Coord (Bottom Left)

//Bottom Right
glTexCoord2f(cx+0.03846f,1-cy-0.1f); // Texture Coord (Bottom Right)
glVertex2i(15.3f,-25.6f); // Vertex Coord (Bottom Right)

//Top Right
glTexCoord2f(cx+0.03846f,1-cy); // Texture Coord (Top Right)
glVertex2i(15.3f,25.6f); // Vertex Coord (Top Right)

//Top Left
glTexCoord2f(cx,1-cy); // Texture Coord (Top Left)
glVertex2i(-15.3f,25.6f); // Vertex Coord (Top Left)

glEnd(); // Done Building Our Quad (Character)
glTranslated(30.6,0,0); // Move To The Right Of The Character

glEndList(); // Done Building The Display List
}

This creates the list and allocates different parts of the .bmp to my quads.


void GLWidget::Print(int x, int y, QString *sText, int set) //'set' is used for selecting the font set i.e. we can have a set of bold, a set of italicized, as set of normal fonts etc...
{
if (set>1)
{
set=1;
}

glBindTexture(GL_TEXTURE_2D, texture[1]);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glPushMatrix(); // Store The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
glOrtho(0,619,0,486,-1,1); // Set Up An Ortho Screen
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glPushMatrix(); // Store The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix

//This line positions the text
glTranslated(x,y,0); // Position The Text (0,0 - Bottom Left)
glListBase(m_iDisplaySquare+1-32+(128*set)); // Choose The Font Set (0 or 1)
glCallLists(sText->size(),GL_UNSIGNED_BYTE,sText); // Write The Text To The Screen
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glPopMatrix(); // Restore The Old Projection Matrix
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glPopMatrix(); // Restore The Old Projection Matrix
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
}

This is what I'm using to print. As I said, when I do:


QString sStringText;
sStringText = "abcdefg";
QString *pStringPointer = &sStringText;

Print(619/4.63,400, pStringPointer, 0);

What I get is jibberish. I have 7 lines of text in my .bmp with each line representing a unique set (each one differs by colour). At the moment, I get random letters of random colours popping up. For some reason I keep getting 6 letters popping up despite the fact that abcdefg is obviously a string of 7 characters.

I have gone through the tutorial by NeHe many times and nowhere do I see obvious code that define that say the 3 value in our list is c, nor do I see the evocation of that 3rd element when asking specifically for a c.

wysota
13th January 2013, 15:35
Why are you passing a pointer to QString to glCallLists()?

According to the docs glCallLists accepts "the address of an array of name offsets in the display list". A pointer to QString does not conform to such specification.

Atomic_Sheep
14th January 2013, 09:50
If I understood you correctly then what you said has cleared up a few questions but has also made me question the code that NeHe provided which in itself is a worry since he knows more than me. That's where I got my code from:

http://nehe.gamedev.net/tutorial/2d_texture_font/18002/

I tried posting the whole piece of code without all the comments but unfortunately it ended up too big to post.

Nowhere in there do I see an array being used and a conversion of a string to an array that would enable calling specific elements from our quad list. I was confused about how the program knew which elements from the list to pull by just putting in a string when I first saw the tutorial and no matter how many time I've reviewed it since, that mystery has eluded me. Hence my original question.

wysota
14th January 2013, 11:10
They are using char* as the "string" which is an array of char (aka unsigned byte) elements which is ok. This is totally different than a pointer to QString.

Copying tutorials you don't understand is not a good idea.

Atomic_Sheep
14th January 2013, 11:30
Ah I see, thanks, somewhat get it. In terms of copying, fake it till you make it :). Have started reading up on char strings, didn't know that was a thing :).

wysota
14th January 2013, 11:52
The tutorial clearly states "as we did in all other font tutorials". Did you read through all those other tutorials? I'm sure the approach was explained there.

Atomic_Sheep
14th January 2013, 12:13
No I didn't read those other tutorials because I wasn't trying to create text using other techniques.

EDIT: having read about char pointers, there's one thing I still don't understand:

When we create a string using char i.e. an array of chars, how does that allow us to access numerical references of our quads in the texture problem? Not sure if I expressed myself comprehensibly enough, so just to make sure I've crossed the ts and dotted the i's, if I create a string using char:

char test[] = "test";
char *testPointer;

how does that enable me to pull an array element of say base[15] from the 256 array elements that get created when I put in a char pointer into the print function? If my memory serves me correctly, each character has it's own 0-255 code somewhere? So all that one has to do is to create a bitmap that complies with the naming and ordering of characters?

P.S. Many thanks, got the string length bit working perfectly now, just gotta figure out the final piece of the puzzle :).

wysota
15th January 2013, 08:41
No I didn't read those other tutorials because I wasn't trying to create text using other techniques.
And now three days later your problem still remains unsolved.

Atomic_Sheep
15th January 2013, 11:14
I don't disagree with what you're saying but I can only progress as much as I can, unless I'm staring the obvious right in the face and am missing the point.

wysota
15th January 2013, 12:30
It would be obvious if you read earlier tutorials. Since you didn't, it's not obvious for you. You wanted to save three hours of reading but you wasted three days of struggling for a solution. I can only guess they have a texture with a sprite of all glyphs with glyph positions related to ASCII codes of particular glyphs, so putting a character on the screen is equivalent to displaying a quad textured with the proper part of the sprite.

Atomic_Sheep
16th January 2013, 11:10
That's correct, but I understand this, I wasn't trying to fix the problem with the pointers being wrong, I know they were wrong and I have now fixed it, what I was getting at was how does one type:


char text[15] = "test";

and then when passing that into the print function expect to get the correct quad to pop up? The quads are sequenced numerically while the alphabet is alphanumeric, so how does passing a pointer to the first letter of the string 't' yield to me calling the 20th quad form my list? (t is the 20th letter in the alphabet and I have created a bmp image of the alphabet, with the letters sequenced as expected i.e. abcdef...). Hopefully now my original question makes more sense.

wysota
16th January 2013, 12:08
I have created a bmp image of the alphabet, with the letters sequenced as expected i.e. abcdef...

How do you know this is sequenced "as expected"? I would rather claim letter 'a' is to be 98th glyph in the bitmap and not the 1st one. Even the beginning of the tutorial says the technique allows to display 256 different characters, it doesn't say anything about "26 letters". If you just want to display letters, you have to modify the code to only include letters.

Atomic_Sheep
17th January 2013, 05:56
Correct, it allows up to 256, since I don't need that many, I'm not worried about that for now and am trying to display just 26. Well in actuality, I'm trying to display 7 sets at the moment and I've modified my code accordingly. But for now I'm just working on getting one of these sets to work the way I would expect it to i.e. put in a string, and boom, it calls the correct list members. I mean I know how to do it the long way with a lot of 'if' statements, but that's going to take forever and I'd rather not spend the next 3 days doing it that way.

By 'as expected' I meant that the letters are ordered in the normal alphabetical order rather than some alternative way using for example qwerty keyboard rows to order the letters or using a german keyboard or something. Consequently, the firsty glyph will be an 'A' second one will be 'B' etc, question now is, as I said, if input a char array/string into the print function, how on earth does the code know how to match up what a memory location has stored which is alphanumerical to the value that I have assigned to each of my list members?

wysota
17th January 2013, 06:41
By 'as expected' I meant that the letters are ordered in the normal alphabetical order rather than some alternative way using for example qwerty keyboard rows to order the letters or using a german keyboard or something. Consequently, the firsty glyph will be an 'A' second one will be 'B' etc, question now is, as I said, if input a char array/string into the print function, how on earth does the code know how to match up what a memory location has stored which is alphanumerical to the value that I have assigned to each of my list members?

First 64 glyphs need to be empty, then there should be glyphs for uppercase letters in alphabetical order, then the same for lowercase. If you need numbers, you need to put them in positions 48 upwards. The position is determined by the value stored in the char variable.


const char * str = "The Sturpor of OpenGL Lists";
for(int i=0;str[i]!=0;++i) {
printf("%c = %d\n", str[i], str[i]);
}

Do you understand now?

Atomic_Sheep
17th January 2013, 10:21
Unfortunately no. Why must the first 64 be empty? I'm not adding additional fonts to what was provided in the tutorial, I'm only using my own image which is 26x7. And why are the numbers from 48 onwards? 64 -16 is 48 but why is that signifcant? Yes NeHe's example uses a 16x16 glyph matrix but why the last 16 for numbers, why last and not first? The glyph he uses has random chars first, then numbers, then capitals, then lower case, the italic caps and then italic lower.

The main thing I don't understand is why:


glCallLists(16, GL_UNSIGNED_BYTE, sText);

results in the relevant quads being drawn?

The definition of the last term of glCallLists:

"Specifies the address of an array of name offsets in the display list. The pointer type is void because the offsets can be bytes, shorts, ints, or floats, depending on the value of type."

What on earth does that mean? Specifies the address of an array of name offsets. Sounds like mumbo jumbo to me. When I create the string


char text[20] = "test";

it's just that, an array that stores various values. I don't understand how text[0] which equals 't' is a name offset which according to the above definition is meant to 'call' the appropriate quad with its respective texture?


I can't help but feel we're on different wavelengths here.

wysota
17th January 2013, 11:08
Unfortunately no.
Did you run the example I posted?

Atomic_Sheep
17th January 2013, 12:30
Interesting... but I get a = 97 and so on, not 64 or 65. What's the underlying reason behind this number? Where does this 97 come from?

wysota
17th January 2013, 12:38
but I get a = 97 and so on, not 64 or 65.
Because it's lowercase and not uppercase. For uppercase you will get 64 or 65 (most likely 65 since the difference between upper and lower case characters is 32). Adjust the example for all the characters you need and see what values you get.


What's the underlying reason behind this number? Where does this 97 come from?

97 is the integer value of the character 'a' in ASCII code as already said two days ago.

Atomic_Sheep
17th January 2013, 12:44
Nooow it's clicked, thanks. Didn't give the last mention about ASCII codes a second though last time I read over that post. I had seen the term previously but didn't know what it was hence didn't think it was important.

wysota
17th January 2013, 12:54
I hope you won't do the same with the term "security guidelines" when someone handles you a grenade...

Atomic_Sheep
18th January 2013, 09:10
That's the thing about ignorance, you don't know what you don't know, that's the dangerous one.