Pages: 1
  Print  
Author Topic: sprite_create_from_surface  (Read 12942 times)
Offline (Unknown gender) TheExDeus
Posted on: December 16, 2011, 06:48:55 pm

Developer
Joined: Apr 2008
Posts: 1860

View Profile
Hi. I went back to finish some of the surface functions I was working on, and I still can't figure this one out. I have this code:
Code: [Select]
int sprite_create_from_surface(int id,int x,int y,int w,int h,bool removeback,bool smooth,int xorig,int yorig)
{
    enigma::surface* surf=enigma::surface_array[id];
    int sprid=enigma::sprite_idmax, full_width=nlpo2dc(w)+1, full_height=nlpo2dc(h)+1;
    enigma::sprite_new_empty(sprid, 1, w, h, xorig, yorig, 0, h, 0, w, 1,0);

    unsigned sz=full_width*full_height;
    unsigned char *surfbuf=new unsigned char[sz*4];
int prevFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prevFbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, surf->fbo);
glReadPixels(x,y,w,h,GL_RGBA,GL_UNSIGNED_BYTE,surfbuf);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFbo);

    enigma::sprite_set_subimage(sprid, 0, xorig, yorig, w, h, surfbuf);
    delete[] surfbuf;
    return sprid;
}
Pretty simple, and it works. The problem is that it breaks after certain amount of usage. For me this breaks when I execute it 4 times. Then artifacts appear on the surface (when something is drawn on it). After fifth time the artifacts become more massive (like solid rectangles) and after that the surface just becomes totally solid color. The game doesn't break though (no freezing) so I don't think I overwrite anything important, but I do overwrite something.
So, ideas?

Also, I guess I could put this here as well:
I have made surface_save and surface_save_part functions. The problem is that the output bmp is vertically flipped. I used basically the same function that is used to save the screen and it works right there. This functions is like so:
Code: [Select]
int surface_save(int id, string filename)
{
FILE *bmp=fopen(filename.c_str(),"wb");
if(!bmp) return -1;
    enigma::surface* surf=enigma::surface_array[id];
unsigned int w=surf->width,h=surf->height,sz=w*h;
char *surfbuf=new char[sz*3];
    int prevFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prevFbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, surf->fbo);
glReadPixels(0,0,w,h,GL_BGR,GL_UNSIGNED_BYTE,surfbuf);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFbo);
fwrite("BM",2,1,bmp);
sz<<=2;

fwrite(&sz,4,1,bmp);
fwrite("\0\0\0\0\x36\0\0\0\x28\0\0",12,1,bmp);
fwrite(&w,4,1,bmp);
fwrite(&h,4,1,bmp);
fwrite("\1\0\x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",28,1,bmp);

if(w&3)
{
size_t pad=w&3;
w*=3;
sz-=sz>>2;
for(unsigned int i=0;i<sz;i+=w)
{
fwrite(surfbuf+i,w,1,bmp);
fwrite("\0\0",pad,1,bmp);
}
} else fwrite(surfbuf,w*3,h,bmp);
fclose(bmp);
delete[] surfbuf;
return 1;
}

Also, I would want to know how png's could be saved. ENIGMA already uses zlib for that I think, so maybe we could add two functions like:
save_texture_bmp and save_texture_png. Then saving surfaces, backgrounds and sprites would be identical and would only require a small wrapping function.
Logged
Offline (Male) Josh @ Dreamland
Reply #1 Posted on: December 16, 2011, 08:19:41 pm

Prince of all Goldfish
Developer
Location: Pittsburgh, PA, USA
Joined: Feb 2008
Posts: 2950

View Profile Email
We don't use PNG, we just zlib raw pixel data.

Anyway, that function of yours shouldn't work at all. The sprite_new_empty function doesn't do spritestructarray allocation; it just allocates a new sprite and assigns it to the existing array. I haven't added one that does all allocation.

Bitmap pixels are stored upside-down in the specification. The screen projection is already flipped vertically.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TheExDeus
Reply #2 Posted on: December 16, 2011, 08:35:52 pm

Developer
Joined: Apr 2008
Posts: 1860

View Profile
Quote
We don't use PNG, we just zlib raw pixel data.
Thats a bummer. We should add png support though (for loading and saving in runtime).

Quote
Anyway, that function of yours shouldn't work at all. The sprite_new_empty function doesn't do spritestructarray allocation; it just allocates a new sprite and assigns it to the existing array. I haven't added one that does all allocation.
Isn't this it:
Code: [Select]
    sprite *as = new sprite(subc);
    spritestructarray[sprid] = as;
? What you do in spriteinit (the code that does the initial sprite loading) is that you go trough all sprites, call sprite_new_empty, and then for every subimage you do sprite_set_subimage, that's it. No additional allocating. So it works and should work just fine, but for some reason it works only for like 4 times.

Quote
Bitmap pixels are stored upside-down in the specification. The screen projection is already flipped vertically.
I know this, and the only explanation I could think why my code doesn't work is that when I bind surface then I have to flip the projection again.
Logged
Offline (Male) Josh @ Dreamland
Reply #3 Posted on: December 17, 2011, 09:19:27 am

Prince of all Goldfish
Developer
Location: Pittsburgh, PA, USA
Joined: Feb 2008
Posts: 2950

View Profile Email
> What you do in spriteinit (the code that does the initial sprite loading) is that you go trough all sprites, call sprite_new_empty, and then for every subimage you do sprite_set_subimage, that's it. No additional allocating.
Yes.

>So it works and should work just fine, but for some reason it works only for like 4 times.
No.

The allocation for the initial sprite count is done in the sprite initialization code. Room for all included sprites is allocated, and the array is zeroed.

> I know this, and the only explanation I could think why my code doesn't work is that when I bind surface then I have to flip the projection again.

If rendering to surfaces work as they are, don't flip them. Otherwise, by all means.
Logged
"That is the single most cryptic piece of code I have ever seen." -Master PobbleWobble
"I disapprove of what you say, but I will defend to the death your right to say it." -Evelyn Beatrice Hall, Friends of Voltaire
Offline (Unknown gender) TheExDeus
Reply #4 Posted on: December 17, 2011, 10:37:45 am

Developer
Joined: Apr 2008
Posts: 1860

View Profile
Quote
The allocation for the initial sprite count is done in the sprite initialization code. Room for all included sprites is allocated, and the array is zeroed.
I will look into that.

Quote
If rendering to surfaces work as they are, don't flip them. Otherwise, by all means.
You have to set projections and stuff for rendering on surface, but they don't seem to affect glReadPixels, so I don't know what the hell is up.
Logged
Pages: 1
  Print