Sign in to follow this  
BeginGamer

Texture Error

Recommended Posts

I was battling with my code for today, and I pin-pointed the error of my sdl program instantly closing from error with the generation of my textures...


[CODE]
// in my DrawingGame definition source file
static void uploadImage( std::string & filename, GLuint & id )
{
SDL_Surface * tempt = IMG_Load(filename.c_str());
if(!tempt)
{
id = 0;
}
SDL_Surface * nCopy = SDL_CreateRGBSurface(SDL_SWSURFACE,tempt->w,tempt->h,32,
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
#else
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
#endif
);
SDL_BlitSurface(tempt,NULL,nCopy,NULL);
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
nCopy->w, nCopy->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, nCopy->pixels);
SDL_FreeSurface(tempt);
SDL_FreeSurface(nCopy);
}

void gameDraw::Render_2D::getSpriteSheets(const std::vector<std::string> & imagefiles )
{
std::vector<GLuint>::iterator it;
unsigned int nSize = imagefiles.size();
textures.insert(it,nSize, 0);
unsigned int i = 0;
BOOST_FOREACH( std::string image, imagefiles )
{
uploadImage(image, textures[i]);
++i;
}
}

[/CODE]

Share this post


Link to post
Share on other sites
You should specify the "it" first:
it = textures.begin();

if you want to insert to the beginning of vector :
textures.insert(it, nSize, value); (value : choose by urself)

if not the beginning

textures.insert(it + number, nSize, value) (number: is where you want); Edited by KhoaVN

Share this post


Link to post
Share on other sites
why u must use it = textures.begin()
Let see this example:

i have a vector which has 2 items value 10:
myvector: | 10 | 10 |

I want to add 2 items (value : 20) to the myvector to form this one:
myvector: | 20 | 20 | 10 | 10 |

I must do : it = myvector.begin();
It means I want a place holder (we dont need to know the size) at the beginning of the myvector
myvector: |....place_holder......| 10 | 10 |
so "it" is your place_holder

then fill the place_holder with value u want
myvector.insert(it, nSize, value);
it means let myvector fills the "it" (the place_holder) with the "value" and "nSize" i want.

Another example:
your vector here:
myvector: | 10 | 10 |
add 2 more items to the middle
it = myvector.begin();
myvector.insert( it + 1, nSize, value);

you will have | 10 | 20 | 20 | 10 |

Share this post


Link to post
Share on other sites
I tried that and still got an error , and I also tried
[CODE]
void gameDraw::Render_2D::getSpriteSheets(const std::vector<std::string> & imagefiles )
{
unsigned int nSize = imagefiles.size();
std::vector<GLuint> SpriteSheets(nSize, 0);
unsigned int i = 0;
BOOST_FOREACH( std::string image, imagefiles )
{
uploadImage(image, SpriteSheets[i]);
++i;
}
textures = SpriteSheets;
}
[/CODE]

Share this post


Link to post
Share on other sites
Another problem i found in your logic:

if temp is null

how can u call func :
SDL_CreateRGBSurface()

if temp is null, u should return.

Share this post


Link to post
Share on other sites
oh sorry,
I found another. vertor operator [] returns a "reference" not an "int".

So my advice is to use a GLint* (int pointer) instead of vector<GLint>

example:
GLint* SpriteSheep = new GLint[nSize];
then
u can use uploadImage(image, SpriteSheet[i]); Edited by KhoaVN

Share this post


Link to post
Share on other sites
it compiles and works... with GLuint * texture yet now it's not printing my sprites... but it does print background... if you want to see my rendering code


[CODE]
void gameDraw::Render_2D::Render(glSDL_Config & gConfig )
{
if( gConfig.Draw_Background)
{
GLubyte bk_indices [] = {
0, 1 , 2,
0, 2 , 3
};

glBindTexture(GL_TEXTURE_2D , textures[gConfig.background]);

glSDL_Vertex bk_vRect = gConfig.bk_Vertex;
glSDL_texture bk_tRect = gConfig.bk_texture;
GLfloat bk_vertices[ ] = {
bk_vRect.x , bk_vRect.y + bk_vRect.h, 0,
bk_vRect.x , bk_vRect.y , 0,
bk_vRect.x + bk_vRect.w , bk_vRect.y , 0,
bk_vRect.x + bk_vRect.w , bk_vRect.y + bk_vRect.h, 0
};
GLfloat bk_Texvertices[ ] = {
bk_tRect.x , bk_tRect.y + bk_tRect.num,
bk_tRect.x , bk_tRect.y ,
bk_tRect.x + bk_tRect.num , bk_tRect.y ,
bk_tRect.x + bk_tRect.num , bk_tRect.y + bk_tRect.num
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT,0, bk_Texvertices);
glVertexPointer(3, GL_FLOAT, 0, bk_vertices);
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, bk_indices);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
if( gConfig.Draw_Sprite)
{
if( gConfig.foreground != gConfig.background)
{
glBindTexture(GL_TEXTURE_2D, textures[gConfig.foreground]);
}
int nSize = RenderArray.size();
GLfloat vertices[nSize * 12];
GLfloat texvertices[nSize * 8];
glSDL_Vertex vtemp;
glSDL_texture textemp;
unsigned int itv = 0;
unsigned int itex = 0;
BOOST_FOREACH( SpriteData & iter , RenderArray )
{
vtemp = boost::get<0>(iter);
textemp = boost::get<1>(iter);
//buttom left
vertices[itv] = vtemp.x;
vertices[itv + 1] = vtemp.y + vtemp.h;
vertices[itv + 2] = vtemp.layer;
//upper left
vertices[itv + 3] = vtemp.x;
vertices[itv + 4] = vtemp.y;
vertices[itv + 5] = vtemp.layer;
//upper right
vertices[itv + 6] = vtemp.x + vtemp.w;
vertices[itv + 7] = vtemp.y;
vertices[itv + 8] = vtemp.layer;
//lower right
vertices[itv + 9] = vtemp.x + vtemp.w;
vertices[itv + 10] = vtemp.y + vtemp.h;
vertices[itv + 11] = vtemp.layer;
itv += 12;
//buttom left
texvertices[itex] = textemp.x;
texvertices[itex + 1] = textemp.y + textemp.num;
//upper left
texvertices[itex + 2] = textemp.x;
texvertices[itex + 3] = textemp.y;
//upper right
texvertices[itex + 4] = textemp.x + textemp.num;
texvertices[itex + 5] = textemp.y;
//buttom right
texvertices[itex + 6] = textemp.x + textemp.num;
texvertices[itex + 7] = textemp.y + textemp.num;
itex += 8;
}
RenderArray.clear();
unsigned short quadindices[nSize * 6 ];
unsigned short *ndx = quadindices;
for (int i = 0, fv = 0; i < nSize; i++, fv += 4, ndx += 6)
{
ndx[0] = fv;
ndx[1] = fv + 1;
ndx[2] = fv + 2;
ndx[3] = fv;
ndx[4] = fv + 2;
ndx[5] = fv + 3;
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//Enable drawing state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT,0, texvertices);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, quadindices);
//Done with drawing state
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
}
SDL_GL_SwapBuffers();

}
[/CODE]

I should make a test if the vertices and texvertices data have came in ~_~..... Edited by BeginGamer

Share this post


Link to post
Share on other sites
Yup, at this point, no syntax error, you should debug by yourself. I am sure u will find the answer.
I cant help u now coz that is ur code and just u know how it works.
Syntax error is always easy to find than meaning error. [img]http://public.gamedev.net//public/style_emoticons/default/sad.png[/img]
Good luck [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img] Edited by KhoaVN

Share this post


Link to post
Share on other sites
Thanks for everything.. Apparently, the image wasn't loading.. it had a weird extensions LOL.... *Debugging is key* is there anyway to store Gluint in vector or just simply stick with gluint array? Also, do I need to use glDeletetextures ?

Share this post


Link to post
Share on other sites
[quote name='KhoaVN' timestamp='1341733529' post='4956853']
oh sorry,
I found another. vertor operator [] returns a "reference" not an "int".

So my advice is to use a GLint* (int pointer) instead of vector<GLint>

example:
GLint* SpriteSheep = new GLint[nSize];
then
u can use uploadImage(image, SpriteSheet[i]);
[/quote]

I would advice you to completely ignore that advice. Passing a vector element by reference to uploadImage (and then taking its address for glGenTextures) as in your original code was completely correct and the most natural and least error-prone way to do it. The problem was in the way you filled that vector (not counting possible other bugs in the code). I'm not completely sure what the standard says about passing a default constructed iterator to std::vector::insert but I assume that puts us in the happy land of undefined behavior.

For the way you use the vector I would suggest textures.resize(imagefiles.size()) instead of the wonky insert. If not, a short debugging session or an update of this thread with the current code and behavior should put you much closer to your goal.

I would also advise to take what else KhoaVN said with a lot of grains of salt. I freely admit being biased against excessive user of 1337-speak but at the very least the post I quoted is very much not helpful and shows a serious lack of understanding regarding the issues at hand.

There are two schools of thought about using glDeleteTextures. On the one hand, resources you allocated should be freed again. On the other hand the operating system will free all resources claimed by your application when it terminates. Freeing resources after you are done with them is only required if the program does something else for a while before terminating (for example loading another level, and then another). That said, for anything bigger you need to learn about proper resource management anyway, so why not start now in a project where it will not shoot you in the foot for a while?

Share this post


Link to post
Share on other sites
[quote name='BitMaster' timestamp='1341816012' post='4957167']

I would also advise to take what else KhoaVN said with a lot of grains of salt. I freely admit being biased against excessive user of 1337-speak but at the very least the post I quoted is very much not helpful and shows a serious lack of understanding regarding the issues at hand.

[/quote]

@BitMaster: You're right. That's my fault.
@BeginGamer: Sorry for bad things.

Share this post


Link to post
Share on other sites
[quote]
For the way you use the vector I would suggest textures.resize(imagefiles.size()) instead of the wonky insert. If not, a short debugging session or an update of this thread with the current code and behavior should put you much closer to your goal.
[/quote]
Yes! You was absolutely right...

Though, I still have this problem of drawing both images.... It draws the background fine but not the sprite image...

I updated both the renderer and image upload with debug feed back. Usually, it tells me that it couldn't open the certain sprite file from IMG_LOAD.. Though, I have the filename correct and the format isn't wrong, it's just a simple png with transparent background. I even tested with a another sprite that work in another program I made just to make sure... The dlls are correct, because I just copy/paste from another working program.. So, I'm kind of scratching my head why it isn't working... I did test if my program receive the proper vertices and texvertices as well for the render function.. No errors was shown and had the positional values that I wanted..

Share this post


Link to post
Share on other sites
How does "it tells me that it couldn't open the certain sprite file from IMG_LOAD"? What happens? Are both images PNG files? Because if not, the SDL Wiki entry of IMG_Load [1] suggests that PNG support requires the presence of both the PNG and ZLIB dynamic libraries.

[1] http://sdl.beuc.net/sdl.wiki/SDL_image

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