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
|
|
|
|
*/
|
2006-07-22 16:35:48 -07:00
|
|
|
/* Texture stuff. Alex McLean, Pumpkin Studios, EIDOS Interactive, 1997 */
|
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-06-28 10:47:08 -07:00
|
|
|
#include "display3ddef.h"
|
|
|
|
#include "texture.h"
|
|
|
|
#include "radar.h"
|
|
|
|
|
|
|
|
#define MAX_TERRAIN_PAGES 20
|
2006-12-08 11:14:32 -08:00
|
|
|
// 4 byte depth == 32 bpp
|
2007-06-28 10:47:08 -07:00
|
|
|
#define PAGE_DEPTH 4
|
|
|
|
#define TEXTURE_PAGE_SIZE PAGE_WIDTH*PAGE_HEIGHT*PAGE_DEPTH
|
|
|
|
|
2006-09-01 14:01:17 -07:00
|
|
|
/* Stores the graphics data for the terrain tiles textures (in src/data.c) */
|
2007-05-01 13:34:54 -07:00
|
|
|
iTexture tilesPCX = { 0, 0, 0, NULL };
|
2006-09-01 14:01:17 -07:00
|
|
|
|
2006-07-22 16:35:48 -07:00
|
|
|
/* How many pages have we loaded */
|
2007-06-28 10:47:08 -07:00
|
|
|
SDWORD firstTexturePage;
|
|
|
|
SDWORD numTexturePages;
|
|
|
|
int pageId[MAX_TERRAIN_PAGES];
|
|
|
|
|
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-05-01 13:34:54 -07:00
|
|
|
static void getRectFromPage(UDWORD width, UDWORD height, unsigned char *src, UDWORD bufWidth, unsigned char *dest);
|
|
|
|
static void putRectIntoPage(UDWORD width, UDWORD height, unsigned char *dest, UDWORD bufWidth, unsigned char *src);
|
2007-06-28 10:47:08 -07:00
|
|
|
static void buildTileIndexes(void);
|
|
|
|
|
2006-05-27 09:37:17 -07:00
|
|
|
/*
|
2007-06-28 10:47:08 -07:00
|
|
|
Extracts the tile textures into separate texture pages and builds
|
|
|
|
a table of which texture page to find each tile in, as well as which one it is
|
2006-05-27 09:37:17 -07:00
|
|
|
within that page.
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
0123
|
|
|
|
4567
|
|
|
|
89AB
|
|
|
|
CDEF
|
2006-05-27 09:37:17 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
The above shows the different possible locations for a tile in the page.
|
|
|
|
So we have a table of MAX_TILES showing
|
|
|
|
|
|
|
|
pageNumber and [0..15]
|
2006-05-27 09:37:17 -07:00
|
|
|
|
|
|
|
We must then make sure that we source in that texture page and set the
|
2007-06-28 10:47:08 -07:00
|
|
|
texture coordinate for a complete tile to be its position.
|
|
|
|
*/
|
2007-05-01 13:34:54 -07:00
|
|
|
void makeTileTexturePages(iV_Image * src, UDWORD tileWidth, UDWORD tileHeight)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-04-28 13:21:16 -07:00
|
|
|
UDWORD i, j;
|
2007-05-01 13:34:54 -07:00
|
|
|
UDWORD pageNumber = 0;
|
|
|
|
UDWORD tilesAcross = src->width / tileWidth, tilesDown = src->height / tileHeight;
|
|
|
|
UDWORD tilesAcrossPage = PAGE_WIDTH / tileWidth, tilesDownPage = PAGE_HEIGHT / tileHeight;
|
|
|
|
UDWORD tilesPerPage = tilesAcrossPage * tilesDownPage, tilesPerSource = tilesAcross * tilesDown;
|
|
|
|
UDWORD tilesProcessed = 0;
|
|
|
|
iTexture sprite = { PAGE_WIDTH, PAGE_HEIGHT, PAGE_DEPTH, malloc(TEXTURE_PAGE_SIZE) };
|
|
|
|
/* Get enough memory to store one tile */
|
|
|
|
unsigned char *tileStorage = malloc(tileWidth * tileHeight * PAGE_DEPTH);
|
|
|
|
unsigned char *presentLoc = sprite.bmp;
|
|
|
|
unsigned char *srcBmp = src->bmp;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
/* This is how many pages are already used on hardware */
|
2007-04-07 06:23:14 -07:00
|
|
|
firstTexturePage = pie_GetLastPageDownloaded();
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-05-01 13:34:54 -07:00
|
|
|
debug(LOG_TEXTURE, "makeTileTexturePages: src(%d,%d) tile(%d,%d) pages used=%d", src->width, src->height, tileWidth, tileHeight, firstTexturePage);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-04-28 13:21:16 -07:00
|
|
|
for (i=0; i<tilesDown; i++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-04-28 13:21:16 -07:00
|
|
|
for (j=0; j<tilesAcross; j++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-05-01 13:34:54 -07:00
|
|
|
getRectFromPage(tileWidth, tileHeight, srcBmp, src->width, tileStorage);
|
2007-04-28 13:21:16 -07:00
|
|
|
putRectIntoPage(tileWidth, tileHeight, presentLoc, PAGE_WIDTH, tileStorage);
|
2007-06-28 10:47:08 -07:00
|
|
|
tilesProcessed++;
|
2007-04-28 13:21:16 -07:00
|
|
|
presentLoc += tileWidth * PAGE_DEPTH;
|
2007-05-01 13:34:54 -07:00
|
|
|
srcBmp += tileWidth * PAGE_DEPTH;
|
2007-06-28 10:47:08 -07:00
|
|
|
/* Have we got all the tiles from the source!? */
|
2007-04-28 13:21:16 -07:00
|
|
|
if (tilesProcessed == tilesPerSource)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-04-28 13:21:16 -07:00
|
|
|
pageId[pageNumber] = pie_AddTexPage(&sprite, "terrain", 0, FALSE);
|
2007-06-28 10:47:08 -07:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Have we run out of texture page? */
|
2007-04-28 13:21:16 -07:00
|
|
|
if (tilesProcessed % tilesPerPage == 0)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
debug(LOG_TEXTURE, "makeTileTexturePages: ran out of texture page ...");
|
2007-04-28 13:21:16 -07:00
|
|
|
debug(LOG_TEXTURE, "tilesDown=%d tilesAcross=%d tilesProcessed=%d tilesPerPage=%d", tilesDown, tilesAcross, tilesProcessed, tilesPerPage);
|
2007-06-28 10:47:08 -07:00
|
|
|
/* If so, download this one and reset to start again */
|
2007-04-28 13:21:16 -07:00
|
|
|
pageId[pageNumber] = pie_AddTexPage(&sprite, "terrain", 0, FALSE);
|
2007-05-01 13:34:54 -07:00
|
|
|
sprite.bmp = malloc(TEXTURE_PAGE_SIZE);
|
2007-06-28 10:47:08 -07:00
|
|
|
presentLoc = sprite.bmp;
|
2007-05-01 13:34:54 -07:00
|
|
|
pageNumber++;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-04-28 13:21:16 -07:00
|
|
|
else if (tilesProcessed % tilesAcrossPage == 0)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
/* Right hand side of texture page */
|
|
|
|
/* So go to one tile down */
|
2007-04-28 13:21:16 -07:00
|
|
|
presentLoc += (tileHeight-1) * PAGE_WIDTH * PAGE_DEPTH;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
2007-05-01 13:34:54 -07:00
|
|
|
srcBmp += (tileHeight-1) * src->width * PAGE_DEPTH;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-04-07 06:23:14 -07:00
|
|
|
ASSERT(FALSE, "we should have exited the loop using the goto");
|
2007-04-28 13:21:16 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
exit:
|
2007-04-07 06:23:14 -07:00
|
|
|
numTexturePages = pageNumber+1;
|
2007-04-15 03:43:05 -07:00
|
|
|
free(tileStorage);
|
2007-06-28 10:47:08 -07:00
|
|
|
buildTileIndexes();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-05-01 13:34:54 -07:00
|
|
|
void remakeTileTexturePages(iV_Image * src, UDWORD tileWidth, UDWORD tileHeight)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-04-28 13:21:16 -07:00
|
|
|
UDWORD i, j;
|
2007-05-01 13:34:54 -07:00
|
|
|
UDWORD pageNumber = 0;
|
|
|
|
UDWORD tilesAcross = src->width / tileWidth, tilesDown = src->height / tileHeight;
|
|
|
|
UDWORD tilesAcrossPage = PAGE_WIDTH / tileWidth, tilesDownPage = PAGE_HEIGHT / tileHeight;
|
|
|
|
UDWORD tilesPerPage = tilesAcrossPage * tilesDownPage, tilesPerSource = tilesAcross * tilesDown;
|
|
|
|
UDWORD tilesProcessed = 0;
|
|
|
|
iTexture sprite = { PAGE_WIDTH, PAGE_HEIGHT, PAGE_DEPTH, malloc(TEXTURE_PAGE_SIZE) };
|
2007-06-28 10:47:08 -07:00
|
|
|
/* Get enough memory to store one tile */
|
2007-05-01 13:34:54 -07:00
|
|
|
unsigned char *tileStorage = malloc(tileWidth * tileHeight * PAGE_DEPTH);
|
|
|
|
unsigned char *presentLoc = sprite.bmp;
|
|
|
|
unsigned char *srcBmp = src->bmp;
|
|
|
|
|
|
|
|
debug(LOG_TEXTURE, "remakeTileTexturePages: src(%d,%d), tile(%d, %d)", src->width, src->height, tileWidth, tileHeight);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-04-28 13:21:16 -07:00
|
|
|
for (i=0; i<tilesDown; i++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-04-28 13:21:16 -07:00
|
|
|
for (j=0; j<tilesAcross; j++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-05-01 13:34:54 -07:00
|
|
|
getRectFromPage(tileWidth, tileHeight, srcBmp, src->width, tileStorage);
|
2007-04-28 13:21:16 -07:00
|
|
|
putRectIntoPage(tileWidth, tileHeight, presentLoc, PAGE_WIDTH, tileStorage);
|
2007-06-28 10:47:08 -07:00
|
|
|
tilesProcessed++;
|
2007-04-28 13:21:16 -07:00
|
|
|
presentLoc += tileWidth * PAGE_DEPTH;
|
2007-05-01 13:34:54 -07:00
|
|
|
srcBmp += tileWidth * PAGE_DEPTH;
|
2007-06-28 10:47:08 -07:00
|
|
|
/* Have we got all the tiles from the source!? */
|
2007-04-28 13:21:16 -07:00
|
|
|
if (tilesProcessed == tilesPerSource)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-02-16 15:19:33 -08:00
|
|
|
pie_ChangeTexPage(pageId[pageNumber], &sprite, 0, FALSE);
|
2007-06-28 10:47:08 -07:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Have we run out of texture page? */
|
2007-04-28 13:21:16 -07:00
|
|
|
if (tilesProcessed % tilesPerPage == 0)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
debug(LOG_TEXTURE, "remakeTileTexturePages: ran out of texture page ...");
|
2007-04-28 13:21:16 -07:00
|
|
|
debug(LOG_TEXTURE, "tilesDown=%d tilesAcross=%d tilesProcessed=%d tilesPerPage=%d", tilesDown, tilesAcross, tilesProcessed, tilesPerPage);
|
2007-02-16 15:19:33 -08:00
|
|
|
pie_ChangeTexPage(pageId[pageNumber], &sprite, 0, FALSE);
|
2007-06-28 10:47:08 -07:00
|
|
|
pageNumber++;
|
|
|
|
presentLoc = sprite.bmp;
|
|
|
|
}
|
2007-04-28 13:21:16 -07:00
|
|
|
else if (tilesProcessed % tilesAcrossPage == 0)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
/* Right hand side of texture page */
|
|
|
|
/* So go to one tile down */
|
2007-04-28 13:21:16 -07:00
|
|
|
presentLoc += (tileHeight-1) * PAGE_WIDTH * PAGE_DEPTH;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
2007-05-01 13:34:54 -07:00
|
|
|
srcBmp += (tileHeight-1) * src->width * PAGE_DEPTH;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//check numTexturePages == pageNumber;
|
2007-04-28 13:21:16 -07:00
|
|
|
ASSERT( numTexturePages >= (SDWORD)pageNumber, "New Tertiles too large" );
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
exit:
|
2007-04-15 03:43:05 -07:00
|
|
|
free(tileStorage);
|
2007-06-28 10:47:08 -07:00
|
|
|
buildTileIndexes();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL getTileRadarColours(void)
|
|
|
|
{
|
|
|
|
UDWORD x, y, i, j, w, h, t;
|
|
|
|
iBitmap *b, *s;
|
2007-05-01 13:34:54 -07:00
|
|
|
unsigned char tempBMP[TILE_WIDTH * TILE_HEIGHT];
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
w = tilesPCX.width / TILE_WIDTH;
|
|
|
|
h = tilesPCX.height / TILE_HEIGHT;
|
|
|
|
|
|
|
|
t = 0;
|
2006-05-27 09:37:17 -07:00
|
|
|
for (i=0; i<h; i++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-05-27 09:37:17 -07:00
|
|
|
for (j=0; j<w; j++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
b = tilesPCX.bmp + j * TILE_WIDTH + i * tilesPCX.width * TILE_HEIGHT;
|
|
|
|
s = &tempBMP[0];
|
2006-05-27 09:37:17 -07:00
|
|
|
if (s)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
//copy the bitmap to temp buffer for colour calc
|
2006-05-27 09:37:17 -07:00
|
|
|
for (y=0; y<TILE_HEIGHT; y++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
for (x=0; x<TILE_WIDTH; *s++ = b[x++])
|
|
|
|
{
|
|
|
|
; /* NOP */
|
|
|
|
}
|
|
|
|
b+=tilesPCX.width;
|
|
|
|
}
|
|
|
|
calcRadarColour(&tempBMP[0],t);
|
|
|
|
t++;
|
2006-05-27 09:37:17 -07:00
|
|
|
}
|
|
|
|
else
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-07-22 16:35:48 -07:00
|
|
|
void freeTileTextures(void)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 07:25:06 -07:00
|
|
|
unsigned int i;
|
2006-07-22 16:35:48 -07:00
|
|
|
|
|
|
|
for (i = 0; i < numTexturePages; i++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-05-01 13:34:54 -07:00
|
|
|
iV_unloadImage(&_TEX_PAGE[(firstTexturePage+i)].tex);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-18 07:25:06 -07:00
|
|
|
static inline WZ_DECL_CONST unsigned int getTileXIndex(unsigned int tileNumber)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 07:25:06 -07:00
|
|
|
return (tileNumber % TILES_IN_PAGE) % TILES_IN_PAGE_COLUMN;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-06-18 07:25:06 -07:00
|
|
|
static inline WZ_DECL_CONST unsigned int getTileYIndex(unsigned int tileNumber)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 07:25:06 -07:00
|
|
|
return (tileNumber % TILES_IN_PAGE) / TILES_IN_PAGE_ROW;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Extracts a rectangular buffer from a source buffer, storing result in one contiguous
|
|
|
|
chunk */
|
2007-05-01 13:34:54 -07:00
|
|
|
static void getRectFromPage(UDWORD width, UDWORD height, unsigned char *src, UDWORD bufWidth, unsigned char *dest)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 07:25:06 -07:00
|
|
|
unsigned int i, j;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-06-18 07:25:06 -07:00
|
|
|
for (i = 0; i < height; i++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 07:25:06 -07:00
|
|
|
for(j = 0; j < width * PAGE_DEPTH; j++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
*dest++ = *src++;
|
|
|
|
}
|
2007-06-18 07:25:06 -07:00
|
|
|
src += (bufWidth - width) * PAGE_DEPTH;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Inserts a rectangle into a dest rectangle */
|
2007-05-01 13:34:54 -07:00
|
|
|
static void putRectIntoPage(UDWORD width, UDWORD height, unsigned char *dest, UDWORD bufWidth, unsigned char *src)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 07:25:06 -07:00
|
|
|
unsigned int i, j;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-06-18 08:46:12 -07:00
|
|
|
for(i = 0; i < height; i++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2007-06-18 07:25:06 -07:00
|
|
|
for(j = 0; j < width * PAGE_DEPTH; j++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
*dest++ = *src++;
|
|
|
|
}
|
2007-06-18 07:25:06 -07:00
|
|
|
dest += (bufWidth - width) * PAGE_DEPTH;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void buildTileIndexes(void)
|
|
|
|
{
|
2007-06-18 07:25:06 -07:00
|
|
|
unsigned int i;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-06-18 07:25:06 -07:00
|
|
|
for(i = 0; i < MAX_TILES; i++)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
tileTexInfo[i].xOffset = getTileXIndex(i);
|
|
|
|
tileTexInfo[i].yOffset = getTileYIndex(i);
|
2007-06-18 07:25:06 -07:00
|
|
|
tileTexInfo[i].texPage = pageId[i / TILES_IN_PAGE];
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|