Archived

This topic is now archived and is closed to further replies.

graveyard filla

newbie OpenGL questions ......

Recommended Posts

high, im currently learning openGL to make 2d games. anyway, i have some questions and would appreciate any answers: when you draw this to the screen, say a Quad and (one of) the call looks like this glVertex3f(-1.0f,0.5f,0.0f); so when you call that function, its saying "draw this point at 1.0f to the left of the CENTER of the screen, .5 below the CENTER of the screen, and 0 into/out of the CENTER of the screen??" basically my question is, so anything you draw, is drawn at (or relative to) the center of the screen? and you change what the center is, by calling glTranslate() ??? just wanting to confirm, im reading the nehe tutorials but he doesnt really explain this (maybe i missed it?) also, 3d graphics use cartesian coordinate system? so i guess i can throw out the whole idea that the top left corner is 0,0 and Y increses by going down, eh? also, can you not translate from inside a glBegin(GL_XXXX) call? because i tried drawing 2 quads in the same bracket of glBegin(GL_QUADS) , and i translated after drawing the first quad, but when i executed the program, the second quad was on top of the first one i drew.... im thinking Translate has to be called from outside of a glBegin() bracket? or can you not draw multiple quads in a single glBegin() bracket? (nehe says otherwise, but im getting this weird thing so... also, when i made the 2 quads drawn in seperate glBegin() brackets, and translated in-between, it worked fine) thanks for any help!!

Share this post


Link to post
Share on other sites
Well technically all 3D drawing is in terms of local coordinates. When you start off the object matrix is inline with the world world coordinates. translate, rotate, etc, shift these coordinates to wherever you want on screen. Also there is no reason all your coordinates have to be with 0.0, 0.0 in the center of the screen for your world. They will just end up that way after running through the pipeline matrices which align the camera (which has its own coordinate system) with the world and the center of projection (or direction of projection if your doing parrallel).


I think your translate problem is do to when the object matrix is applied to your points. I''m not sure when OpenGL applies this, but it is likely done after glEnd inorder to allow a batching of the vertices being transformed at once.

Share this post


Link to post
Share on other sites
Yes, you have to put your translations outside of the glBegin()/glEnd() calls. There is a very limited list of GL calls you may make between glBegin() and glEnd():

glVertex
glColor
glIndex
glNormal
glTexCoord
glEvalCoord
glEvalPoint
glMaterial
glEdgeFlag

(This is yoinked directly from MSDN). Obviously, these are just the root versions of the functions, add parameter number and type as appropriate.

Any other OpenGL calls will not work inside those two calls. They won''t crash or anything, but they won''t do anything useful either.

-Auron

Share this post


Link to post
Share on other sites
Since you''re doing 2d graphics, use ortho mode instead of perspective. NeHe doesn''t cover this well (or at all? can''t remember).

Instead of something like this

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,(float)w/h,1,100);


do this

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,w,0,h);



Then instead of glVertex3f use glVertex2f. The end result is that coordinates coospond to screen space, with 0,0, being the lower left corner. Have fun!

--------------------------------------------------------
Life would be so much easier if we could just get the source code.

Share this post


Link to post
Share on other sites
All right, let me give you a brief rundown of how coordinate systems in these APIs work.

Basically, they're managed by matrices. To understand exactly how this works you need to know some linear algebra, but basically, it's possible to encode a set of axes (aka a coordinate system) in a matrix. If you multiply a position vector by this matrix, the vector will be placed in the new coordinate system. It will still be in the same "place", but the origin moves, or the axes are rotated, and so the vector's location and/or orientation changes relative to the origin.

Now, as far as I remember, OpenGL has this one matrix called the WORLDVIEW matrix. This one is responsible for containing an origin and a set of axes for your world. When calling glVertex3f(), you specify the points in local coordinates . Usually, this means that the origin is at the center of whatever object you're drawing (NOT necessarily at the center of the screen! The objects are not placed anywhere on the actual screen yet). Then, while drawing, OpenGL will multiply these coordinates by the WORLDVIEW matrix to move the point to an absolute location in the world (and it'll do some other stuff with other matrices, but you don't have to worry about that).

Functions like glTranslatef() modify the WORLDVIEW matrix (or maybe whatever matrix you have active at the time, but that's usually WORLDVIEW, I think...) So, when you call glTranslatef(), you're essentially moving the origin of the world somewhere else.

Anyway, I haven't used OpenGL in a while, so please correct me wherever I'm wrong.

Here's what a typical matrix looks like as far as I can remem,er, although the arrangement of the terms may not be exactly correct:

ix iy iz 0
jx jy jz 0
kx ky kz 0
ox oy oz 1

Where i, j, and k are 3D basis vectors that act as the axes of your new coordinate system, and o is a position vector that represents the origin of the new coordinate system relative to the old one.

[edited by - twix on May 19, 2004 10:46:58 PM]

Share this post


Link to post
Share on other sites
the OP stated things more clearly than anyone since ...

YES, glTranslate changes the current "center" of the world ... glRotate changes the "orientation" of the current "center" of the world, glScale changes the relative scale of the current world (relative to the previous state).

Share this post


Link to post
Share on other sites
You can kinda think of it like the solar system:

On the bottom level, you''ve got the moon. The moon goes around the earth, the earth around the sun. However, the moon moves relative to the earth, NOT the sun.



The sun stays still, so it''s like just drawing in GL straight-up without any translation or scaling whatsoever.

// sun
draw the sun

Now we draw the earth. It''s X,Y,Z away and it''s rotated so-and-so. We push a matrix onto the stack. That means "move the universe over here so i can draw the earth now" and makes for an easy "undo" later on.

// earth
push a new stack
glRotate( so-and-so )
glTranslate( X, Y, Z );
draw earth

now we draw the moon. The moon is offset X,Y,Z and so-and-so in relation to the earth, not the sun. So we push another matrix onto the stack for the moon and do another set of offsets:

// moon
push a new stack
glRotate( so-and-so )
glTranslate( X, Y, Z );
draw moon

Now we''ve "moved the universe" over a bit for the earth and over a bit more for the moon. Sorta like if you walk across an elevator while the elevator is moving down, you are actually travelling at an angle in relation to the ground. You are combining movements. In openGL, when you push matrices, you are combining all these "movements" (translate, scale, rotate) together into one big movement (when the screen is drawn).

When we are done drawing things, we want to undo our stacks. Otherwise, everytime we draw them, they will all be off by that much more every frame. so...

pop the moon matrix from the stack
pop the earth matrix from the stack

... and now we are back to the "real" center where the sun is.

at least, that''s how i understand ;-)

The other option is just to draw everything according to an unchanging world, but that''s no fun :-) It''s also sometimes difficult to figure out if you have objects that move in relation to other objects and in general, not an organized way to do it.

Take everything i just said with a large grain of salt. I''m new to OpenGL too.

Share this post


Link to post
Share on other sites
Well you don''t have to push matrices on the stack to accomplish translations, but everytime you want to go back to the world origin you''d have to load the identity matrix. :-) At first the whole matrix use thing may seem more difficult. It took my friend almost all semester to wrap her mind around the whole concept in the Computer Graphics class we took (most of the guys did well since they had already done some 3D programming using DirectX or OpenGL). When she finally got it though, she realized how much easier it is to deal with then 2D games she had to make for previous classes.

It took me a while to get used to it all too. Now it is no sweat. I can usually figure out what a set just by looking at it. If your doint 2D you might want to stick what opengl calls Ortho project (or parrallel mode). However, if you try to do anything height based and you want to show that perspective, perspective mode can be very useful. BTW, technically you can use any Coordinate system you want as long as you can translate back to OpenGL''s Cartesian system. Like I said before you can set your coordinate system to where top left of the screen is 0,0 and bottom right is whatever you want. It all involves with making custom matrices.

Share this post


Link to post
Share on other sites
thanks everyone, i didnt really understand most of your replies as soon as you started talkin math, i got screwed up. i have no math skills and probably will never get them (in college now, but im in CIS so we only take up to college algabra and statistics... in HS i never made it past basic algabra)

anyway, i dont know what a matrix, vector, or any of that stuff is. but i dont think ill be needing it just yet. i figured out how to get ortho mode to work (0,0 in top left corner and my Y axis increases while going down like good old SDL).. anyway, im having a problem now i hope someoen can help with. im trying to map a texture to a quad, but im having problems. i load in the image, and when i draw the quad i map each piece of the texture with the point i specify... anyway, the result looks like this



the original image looks like this..




does anyone know what the problem is? why are my colors getting distorted like this? also, before i even tried uploading and using the texture, my colors were distorted very similarly when even specifying colors using glColor3f(r,g,b).. i noticed when i remmoved the call to glEnable( GL_TEXTURE_2D );

that this stopped the distortion. but anyway, i added the line back in, and texture mapped my quads, and now im getting this problem. also, when i maximize the window, my screen turns white and if i re-windowize it, it stays all white like this.. really weird... heres what my initialization/loading of texture code looks like:


int initGL( GLvoid )
{
/* Load in the texture */
if ( !Load_Textures( ) )
return FALSE;

/* Enable Texture Mapping ( NEW ) */
glEnable( GL_TEXTURE_2D );

/* Enable smooth shading */
glShadeModel(GL_SMOOTH);

/* Set the background black */
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

/* Depth buffer setup */
glClearDepth(1.0f);

/* Enables Depth Testing */
glEnable(GL_DEPTH_TEST);

/* The Type Of Depth Test To Do */
glDepthFunc(GL_LEQUAL);

/* Really Nice Perspective Calculations */
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

return TRUE;
}


bool Load_Textures( )
{
/* Status indicator */
int Status = FALSE;

/* Create storage space for the texture */
SDL_Surface *TextureImage[1];

/* Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit */
if (( TextureImage[0] = SDL_LoadBMP( "tile1.bmp")))
{

/* Set the status to true */
Status = TRUE;

/* Create The Texture */
glGenTextures( 1, &texture[0] );

/* Typical Texture Generation Using Data From The Bitmap */
glBindTexture( GL_TEXTURE_2D, texture[0] );


/* Generate The Texture */
//GL_TEXTURE_2d says its a 2d texture

//0 is recommended

//3 is its using 3 colors (RGB)

//w,h of the actual image

//0 is recommended again

//

glTexImage2D( GL_TEXTURE_2D, 0, 3, TextureImage[0]->w,TextureImage[0]->h, 0, GL_RGB,
GL_UNSIGNED_BYTE, TextureImage[0]->pixels );

/* Linear Filtering */
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}

/* Free up any memory we may have used */
if ( TextureImage[0] )
SDL_FreeSurface( TextureImage[0] );

return Status;
}


now heres the drawing code...



void Draw_Quad(float x, float y)
{
glBindTexture(GL_TEXTURE_2D, texture[0]);


glBegin(GL_QUADS); /* Draw A Quad */


glTexCoord2f(0.0f, 1.0f);
glVertex2f(x, y + 32.0f); /* Bottom Left */

glTexCoord2f(1.0f, 1.0f);
glVertex2f(x + 32.0f,y + 32.0f); /* Bottom Right */


glTexCoord2f(1.0f, 0.0f);
glVertex2f(x + 32.0f,y); /* Top Right */

glTexCoord2f(0.0f, 0.0f);
glVertex2f(x,y); /* Top Left */



glEnd();
}


(theres a global variable called GLuint texture[1])
(so OpenGL keeps all its texture data inside an unsigned int?)

thanks for any help.. im using 2d ortho mode setting the origin to the top left corner of the screen... also using SDL for all the 'support' code obviously...

[edited by - graveyard filla on May 20, 2004 3:49:26 AM]

Share this post


Link to post
Share on other sites
2 things:

1) Check the part where you load the texture. One of the options is GL_RGB. That assumes pixel data is stored in R G B order, which it may not be. Your color rotation seems to indicate it''s probably GBR or some other weird thing. Just try different combos and see which one works right.

2) OpenGL is one big mutha state machine. That means that any time you change something, it stays that way until you change it again. I noticed that you do not specify the color when you are drawing the quad. That''s okay if you can guarantee that the color will be white going into the drawing phase, but otherwise, set your color to

glColor4f(1,1,1,1);

before you glBegin() all the other info. That will make sure your textures don''t get a weird color cast from some other thing you drew.

Share this post


Link to post
Share on other sites
thanks for the help leia, but thats not working. changing the GL_XXX to anything besides GL_RGB gives me an undeclared identifier error. maybe i dont have the latest version or something?i am using vis studio .net 2k3.... also, i tried setting the color like that before drawing my quads, and still no luck... thanks for any more help

Share this post


Link to post
Share on other sites
Check out Cone3D's tutorials for how to properly load textures with SDL. SDL's format is not entirely compatible with OpenGL, so you have to flip the image over and maybe fiddle with the color channels, if I remember correctly.

Also, glTexCoord2f(0.0, 0.0) is bottom left. You got the coordinates mixed up.

[edited by - twix on May 20, 2004 2:22:24 PM]

Share this post


Link to post
Share on other sites
in the nehe tutorial, it says

/* NOTE:
* The x coordinates of the glTexCoord2f function need to inverted
* for SDL because of the way SDL_LoadBmp loads the data. So where
* in the tutorial it has glTexCoord2f( 1.0f, 0.0f ); it should
* now read glTexCoord2f( 0.0f, 0.0f );
*/

thats why i have the stuff flipped around. it doesnt look like the image is flipped, anyway, it looks like the color is screwed up only.. although the image is kind of seamless, so i guess it could be flipped and would be too hard to tell.. i dunno.. guess ill have to check out cone3d after school.. thanks guys...

Share this post


Link to post
Share on other sites
also, i dont think it has anything to do with textures...

if i draw a regular white quad, like this, with no texture mapping:


glBegin(GL_QUADS); /* Draw A Quad */

glColor3f(1.0f,1.0f,1.0f);
glVertex2f(player_x,player_y); /* Top Left */

glVertex2f(player_x + 32.0f,player_y); /* Top Right */


glVertex2f(player_x + 32.0f,player_y + 32.0f); /* Bottom Right */

glVertex2f(player_x, player_y + 32.0f); /* Bottom Left */

glEnd();


this quad comes out a dark navy blue just like in the picture!! does anyone know why this is happening?

also - if i change the above code, to make the quad RED instead of white, the navy blue quad turns black! also, if i comment out this line:

glEnable( GL_TEXTURE_2D );

the quad is drawn the way its suposed to! it will come out red if i say red, or white if i say white, but of course, all my textured quads are completely white if i comment this out...

anyone know what the deal is? thanks for any help!

Share this post


Link to post
Share on other sites
using your simple "white quad" code, it's draws grey on my computer. I fixed it with this before drawing the quad:

glBindTexture( GL_TEXTURE_2D, 0 );

that binds to a null texture object (assuming you didn't try to create a texture labeled "0")

That doesn't explain the wacked out colors on the quads you are drawing WITH textures though.

The other thing i noticed is that (i think, correct me if i'm wrong) you are drawing your vertices in reverse order. I believe they should be counter-clockwise.

[edited by - leiavoia on May 20, 2004 12:04:39 AM]

Share this post


Link to post
Share on other sites
i think the drawing is fine (i am drawing counter clockwise) but its something with the texture... i just tried using a different tile that i made just for testing.. the L and R i marked to make sure the image wasnt flipped or anything....

heres what the picture really looks like ( 32x32 image i blew up the pictures so you could see them better)


heres what it looked like rendered in the program


why are the colors acting like this? also, the 'player' which is suposed to be a white quad is a grey quad, earily looking exactly like the grey in the background of my happy face image... i went to cone3d and couldnt find a texture mapping tutorial, maybe im just stupid and didnt see it? i saw a rendering to texture thing, but this isnt what im looking for i dont think...heres the relavent code to the program (its nehes first texture mapping tutorial modified to fill the screen with quads (ie a "map") instead of draw a single cube, also a "player" which is just a white quad drawn to the screen):


int initGL( GLvoid )
{
/* Load in the texture */
if ( !Load_Textures( ) )
return FALSE;

/* Enable Texture Mapping ( NEW ) */
glEnable( GL_TEXTURE_2D);

/* Enable smooth shading */
glShadeModel(GL_SMOOTH);

/* Set the background black */
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

/* Depth buffer setup */
glClearDepth(1.0f);

/* Enables Depth Testing */
glEnable(GL_DEPTH_TEST);

/* The Type Of Depth Test To Do */
glDepthFunc(GL_LEQUAL);

/* Really Nice Perspective Calculations */
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

return TRUE;
}

/* Here goes our drawing code */
int drawGLScene( GLvoid )
{

/* Clear The Screen And The Depth Buffer */
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

/* Move Left 1.5 Units And Into The Screen 6.0 */
glLoadIdentity();

glColor4f(1.0f,1.0f,1.0f,1.0f);

for(int x = 0; x < 20; x++)
{

for(int y = 0; y < 25; y++)
{
Draw_Quad(x*32,y*32);
}

}

Draw_Player();
/* Draw it to the screen */
SDL_GL_SwapBuffers( );

return( TRUE );
}

void Draw_Quad(float x, float y)
{
glBindTexture(GL_TEXTURE_2D, texture[0]);
glColor3f(1.0f,1.0f,1.0f);


glBegin(GL_QUADS); /* Draw A Quad */

glTexCoord2f(0.0f, 1.0f);
glVertex2f(x, y + 32.0f); /* Bottom Left */

glTexCoord2f(1.0f, 1.0f);
glVertex2f(x + 32.0f,y + 32.0f); /* Bottom Right */

glTexCoord2f(1.0f, 0.0f);
glVertex2f(x + 32.0f,y); /* Top Right */

glTexCoord2f(0.0f, 0.0f);
glVertex2f(x,y); /* Top Left */

glEnd();
}

void Draw_Player()
{

glBegin(GL_QUADS); /* Draw A Quad */

glColor3f(1.0f,1.0f,1.0f);

glVertex2f(player_x,player_y); /* Top Left */

glVertex2f(player_x + 32.0f,player_y); /* Top Right */

glVertex2f(player_x + 32.0f,player_y + 32.0f); /* Bottom Right */

glVertex2f(player_x, player_y + 32.0f); /* Bottom Left */

glEnd();

}




bool Load_Textures( )
{
/* Status indicator */
int Status = FALSE;

/* Create storage space for the texture */
SDL_Surface *TextureImage[1];

/* Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit */
if (( TextureImage[0] = SDL_LoadBMP( "tile1.bmp")))
{

/* Set the status to true */
Status = TRUE;

/* Create The Texture */
glGenTextures( 1, &texture[0] );

/* Typical Texture Generation Using Data From The Bitmap */
glBindTexture( GL_TEXTURE_2D, texture[0] );


/* Generate The Texture */
glTexImage2D( GL_TEXTURE_2D, 0, 3, TextureImage[0]->w,TextureImage[0]->h, 0, GL_RGB,
GL_UNSIGNED_BYTE, TextureImage[0]->pixels );

/* Linear Filtering */
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}

/* Free up any memory we may have used */
if (TextureImage[0])
SDL_FreeSurface(TextureImage[0]);

return Status;
}


thanks for any help...

[edited by - graveyard filla on May 20, 2004 12:36:58 AM]

[edited by - graveyard filla on May 20, 2004 12:37:21 AM]

[edited by - graveyard filla on May 20, 2004 12:48:34 AM]

Share this post


Link to post
Share on other sites
the image you are loading is being loaded in BGR format, and you are telling OpenGL it is in RGB format, thus the stuff which should be blue is coming out red.

You have a choice:
- Load the image and then convert it to RGB format (I''m sure SDL has a method for doing that)
- Tell OpenGL its a GL_BGR (or maybe it should be GL_BGR_EXT) image instead of a GL_RGB image

Share this post


Link to post
Share on other sites
yes, your RGB is definately swapped. I can tell just by analyzing the color differences. It looks like BGR ("booger"!). The image you are storing has it''s pixel data reversed, or it''s being read in reverse, or something. Try saving the image as a TGA or PNG and load the file via SDL_image ( IMG_Load() ), or else find some creative way to swap the colors around yourself. Possibly use SDL_ConvertSurface()

The other method is to pass GL_BGR to the teture creation function but i ran into the same problem you mentioned. Window''s supplied version of OpenGL is old. It doesn''t seem to contain the enum values for GL_BGR like my linux version does (libMESA), so you have to find a way to rearrange the pixel data manually as mentioned aboce :-(

Share this post


Link to post
Share on other sites
thanks guys... that GL_BGR_EXT thing worked.. my texture is normal, but i still have a few problems.. if i resize the window at all, the screen turns completely white... does anyone know what could be causing this? heres my resizing code

when i take input and look for events..


case SDL_VIDEORESIZE:
/* handle resize event */
screen = SDL_SetVideoMode( event.resize.w,event.resize.h,SCREEN_BPP, videoFlags );
if ( !screen )
{
fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
exit(1);
}

resizeWindow( event.resize.w, event.resize.h );


in resizeWindow

int resizeWindow( int width, int height )
{

/* Protect against a divide by zero */
if ( height == 0 )
height = 1;

/* Setup our viewport. */
glViewport(0,0,width,height);

/* change to the projection matrix and set our viewing volume. */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluOrtho2D(0,width,height,0);

//glOrtho(0.0f,width,height,0.0f,-1.0f,1.0f);


glMatrixMode(GL_MODELVIEW);

/* Reset The View */
glLoadIdentity( );

return TRUE;
}



also, another thing that is really bothering me is my window leaves trails when i resize it, or move it below the screen. havent been able to fix this yet..
thanks for anymore help!

Share this post


Link to post
Share on other sites
here's mine (hacked up from the same source as you can see :-)


/* function to reset our viewport after a window resize */
int resizeWindow( int width, int height )
{
/* Protect against a divide by zero */
if ( height == 0 )
height = 1;

/* Setup our viewport. */
glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );

/* change to the projection matrix and set our viewing volume. */
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );

/* Set our perspective */
// gluPerspective( 45.0f, ratio, 0.1f, 100.0f );

glOrtho(0.0f,width,height,0.0f,-1.0f,1.0f);

/* Make sure we're changing the model view and not the projection */
glMatrixMode( GL_MODELVIEW );

/* Reset The View */
glLoadIdentity( );


return( true );
}


[edited by - leiavoia on May 21, 2004 9:05:58 PM]

Share this post


Link to post
Share on other sites
thanks leia, but that is pretty much exactly what i have (except you set the ortho differently but it does the exact same thing i think)... does anyone know why this is happening? anytime i resize the window, the whole screen turns white (i think its my quads are losing their textures somehow.. i tried running the nehe spinning cube/texturing tutorial, and when i resize the window, the texture on the cube disapears... the cube is still spinning, and you can see it, but its all white)... also, id love to know why my window is leaving trails when i resize/ move it below the screen... this really sucks because i just have to fix these 2 things and i can change all my drawing code in my game to use OpenGL instead of SDL.. but i cant figure this part out... thanks for any help!!

ps- im thinking about locking it so you cant resize the window anyway, because my collision detection is tile based... therefore, the window has to be the same size all the time, because im checking in terms of pixels/ tiles (i do something like player_position/TILESIZE to find which tile the player is on to do collision detections... if the window can be resized, and everything scales, wont this screw things up? or is there something im missing?) .. id still like to know WHY this is happening though...
also the trailing window thing is bothering me the most... the post is still un-answered in the Nehe forum



thanks for any help!!

Share this post


Link to post
Share on other sites