Ejemplo n.º 1
0
bool replaceTexture(const QString &oldfile, const QString &newfile)
{
	char tmpname[iV_TEXNAME_MAX];

	// Load new one to replace it
	iV_Image image;
	if (!iV_loadImage_PNG(QString("texpages/" + newfile).toUtf8().constData(), &image))
	{
		debug(LOG_ERROR, "Failed to load image: %s", newfile.toUtf8().constData());
		return false;
	}
	sstrcpy(tmpname, oldfile.toUtf8().constData());
	pie_MakeTexPageName(tmpname);
	// Have we already loaded this one?
	for (int i = 0; i < _TEX_PAGE.size(); i++)
	{
		if (strcmp(tmpname, _TEX_PAGE[i].name) == 0)
		{
			GL_DEBUG("Replacing texture");
			debug(LOG_TEXTURE, "Replacing texture %s with %s from index %d (tex id %u)", _TEX_PAGE[i].name, newfile.toUtf8().constData(), i, _TEX_PAGE[i].id);
			sstrcpy(tmpname, newfile.toUtf8().constData());
			pie_MakeTexPageName(tmpname);
			pie_AddTexPage(&image, tmpname, true, i);
			iV_unloadImage(&image);
			return true;
		}
	}
	iV_unloadImage(&image);
	debug(LOG_ERROR, "Nothing to replace!");
	return false;
}
Ejemplo n.º 2
0
/** Retrieve the texture number for a given texture resource.
 *
 *  @note We keep textures in a separate data structure _TEX_PAGE apart from the
 *        normal resource system.
 *
 *  @param filename The filename of the texture page to search for.
 *
 *  @return a non-negative index number for the texture, negative if no texture
 *          with the given filename could be found
 */
int iV_GetTexture(const char *filename)
{
    unsigned int i = 0;
    iV_Image sSprite;
    char path[PATH_MAX];

    /* Have we already loaded this one then? */
    sstrcpy(path, filename);
    pie_MakeTexPageName(path);
    for (i = 0; i < iV_TEX_MAX; i++)
    {
        if (strncmp(path, _TEX_PAGE[i].name, iV_TEXNAME_MAX) == 0)
        {
            return i;
        }
    }

    // Try to load it
    sstrcpy(path, "texpages/");
    sstrcat(path, filename);
    if (!iV_loadImage_PNG(path, &sSprite))
    {
        debug(LOG_ERROR, "Failed to load %s", path);
        return -1;
    }
    sstrcpy(path, filename);
    pie_MakeTexPageName(path);
    return pie_AddTexPage(&sSprite, path, 0, -1, true);	// FIXME, -1, use getTextureSize()
}
Ejemplo n.º 3
0
/** Retrieve the texture number for a given texture resource.
 *
 *  @note We keep textures in a separate data structure _TEX_PAGE apart from the
 *        normal resource system.
 *
 *  @param filename The filename of the texture page to search for.
 *  @param compression If we need to load it, should we use texture compression?
 *
 *  @return a non-negative index number for the texture, negative if no texture
 *          with the given filename could be found
 */
int iV_GetTexture(const char *filename, bool compression)
{
	iV_Image sSprite;
	char path[PATH_MAX];

	/* Have we already loaded this one then? */
	sstrcpy(path, filename);
	pie_MakeTexPageName(path);
	for (int i = 0; i < _TEX_PAGE.size(); i++)
	{
		if (strncmp(path, _TEX_PAGE[i].name, iV_TEXNAME_MAX) == 0)
		{
			return i;
		}
	}

	// Try to load it
	sstrcpy(path, "texpages/");
	sstrcat(path, filename);
	if (!iV_loadImage_PNG(path, &sSprite))
	{
		debug(LOG_ERROR, "Failed to load %s", path);
		return -1;
	}
	sstrcpy(path, filename);
	pie_MakeTexPageName(path);
	return pie_AddTexPage(&sSprite, path, compression);
}
Ejemplo n.º 4
0
void GFX::loadTexture(const char *filename, GLenum filter)
{
	const char *extension = strrchr(filename, '.'); // determine the filetype
	iV_Image image;
	if (!extension || strcmp(extension, ".png") != 0)
	{
		debug(LOG_ERROR, "Bad image filename: %s", filename);
		return;
	}
	if (iV_loadImage_PNG(filename, &image))
	{
		makeTexture(image.width, image.height, filter, iV_getPixelFormat(&image), image.bmp);
		iV_unloadImage(&image);
	}
}
Ejemplo n.º 5
0
/*!
 * Load an image from file
 */
static bool dataImageLoad(const char *fileName, void **ppData)
{
	iV_Image *psSprite = (iV_Image *)malloc(sizeof(iV_Image));
	if (!psSprite)
	{
		return false;
	}

	if (!iV_loadImage_PNG(fileName, psSprite))
	{
		debug( LOG_ERROR, "IMGPAGE load failed" );
		return false;
	}

	*ppData = psSprite;

	return true;
}
Ejemplo n.º 6
0
/**
	init_system_ColorCursor()-- Create a colored mouse cursor image
 */
SDL_Cursor *init_system_ColorCursor(CURSOR cur, const char *fileName)
{

	iV_Image *psSprite = (iV_Image *)malloc(sizeof(iV_Image));
	if (!psSprite)
	{
		debug(LOG_FATAL, "Could not allocate memory for cursor sprite. Exiting.");
		exit(-1);
	}

	if (!iV_loadImage_PNG(fileName, psSprite))
	{
		debug(LOG_FATAL, "Could not load cursor sprite. Exiting.");
		exit(-1);
	}

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	uint32_t rmask = 0xff000000;
	uint32_t gmask = 0x00ff0000;
	uint32_t bmask = 0x0000ff00;
	uint32_t amask = 0x000000ff;
#else
	uint32_t rmask = 0x000000ff;
	uint32_t gmask = 0x0000ff00;
	uint32_t bmask = 0x00ff0000;
	uint32_t amask = 0xff000000;
#endif

	SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(psSprite->bmp, psSprite->width, psSprite->height, psSprite->depth * 8, psSprite->width * 4, rmask, gmask, bmask, amask);
	SDL_Cursor *pointer = SDL_CreateColorCursor(surface, psSprite->width / 2, psSprite->height / 2);	// We center the hotspot for all (FIXME ?)
	if (!pointer)
	{
		debug(LOG_FATAL, "Could not create cursor because %s", SDL_GetError());
		exit(-1);
	}

	// free up image & surface data
	free(psSprite->bmp);
	free(psSprite);
	SDL_FreeSurface(surface);

	return pointer;
}
Ejemplo n.º 7
0
void screen_SetBackDropFromFile(const char* filename)
{
	// HACK : We should use a resource handler here!
	const char *extension = strrchr(filename, '.');// determine the filetype
	iV_Image image;

	if(!extension)
	{
		debug(LOG_ERROR, "Image without extension: \"%s\"!", filename);
		return; // filename without extension... don't bother
	}

	// Make sure the current texture page is reloaded after we are finished
	// Otherwise WZ will think it is still loaded and not load it again
	pie_SetTexturePage(TEXPAGE_EXTERN);

	if( strcmp(extension,".png") == 0 )
	{
		if (iV_loadImage_PNG( filename, &image ) )
		{
			if (~backDropTexture == 0)
				glGenTextures(1, &backDropTexture);

			glBindTexture(GL_TEXTURE_2D, backDropTexture);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
					image.width, image.height,
					0, iV_getPixelFormat(&image), GL_UNSIGNED_BYTE, image.bmp);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

			iV_unloadImage(&image);
		}
		return;
	}
	else
		debug(LOG_ERROR, "Unknown extension \"%s\" for image \"%s\"!", extension, filename);
}
Ejemplo n.º 8
0
bool texLoad(const char *fileName)
{
	char fullPath[PATH_MAX], partialPath[PATH_MAX], *buffer;
	unsigned int i, j, k, size;
	int texPage;
	GLint glval;

	firstPage = _TEX_INDEX;

	ASSERT_OR_RETURN(false, _TEX_INDEX < iV_TEX_MAX, "Too many texture pages used");
	ASSERT_OR_RETURN(false, MIPMAP_MAX == TILE_WIDTH && MIPMAP_MAX == TILE_HEIGHT, "Bad tile sizes");
	
	// store the filename so we can later determine which tileset we are using
	if (tileset) free(tileset);
	tileset = strdup(fileName);

	// reset defaults
	mipmap_max = MIPMAP_MAX;
	mipmap_levels = MIPMAP_LEVELS;

	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glval);

	while (glval < mipmap_max * TILES_IN_PAGE_COLUMN)
	{
		mipmap_max /= 2;
		mipmap_levels--;
		debug(LOG_ERROR, "Max supported texture size %dx%d is too low - reducing texture detail to %dx%d.",
		      (int)glval, (int)glval, mipmap_max, mipmap_max);
		ASSERT(mipmap_levels > 0, "Supported texture size %d is too low to load any mipmap levels!",
		       (int)glval);
		if (mipmap_levels == 0)
		{
			exit(1);
		}
	}
	while (maxTextureSize < mipmap_max)
	{
		mipmap_max /= 2;
		mipmap_levels--;
		debug(LOG_TEXTURE, "Downgrading texture quality to %d due to user setting %d", mipmap_max, maxTextureSize);
	}

	/* Get and set radar colours */

	sprintf(fullPath, "%s.radar", fileName);
	if (!loadFile(fullPath, &buffer, &size))
	{
		debug(LOG_FATAL, "texLoad: Could not find radar colours at %s", fullPath);
		abort(); // cannot recover; we could possibly generate a random palette?
	}
	i = 0; // tile
	j = 0; // place in buffer
	do {
		unsigned int r, g, b;
		int cnt = 0;

		k = sscanf(buffer + j, "%2x%2x%2x%n", &r, &g, &b, &cnt);
		j += cnt;
		if (k >= 3)
		{
			radarColour(i, r, g, b);
		}
		i++; // next tile
	} while (k >= 3 && j + 6 < size);
	free(buffer);

	/* Now load the actual tiles */

	i = mipmap_max; // i is used to keep track of the tile dimensions
	for (j = 0; j < mipmap_levels; j++)
	{
		int xOffset = 0, yOffset = 0; // offsets into the texture atlas
		int xSize = 1;
		int ySize = 1;
		const int xLimit = TILES_IN_PAGE_COLUMN * i;
		const int yLimit = TILES_IN_PAGE_ROW * i;

		// pad width and height into ^2 values
		while (xLimit > (xSize *= 2)) {}
		while (yLimit > (ySize *= 2)) {}

		// Generate the empty texture buffer in VRAM
		texPage = newPage(fileName, j, xSize, ySize, 0);

		sprintf(partialPath, "%s-%d", fileName, i);

		// Load until we cannot find anymore of them
		for (k = 0; k < MAX_TILES; k++)
		{
			iV_Image tile;

			sprintf(fullPath, "%s/tile-%02d.png", partialPath, k);
			if (PHYSFS_exists(fullPath)) // avoid dire warning
			{
				bool retval = iV_loadImage_PNG(fullPath, &tile);
				ASSERT_OR_RETURN(false, retval, "Could not load %s!", fullPath);
			}
			else
			{
				// no more textures in this set
				ASSERT_OR_RETURN(false, k > 0, "Could not find %s", fullPath);
				break;
			}
			// Insert into texture page
			glTexSubImage2D(GL_TEXTURE_2D, j, xOffset, yOffset, tile.width, tile.height,
			                GL_RGBA, GL_UNSIGNED_BYTE, tile.bmp);
			free(tile.bmp);
			if (i == mipmap_max) // dealing with main texture page; so register coordinates
			{
				tileTexInfo[k].uOffset = (float)xOffset / (float)xSize;
				tileTexInfo[k].vOffset = (float)yOffset / (float)ySize;
				tileTexInfo[k].texPage = texPage;
				debug(LOG_TEXTURE, "  texLoad: Registering k=%d i=%d u=%f v=%f xoff=%d yoff=%d xsize=%d ysize=%d tex=%d (%s)",
				     k, i, tileTexInfo[k].uOffset, tileTexInfo[k].vOffset, xOffset, yOffset, xSize, ySize, texPage, fullPath);
			}
			xOffset += i; // i is width of tile
			if (xOffset + i > xLimit)
			{
				yOffset += i; // i is also height of tile
				xOffset = 0;
			}
			if (yOffset + i > yLimit)
			{
				/* Change to next texture page */
				xOffset = 0;
				yOffset = 0;
				debug(LOG_TEXTURE, "texLoad: Extra page added at %d for %s, was page %d, opengl id %u",
				      k, partialPath, texPage, (unsigned int)_TEX_PAGE[texPage].id);
				texPage = newPage(fileName, j, xSize, ySize, k);
			}
		}
		debug(LOG_TEXTURE, "texLoad: Found %d textures for %s mipmap level %d, added to page %d, opengl id %u",
		      k, partialPath, i, texPage, (unsigned int)_TEX_PAGE[texPage].id);
		i /= 2;	// halve the dimensions for the next series; OpenGL mipmaps start with largest at level zero
	}

	return true;
}
Ejemplo n.º 9
0
IMAGEFILE *iV_LoadImageFile(const char *fileName)
{
	// Find the directory of images.
	std::string imageDir = fileName;
	if (imageDir.find_last_of('.') != std::string::npos)
	{
		imageDir.erase(imageDir.find_last_of('.'));
	}
	imageDir += '/';

	// Load the image list file.
	char *pFileData;
	unsigned pFileSize;
	if (!loadFile(fileName, &pFileData, &pFileSize))
	{
		debug(LOG_ERROR, "iV_LoadImageFile: failed to open %s", fileName);
		return NULL;
	}

	char *ptr = pFileData;
	// count lines, which is identical to number of images
	int numImages = 0;
	while (ptr < pFileData + pFileSize && *ptr != '\0')
	{
		numImages += *ptr == '\n';
		++ptr;
	}
	IMAGEFILE *imageFile = new IMAGEFILE;
	imageFile->imageDefs.resize(numImages);
	imageFile->imageNames.resize(numImages);
	ImageMerge pageLayout;
	pageLayout.images.resize(numImages);
	ptr = pFileData;
	numImages = 0;
	while (ptr < pFileData + pFileSize)
	{
		int temp, retval;
		ImageDef *ImageDef = &imageFile->imageDefs[numImages];

		char tmpName[256];
		retval = sscanf(ptr, "%d,%d,%255[^\r\n\",]%n", &ImageDef->XOffset, &ImageDef->YOffset, tmpName, &temp);
		if (retval != 3)
		{
			debug(LOG_ERROR, "Bad line in \"%s\".", fileName);
			return NULL;
		}
		imageFile->imageNames[numImages].first = tmpName;
		imageFile->imageNames[numImages].second = numImages;
		std::string spriteName = imageDir + tmpName;

		ImageMergeRectangle *imageRect = &pageLayout.images[numImages];
		imageRect->index = numImages;
		imageRect->data = new iV_Image;
		if (!iV_loadImage_PNG(spriteName.c_str(), imageRect->data))
		{
			debug(LOG_ERROR, "Failed to find image \"%s\" listed in \"%s\".", spriteName.c_str(), fileName);
			return NULL;
		}
		imageRect->siz = Vector2i(imageRect->data->width, imageRect->data->height);
		numImages++;
		ptr += temp;
		while (ptr < pFileData + pFileSize && *ptr++ != '\n') {} // skip rest of line

		images.insert(tmpName, ImageDef);
	}
	free(pFileData);

	std::sort(imageFile->imageNames.begin(), imageFile->imageNames.end());

	pageLayout.arrange();  // Arrange all the images onto texture pages (attempt to do so with as few pages as possible).
	imageFile->pages.resize(pageLayout.pages.size());

	std::vector<iV_Image> ivImages(pageLayout.pages.size());

	for (unsigned p = 0; p < pageLayout.pages.size(); ++p)
	{
		int size = pageLayout.pages[p];
		ivImages[p].depth = 4;
		ivImages[p].width = size;
		ivImages[p].height = size;
		ivImages[p].bmp = (unsigned char *)malloc(size*size*4);  // MUST be malloc, since this is free()d later by pie_AddTexPage().
		memset(ivImages[p].bmp, 0x00, size*size*4);
		imageFile->pages[p].size = size;
		// Must set imageFile->pages[p].id later, after filling out ivImages[p].bmp.
	}

	for (std::vector<ImageMergeRectangle>::const_iterator r = pageLayout.images.begin(); r != pageLayout.images.end(); ++r)
	{
		imageFile->imageDefs[r->index].TPageID = r->page;
		imageFile->imageDefs[r->index].Tu = r->loc.x;
		imageFile->imageDefs[r->index].Tv = r->loc.y;
		imageFile->imageDefs[r->index].Width = r->siz.x;
		imageFile->imageDefs[r->index].Height = r->siz.y;

		// Copy image data onto texture page.
		iV_Image *srcImage = r->data;
		int srcDepth = srcImage->depth;
		int srcStride = srcImage->width*srcDepth;  // Not sure whether to pad in the case that srcDepth ≠ 4, however this apparently cannot happen.
		unsigned char *srcBytes = srcImage->bmp + 0*srcDepth + 0*srcStride;
		iV_Image *dstImage = &ivImages[r->page];
		int dstDepth = dstImage->depth;
		int dstStride = dstImage->width*dstDepth;
		unsigned char *dstBytes = dstImage->bmp + r->loc.x*dstDepth + r->loc.y*dstStride;
		Vector2i size = r->siz;
		unsigned char rgba[4] = {0x00, 0x00, 0x00, 0xFF};
		for (int y = 0; y < size.y; ++y)
			for (int x = 0; x < size.x; ++x)
		{
			memcpy(rgba, srcBytes + x*srcDepth + y*srcStride, srcDepth);
			memcpy(dstBytes + x*dstDepth + y*dstStride, rgba, dstDepth);
		}

		// Finished reading the image data and copying it to the texture page, delete it.
		free(r->data->bmp);
		delete r->data;
	}

	// Debug usage only. Dump all images to disk (do mkdir images/, first). Doesn't dump the alpha channel, since the .ppm format doesn't support that.
	/*for (unsigned p = 0; p < pageLayout.pages.size(); ++p)
	{
		char fName[100];
		sprintf(fName, "%s-%d", fileName, p);
		printf("Dump %s\n", fName);
		FILE *f = fopen(fName, "wb");
		iV_Image *image = &ivImages[p];
		fprintf(f, "P6\n%d %d\n255\n", image->width, image->height);
		for (int x = 0; x < image->width*image->height; ++x)
			if (fwrite(image->bmp + x*4, 3, 1, f) == 0)
				abort();
		fclose(f);
	}*/

	// Upload texture pages and free image data.
	for (unsigned p = 0; p < pageLayout.pages.size(); ++p)
	{
		char arbitraryName[256];
		ssprintf(arbitraryName, "%s-%03u", fileName, p);
		// Now we can set imageFile->pages[p].id. This free()s the ivImages[p].bmp array!
		imageFile->pages[p].id = pie_AddTexPage(&ivImages[p], arbitraryName, 0, 0, true);
	}

	// duplicate some data, since we want another access point to these data structures now, FIXME
	for (unsigned i = 0; i < imageFile->imageDefs.size(); i++)
	{
		imageFile->imageDefs[i].textureId = imageFile->pages[imageFile->imageDefs[i].TPageID].id;
		imageFile->imageDefs[i].invTextureSize = 1.f / imageFile->pages[imageFile->imageDefs[i].TPageID].size;
	}

	files.append(imageFile);

	return imageFile;
}