Sign in to follow this  
FlyingIsFun1217

SDL + OpenGL issues

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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 members
SGE::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
}

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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 :)

Share this post


Link to post
Share on other sites
Quote:
Original post by FlyingIsFun1217
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 :)


No, the loop in main is fine. The problem is the outer loop in closeRequest. That is the loop that never finishes until we get a QUIT event.

Share this post


Link to post
Share on other sites
Yes, I finally figured out what was going on there ;)

Last problem (hopefully!)... Compiler gives the warning: 'ISO C++ forbids comparison between pointer and integer' on 'if(event.type == SDL_Quit)'. Is it seeing 'type' as a pointer? Seems kinda wierd, since it worked the first time :/

FlyingIsFun1217

Share this post


Link to post
Share on other sites
SDL_Quit is a function, 'SDL_Quit()'. SDL_QUIT is a event enum, which is what you are wanting. It's what you are supposed to check against. SDL sends SDL_QUIT when the user clicks the 'x' button of the window. SDL_Quit() is a function that shuts down SDL when you are done using it.

The compiler thinks you are trying to compare a int value 'event.type' to a function pointer, 'SDL_Quit'. SDL_Quit is a pointer, because dropping the '(' ')' from functions is used to get a pointer to that function. Capitalization matters, I've made the same mistake a few times myself. [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by Servant of the Lord
SDL_Quit is a function, 'SDL_Quit()'. SDL_QUIT is a event enum, which is what you are wanting. It's what you are supposed to check against. SDL sends SDL_QUIT when the user clicks the 'x' button of the window. SDL_Quit() is a function that shuts down SDL when you are done using it.

The compiler thinks you are trying to compare a int value 'event.type' to a function pointer, 'SDL_Quit'. SDL_Quit is a pointer, because dropping the '(' ')' from functions is used to get a pointer to that function. Capitalization matters, I've made the same mistake a few times myself. [smile]


Hehe. Tricky.

Guess I outta take a nice look through the SDL documentation project, eh? :)

Many thanks to everybody who helped me out! I hope I have rated you accordingly ;)

Thanks!
FlyingIsFun1217

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this