/** * @brief Generates an filled circle texture. * * @param radius Radius of the circle to generate. * @return The tetxure containing the generated circle. */ static glTexture *gl_genCircle( int radius ) { int i,j,k, n,m; SDL_Surface *sur; uint8_t *pix, *buf; int h, w; double a; char name[PATH_MAX]; /* Calculate parameters. */ w = 2*radius+1; h = 2*radius+1; /* Create the surface. */ sur = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, 32, RGBAMASK ); pix = sur->pixels; /* Generate the circle. */ SDL_LockSurface( sur ); /* Create temporary buffer to draw circle in. */ k = 3; buf = malloc( (h*k) * (w*k) ); for (i=0; i<k*h; i++) { for (j=0; j<k*w; j++) { if (pow2(i-k*radius)+pow2(j-k*radius) < pow2(k*radius)) buf[ i*k*w + j] = 0xFF; } } /* Draw the circle with filter. */ for (i=0; i<h; i++) { for (j=0; j<w; j++) { /* Calculate blur. */ a = 0.; for (n=0; n<k; n++) for (m=0; m<k; m++) a += buf[ (i*k+n)*k*w + (j*k+m) ]; a /= k*k; /* Set pixel. */ pix[i*sur->pitch + j*4 + 0] = 0xFF; pix[i*sur->pitch + j*4 + 1] = 0xFF; pix[i*sur->pitch + j*4 + 2] = 0xFF; pix[i*sur->pitch + j*4 + 3] = (uint8_t)a; } } /* Clean up. */ free(buf); SDL_UnlockSurface( sur ); /* Return texture. */ nsnprintf( name, sizeof(name), "gencircle%d", radius ); return gl_loadImagePad( name, sur, OPENGL_TEX_MIPMAPS, sur->w, sur->h, 1, 1, 1 ); }
/** * @brief Loads the SDL_Surface to a glTexture. * * @param surface Surface to load. * @param flags Flags to use. * @return The glTexture for surface. */ glTexture* gl_loadImage( SDL_Surface* surface, unsigned int flags ) { return gl_loadImagePad( NULL, surface, flags, surface->w, surface->h, 1, 1, 1 ); }
/** * @brief Wrapper for gl_loadImagePad that includes transparency mapping. * * @param name Name to load with. * @param surface Surface to load. * @param rw RWops containing data to hash. * @param flags Flags to use. * @param w Non-padded width. * @param h Non-padded height. * @param sx X sprites. * @param sy Y sprites. * @param freesur Whether or not to free the surface. * @return The glTexture for surface. */ glTexture* gl_loadImagePadTrans( const char *name, SDL_Surface* surface, SDL_RWops *rw, unsigned int flags, int w, int h, int sx, int sy, int freesur ) { glTexture *texture; int i, filesize; size_t cachesize, pngsize; uint8_t *trans; char *cachefile, *data; char digest[33]; md5_state_t md5; md5_byte_t *md5val; if (name != NULL) { texture = gl_texExists( name ); if (texture != NULL) return texture; } if (flags & OPENGL_TEX_MAPTRANS) flags ^= OPENGL_TEX_MAPTRANS; /* Appropriate size for the transparency map, see SDL_MapTrans */ cachesize = gl_transSize(w, h); cachefile = NULL; trans = NULL; if (rw != NULL) { md5val = malloc(16); md5_init(&md5); pngsize = SDL_RWseek( rw, 0, SEEK_END ); SDL_RWseek( rw, 0, SEEK_SET ); data = malloc(pngsize); if (data == NULL) WARN("Out of memory!"); else { SDL_RWread( rw, data, pngsize, 1 ); md5_append( &md5, (md5_byte_t*)data, pngsize ); free(data); } md5_finish( &md5, md5val ); for (i=0; i<16; i++) nsnprintf( &digest[i * 2], 3, "%02x", md5val[i] ); free(md5val); cachefile = malloc( PATH_MAX ); nsnprintf( cachefile, PATH_MAX, "%scollisions/%s", nfile_cachePath(), digest ); /* Attempt to find a cached transparency map. */ if (nfile_fileExists(cachefile)) { trans = (uint8_t*)nfile_readFile( &filesize, cachefile ); /* Consider cached data invalid if the length doesn't match. */ if (trans != NULL && cachesize != (unsigned int)filesize) { free(trans); trans = NULL; } /* Cached data matches, no need to overwrite. */ else { free(cachefile); cachefile = NULL; } } } else { /* We could hash raw pixel data here, but that's slower than just * generating the map from scratch. */ WARN("Texture '%s' has no RWops", name); } if (trans == NULL) { SDL_LockSurface(surface); trans = SDL_MapTrans( surface, w, h ); SDL_UnlockSurface(surface); if (cachefile != NULL) { /* Cache newly-generated transparency map. */ nfile_dirMakeExist( "%s/collisions/", nfile_cachePath() ); nfile_writeFile( (char*)trans, cachesize, cachefile ); free(cachefile); } } texture = gl_loadImagePad( name, surface, flags, w, h, sx, sy, freesur ); texture->trans = trans; return texture; }