2007-01-15 12:09:25 -08:00
|
|
|
/*
|
|
|
|
This file is part of Warzone 2100.
|
|
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
|
|
Copyright (C) 2005-2007 Warzone Resurrection Project
|
|
|
|
|
|
|
|
Warzone 2100 is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Warzone 2100 is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Warzone 2100; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2007-07-31 13:16:38 -07:00
|
|
|
|
|
|
|
/* This is where we do texture atlas generation */
|
|
|
|
|
2006-11-06 06:40:07 -08:00
|
|
|
#include <string.h>
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-05-27 09:37:17 -07:00
|
|
|
#include "lib/framework/frame.h"
|
|
|
|
#include "lib/ivis_common/pietypes.h"
|
|
|
|
#include "lib/ivis_common/piestate.h"
|
2006-07-22 16:35:48 -07:00
|
|
|
#include "lib/ivis_common/tex.h"
|
2006-05-27 09:37:17 -07:00
|
|
|
#include "lib/ivis_common/piepalette.h"
|
2006-07-22 16:35:48 -07:00
|
|
|
#include "lib/ivis_opengl/pietexture.h"
|
2007-07-31 13:16:38 -07:00
|
|
|
#include "lib/ivis_opengl/screen.h"
|
2007-06-28 10:47:08 -07:00
|
|
|
#include "display3ddef.h"
|
|
|
|
#include "texture.h"
|
|
|
|
#include "radar.h"
|
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
#include <physfs.h>
|
|
|
|
#include <SDL/SDL_opengl.h>
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#include <opengl/glu.h>
|
|
|
|
#else
|
|
|
|
#include <GL/glu.h>
|
|
|
|
#endif
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
#define MIPMAP_LEVELS 4
|
|
|
|
#define MIPMAP_MIN 16
|
|
|
|
#define MIPMAP_MAX 128
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-09-01 14:01:17 -07:00
|
|
|
/* Texture page and coordinates for each tile */
|
2007-06-18 07:25:06 -07:00
|
|
|
TILE_TEX_INFO tileTexInfo[MAX_TILES];
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
static int firstPage; // the last used page before we start adding terrain textures
|
|
|
|
|
|
|
|
// Generate a new texture page both in the texture page table, and on the graphics card
|
|
|
|
static int newPage(const char *name, int level, int width, int height, int count)
|
|
|
|
{
|
|
|
|
int texPage = firstPage + ((count + 1) / TILES_IN_PAGE);
|
|
|
|
|
2007-08-21 05:59:05 -07:00
|
|
|
// debug(LOG_TEXTURE, "newPage: texPage=%d firstPage=%d %s %d (%d,%d) (count %d + 1) / %d _TEX_INDEX=%u",
|
2007-07-31 13:16:38 -07:00
|
|
|
// texPage, firstPage, name, level, width, height, count, TILES_IN_PAGE, _TEX_INDEX);
|
|
|
|
if (texPage == _TEX_INDEX)
|
|
|
|
{
|
|
|
|
// We need to create a new texture page; create it and increase texture table to store it
|
|
|
|
glGenTextures(1, (GLuint *) &_TEX_PAGE[texPage].id);
|
|
|
|
_TEX_INDEX++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(_TEX_INDEX > texPage, "newPage: Index too low (%d > %d)", _TEX_INDEX, texPage);
|
|
|
|
ASSERT(_TEX_INDEX < iV_TEX_MAX, "Too many texture pages used");
|
|
|
|
|
|
|
|
strncpy(_TEX_PAGE[texPage].name, name, iV_TEXNAME_MAX);
|
|
|
|
|
|
|
|
pie_SetTexturePage(texPage);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MIPMAP_LEVELS - 1);
|
|
|
|
// debug(LOG_TEXTURE, "newPage: glTexImage2D(page=%d, level=%d) opengl id=%u", texPage, level, _TEX_PAGE[texPage].id);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, level, wz_texture_compression, width, height, 0,
|
|
|
|
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
2007-08-01 06:27:40 -07:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
2007-08-25 14:53:04 -07:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
2007-07-31 13:16:38 -07:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
|
|
|
|
return texPage;
|
|
|
|
}
|
|
|
|
|
2007-07-27 07:58:17 -07:00
|
|
|
void texLoad(const char *fileName)
|
2007-07-27 05:10:31 -07:00
|
|
|
{
|
2007-08-21 05:59:05 -07:00
|
|
|
char fullPath[PATH_MAX], partialPath[PATH_MAX], *buffer;
|
2007-07-31 06:02:31 -07:00
|
|
|
unsigned int i, j, k, size;
|
2007-07-31 13:16:38 -07:00
|
|
|
int texPage;
|
2007-07-27 05:10:31 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
firstPage = _TEX_INDEX;
|
2007-07-27 05:10:31 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
ASSERT(_TEX_INDEX < iV_TEX_MAX, "Too many texture pages used");
|
|
|
|
ASSERT(MIPMAP_MAX == TILE_WIDTH && MIPMAP_MAX == TILE_HEIGHT, "Bad tile sizes");
|
2007-07-31 06:02:31 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
/* Get and set radar colours */
|
2007-07-31 06:02:31 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
sprintf(fullPath, "%s.radar", fileName);
|
2007-07-31 06:02:31 -07:00
|
|
|
if (!loadFile(fullPath, &buffer, &size))
|
|
|
|
{
|
|
|
|
debug(LOG_ERROR, "texLoad: Could not find radar colours at %s", fullPath);
|
|
|
|
abort(); // cannot recover; we could possibly generate a random palette?
|
|
|
|
}
|
|
|
|
i = 0; // tile
|
|
|
|
k = 0; // number of values read
|
|
|
|
j = 0; // place in buffer
|
|
|
|
do {
|
2007-08-03 01:52:25 -07:00
|
|
|
unsigned int r, g, b;
|
2007-08-02 15:34:33 -07:00
|
|
|
int cnt = 0;
|
2007-07-31 06:02:31 -07:00
|
|
|
|
2007-08-03 01:52:25 -07:00
|
|
|
k = sscanf(buffer + j, "%2x%2x%2x%n", &r, &g, &b, &cnt);
|
2007-07-31 06:02:31 -07:00
|
|
|
j += cnt;
|
|
|
|
if (k >= 3)
|
|
|
|
{
|
|
|
|
radarColour(i, r, g, b);
|
|
|
|
}
|
|
|
|
i++; // next tile
|
2007-08-02 15:34:33 -07:00
|
|
|
} while (k >= 3 && j + 6 < size);
|
2007-07-31 06:02:31 -07:00
|
|
|
free(buffer);
|
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
/* Now load the actual tiles */
|
2006-05-27 09:37:17 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
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
|
2007-09-29 09:00:31 -07:00
|
|
|
int xSize = 1;
|
|
|
|
int ySize = 1;
|
|
|
|
|
|
|
|
// pad width and height into ^2 values
|
|
|
|
while (TILES_IN_PAGE_COLUMN * i > (xSize *= 2));
|
|
|
|
while (TILES_IN_PAGE_ROW * i > (ySize *= 2));
|
2006-05-27 09:37:17 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
// Generate the empty texture buffer in VRAM
|
|
|
|
texPage = newPage(fileName, j, xSize, ySize, 0);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-08-16 06:45:48 -07:00
|
|
|
sprintf(partialPath, "%s-%d", fileName, i);
|
2006-05-27 09:37:17 -07:00
|
|
|
|
2007-07-31 13:16:38 -07:00
|
|
|
// Load until we cannot find anymore of them
|
|
|
|
for (k = 0; k < MAX_TILES; k++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-07-31 13:16:38 -07:00
|
|
|
iTexture tile;
|
|
|
|
|
2007-08-25 15:33:14 -07:00
|
|
|
sprintf(fullPath, "%s/tile-%02d.png", partialPath, k);
|
2007-07-31 13:16:38 -07:00
|
|
|
if (PHYSFS_exists(fullPath)) // avoid dire warning
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-07-31 13:16:38 -07:00
|
|
|
BOOL retval = iV_loadImage_PNG(fullPath, &tile);
|
|
|
|
ASSERT(retval, "texLoad: Could not load %s", fullPath);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-07-31 13:16:38 -07:00
|
|
|
else
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-07-31 13:16:38 -07:00
|
|
|
// no more textures in this set
|
|
|
|
ASSERT(k > 0, "texLoad: Could not find %s", fullPath);
|
|
|
|
break;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-07-31 13:16:38 -07:00
|
|
|
// Insert into texture page
|
2007-08-21 05:59:05 -07:00
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, j, xOffset, yOffset, tile.width, tile.height,
|
2007-07-31 13:16:38 -07:00
|
|
|
GL_RGBA, GL_UNSIGNED_BYTE, tile.bmp);
|
|
|
|
free(tile.bmp);
|
2007-09-29 09:00:31 -07:00
|
|
|
if (i == TILE_WIDTH) // dealing with main texture page; so register coordinates
|
|
|
|
{
|
|
|
|
// 256 is an integer hack for GLfloat texture coordinates
|
|
|
|
tileTexInfo[k].uOffset = xOffset / (xSize / 256);
|
|
|
|
tileTexInfo[k].vOffset = yOffset / (ySize / 256);
|
|
|
|
tileTexInfo[k].texPage = texPage;
|
|
|
|
debug(LOG_ERROR, " 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);
|
|
|
|
}
|
2007-07-31 13:16:38 -07:00
|
|
|
xOffset += i; // i is width of tile
|
|
|
|
if (xOffset >= xSize)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-07-31 13:16:38 -07:00
|
|
|
yOffset += i; // i is also height of tile
|
|
|
|
xOffset = 0;
|
|
|
|
}
|
|
|
|
if (yOffset >= ySize)
|
|
|
|
{
|
|
|
|
/* Change to next texture page */
|
|
|
|
xOffset = 0;
|
|
|
|
yOffset = 0;
|
2007-08-21 05:59:05 -07:00
|
|
|
debug(LOG_TEXTURE, "texLoad: Extra page added at %d for %s, was page %d, opengl id %u",
|
2007-07-31 13:16:38 -07:00
|
|
|
k, partialPath, texPage, _TEX_PAGE[texPage].id);
|
|
|
|
texPage = newPage(fileName, j, xSize, ySize, k);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
2007-08-21 05:59:05 -07:00
|
|
|
debug(LOG_TEXTURE, "texLoad: Found %d textures for %s mipmap level %d, added to page %d, opengl id %u",
|
2007-07-31 13:16:38 -07:00
|
|
|
k, partialPath, i, texPage, _TEX_PAGE[texPage].id);
|
|
|
|
i /= 2; // halve the dimensions for the next series; OpenGL mipmaps start with largest at level zero
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|