void TextureBuilder::PrepareSurface() { if (m_prepared) return; if (!m_surface && m_filename.length() > 0) LoadSurface(); TextureFormat targetTextureFormat; SDL_PixelFormat *targetPixelFormat; bool needConvert = !GetTargetFormat(m_surface->format, &targetTextureFormat, &targetPixelFormat, m_forceRGBA); if (needConvert) { SDL_Surface *s = SDL_ConvertSurface(m_surface, targetPixelFormat, SDL_SWSURFACE); SDL_FreeSurface(m_surface); m_surface = s; } unsigned int virtualWidth, actualWidth, virtualHeight, actualHeight; virtualWidth = actualWidth = m_surface->w; virtualHeight = actualHeight = m_surface->h; if (m_potExtend) { // extend to power-of-two if necessary actualWidth = ceil_pow2(m_surface->w); actualHeight = ceil_pow2(m_surface->h); if (actualWidth != virtualWidth || actualHeight != virtualHeight) { SDL_Surface *s = SDL_CreateRGBSurface(SDL_SWSURFACE, actualWidth, actualHeight, targetPixelFormat->BitsPerPixel, targetPixelFormat->Rmask, targetPixelFormat->Gmask, targetPixelFormat->Bmask, targetPixelFormat->Amask); SDL_SetAlpha(m_surface, 0, 0); SDL_SetAlpha(s, 0, 0); SDL_BlitSurface(m_surface, 0, s, 0); SDL_FreeSurface(m_surface); m_surface = s; } } else if (m_filename.length() > 0) { // power-of-to check unsigned long width = ceil_pow2(m_surface->w); unsigned long height = ceil_pow2(m_surface->h); if (width != virtualWidth || height != virtualHeight) fprintf(stderr, "WARNING: texture '%s' is not power-of-two and may not display correctly\n", m_filename.c_str()); } m_descriptor = TextureDescriptor( targetTextureFormat, vector2f(actualWidth,actualHeight), vector2f(float(virtualWidth)/float(actualWidth),float(virtualHeight)/float(actualHeight)), m_sampleMode, m_generateMipmaps); m_prepared = true; }
Mesh item3DImage(TextureDescriptor td, float thickness) { assert(td); assert(td.maxU <= 1 && td.minU >= 0 && td.maxV <= 1 && td.minV >= 0); Image image = td.image; unsigned iw = image.width(); unsigned ih = image.height(); float fMinX = iw * td.minU; float fMaxX = iw * td.maxU; float fMinY = ih * (1 - td.maxV); float fMaxY = ih * (1 - td.minV); int minX = ifloor(1e-5f + fMinX); int maxX = ifloor(-1e-5f + fMaxX); int minY = ifloor(1e-5f + fMinY); int maxY = ifloor(-1e-5f + fMaxY); assert(minX <= maxX && minY <= maxY); float scale = std::min<float>(1.0f / (1 + maxX - minX), 1.0f / (1 + maxY - minY)); if(thickness <= 0) thickness = scale; TextureDescriptor backTD = td; backTD.maxU = td.minU; backTD.minU = td.maxU; float faceMinX = scale * (fMinX - minX); float faceMinY = scale * (maxY - fMaxY + 1); float faceMaxX = faceMinX + scale * (fMaxX - fMinX); float faceMaxY = faceMinY + scale * (fMaxY - fMinY); Mesh retval = transform(Matrix::translate(faceMinX, faceMinY, -0.5f).concat(Matrix::scale(faceMaxX - faceMinX, faceMaxY - faceMinY, thickness)), unitBox(TextureDescriptor(), TextureDescriptor(), TextureDescriptor(), TextureDescriptor(), backTD, td)); for(int iy = minY; iy <= maxY; iy++) { for(int ix = minX; ix <= maxX; ix++) { bool transparent = isPixelTransparent(image.getPixel(ix, iy)); if(transparent) continue; bool transparentNIX = true, transparentPIX = true, transparentNIY = true, transparentPIY = true; // image transparent for negative and positive image coordinates if(ix > minX) transparentNIX = isPixelTransparent(image.getPixel(ix - 1, iy)); if(ix < maxX) transparentPIX = isPixelTransparent(image.getPixel(ix + 1, iy)); if(iy > minY) transparentNIY = isPixelTransparent(image.getPixel(ix, iy - 1)); if(iy < maxY) transparentPIY = isPixelTransparent(image.getPixel(ix, iy + 1)); float pixelU = (ix + 0.5f) / iw; float pixelV = 1.0f - (iy + 0.5f) / ih; TextureDescriptor pixelTD = TextureDescriptor(image, pixelU, pixelU, pixelV, pixelV); TextureDescriptor nx, px, ny, py; if(transparentNIX) nx = pixelTD; if(transparentPIX) px = pixelTD; if(transparentNIY) py = pixelTD; if(transparentPIY) ny = pixelTD; Matrix tform = Matrix::translate(static_cast<float>(ix - minX), static_cast<float>(maxY - iy), -0.5f).concat(Matrix::scale(scale, scale, thickness)); retval.append(transform(tform, unitBox(nx, px, ny, py, TextureDescriptor(), TextureDescriptor()))); } } return std::move(retval); }
void TextureBuilder::PrepareSurface() { if (m_prepared) return; if (!m_surface && !m_filename.empty()) { std::string filename = m_filename; std::transform(filename.begin(), filename.end(), filename.begin(), ::tolower); if (ends_with_ci(filename, ".dds")) { LoadDDS(); } else { LoadSurface(); } } TextureFormat targetTextureFormat; unsigned int virtualWidth, actualWidth, virtualHeight, actualHeight, numberOfMipMaps = 0, numberOfImages = 1; if( m_surface ) { SDL_PixelFormat *targetPixelFormat; bool needConvert = !GetTargetFormat(m_surface->format, &targetTextureFormat, &targetPixelFormat, m_forceRGBA); if (needConvert) { if(m_textureType == TEXTURE_2D) { SDL_Surface *s = SDL_ConvertSurface(m_surface.Get(), targetPixelFormat, SDL_SWSURFACE); m_surface = SDLSurfacePtr::WrapNew(s); } else if(m_textureType == TEXTURE_CUBE_MAP) { assert(m_cubemap.size() == 6); for(unsigned int i = 0; i < 6; ++i) { SDL_Surface *s = SDL_ConvertSurface(m_cubemap[i].Get(), targetPixelFormat, SDL_SWSURFACE); m_cubemap[i] = SDLSurfacePtr::WrapNew(s); } } else { // Unknown texture type assert(0); } } virtualWidth = actualWidth = m_surface->w; virtualHeight = actualHeight = m_surface->h; if (m_potExtend) { // extend to power-of-two if necessary actualWidth = ceil_pow2(m_surface->w); actualHeight = ceil_pow2(m_surface->h); if (actualWidth != virtualWidth || actualHeight != virtualHeight) { if(m_textureType == TEXTURE_2D) { SDL_Surface *s = SDL_CreateRGBSurface(SDL_SWSURFACE, actualWidth, actualHeight, targetPixelFormat->BitsPerPixel, targetPixelFormat->Rmask, targetPixelFormat->Gmask, targetPixelFormat->Bmask, targetPixelFormat->Amask); SDL_SetSurfaceBlendMode(m_surface.Get(), SDL_BLENDMODE_NONE); SDL_BlitSurface(m_surface.Get(), 0, s, 0); m_surface = SDLSurfacePtr::WrapNew(s); } else if(m_textureType == TEXTURE_CUBE_MAP) { assert(m_cubemap.size() == 6); for(unsigned int i = 0; i < 6; ++i) { SDL_Surface *s = SDL_CreateRGBSurface(SDL_SWSURFACE, actualWidth, actualHeight, targetPixelFormat->BitsPerPixel, targetPixelFormat->Rmask, targetPixelFormat->Gmask, targetPixelFormat->Bmask, targetPixelFormat->Amask); SDL_SetSurfaceBlendMode(m_cubemap[i].Get(), SDL_BLENDMODE_NONE); SDL_BlitSurface(m_cubemap[i].Get(), 0, s, 0); m_cubemap[i] = SDLSurfacePtr::WrapNew(s); } } else { assert(0); } } } else if (! m_filename.empty()) { // power-of-two check unsigned long width = ceil_pow2(m_surface->w); unsigned long height = ceil_pow2(m_surface->h); if (width != virtualWidth || height != virtualHeight) Output("WARNING: texture '%s' is not power-of-two and may not display correctly\n", m_filename.c_str()); } } else { switch(m_dds.GetTextureFormat()) { case PicoDDS::FORMAT_DXT1: targetTextureFormat = TEXTURE_DXT1; break; case PicoDDS::FORMAT_DXT5: targetTextureFormat = TEXTURE_DXT5; break; default: Output("ERROR: DDS texture with invalid format '%s' (only DXT1 and DXT5 are supported)\n", m_filename.c_str()); assert(false); return; } virtualWidth = actualWidth = m_dds.imgdata_.width; virtualHeight = actualHeight = m_dds.imgdata_.height; numberOfMipMaps = m_dds.imgdata_.numMipMaps; numberOfImages = m_dds.imgdata_.numImages; if(m_textureType == TEXTURE_CUBE_MAP) { // Cube map must be fully defined (6 images) to be used correctly assert(numberOfImages == 6); } } m_descriptor = TextureDescriptor( targetTextureFormat, vector2f(actualWidth,actualHeight), vector2f(float(virtualWidth)/float(actualWidth),float(virtualHeight)/float(actualHeight)), m_sampleMode, m_generateMipmaps, m_compressTextures, numberOfMipMaps, m_textureType); m_prepared = true; }