Here’s how I usually do it.
First setup SetGLWindow()
void SetGLWindow(int width, int height)
{
GLfloat ratio;
if(height == 0)
height = 1;
ratio = (GLfloat)width/(GLfloat)height;
glViewport(0, 0, (GLint)width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
Then I wait for a resize event in my main loop
while(!done)
{
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_ACTIVEEVENT:
if(event.active.gain == 0)
isActive = FALSE;
else
isActive = TRUE;
break;
case SDL_VIDEORESIZE:
if((surface = SDL_SetVideoMode(event.resize.w,
event.resize.h,
SCREEN_BPP,
videoFlags)) == NULL)
{
fprintf(stderr,“Unable to grab surface after resize event:
%s\n”,SDL_GetError());
Quit(1);
}
SetGLWindow(event.resize.w, event.resize.h);
break;
case SDL_KEYDOWN:
HandleKeyDown(&event.key.keysym);
break;
case SDL_QUIT:
done = TRUE;
break;
default:
break;
}
}
if(isActive)
DrawScreen();
}
**** – Below is the full example program. More examples can be found on
http://nehe.gamedev.net
/***** Begin Code Paste *****/
/* build with:
- gcc -ggdb -Wall -L/usr/X11R6/lib -lGL -lGLU
sdl-config --cflags --libs
sdl-gl-18.c -o sdl-gl-18
*/
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 32
#define TRUE 1
#define FALSE 0
SDL_Surface *surface;
int light = FALSE;
GLdouble part1, part2;
GLdouble p1 = 0;
GLdouble p2 = 1;
GLfloat xRot, yRot, ySpeed, xSpeed;
GLfloat z = -5.0f;
GLfloat ambientLight[] = {0.5f, 0.5f, 0.5f, 1.0f };
GLfloat diffusedLight[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPosition[] = {0.0f, 0.0f, 2.0f, 1.0f};
GLUquadricObj *quadric;
GLuint object = 0;
GLuint filter;
GLuint texture[3];
void Quit(int returnCode)
{
gluDeleteQuadric(quadric);
glDeleteTextures(3, texture);
SDL_Quit();
if(returnCode != 42)
exit(returnCode);
}
int LoadTextures()
{
int status = FALSE;
SDL_Surface *textureImage;
if((textureImage=SDL_LoadBMP(“q_tex.bmp”)))
{
status = TRUE;
glGenTextures(3, texture);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D,
0,
3,
textureImage->w,
textureImage->h,
0,
GL_BGR,
GL_UNSIGNED_BYTE,
textureImage->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexImage2D(GL_TEXTURE_2D,
0,
3,
textureImage->w,
textureImage->h,
0,
GL_BGR,
GL_UNSIGNED_BYTE,
textureImage->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, texture[2]);
gluBuild2DMipmaps(GL_TEXTURE_2D,
3,
textureImage->w,
textureImage->h,
GL_BGR,
GL_UNSIGNED_BYTE,
textureImage->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
SDL_FreeSurface(textureImage);
}
return status;
}
int InitGL(void)
{
if(!LoadTextures())
return FALSE;
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffusedLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glEnable(GL_LIGHT0);
quadric = gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
gluQuadricTexture(quadric, GL_TRUE);
return TRUE;
}
void SetGLWindow(int width, int height)
{
GLfloat ratio;
if(height == 0)
height = 1;
ratio = (GLfloat)width/(GLfloat)height;
glViewport(0, 0, (GLint)width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void HandleKeyDown(SDL_keysym *keysym)
{
switch(keysym->sym)
{
case SDLK_ESCAPE:
case SDLK_q:
Quit(0);
break;
case SDLK_F1:
SDL_WM_ToggleFullScreen(surface);
break;
case SDLK_f:
filter = (++filter)%3;
break;
case SDLK_l:
light = !light;
if(!light)
glDisable(GL_LIGHTING);
else
glEnable(GL_LIGHTING);
break;
case SDLK_SPACE:
object = (++object)%6;
break;
case SDLK_PAGEUP:
if(keysym->mod & KMOD_SHIFT)
z -= 0.08;
else
z -= 0.02;
break;
case SDLK_PAGEDOWN:
if(keysym->mod & KMOD_SHIFT)
z += 0.08;
else
z += 0.02;
break;
case SDLK_UP:
if(keysym->mod & KMOD_SHIFT)
xSpeed -= 0.04;
else
xSpeed -= 0.01;
break;
case SDLK_DOWN:
if(keysym->mod & KMOD_SHIFT)
xSpeed += 0.04;
else
xSpeed += 0.01;
break;
case SDLK_RIGHT:
if(keysym->mod & KMOD_SHIFT)
ySpeed += 0.04;
else
ySpeed += 0.01;
break;
case SDLK_LEFT:
if(keysym->mod & KMOD_SHIFT)
ySpeed -= 0.04;
else
ySpeed -= 0.01;
break;
default:
break;
}
}
void DrawCube(void)
{
glBegin (GL_QUADS);
{
/* draw cube */
/* each face drawn counter clockwise
* beginining from the bottom left corner */
/* front face */
glNormal3f( 0.0, 0.0, 1.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
/* right face */
glNormal3f(1.0, 0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
/* back face */
glNormal3f(0.0, 0.0, -1.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
/* left face */
glNormal3f(1.0, 0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
/* top face */
glNormal3f(0.0, 1.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, 1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
/* bottom face */
glNormal3f(0.0, -1.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
}
glEnd();
}
void DrawScreen(void)
{
static GLint timeA, timeB, frames = 0;
static GLfloat fps, seconds = 0.0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0, 0.0, z);
glRotatef(xRot, 1.0, 0.0, 0.0);
glRotatef(yRot, 0.0, 1.0, 0.0);
glBindTexture(GL_TEXTURE_2D, texture[filter]);
switch(object)
{
case 0:
glTranslatef(0.0, 0.0, 1.0);
gluDisk(quadric, 0.5, 1.0, 32, 32);
glTranslatef(0.0, 0.0, -1.5f);
gluCylinder(quadric, 1.0, 1.0, 3.0, 32, 32);
break;
case 1:
gluDisk(quadric, 0.5, 1.5, 32, 32);
break;
case 2:
DrawCube();
break;
case 3:
gluSphere(quadric, 1.3f, 32, 32);
break;
case 4:
/* draw a cone */
glTranslatef(0.0, 0.0, -1.5);
gluCylinder(quadric, 1.0, 0.0, 3.0, 32, 32);
break;
case 5:
part1 += p1;
part2 += p2;
if(part1 > 359)
{
part1 = 0;
p1 = 0;
p2 = 1;
part2 = 0;
}
if(part2 > 359)
{
p1 = 1;
p2 = 0;
}
gluPartialDisk(quadric, 0.5, 1.5, 32, 32, part1, part2-part1);
break;
}
SDL_GL_SwapBuffers();
frames++;
timeB = SDL_GetTicks();
if(timeB - timeA >= 5000)
{
seconds = (timeB - timeA) / 1000.0;
fps = frames / seconds;
fprintf(stdout, “%d frames in %g seconds = %g fps.\n”, frames, seconds,
fps);
timeA = timeB;
frames = 0;
}
xRot += xSpeed;
yRot += ySpeed;
}
int main(int argc, char **argv)
{
int videoFlags;
int done = FALSE;
SDL_Event event;
int isActive = TRUE;
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr,“Unable to init video: %s\n”, SDL_GetError());
Quit(1);
}
videoFlags =
SDL_OPENGL |
SDL_GL_DOUBLEBUFFER |
SDL_HWPALETTE |
SDL_RESIZABLE |
SDL_HWSURFACE |
SDL_HWACCEL;
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if((surface = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
videoFlags)) == NULL)
{
fprintf(stderr,“Unable to grab surface: %s\n”,SDL_GetError());
Quit(1);
}
if((SDL_EnableKeyRepeat(100, SDL_DEFAULT_REPEAT_INTERVAL)) > 0)
{
fprintf(stderr,“Unable to setup keyboad repeat: %s\n”,SDL_GetError());
Quit(1);
}
if(!InitGL())
{
fprintf(stderr,“Unable to init OpenGL: %s\n”, SDL_GetError());
}
SetGLWindow(SCREEN_WIDTH, SCREEN_HEIGHT);
while(!done)
{
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_ACTIVEEVENT:
if(event.active.gain == 0)
isActive = FALSE;
else
isActive = TRUE;
break;
case SDL_VIDEORESIZE:
if((surface = SDL_SetVideoMode(event.resize.w,
event.resize.h,
SCREEN_BPP,
videoFlags)) == NULL)
{
fprintf(stderr,“Unable to grab surface after resize event:
%s\n”,SDL_GetError());
Quit(1);
}
SetGLWindow(event.resize.w, event.resize.h);
break;
case SDL_KEYDOWN:
HandleKeyDown(&event.key.keysym);
break;
case SDL_QUIT:
done = TRUE;
break;
default:
break;
}
}
if(isActive)
DrawScreen();
}
Quit(42);
return 0;
}On Wednesday 12 January 2005 08:31 am, Michael Wyrzykowski wrote:
On Tue, 2005-01-11 at 19:11 +0000, Michael Wyrzykowski wrote:
The SDL_VIDEORESIZE event doesn’t do anything by itself. SDL does not
take any action when it sees that event or when it generates that
event. The event is there to tell you that the window has changed
size. Your code is responsible for actually changing the displayable
size of the window. What does your code do to handle the event? It
should be calling SDL_SetVideoMode() to make the SDL surface match
the new window size, and then (on Windows) reloading all your
textures and probably recreating your OpenGL context.
If your code is not handling the SDL_VIDEORESIZE event then your
program is not doing the right things when the window changes
size.
Bob Pendleton
I am handling the SDL_VIDEORESIZE event like:
if(event.type == SDL_VIDEORESIZE)
{
int width = event.resize.w;
int height = event.resize.h;
float scale_width = float(width)/800; //game logic set for
float scale_height = float(height)/600;// 800x600 resolution
glViewport( 0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, width, height, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef( scale_width, scale_height, 1.0f );
}
Yeah, you really are supposed to call SDL_SetVideoMode to make the SDL
view of the window match the windowing systems view of the window. >
What happens when you make the window larger than the original window?
Bob Pendleton
When I make the window larger my using the mouse, the call to glScalef()
simply scales everything that it draws so that whatever size the window is,
then images will be scaled appropriately to fit. Nothing is cut off. For
example, the size of my background image is 800x600 (also the default size
to the window). If the user changes the window size with the mouse to
400x600, then glScalef() will be called to scale all images by 0.5 on the
x-axis, 1.0 on the y-axis, and 1.0 on the z-axis.
When resizing the window with the mouse, I do not need to reload in any
textures, and everything displays properly. However, I wanted to be able to
specify the sizes the user could choose, so the graphics do not looked
distorted from changing a 800x600 window to something like 600x800 (making
all graphics look taller and less wide).
I’m thinking that the proper thing to do would be to actually call
SetVideoMode again to request the correct resolution. It may be that I am
developing a laptop that I did not notice any difference (an LCD display
scales images because it only has one true resolution).
Speed up your surfing with Juno SpeedBand.
Now includes pop-up blocker!
Only $14.95/month -visit http://www.juno.com/surf to sign up today!
SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl
–
They that can give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety. --Benjamin Franklin