jmg
11-30-2002, 08:01 AM
I posted this in the beginner area but no luck.
Below is the complete program so you can have something to copy/paste/compile/run if you'd like to try it yourself and see if you can help.
The program draws glColor3d()'d coordinate axes, a single lit shaded triangle in the x-z plane (y is up), with a light circling around the triangle, about the (+) z axis, in the x-y plane. I draw a little glColor3d()'d GL_POINT where the light is.
The problem is, the little dot is only drawn in the first frame. After that it's not drawn, but everything else works fine. I put in an SDL_Delay( 500 ) to make this effect more obvious.
If I change the last arg in the glLightfv() call (in draw(), where the // XXX is) from light_pos to light_dir, the problem goes away. Am I using glLightfv() incorrectly?
// tiny_sdl_gl
//
// main.cpp
#include <cstdlib>
#include <iostream>
#include <gl.h>
#include <glu.h>
#include <SDL.h>
#include <SDL_video.h>
using std::exit;
using std::cout;
using std::endl;
//------------------------------
GLfloat radius = 2.5;
GLfloat light_pos[] = { 0.0, radius, 0.0, 1.0 }; // positional
GLfloat light_dir[] = { 0.0, radius, 0.0, 0.0 }; // directional
GLfloat theta = 0; // rotation of light about the z-axis.
//---------------------------------------------------------------------
void processEvents()
{
SDL_Event event;
while( SDL_PollEvent( &event ) )
{
if ( event.type == SDL_QUIT )
{
cout << "quit has been requested via ctrl-c or close window"
<< endl;
SDL_Quit();
exit( 0 );
break;
}
}
}
//---------------------------------------------------------
void initSDL(int width, int height)
{
if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
{
cout << "couldn't initialize SDL: " << SDL_GetError() << endl;
SDL_Quit();
exit(1);
}
const SDL_VideoInfo * vid_info = SDL_GetVideoInfo();
int bpp = vid_info->vfmt->BitsPerPixel;
cout << "Found bpp = " << bpp << endl;
unsigned int vid_flags =
SDL_DOUBLEBUF |
SDL_OPENGL |
SDL_HWPALETTE |
SDL_HWACCEL;
if ( vid_info->hw_available )
{
cout << "Found hw_available. Setting vid_flags |= SDL_HWSURFACE." << endl;
vid_flags |= SDL_HWSURFACE;
}
else
{
cout << "Didn't find hw_available. Setting vid_flags |= SDL_SWSURFACE." << endl;
vid_flags |= SDL_SWSURFACE;
}
if ( vid_info->blit_hw )
{
cout << "Found blit_hw. Setting vid_flags |= SDL_HWACCEL." << endl;
vid_flags |= SDL_HWACCEL;
}
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 ); // default anyway.
SDL_Surface * surf = SDL_SetVideoMode( width, height, bpp, vid_flags );
if ( surf == NULL )
{
cout << "unable to set video mode: " << SDL_GetError() << endl;
SDL_Quit();
exit(1);
}
SDL_WM_SetCaption( "sdl_ast", "sdl_ast" );
}
//---------------------------------------------------------
void initGL(int width, int height)
{
glPolygonMode( GL_FRONT, GL_FILL );
glShadeModel( GL_SMOOTH );
glCullFace( GL_BACK );
glEnable( GL_CULL_FACE );
glClearColor( 0.0, 0.0, 0.0, 0.0 );
glPointSize( 4.0 );
glLineWidth( 2.0 );
glEnable( GL_DEPTH_TEST );
GLfloat mat_spec[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shin = 50.0;
GLfloat mat_emerald[] = { 0.0, 0.8, 0.1, 1.0 };
GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat amb_light[] = { 0.2, 0.2, 0.2, 1.0 };
glMaterialfv( GL_FRONT, GL_SPECULAR, mat_spec );
glMaterialf( GL_FRONT, GL_SHININESS, mat_shin );
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_emerald );
glLightfv( GL_LIGHT0, GL_AMBIENT, amb_light );
glLightfv( GL_LIGHT0, GL_DIFFUSE, white_light );
glLightfv( GL_LIGHT0, GL_SPECULAR, white_light );
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 40.0, 1.0, 4.0, 16.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
//------------------------------------------------
void draw()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
gluLookAt( 2.0, 4.0, 7.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0 );
glPushMatrix();
glRotated( theta, 0.0, 0.0, 1.0 );
glLightfv( GL_LIGHT0, GL_POSITION, light_pos ); // XXX
// Draw the dot representing the light.
glDisable( GL_LIGHTING );
glBegin( GL_POINTS );
glColor3d( 1.0, 1.0, 1.0 );
glVertex4fv( light_pos );
glEnd();
glEnable( GL_LIGHTING );
glPopMatrix();
// Draw the x y z coordinate axes.
glDisable( GL_LIGHTING );
glBegin( GL_LINES );
glColor3d( 1.0, 0.0, 0.0 );
glVertex3d( 0.0, 0.0, 0.0 );
glVertex3d( 2.0, 0.0, 0.0 );
glColor3d( 0.0, 1.0, 0.0 );
glVertex3d( 0.0, 0.0, 0.0 );
glVertex3d( 0.0, 2.0, 0.0 );
glColor3d( 0.0, 0.0, 1.0 );
glVertex3d( 0.0, 0.0, 0.0 );
glVertex3d( 0.0, 0.0, 2.0 );
glEnd();
glEnable( GL_LIGHTING );
// Draw a simple triangle facing up near the origin.
glBegin( GL_TRIANGLES );
glNormal3d( 0.0, 1.0, 0.0 ); // Normal facing up.
// The winding is correct so the "front" is facing up,
// in the same direction as the normal.
glVertex3d( 0.0, 0.0, 0.0 );
glVertex3d( 0.5, 0.0, 1.0 );
glVertex3d( 1.0, 0.0, 0.2 );
glEnd();
glPopMatrix();
glFinish();
}
//------------------------------------------------
int main( int argc, char * argv[] )
{
int width = 400;
int height = 400;
initSDL( width, height );
initGL( width, height );
while ( true )
{
SDL_Delay( 500 ); // This is just here to slow things down
// enough to see the effect I'm asking about.
processEvents();
theta += 5.0;
if ( theta > 360.0 )
{
theta -= 360.0;
}
draw();
SDL_GL_SwapBuffers();
}
SDL_Quit();
return 0;
}
//------------------------------------------------
And here's the makefile:
# makefile for tiny_sdl_gl
#
APP_NAME = tiny_sdl_gl
LDFLAGS = `sdl-config --libs` -L/usr/X11R6/lib -lGL -lGLU
CFLAGS = -c `sdl-config --cflags` -I/usr/X11R6/include/GL
#----------------------------------------------
$(APP_NAME): main.o
g++ -o $(APP_NAME) $(LDFLAGS) main.o
main.o: main.cpp
g++ $(CFLAGS) main.cpp
clean:
rm -f $(APP_NAME)
rm -f *.o
[This message has been edited by jmg (edited 11-30-2002).]
Below is the complete program so you can have something to copy/paste/compile/run if you'd like to try it yourself and see if you can help.
The program draws glColor3d()'d coordinate axes, a single lit shaded triangle in the x-z plane (y is up), with a light circling around the triangle, about the (+) z axis, in the x-y plane. I draw a little glColor3d()'d GL_POINT where the light is.
The problem is, the little dot is only drawn in the first frame. After that it's not drawn, but everything else works fine. I put in an SDL_Delay( 500 ) to make this effect more obvious.
If I change the last arg in the glLightfv() call (in draw(), where the // XXX is) from light_pos to light_dir, the problem goes away. Am I using glLightfv() incorrectly?
// tiny_sdl_gl
//
// main.cpp
#include <cstdlib>
#include <iostream>
#include <gl.h>
#include <glu.h>
#include <SDL.h>
#include <SDL_video.h>
using std::exit;
using std::cout;
using std::endl;
//------------------------------
GLfloat radius = 2.5;
GLfloat light_pos[] = { 0.0, radius, 0.0, 1.0 }; // positional
GLfloat light_dir[] = { 0.0, radius, 0.0, 0.0 }; // directional
GLfloat theta = 0; // rotation of light about the z-axis.
//---------------------------------------------------------------------
void processEvents()
{
SDL_Event event;
while( SDL_PollEvent( &event ) )
{
if ( event.type == SDL_QUIT )
{
cout << "quit has been requested via ctrl-c or close window"
<< endl;
SDL_Quit();
exit( 0 );
break;
}
}
}
//---------------------------------------------------------
void initSDL(int width, int height)
{
if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
{
cout << "couldn't initialize SDL: " << SDL_GetError() << endl;
SDL_Quit();
exit(1);
}
const SDL_VideoInfo * vid_info = SDL_GetVideoInfo();
int bpp = vid_info->vfmt->BitsPerPixel;
cout << "Found bpp = " << bpp << endl;
unsigned int vid_flags =
SDL_DOUBLEBUF |
SDL_OPENGL |
SDL_HWPALETTE |
SDL_HWACCEL;
if ( vid_info->hw_available )
{
cout << "Found hw_available. Setting vid_flags |= SDL_HWSURFACE." << endl;
vid_flags |= SDL_HWSURFACE;
}
else
{
cout << "Didn't find hw_available. Setting vid_flags |= SDL_SWSURFACE." << endl;
vid_flags |= SDL_SWSURFACE;
}
if ( vid_info->blit_hw )
{
cout << "Found blit_hw. Setting vid_flags |= SDL_HWACCEL." << endl;
vid_flags |= SDL_HWACCEL;
}
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 ); // default anyway.
SDL_Surface * surf = SDL_SetVideoMode( width, height, bpp, vid_flags );
if ( surf == NULL )
{
cout << "unable to set video mode: " << SDL_GetError() << endl;
SDL_Quit();
exit(1);
}
SDL_WM_SetCaption( "sdl_ast", "sdl_ast" );
}
//---------------------------------------------------------
void initGL(int width, int height)
{
glPolygonMode( GL_FRONT, GL_FILL );
glShadeModel( GL_SMOOTH );
glCullFace( GL_BACK );
glEnable( GL_CULL_FACE );
glClearColor( 0.0, 0.0, 0.0, 0.0 );
glPointSize( 4.0 );
glLineWidth( 2.0 );
glEnable( GL_DEPTH_TEST );
GLfloat mat_spec[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shin = 50.0;
GLfloat mat_emerald[] = { 0.0, 0.8, 0.1, 1.0 };
GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat amb_light[] = { 0.2, 0.2, 0.2, 1.0 };
glMaterialfv( GL_FRONT, GL_SPECULAR, mat_spec );
glMaterialf( GL_FRONT, GL_SHININESS, mat_shin );
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_emerald );
glLightfv( GL_LIGHT0, GL_AMBIENT, amb_light );
glLightfv( GL_LIGHT0, GL_DIFFUSE, white_light );
glLightfv( GL_LIGHT0, GL_SPECULAR, white_light );
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 40.0, 1.0, 4.0, 16.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
//------------------------------------------------
void draw()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
gluLookAt( 2.0, 4.0, 7.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0 );
glPushMatrix();
glRotated( theta, 0.0, 0.0, 1.0 );
glLightfv( GL_LIGHT0, GL_POSITION, light_pos ); // XXX
// Draw the dot representing the light.
glDisable( GL_LIGHTING );
glBegin( GL_POINTS );
glColor3d( 1.0, 1.0, 1.0 );
glVertex4fv( light_pos );
glEnd();
glEnable( GL_LIGHTING );
glPopMatrix();
// Draw the x y z coordinate axes.
glDisable( GL_LIGHTING );
glBegin( GL_LINES );
glColor3d( 1.0, 0.0, 0.0 );
glVertex3d( 0.0, 0.0, 0.0 );
glVertex3d( 2.0, 0.0, 0.0 );
glColor3d( 0.0, 1.0, 0.0 );
glVertex3d( 0.0, 0.0, 0.0 );
glVertex3d( 0.0, 2.0, 0.0 );
glColor3d( 0.0, 0.0, 1.0 );
glVertex3d( 0.0, 0.0, 0.0 );
glVertex3d( 0.0, 0.0, 2.0 );
glEnd();
glEnable( GL_LIGHTING );
// Draw a simple triangle facing up near the origin.
glBegin( GL_TRIANGLES );
glNormal3d( 0.0, 1.0, 0.0 ); // Normal facing up.
// The winding is correct so the "front" is facing up,
// in the same direction as the normal.
glVertex3d( 0.0, 0.0, 0.0 );
glVertex3d( 0.5, 0.0, 1.0 );
glVertex3d( 1.0, 0.0, 0.2 );
glEnd();
glPopMatrix();
glFinish();
}
//------------------------------------------------
int main( int argc, char * argv[] )
{
int width = 400;
int height = 400;
initSDL( width, height );
initGL( width, height );
while ( true )
{
SDL_Delay( 500 ); // This is just here to slow things down
// enough to see the effect I'm asking about.
processEvents();
theta += 5.0;
if ( theta > 360.0 )
{
theta -= 360.0;
}
draw();
SDL_GL_SwapBuffers();
}
SDL_Quit();
return 0;
}
//------------------------------------------------
And here's the makefile:
# makefile for tiny_sdl_gl
#
APP_NAME = tiny_sdl_gl
LDFLAGS = `sdl-config --libs` -L/usr/X11R6/lib -lGL -lGLU
CFLAGS = -c `sdl-config --cflags` -I/usr/X11R6/include/GL
#----------------------------------------------
$(APP_NAME): main.o
g++ -o $(APP_NAME) $(LDFLAGS) main.o
main.o: main.cpp
g++ $(CFLAGS) main.cpp
clean:
rm -f $(APP_NAME)
rm -f *.o
[This message has been edited by jmg (edited 11-30-2002).]