SDL + OpenGL issues

Started by
12 comments, last by FlyingIsFun1217 16 years, 4 months ago
Hey! I'm attempting to create a modularized SDL + OGL engine. So far things have been going pretty well, I'm starting to learn how to do this stuff, which makes me excited. Here's some of my code:

int SW;
int SH;
int BPP;

class SGE
{
	public:
		SGE();
		~SGE();
		void startWindow(int screenWidth, int screenHeight, int bitsPerPixel);
		bool stopWindow();
		void draw();
		
	private:
	    	
};
[...]
void SGE::startWindow(int screenWidth, int screenHeight, int bitsPerPixel)
{
     screenWidth = SW;
     screenHeight = SH;
     bitsPerPixel = BPP;
     
     log logIns;
     
     SDL_Surface *screen;
     
     if(SDL_Init(SDL_INIT_VIDEO) != 0)
     {
         logIns.logMsg("ERROR: Could not initialize SDL_Video!");
         stopWindow();
     }
     
     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
     
     screen = SDL_SetVideoMode(SW, SH, BPP, SDL_OPENGL /*| SDL_FULLSCREEN*/);
     
     if(!screen)
     {
         logIns.logMsg("ERROR: Could not set video mode!");
         stopWindow();
     }
}
[...]
void SGE::draw()
{
     glClear(GL_COLOR_BUFFER_BIT);
     glColor3f(0.7, 0.5, 0.8);
     glRectf(1.0, 1.0, 3.0, 2.0);
     SDL_GL_SwapBuffers();
}



That's my header, I initialize it like so:

int main(int argc, char *argv[])
{
    SGE      engineInstance;
    log      logInstance;
    events   eventInstance;
    
    engineInstance.startWindow(300, 300, 32);

    if(eventInstance.closeRequest() == true)
    {
        engineInstance.stopWindow();
    }
    
    engineInstance.draw();
}



As is, there are only two problems that I am dealing with at the moment (besides the fact that I'm not really doing any OGL stuff...): 1. It seems that when I pass over the SW, SH, BPP int's to SDL_SetVideoMode, it doesn't... accept(?) them. If I hard-code in, say 640x480x16, all seems to work just fine. What is causing this? 2. I know that it's only rendering what's in SGE::draw() once, and obviously, thats a problem. I would love it to just keep redrawing whatever I tell it to until it gets that quit signal. What do I need to do to get it to respond in such a way? I've tried loops galore, but nothing seems to work! Thanks for the help, I greatly appreciate it! FlyingIsFun1217
Advertisement
You have 3 globals, SW, SH and SBPP. ince they are never given values, they cannot have reasonable values inside startWindow. Just use the parameter values instead. In addition, I imagine stopWindow() calls SDL_Quit. Why not put the code in stop window in the destructor? (or make stopWindow private, and call it from the destructor and the contructor in the event of an error). Also, I suggest that a bad error (not being able to set up the screen) might result in an exception being thrown in the SGE constructor.

As for the draw, shouldn't draw be inside a loop:
int main(int argc, char *argv[]){    // ...    while(!eventInstance.closeRequest())    {        engineInstance.draw();    }    // if you move this to a destructor as mentioned, you can drop this    // engineInstance.stopWindow();        // ...}


I hope your SGE class is divided into header and source files, for the function definitions. Otherwise when you include them elsewhere you will get linking errors.
Thanks for the pointers, I will try as you suggest.

As to SW, SH, BPP... why wouldn't they have values? Don't I pass those int values to them through startWindow?

When you mean 'separate the SGE class into different source and header files, do you mean declaring the class in a header, and putting the class members each in separate source files? What is the benefit of this? I can only see it making the project more complicated with much more files.

Thanks again!
FlyingIsFun1217
I think what rip-off means is that nowhere in the code you posted initializes or sets value of SW, SH and BPP. So they are likely to be garbage value (i.e. BPP having values like 30238482 kind of thing).

unless the following lines in startWindow:

void SGE::startWindow(int screenWidth, int screenHeight, int bitsPerPixel){     screenWidth = SW;     screenHeight = SH;     bitsPerPixel = BPP;


is meant to be:
void SGE::startWindow(int screenWidth, int screenHeight, int bitsPerPixel){     SW = screenWidth;     SH = screenHeight;     BPP = bitsPerPixel;
Quote:Original post by tts1980
unless the following lines in startWindow:

*** Source Snippet Removed ***

is meant to be:
*** Source Snippet Removed ***


Holey moley! I can't believe I overlooked that!

Problem solved! Thanks for the hint ;)

FlyingIsFun1217

Hey...

It seems that no matter what I try and do to get it to render right, it just produces a window that grabs the contents that were below it when it started.

Here (http://www.mediamax.com/flyingisfun1217/Hosted/SGT.zip) is the zipped up source. Would anybody be willing to look through it? I just didn't feel like spamming the board with more source :P

Thanks again, I really appreciate it!
FlyingIsFun1217
Your new problem is in events.h

Look carefully at this code:
bool events::closeRequest(){     bool closeRequest = false;          while(closeRequest == false)     {         while(SDL_PollEvent(&event))         {             if(event.type == SDL_QUIT)             {                 closeRequest = true;             }         }     }          return closeRequest;                                                 }


Be cause we have an outer while loop that says 'while( closeRequest == false )', the entire function cannot return until this condition is met. Obviously the only way for this condition to be true is if we receive the SDL_QUIT event. A better name for this function might be loopForeverUntilWindowIsClosed [smile].

We can re-write simply:
bool events::closeRequest(){    while(SDL_PollEvent(&event))    {        if(event.type == SDL_QUIT)        {             return true;        }    }    return false;                                                }


Here is how I would re-write your code (bear in mind I threw it all into a single file, you will have to separate it again):
#include <iostream>#include <stdexcept>#include "SDL.h"#include "SDL_opengl.h"class SGE{public:    // Don't write empty constructors    // Especially when there is a sane task we can give the constructor    SGE(int screenWidth, int screenHeight, int bitsPerPixel);    ~SGE();    // removed in favour of the constructor    // void startWindow();    // avoid functions returning a boolean or integer    // that always return the same value. use 'void'    // bool stopWindow();    void draw();private:    // we can be a little more descriptive with our variable names ;)    int screenWidth;    int screenHeight;    int bitsPerPixel;};// In C++, we initialise variables in the constructors 'intialiser list'// You start with a colon following the end of the argument list// then you place each member variable you want to initialise// with parentheses around what you wish to initialise it with.// also note I used the same name for the parameters as the members// this is ok, C++ knows that in an initialiser list the only thing that// can be initialised are membersSGE::SGE(int screenWidth, int screenHeight, int bitsPerPixel):    screenWidth(screenWidth),    screenHeight(screenHeight),    bitsPerPixel(bitsPerPixel){    // logging removed because you didn't include it in zip    // log logIns;    // prefer to declare variables at point of use    // SDL_Surface *screen;    if(SDL_Init(SDL_INIT_VIDEO) != 0)    {        // as a fatal error, throwing an exception is a reasonable thing to do        throw std::runtime_error(SDL_GetError());    }    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);    SDL_Surface * screen = SDL_SetVideoMode(screenWidth, screenHeight, bitsPerPixel, SDL_OPENGL /*| SDL_FULLSCREEN*/);    if(!screen)    {        // same as above regarding fatal error        // also note we need to call SDL_Quit() here        // destructors do not get called when an object throws an        // exception in its constructor        SDL_Quit();        throw std::runtime_error(SDL_GetError());    }}SGE::~SGE(){    SDL_Quit();}void SGE::draw(){    glClearColor(0.0, 0.0, 0.0, 0.0);    glBegin(GL_LINES);    glVertex3f(6.0, 4.0, 2.0);    glVertex3f(2.0, -4.0, 3.3);    glVertex3f(5.0, 8.0, 8.0);    glVertex3f(-4.7, 5.0, -3.0);    glVertex3f(0.0, 0.0, 0.0);    glVertex3f(6.0, -1.0, -7.0);    glEnd();    SDL_GL_SwapBuffers();}class events{public:    // Don't write empty constructors and destructors    // C++ will generate these for you if you don't provide them    // C++ will also generate copy constructors and operator=()    // which are not always desired    // events();    // ~events();    bool closeRequest();private:    SDL_Event event;};bool events::closeRequest(){    while(SDL_PollEvent(&event))    {        if(event.type == SDL_QUIT)        {            return true;        }    }    // if we reach here, then we must not have received the SDL_QUIT event    return false;}int main(int argc, char *argv[]){    SGE      engineInstance(300,300,32);    // logging removed because you didn't include it in zip    //log      logInstance;    events   eventInstance;    while(eventInstance.closeRequest() == false)    {        engineInstance.draw();    }    return 0;    // engineInstance destructor cleans up SDL for us}
Cool, thanks for reviewing it... again! Even when you didn't have to :)

One thing I noticed you did, I think it was mentioned earlier, was that I could just put SDL_Quit(); in the destructor. Guess this was another thing I kept overlooking.

I'm still kinda confused though as to why the event is bad. Here goes a (most likely) stupid question again. Won't the function just keep going through keeping closeRequest as false until it has been deemed true through an SDL_Quit() event?

Thanks again for the help!
FlyingIsFun1217
Quote:Original post by FlyingIsFun1217
I'm still kinda confused though as to why the event is bad. Here goes a (most likely) stupid question again. Won't the function just keep going through keeping closeRequest as false until it has been deemed true through an SDL_Quit() event?


Yes, but you want to draw the screen too [smile]
Quote:Original post by rip-off
Yes, but you want to draw the screen too [smile]


So by doing a loop in main.cpp, it's only checking for the event, and doesn't draw until it gets one?

FlyingIsFun1217 :)

This topic is closed to new replies.

Advertisement