mirror of
https://github.com/tribes2/engine.git
synced 2026-04-21 04:15:24 +00:00
t2 engine svn checkout
This commit is contained in:
commit
ff569bd2ae
988 changed files with 394180 additions and 0 deletions
52
dgl/bitmapBm8.cc
Normal file
52
dgl/bitmapBm8.cc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "dgl/gPalette.h"
|
||||
#include "Core/stream.h"
|
||||
#include "Platform/platform.h"
|
||||
|
||||
|
||||
bool GBitmap::readBmp8(Stream& stream)
|
||||
{
|
||||
stream.read(&byteSize);
|
||||
stream.read(&width);
|
||||
stream.read(&height);
|
||||
stream.read(&bytesPerPixel);
|
||||
stream.read(&numMipLevels);
|
||||
U32 i;
|
||||
for (i = 0; i < numMipLevels; i++)
|
||||
stream.read(&mipLevelOffsets[i]);
|
||||
internalFormat = GBitmap::Palettized;
|
||||
|
||||
pPalette = new GPalette;
|
||||
pPalette->read(stream);
|
||||
|
||||
pBits = new U8[byteSize];
|
||||
stream.read(byteSize, pBits);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GBitmap::writeBmp8(Stream& stream)
|
||||
{
|
||||
AssertFatal(pPalette != NULL, "Error, must have a palette to write the bmp!");
|
||||
|
||||
stream.write(byteSize);
|
||||
stream.write(width);
|
||||
stream.write(height);
|
||||
stream.write(bytesPerPixel);
|
||||
stream.write(numMipLevels);
|
||||
U32 i;
|
||||
for (i = 0; i < numMipLevels; i++)
|
||||
stream.write(mipLevelOffsets[i]);
|
||||
|
||||
pPalette->write(stream);
|
||||
stream.write(byteSize, pBits);
|
||||
|
||||
return true;
|
||||
}
|
||||
205
dgl/bitmapBmp.cc
Normal file
205
dgl/bitmapBmp.cc
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "dgl/gPalette.h"
|
||||
#include "Core/stream.h"
|
||||
#include "Platform/platform.h"
|
||||
|
||||
// structures mirror those defined by the win32 API
|
||||
|
||||
struct RGBQUAD {
|
||||
U8 rgbBlue;
|
||||
U8 rgbGreen;
|
||||
U8 rgbRed;
|
||||
U8 rgbReserved;
|
||||
};
|
||||
|
||||
struct BITMAPFILEHEADER {
|
||||
U16 bfType;
|
||||
U32 bfSize;
|
||||
U16 bfReserved1;
|
||||
U16 bfReserved2;
|
||||
U32 bfOffBits;
|
||||
};
|
||||
|
||||
struct BITMAPINFOHEADER{
|
||||
U32 biSize;
|
||||
S32 biWidth;
|
||||
S32 biHeight;
|
||||
U16 biPlanes;
|
||||
U16 biBitCount;
|
||||
U32 biCompression;
|
||||
U32 biSizeImage;
|
||||
S32 biXPelsPerMeter;
|
||||
S32 biYPelsPerMeter;
|
||||
U32 biClrUsed;
|
||||
U32 biClrImportant;
|
||||
};
|
||||
|
||||
// constants for the biCompression field
|
||||
#define BI_RGB 0L
|
||||
#define BI_RLE8 1L
|
||||
#define BI_RLE4 2L
|
||||
#define BI_BITFIELDS 3L
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- Supplimentary I/O (Partially located in
|
||||
// bitmapPng.cc)
|
||||
//
|
||||
|
||||
bool GBitmap::readMSBmp(Stream& stream)
|
||||
{
|
||||
BITMAPINFOHEADER bi;
|
||||
BITMAPFILEHEADER bf;
|
||||
RGBQUAD rgb[256];
|
||||
|
||||
stream.read(&bf.bfType);
|
||||
stream.read(&bf.bfSize);
|
||||
stream.read(&bf.bfReserved1);
|
||||
stream.read(&bf.bfReserved2);
|
||||
stream.read(&bf.bfOffBits);
|
||||
|
||||
stream.read(&bi.biSize);
|
||||
stream.read(&bi.biWidth);
|
||||
stream.read(&bi.biHeight);
|
||||
stream.read(&bi.biPlanes);
|
||||
stream.read(&bi.biBitCount);
|
||||
stream.read(&bi.biCompression);
|
||||
stream.read(&bi.biSizeImage);
|
||||
stream.read(&bi.biXPelsPerMeter);
|
||||
stream.read(&bi.biYPelsPerMeter);
|
||||
stream.read(&bi.biClrUsed);
|
||||
stream.read(&bi.biClrImportant);
|
||||
|
||||
BitmapFormat fmt = RGB;
|
||||
if(bi.biBitCount == 8)
|
||||
{
|
||||
fmt = Palettized;
|
||||
if(!bi.biClrUsed)
|
||||
bi.biClrUsed = 256;
|
||||
stream.read(sizeof(RGBQUAD) * bi.biClrUsed, rgb);
|
||||
|
||||
pPalette = new GPalette;
|
||||
for (U32 i = 0; i < 256; i++)
|
||||
{
|
||||
(pPalette->getColors())[i].red = rgb[i].rgbRed;
|
||||
(pPalette->getColors())[i].green = rgb[i].rgbGreen;
|
||||
(pPalette->getColors())[i].blue = rgb[i].rgbBlue;
|
||||
(pPalette->getColors())[i].alpha = 255;
|
||||
}
|
||||
}
|
||||
U8 *rowBuffer = new U8[bi.biWidth * 4];
|
||||
allocateBitmap(bi.biWidth, bi.biHeight, false, fmt);
|
||||
S32 width = getWidth();
|
||||
S32 height = getHeight();
|
||||
for(int i = 0; i < bi.biHeight; i++)
|
||||
{
|
||||
U8 *rowDest = getAddress(0, height - i - 1);
|
||||
stream.read(bytesPerPixel * width, rowDest);
|
||||
}
|
||||
|
||||
if(bytesPerPixel == 3) // do BGR swap
|
||||
{
|
||||
U8 *ptr = getAddress(0,0);
|
||||
for(int i = 0; i < width * height; i++)
|
||||
{
|
||||
U8 tmp = ptr[0];
|
||||
ptr[0] = ptr[2];
|
||||
ptr[2] = tmp;
|
||||
ptr += 3;
|
||||
}
|
||||
}
|
||||
delete[] rowBuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GBitmap::writeMSBmp(Stream& io_rStream) const
|
||||
{
|
||||
|
||||
RGBQUAD rgb[256];
|
||||
BITMAPINFOHEADER bi;
|
||||
BITMAPFILEHEADER bf;
|
||||
|
||||
bi.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bi.biWidth = getWidth();
|
||||
bi.biHeight = getHeight(); //our data is top-down
|
||||
bi.biPlanes = 1;
|
||||
|
||||
if(getFormat() == Palettized)
|
||||
{
|
||||
bi.biBitCount = 8;
|
||||
bi.biCompression = BI_RGB;
|
||||
bi.biClrUsed = 256;
|
||||
AssertFatal(pPalette != NULL, "Error, must have a palette");
|
||||
}
|
||||
else if(getFormat() == RGB)
|
||||
{
|
||||
bi.biBitCount = 24;
|
||||
bi.biCompression = BI_RGB;
|
||||
bi.biClrUsed = 0;
|
||||
}
|
||||
|
||||
U32 bytesPP = bi.biBitCount >> 3;
|
||||
bi.biSizeImage = getWidth() * getHeight() * bytesPP;
|
||||
bi.biXPelsPerMeter = 0;
|
||||
bi.biYPelsPerMeter = 0;
|
||||
bi.biClrUsed = 0;
|
||||
bi.biClrImportant = 0;
|
||||
|
||||
bf.bfType = makeFourCCTag('B','M',0,0); //Type of file 'BM'
|
||||
bf.bfOffBits= sizeof(BITMAPINFOHEADER)
|
||||
+ sizeof(BITMAPFILEHEADER)
|
||||
+ (sizeof(RGBQUAD)*bi.biClrUsed);
|
||||
bf.bfSize = bf.bfOffBits + bi.biSizeImage;
|
||||
bf.bfReserved1 = 0;
|
||||
bf.bfReserved2 = 0;
|
||||
|
||||
io_rStream.write(bf.bfType);
|
||||
io_rStream.write(bf.bfSize);
|
||||
io_rStream.write(bf.bfReserved1);
|
||||
io_rStream.write(bf.bfReserved2);
|
||||
io_rStream.write(bf.bfOffBits);
|
||||
|
||||
io_rStream.write(bi.biSize);
|
||||
io_rStream.write(bi.biWidth);
|
||||
io_rStream.write(bi.biHeight);
|
||||
io_rStream.write(bi.biPlanes);
|
||||
io_rStream.write(bi.biBitCount);
|
||||
io_rStream.write(bi.biCompression);
|
||||
io_rStream.write(bi.biSizeImage);
|
||||
io_rStream.write(bi.biXPelsPerMeter);
|
||||
io_rStream.write(bi.biYPelsPerMeter);
|
||||
io_rStream.write(bi.biClrUsed);
|
||||
io_rStream.write(bi.biClrImportant);
|
||||
|
||||
if(getFormat() == Palettized)
|
||||
{
|
||||
for (S32 ndx=0; ndx<256; ndx++)
|
||||
{
|
||||
rgb[ndx].rgbRed = pPalette->getColor(ndx).red;
|
||||
rgb[ndx].rgbGreen = pPalette->getColor(ndx).green;
|
||||
rgb[ndx].rgbBlue = pPalette->getColor(ndx).blue;
|
||||
rgb[ndx].rgbReserved = 0;
|
||||
}
|
||||
io_rStream.write(sizeof(RGBQUAD)*256, (U8*)&rgb);
|
||||
}
|
||||
|
||||
//write the bitmap bits
|
||||
U8* pMSUpsideDownBits = new U8[bi.biSizeImage];
|
||||
for (U32 i = 0; i < getHeight(); i++) {
|
||||
const U8* pSrc = getAddress(0, i);
|
||||
U8* pDst = pMSUpsideDownBits + (getHeight() - i - 1) * getWidth() * bytesPP;
|
||||
|
||||
dMemcpy(pDst, pSrc, getWidth() * bytesPP);
|
||||
}
|
||||
io_rStream.write(bi.biSizeImage, pMSUpsideDownBits);
|
||||
delete [] pMSUpsideDownBits;
|
||||
|
||||
return io_rStream.getStatus() == Stream::Ok;
|
||||
}
|
||||
172
dgl/bitmapGif.cc
Normal file
172
dgl/bitmapGif.cc
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Core/stream.h"
|
||||
#include "Core/fileStream.h"
|
||||
#include "Core/memstream.h"
|
||||
#include "dgl/gPalette.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
|
||||
#include "gif_lib.h"
|
||||
|
||||
|
||||
|
||||
//-------------------------------------- Replacement I/O for standard LIBjpeg
|
||||
// functions. we don't wanna use
|
||||
// FILE*'s...
|
||||
static int gifReadDataFn(GifFileType *gifinfo, GifByteType *data, int length)
|
||||
{
|
||||
Stream *stream = (Stream*)gifinfo->UserData;
|
||||
AssertFatal(stream != NULL, "jpegReadDataFn::No stream.");
|
||||
int pos = stream->getPosition();
|
||||
if (stream->read(length, data))
|
||||
return length;
|
||||
|
||||
if (stream->getStatus() == Stream::EOS)
|
||||
return (stream->getPosition()-pos);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
static int gifWriteDataFn(GifFileType *gifinfo, GifByteType *data, int length)
|
||||
{
|
||||
Stream *stream = (Stream*)gifinfo->UserData;
|
||||
AssertFatal(stream != NULL, "jpegWriteDataFn::No stream.");
|
||||
if (stream->write(length, data))
|
||||
return length;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool GBitmap::readGIF(Stream &stream)
|
||||
{
|
||||
GifFileType *gifinfo = DGifOpen( (void*)&stream, gifReadDataFn);
|
||||
if (!gifinfo)
|
||||
return false;
|
||||
|
||||
GifRecordType recordType;
|
||||
do
|
||||
{
|
||||
if (DGifGetRecordType(gifinfo, &recordType) == GIF_ERROR)
|
||||
break;
|
||||
|
||||
if (recordType == IMAGE_DESC_RECORD_TYPE)
|
||||
{
|
||||
if (DGifGetImageDesc(gifinfo) == GIF_ERROR)
|
||||
break;
|
||||
|
||||
BitmapFormat format = (gifinfo->SBackGroundColor == 0 ) ? RGB : RGBA;
|
||||
allocateBitmap(gifinfo->SWidth, gifinfo->SHeight, false, format);
|
||||
|
||||
U32 gwidth = gifinfo->Image.Width ? gifinfo->Image.Width : width;
|
||||
U32 gheight= gifinfo->Image.Height ? gifinfo->Image.Height : height;
|
||||
U32 gifSize = gwidth * gheight;
|
||||
U8 *data = new U8[gifSize];
|
||||
|
||||
if (DGifGetLine(gifinfo, data, gifSize) != GIF_ERROR)
|
||||
{
|
||||
// use the global or local color table ?
|
||||
GifColorType *color = gifinfo->SColorMap->Colors;
|
||||
if (gifinfo->Image.ColorMap)
|
||||
color = gifinfo->Image.ColorMap->Colors;
|
||||
|
||||
if (color)
|
||||
{
|
||||
U8 *dst = getAddress(gifinfo->Image.Left, gifinfo->Image.Top);
|
||||
U8 *src = data;
|
||||
U32 right = gifinfo->Image.Left + gwidth;
|
||||
U32 bottom = gifinfo->Image.Top + gheight;
|
||||
U32 next = (width - gwidth) * bytesPerPixel;
|
||||
|
||||
if (format == RGBA)
|
||||
{
|
||||
for (U32 y=gifinfo->Image.Top; y<bottom; y++)
|
||||
{
|
||||
for (U32 x=gifinfo->Image.Left; x<right; x++, src++)
|
||||
{
|
||||
if (*src == gifinfo->SBackGroundColor)
|
||||
{
|
||||
// this is a transparent pixel
|
||||
dst[0] = 0; // red
|
||||
dst[1] = 0; // green
|
||||
dst[2] = 0; // blue
|
||||
dst[3] = 0; // alpha
|
||||
}
|
||||
else
|
||||
{
|
||||
dst[0] = color[*src].Red;
|
||||
dst[1] = color[*src].Green;
|
||||
dst[2] = color[*src].Blue;
|
||||
dst[3] = 0; // alpha
|
||||
}
|
||||
dst += bytesPerPixel;
|
||||
}
|
||||
dst += next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 y=gifinfo->Image.Top; y<bottom; y++)
|
||||
{
|
||||
for (U32 x=gifinfo->Image.Left; x<right; x++, src++)
|
||||
{
|
||||
dst[0] = color[*src].Red;
|
||||
dst[1] = color[*src].Green;
|
||||
dst[2] = color[*src].Blue;
|
||||
dst += bytesPerPixel;
|
||||
}
|
||||
dst += next;
|
||||
}
|
||||
}
|
||||
delete [] data;
|
||||
DGifCloseFile(gifinfo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// failure
|
||||
delete [] data;
|
||||
break;
|
||||
}
|
||||
else if (recordType == EXTENSION_RECORD_TYPE)
|
||||
{
|
||||
GifByteType *extension;
|
||||
S32 extCode;
|
||||
|
||||
// Skip any extension blocks in file
|
||||
if (DGifGetExtension(gifinfo, &extCode, &extension) != GIF_ERROR)
|
||||
{
|
||||
while (extension != NULL)
|
||||
{
|
||||
if (DGifGetExtensionNext(gifinfo, &extension) == GIF_ERROR)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}while (recordType != TERMINATE_RECORD_TYPE);
|
||||
|
||||
|
||||
DGifCloseFile(gifinfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GBitmap::writeGIF(Stream&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
189
dgl/bitmapJpeg.cc
Normal file
189
dgl/bitmapJpeg.cc
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Core/stream.h"
|
||||
#include "Core/fileStream.h"
|
||||
#include "Core/memstream.h"
|
||||
#include "dgl/gPalette.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
//-------------------------------------- Replacement I/O for standard LIBjpeg
|
||||
// functions. we don't wanna use
|
||||
// FILE*'s...
|
||||
static int jpegReadDataFn(void *client_data, unsigned char *data, int length)
|
||||
{
|
||||
Stream *stream = (Stream*)client_data;
|
||||
AssertFatal(stream != NULL, "jpegReadDataFn::No stream.");
|
||||
int pos = stream->getPosition();
|
||||
if (stream->read(length, data))
|
||||
return length;
|
||||
|
||||
if (stream->getStatus() == Stream::EOS)
|
||||
return (stream->getPosition()-pos);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
static int jpegWriteDataFn(void *client_data, unsigned char *data, int length)
|
||||
{
|
||||
Stream *stream = (Stream*)client_data;
|
||||
AssertFatal(stream != NULL, "jpegWriteDataFn::No stream.");
|
||||
if (stream->write(length, data))
|
||||
return length;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
static void jpegFlushDataFn(void *)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
static int jpegErrorFn(void *client_data)
|
||||
{
|
||||
Stream *stream = (Stream*)client_data;
|
||||
AssertFatal(stream != NULL, "jpegErrorFn::No stream.");
|
||||
return (stream->getStatus() != Stream::Ok);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool GBitmap::readJPEG(Stream &stream)
|
||||
{
|
||||
JFREAD = jpegReadDataFn;
|
||||
JFERROR = jpegErrorFn;
|
||||
|
||||
jpeg_decompress_struct cinfo;
|
||||
jpeg_error_mgr jerr;
|
||||
|
||||
// We set up the normal JPEG error routines, then override error_exit.
|
||||
//cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
//jerr.pub.error_exit = my_error_exit;
|
||||
|
||||
// if (setjmp(jerr.setjmp_buffer))
|
||||
// {
|
||||
// // If we get here, the JPEG code has signaled an error.
|
||||
// // We need to clean up the JPEG object, close the input file, and return.
|
||||
// jpeg_destroy_decompress(&cinfo);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
|
||||
cinfo.err = jpeg_std_error(&jerr); // set up the normal JPEG error routines.
|
||||
cinfo.client_data = (void*)&stream; // set the stream into the client_data
|
||||
|
||||
// Now we can initialize the JPEG decompression object.
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
jpeg_stdio_src(&cinfo);
|
||||
|
||||
// Read file header, set default decompression parameters
|
||||
jpeg_read_header(&cinfo, true);
|
||||
|
||||
BitmapFormat format;
|
||||
switch (cinfo.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE: format = Alpha; break;
|
||||
case JCS_RGB: format = RGB; break;
|
||||
default:
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start decompressor
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
// allocate the bitmap space and init internal variables...
|
||||
allocateBitmap(cinfo.output_width, cinfo.output_height, false, format);
|
||||
|
||||
// Set up the row pointers...
|
||||
U32 rowBytes = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
U8* pBase = (U8*)getBits();
|
||||
for (U32 i = 0; i < height; i++)
|
||||
{
|
||||
JSAMPROW rowPointer = pBase + (i * rowBytes);
|
||||
jpeg_read_scanlines(&cinfo, &rowPointer, 1);
|
||||
}
|
||||
|
||||
// Finish decompression
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
// Release JPEG decompression object
|
||||
// This is an important step since it will release a good deal of memory.
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GBitmap::writeJPEG(Stream&) const
|
||||
{
|
||||
return false;
|
||||
/*
|
||||
if (compressHard == false) {
|
||||
return _writePNG(stream, 6, 0, PNG_ALL_FILTERS);
|
||||
} else {
|
||||
U8* buffer = new U8[1 << 22]; // 4 Megs. Should be enough...
|
||||
MemStream* pMemStream = new MemStream(1 << 22, buffer, false, true);
|
||||
|
||||
// We have to try the potentially useful compression methods here.
|
||||
|
||||
const U32 zStrategies[] = { Z_DEFAULT_STRATEGY,
|
||||
Z_FILTERED };
|
||||
const U32 pngFilters[] = { PNG_FILTER_NONE,
|
||||
PNG_FILTER_SUB,
|
||||
PNG_FILTER_UP,
|
||||
PNG_FILTER_AVG,
|
||||
PNG_FILTER_PAETH,
|
||||
PNG_ALL_FILTERS };
|
||||
|
||||
U32 minSize = 0xFFFFFFFF;
|
||||
U32 bestStrategy = 0xFFFFFFFF;
|
||||
U32 bestFilter = 0xFFFFFFFF;
|
||||
U32 bestCLevel = 0xFFFFFFFF;
|
||||
|
||||
for (U32 cl = 0; cl <=9; cl++) {
|
||||
for (U32 zs = 0; zs < 2; zs++) {
|
||||
for (U32 pf = 0; pf < 6; pf++) {
|
||||
pMemStream->setPosition(0);
|
||||
|
||||
if (_writePNG(*pMemStream, cl, zStrategies[zs], pngFilters[pf]) == false)
|
||||
AssertFatal(false, "Handle this error!");
|
||||
|
||||
if (pMemStream->getPosition() < minSize) {
|
||||
minSize = pMemStream->getPosition();
|
||||
bestStrategy = zs;
|
||||
bestFilter = pf;
|
||||
bestCLevel = cl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
AssertFatal(minSize != 0xFFFFFFFF, "Error, no best found?");
|
||||
|
||||
delete pMemStream;
|
||||
delete [] buffer;
|
||||
|
||||
|
||||
return _writePNG(stream,
|
||||
bestCLevel,
|
||||
zStrategies[bestStrategy],
|
||||
pngFilters[bestFilter]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
415
dgl/bitmapPng.cc
Normal file
415
dgl/bitmapPng.cc
Normal file
|
|
@ -0,0 +1,415 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Core/stream.h"
|
||||
#include "Core/fileStream.h"
|
||||
#include "Core/memstream.h"
|
||||
#include "dgl/gPalette.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "Sim/frameAllocator.h"
|
||||
|
||||
#define PNG_INTERNAL 1
|
||||
#include "time.h"
|
||||
#include "png.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef NULL
|
||||
#undef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
// Our chunk signatures...
|
||||
static png_byte DGL_CHUNK_dcCf[5] = { 100, 99, 67, 102, '\0' };
|
||||
static png_byte DGL_CHUNK_dcCs[5] = { 100, 99, 67, 115, '\0' };
|
||||
|
||||
static const U32 csgMaxRowPointers = 1024;
|
||||
static png_bytep sRowPointers[1024];
|
||||
|
||||
//-------------------------------------- Instead of using the user_ptr,
|
||||
// we use a global pointer, we
|
||||
// need to ensure that only one thread
|
||||
// at once may be using the variable.
|
||||
// NOTE: Removed mutex for g_varAccess.
|
||||
// may have to re-thread safe this.
|
||||
static Stream* sg_pStream = NULL;
|
||||
|
||||
//-------------------------------------- Replacement I/O for standard LIBPng
|
||||
// functions. we don't wanna use
|
||||
// FILE*'s...
|
||||
static void pngReadDataFn(png_structp /*png_ptr*/,
|
||||
png_bytep data,
|
||||
png_size_t length)
|
||||
{
|
||||
AssertFatal(sg_pStream != NULL, "No stream?");
|
||||
|
||||
bool success = sg_pStream->read(length, data);
|
||||
AssertFatal(success, "Png Read catastrofic error!");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
static void pngWriteDataFn(png_structp /*png_ptr*/,
|
||||
png_bytep data,
|
||||
png_size_t length)
|
||||
{
|
||||
AssertFatal(sg_pStream != NULL, "No stream?");
|
||||
|
||||
sg_pStream->write(length, data);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
static void pngFlushDataFn(png_structp /*png_ptr*/)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
static png_voidp pngMallocFn(png_structp /*png_ptr*/, png_size_t size)
|
||||
{
|
||||
return FrameAllocator::alloc(size);
|
||||
// return (png_voidp)dMalloc(size);
|
||||
}
|
||||
|
||||
static void pngFreeFn(png_structp /*png_ptr*/, png_voidp /*mem*/)
|
||||
{
|
||||
// dFree(mem);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
static void pngFatalErrorFn(png_structp /*png_ptr*/,
|
||||
png_const_charp pMessage)
|
||||
{
|
||||
AssertISV(false, avar("Error reading PNG file:\n %s", pMessage));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
static void pngWarningFn(png_structp, png_const_charp /*pMessage*/)
|
||||
{
|
||||
// AssertWarn(false, avar("Warning reading PNG file:\n %s", pMessage));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool GBitmap::readPNG(Stream& io_rStream)
|
||||
{
|
||||
static const U32 cs_headerBytesChecked = 8;
|
||||
|
||||
U8 header[cs_headerBytesChecked];
|
||||
io_rStream.read(cs_headerBytesChecked, header);
|
||||
|
||||
bool isPng = png_check_sig(header, cs_headerBytesChecked) != 0;
|
||||
if (isPng == false) {
|
||||
AssertWarn(false, "GBitmap::readPNG: stream doesn't contain a PNG");
|
||||
return false;
|
||||
}
|
||||
|
||||
U32 prevWaterMark = FrameAllocator::getWaterMark();
|
||||
png_structp png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
|
||||
NULL,
|
||||
pngFatalErrorFn,
|
||||
pngWarningFn,
|
||||
NULL,
|
||||
pngMallocFn,
|
||||
pngFreeFn);
|
||||
|
||||
if (png_ptr == NULL) {
|
||||
FrameAllocator::setWaterMark(prevWaterMark);
|
||||
return false;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
png_destroy_read_struct(&png_ptr,
|
||||
(png_infopp)NULL,
|
||||
(png_infopp)NULL);
|
||||
FrameAllocator::setWaterMark(prevWaterMark);
|
||||
return false;
|
||||
}
|
||||
|
||||
png_infop end_info = png_create_info_struct(png_ptr);
|
||||
if (end_info == NULL) {
|
||||
png_destroy_read_struct(&png_ptr,
|
||||
&info_ptr,
|
||||
(png_infopp)NULL);
|
||||
FrameAllocator::setWaterMark(prevWaterMark);
|
||||
return false;
|
||||
}
|
||||
|
||||
sg_pStream = &io_rStream;
|
||||
png_set_read_fn(png_ptr, NULL, pngReadDataFn);
|
||||
|
||||
// Read off the info on the image.
|
||||
png_set_sig_bytes(png_ptr, cs_headerBytesChecked);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
// OK, at this point, if we have reached it ok, then we can reset the
|
||||
// image to accept the new data...
|
||||
//
|
||||
deleteImage();
|
||||
|
||||
png_uint_32 width;
|
||||
png_uint_32 height;
|
||||
S32 bit_depth;
|
||||
S32 color_type;
|
||||
|
||||
png_get_IHDR(png_ptr, info_ptr,
|
||||
&width, &height, // obv.
|
||||
&bit_depth, &color_type, // obv.
|
||||
NULL, // interlace
|
||||
NULL, // compression_type
|
||||
NULL); // filter_type
|
||||
|
||||
// First, handle the color transformations. We need this to read in the
|
||||
// data as RGB or RGBA, _always_, with a maximal channel width of 8 bits.
|
||||
//
|
||||
bool transAlpha = false;
|
||||
BitmapFormat format = RGB;
|
||||
|
||||
// Strip off any 16 bit info
|
||||
//
|
||||
if (bit_depth == 16) {
|
||||
png_set_strip_16(png_ptr);
|
||||
}
|
||||
|
||||
// Expand a transparency channel into a full alpha channel...
|
||||
//
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
png_set_expand(png_ptr);
|
||||
transAlpha = true;
|
||||
}
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_expand(png_ptr);
|
||||
format = transAlpha ? RGBA : RGB;
|
||||
} else if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
png_set_expand(png_ptr);
|
||||
//png_set_gray_to_rgb(png_ptr);
|
||||
format = Alpha; //transAlpha ? RGBA : RGB;
|
||||
} else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_expand(png_ptr);
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
format = RGBA;
|
||||
} else if (color_type == PNG_COLOR_TYPE_RGB) {
|
||||
format = transAlpha ? RGBA : RGB;
|
||||
png_set_expand(png_ptr);
|
||||
} else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
png_set_expand(png_ptr);
|
||||
format = RGBA;
|
||||
}
|
||||
|
||||
// Update the info pointer with the result of the transformations
|
||||
// above...
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
png_uint_32 rowBytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
if (format == RGB) {
|
||||
AssertFatal(rowBytes == width * 3,
|
||||
"Error, our rowbytes are incorrect for this transform... (3)");
|
||||
} else if (format == RGBA) {
|
||||
AssertFatal(rowBytes == width * 4,
|
||||
"Error, our rowbytes are incorrect for this transform... (4)");
|
||||
}
|
||||
|
||||
// actually allocate the bitmap space...
|
||||
allocateBitmap(width, height,
|
||||
false, // don't extrude miplevels...
|
||||
format); // use determined format...
|
||||
|
||||
// Set up the row pointers...
|
||||
AssertISV(height <= csgMaxRowPointers, "Error, cannot load pngs taller than 1024 pixels!");
|
||||
png_bytep* rowPointers = sRowPointers;
|
||||
U8* pBase = (U8*)getBits();
|
||||
for (U32 i = 0; i < height; i++)
|
||||
rowPointers[i] = pBase + (i * rowBytes);
|
||||
|
||||
// And actually read the image!
|
||||
png_read_image(png_ptr, rowPointers);
|
||||
|
||||
// We're outta here, destroy the png structs, and release the lock
|
||||
// as quickly as possible...
|
||||
//png_read_end(png_ptr, end_info);
|
||||
png_read_end(png_ptr, NULL);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
|
||||
sg_pStream = NULL;
|
||||
|
||||
// Ok, the image is read in, now we need to finish up the initialization,
|
||||
// which means: setting up the detailing members, init'ing the palette
|
||||
// key, etc...
|
||||
//
|
||||
// actually, all of that was handled by allocateBitmap, so we're outta here
|
||||
//
|
||||
FrameAllocator::setWaterMark(prevWaterMark);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GBitmap::_writePNG(Stream& stream,
|
||||
const U32 compressionLevel,
|
||||
const U32 strategy,
|
||||
const U32 filter) const
|
||||
{
|
||||
// ONLY RGB bitmap writing supported at this time!
|
||||
AssertFatal(getFormat() == RGB || getFormat() == RGBA || getFormat() == Alpha, "GBitmap::writePNG: ONLY RGB bitmap writing supported at this time.");
|
||||
if (internalFormat != RGB && internalFormat != RGBA && internalFormat != Alpha)
|
||||
return (false);
|
||||
|
||||
#define MAX_HEIGHT 4096
|
||||
|
||||
if (height >= MAX_HEIGHT)
|
||||
return (false);
|
||||
|
||||
png_structp png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
|
||||
NULL,
|
||||
pngFatalErrorFn,
|
||||
pngWarningFn,
|
||||
NULL,
|
||||
pngMallocFn,
|
||||
pngFreeFn);
|
||||
if (png_ptr == NULL)
|
||||
return (false);
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL)
|
||||
{
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
sg_pStream = &stream;
|
||||
png_set_write_fn(png_ptr, NULL, pngWriteDataFn, pngFlushDataFn);
|
||||
|
||||
// Set the compression level, image filters, and compression strategy...
|
||||
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
|
||||
png_ptr->zlib_strategy = strategy;
|
||||
png_set_compression_window_bits(png_ptr, 15);
|
||||
png_set_compression_level(png_ptr, compressionLevel);
|
||||
png_set_filter(png_ptr, 0, filter);
|
||||
|
||||
// Set the image information here. Width and height are up to 2^31,
|
||||
// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
|
||||
// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
|
||||
// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
|
||||
// or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
|
||||
// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
|
||||
// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
|
||||
|
||||
if (getFormat() == RGB) {
|
||||
png_set_IHDR(png_ptr, info_ptr,
|
||||
width, height, // the width & height
|
||||
8, PNG_COLOR_TYPE_RGB, // bit_depth, color_type,
|
||||
NULL, // no interlace
|
||||
NULL, // compression type
|
||||
NULL); // filter type
|
||||
}
|
||||
else if (getFormat() == RGBA) {
|
||||
png_set_IHDR(png_ptr, info_ptr,
|
||||
width, height, // the width & height
|
||||
8, PNG_COLOR_TYPE_RGB_ALPHA, // bit_depth, color_type,
|
||||
NULL, // no interlace
|
||||
NULL, // compression type
|
||||
NULL); // filter type
|
||||
}
|
||||
else if (getFormat() == Alpha) {
|
||||
png_set_IHDR(png_ptr, info_ptr,
|
||||
width, height, // the width & height
|
||||
8, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type,
|
||||
NULL, // no interlace
|
||||
NULL, // compression type
|
||||
NULL); // filter type
|
||||
}
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
png_bytep row_pointers[MAX_HEIGHT];
|
||||
for (U32 i=0; i<height; i++)
|
||||
row_pointers[i] = const_cast<png_bytep>(getAddress(0, i));
|
||||
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
|
||||
// Write S3TC data if present...
|
||||
// Write FXT1 data if present...
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GBitmap::writePNG(Stream& stream, const bool compressHard) const
|
||||
{
|
||||
U32 waterMark = FrameAllocator::getWaterMark();
|
||||
|
||||
if (compressHard == false) {
|
||||
bool retVal = _writePNG(stream, 6, 0, PNG_ALL_FILTERS);
|
||||
FrameAllocator::setWaterMark(waterMark);
|
||||
return retVal;
|
||||
} else {
|
||||
U8* buffer = new U8[1 << 22]; // 4 Megs. Should be enough...
|
||||
MemStream* pMemStream = new MemStream(1 << 22, buffer, false, true);
|
||||
|
||||
// We have to try the potentially useful compression methods here.
|
||||
|
||||
const U32 zStrategies[] = { Z_DEFAULT_STRATEGY,
|
||||
Z_FILTERED };
|
||||
const U32 pngFilters[] = { PNG_FILTER_NONE,
|
||||
PNG_FILTER_SUB,
|
||||
PNG_FILTER_UP,
|
||||
PNG_FILTER_AVG,
|
||||
PNG_FILTER_PAETH,
|
||||
PNG_ALL_FILTERS };
|
||||
|
||||
U32 minSize = 0xFFFFFFFF;
|
||||
U32 bestStrategy = 0xFFFFFFFF;
|
||||
U32 bestFilter = 0xFFFFFFFF;
|
||||
U32 bestCLevel = 0xFFFFFFFF;
|
||||
|
||||
for (U32 cl = 0; cl <=9; cl++) {
|
||||
for (U32 zs = 0; zs < 2; zs++) {
|
||||
for (U32 pf = 0; pf < 6; pf++) {
|
||||
pMemStream->setPosition(0);
|
||||
|
||||
if (_writePNG(*pMemStream, cl, zStrategies[zs], pngFilters[pf]) == false)
|
||||
AssertFatal(false, "Handle this error!");
|
||||
|
||||
if (pMemStream->getPosition() < minSize) {
|
||||
minSize = pMemStream->getPosition();
|
||||
bestStrategy = zs;
|
||||
bestFilter = pf;
|
||||
bestCLevel = cl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
AssertFatal(minSize != 0xFFFFFFFF, "Error, no best found?");
|
||||
|
||||
delete pMemStream;
|
||||
delete [] buffer;
|
||||
|
||||
|
||||
bool retVal = _writePNG(stream,
|
||||
bestCLevel,
|
||||
zStrategies[bestStrategy],
|
||||
pngFilters[bestFilter]);
|
||||
FrameAllocator::setWaterMark(waterMark);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GBitmap::writePNGUncompressed(Stream& stream) const
|
||||
{
|
||||
U32 waterMark = FrameAllocator::getWaterMark();
|
||||
|
||||
bool retVal = _writePNG(stream, 0, 0, PNG_FILTER_NONE);
|
||||
FrameAllocator::setWaterMark(waterMark);
|
||||
return retVal;
|
||||
}
|
||||
746
dgl/dgl.cc
Normal file
746
dgl/dgl.cc
Normal file
|
|
@ -0,0 +1,746 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "math/mPoint.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "core/color.h"
|
||||
#include "math/mPoint.h"
|
||||
#include "math/mRect.h"
|
||||
#include "dgl/gFont.h"
|
||||
#include "console/console.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "sim/frameAllocator.h"
|
||||
#include "platform/profiler.h"
|
||||
|
||||
namespace {
|
||||
|
||||
ColorI sg_bitmapModulation(255, 255, 255, 255);
|
||||
ColorI sg_textAnchorColor(255, 255, 255, 255);
|
||||
ColorI sg_stackColor(255, 255, 255, 255);
|
||||
RectI sgCurrentClipRect;
|
||||
|
||||
} // namespace {}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void dglSetBitmapModulation(const ColorF& in_rColor)
|
||||
{
|
||||
ColorF c = in_rColor;
|
||||
c.clamp();
|
||||
sg_bitmapModulation = c;
|
||||
sg_textAnchorColor = sg_bitmapModulation;
|
||||
}
|
||||
|
||||
void dglGetBitmapModulation(ColorF* color)
|
||||
{
|
||||
*color = sg_bitmapModulation;
|
||||
}
|
||||
|
||||
void dglGetBitmapModulation(ColorI* color)
|
||||
{
|
||||
*color = sg_bitmapModulation;
|
||||
}
|
||||
|
||||
void dglClearBitmapModulation()
|
||||
{
|
||||
sg_bitmapModulation.set(255, 255, 255, 255);
|
||||
}
|
||||
|
||||
void dglSetTextAnchorColor(const ColorF& in_rColor)
|
||||
{
|
||||
ColorF c = in_rColor;
|
||||
c.clamp();
|
||||
sg_textAnchorColor = c;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void dglDrawBitmapStretchSR(TextureObject* texture,
|
||||
const RectI& dstRect,
|
||||
const RectI& srcRect,
|
||||
const U32 in_flip)
|
||||
{
|
||||
AssertFatal(texture != NULL, "GSurface::drawBitmapStretchSR: NULL Handle");
|
||||
if(!dstRect.isValidRect())
|
||||
return;
|
||||
AssertFatal(srcRect.isValidRect() == true,
|
||||
"GSurface::drawBitmapStretchSR: routines assume normal rects");
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texture->texGLName);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
F32 texLeft = F32(srcRect.point.x) / F32(texture->texWidth);
|
||||
F32 texRight = F32(srcRect.point.x + srcRect.extent.x) / F32(texture->texWidth);
|
||||
F32 texTop = F32(srcRect.point.y) / F32(texture->texHeight);
|
||||
F32 texBottom = F32(srcRect.point.y + srcRect.extent.y) / F32(texture->texHeight);
|
||||
F32 screenLeft = dstRect.point.x;
|
||||
F32 screenRight = dstRect.point.x + dstRect.extent.x;
|
||||
F32 screenTop = dstRect.point.y;
|
||||
F32 screenBottom = dstRect.point.y + dstRect.extent.y;
|
||||
|
||||
if(in_flip & GFlip_X)
|
||||
{
|
||||
F32 temp = texLeft;
|
||||
texLeft = texRight;
|
||||
texRight = temp;
|
||||
}
|
||||
if(in_flip & GFlip_Y)
|
||||
{
|
||||
F32 temp = texTop;
|
||||
texTop = texBottom;
|
||||
texBottom = temp;
|
||||
}
|
||||
|
||||
glColor4ub(sg_bitmapModulation.red,
|
||||
sg_bitmapModulation.green,
|
||||
sg_bitmapModulation.blue,
|
||||
sg_bitmapModulation.alpha);
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glTexCoord2f(texLeft, texBottom);
|
||||
glVertex2f(screenLeft, screenBottom);
|
||||
|
||||
glTexCoord2f(texRight, texBottom);
|
||||
glVertex2f(screenRight, screenBottom);
|
||||
|
||||
glTexCoord2f(texRight, texTop);
|
||||
glVertex2f(screenRight, screenTop);
|
||||
|
||||
glTexCoord2f(texLeft, texTop);
|
||||
glVertex2f(screenLeft, screenTop);
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void dglDrawBitmap(TextureObject* texture, const Point2I& in_rAt, const U32 in_flip)
|
||||
{
|
||||
AssertFatal(texture != NULL, "GSurface::drawBitmap: NULL Handle");
|
||||
|
||||
// All non-StretchSR bitmaps are transformed into StretchSR calls...
|
||||
//
|
||||
RectI subRegion(0, 0,
|
||||
texture->bitmapWidth,
|
||||
texture->bitmapHeight);
|
||||
RectI stretch(in_rAt.x, in_rAt.y,
|
||||
texture->bitmapWidth,
|
||||
texture->bitmapHeight);
|
||||
dglDrawBitmapStretchSR(texture,
|
||||
stretch,
|
||||
subRegion,
|
||||
in_flip);
|
||||
}
|
||||
|
||||
void dglDrawBitmapStretch(TextureObject* texture, const RectI& dstRect, const U32 in_flip)
|
||||
{
|
||||
AssertFatal(texture != NULL, "GSurface::drawBitmapStretch: NULL Handle");
|
||||
AssertFatal(dstRect.isValidRect() == true,
|
||||
"GSurface::drawBitmapStretch: routines assume normal rects");
|
||||
|
||||
RectI subRegion(0, 0,
|
||||
texture->bitmapWidth,
|
||||
texture->bitmapHeight);
|
||||
dglDrawBitmapStretchSR(texture,
|
||||
dstRect,
|
||||
subRegion,
|
||||
in_flip);
|
||||
}
|
||||
|
||||
void dglDrawBitmapSR(TextureObject *texture, const Point2I& in_rAt, const RectI& srcRect, const U32 in_flip)
|
||||
{
|
||||
AssertFatal(texture != NULL, "GSurface::drawBitmapSR: NULL Handle");
|
||||
AssertFatal(srcRect.isValidRect() == true,
|
||||
"GSurface::drawBitmapSR: routines assume normal rects");
|
||||
|
||||
RectI stretch(in_rAt.x, in_rAt.y,
|
||||
srcRect.len_x(),
|
||||
srcRect.len_y());
|
||||
dglDrawBitmapStretchSR(texture,
|
||||
stretch,
|
||||
srcRect,
|
||||
in_flip);
|
||||
}
|
||||
|
||||
U32 dglDrawText(GFont* font,
|
||||
const Point2I& ptDraw,
|
||||
const void* in_string,
|
||||
const ColorI* colorTable,
|
||||
const U32 maxColorIndex)
|
||||
{
|
||||
return dglDrawTextN(font, ptDraw, in_string, dStrlen((const char *) in_string), colorTable, maxColorIndex);
|
||||
}
|
||||
|
||||
struct TextVertex
|
||||
{
|
||||
Point3F p;
|
||||
Point2F t;
|
||||
ColorI c;
|
||||
void set(F32 x, F32 y, F32 tx, F32 ty, ColorI color)
|
||||
{
|
||||
p.x = x;
|
||||
p.y = y;
|
||||
p.z = 0;
|
||||
t.x = tx;
|
||||
t.y = ty;
|
||||
c = color;
|
||||
}
|
||||
};
|
||||
|
||||
U32 dglDrawTextN(GFont* font,
|
||||
const Point2I& ptDraw,
|
||||
const void* in_string,
|
||||
U32 n,
|
||||
const ColorI* colorTable,
|
||||
const U32 maxColorIndex)
|
||||
{
|
||||
// return on zero length strings
|
||||
if( n < 1 )
|
||||
return ptDraw.x;
|
||||
PROFILE_START(DrawText);
|
||||
|
||||
Point2I pt;
|
||||
U8 c;
|
||||
const U8 *str = (const U8*)in_string;
|
||||
const U8 *endStr = str + n;
|
||||
pt.x = ptDraw.x;
|
||||
|
||||
ColorI currentColor;
|
||||
S32 currentPt = 0;
|
||||
U32 storedWaterMark;
|
||||
|
||||
TextureObject *lastTexture = NULL;
|
||||
|
||||
storedWaterMark = FrameAllocator::getWaterMark();
|
||||
currentColor = sg_bitmapModulation;
|
||||
|
||||
TextVertex *vert = (TextVertex *) FrameAllocator::alloc(4 * n * sizeof(TextVertex));
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(TextVertex), &(vert[0].p) );
|
||||
|
||||
glEnableClientState ( GL_COLOR_ARRAY );
|
||||
glColorPointer ( 4, GL_UNSIGNED_BYTE, sizeof(TextVertex), &(vert[0].c) );
|
||||
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(TextVertex), &(vert[0].t) );
|
||||
|
||||
// first build the point, color, and coord arrays
|
||||
for (c = *str; str < endStr; c = *(++str))
|
||||
{
|
||||
// We have to do a little dance here since \t = 0x9, \n = 0xa, and \r = 0xd
|
||||
if ((c >= 2 && c <= 8) ||
|
||||
(c >= 11 && c <= 12) ||
|
||||
(c == 14))
|
||||
{
|
||||
// Color code
|
||||
if (colorTable)
|
||||
{
|
||||
static U8 remap[15] =
|
||||
{
|
||||
0x0,
|
||||
0x0,
|
||||
0x0,
|
||||
0x1,
|
||||
0x2,
|
||||
0x3,
|
||||
0x4,
|
||||
0x5,
|
||||
0x6,
|
||||
0x0,
|
||||
0x0,
|
||||
0x7,
|
||||
0x8,
|
||||
0x0,
|
||||
0x9
|
||||
};
|
||||
|
||||
U8 remapped = remap[c];
|
||||
// Ignore if the color is greater than the specified max index:
|
||||
if ( remapped <= maxColorIndex )
|
||||
{
|
||||
const ColorI &clr = colorTable[remapped];
|
||||
currentColor = sg_bitmapModulation = clr;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// reset color?
|
||||
if ( c == 15 )
|
||||
{
|
||||
currentColor = sg_textAnchorColor;
|
||||
sg_bitmapModulation = sg_textAnchorColor;
|
||||
continue;
|
||||
}
|
||||
|
||||
// push color:
|
||||
if ( c == 16 )
|
||||
{
|
||||
sg_stackColor = sg_bitmapModulation;
|
||||
continue;
|
||||
}
|
||||
|
||||
// pop color:
|
||||
if ( c == 17 )
|
||||
{
|
||||
currentColor = sg_stackColor;
|
||||
sg_bitmapModulation = sg_stackColor;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tab character
|
||||
if( !font->isValidChar( c ) )
|
||||
{
|
||||
if ( c == '\t' )
|
||||
{
|
||||
const GFont::CharInfo &ci = font->getCharInfo( ' ' );
|
||||
pt.x += ci.xIncrement * GFont::TabWidthInSpaces;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const GFont::CharInfo &ci = font->getCharInfo(c);
|
||||
TextureObject *newObj = font->getTextureHandle(ci.bitmapIndex);
|
||||
if(newObj != lastTexture)
|
||||
{
|
||||
if(currentPt)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, lastTexture->texGLName);
|
||||
glDrawArrays( GL_QUADS, 0, currentPt );
|
||||
currentPt = 0;
|
||||
}
|
||||
lastTexture = newObj;
|
||||
}
|
||||
if(ci.width != 0 && ci.height != 0)
|
||||
{
|
||||
pt.y = ptDraw.y + font->getBaseline() - ci.yOrigin;
|
||||
pt.x += ci.xOrigin;
|
||||
|
||||
F32 texLeft = F32(ci.xOffset) / F32(lastTexture->texWidth);
|
||||
F32 texRight = F32(ci.xOffset + ci.width) / F32(lastTexture->texWidth);
|
||||
F32 texTop = F32(ci.yOffset) / F32(lastTexture->texHeight);
|
||||
F32 texBottom = F32(ci.yOffset + ci.height) / F32(lastTexture->texHeight);
|
||||
|
||||
F32 screenLeft = pt.x;
|
||||
F32 screenRight = pt.x + ci.width;
|
||||
F32 screenTop = pt.y;
|
||||
F32 screenBottom = pt.y + ci.height;
|
||||
vert[currentPt++].set(screenLeft, screenBottom, texLeft, texBottom, currentColor);
|
||||
vert[currentPt++].set(screenRight, screenBottom, texRight, texBottom, currentColor);
|
||||
vert[currentPt++].set(screenRight, screenTop, texRight, texTop, currentColor);
|
||||
vert[currentPt++].set(screenLeft, screenTop, texLeft, texTop, currentColor);
|
||||
pt.x += ci.xIncrement - ci.xOrigin;
|
||||
}
|
||||
else
|
||||
pt.x += ci.xIncrement;
|
||||
}
|
||||
/* if (gOpenGLNoDrawArraysAlpha)
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
for (S32 i = 0; i < rd[page].count; ++i)
|
||||
{
|
||||
glColor4fv((float *) &colArray[rd[page].start+i]);
|
||||
glTexCoord2f(texArray[rd[page].start+i].x, texArray[rd[page].start+i].y);
|
||||
glVertex2f(ptArray[rd[page].start+i].x, ptArray[rd[page].start+i].y);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
else*/
|
||||
if(currentPt)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, lastTexture->texGLName);
|
||||
glDrawArrays( GL_QUADS, 0, currentPt );
|
||||
}
|
||||
|
||||
glDisableClientState ( GL_VERTEX_ARRAY );
|
||||
glDisableClientState ( GL_COLOR_ARRAY );
|
||||
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
// restore the FrameAllocator
|
||||
FrameAllocator::setWaterMark(storedWaterMark);
|
||||
|
||||
AssertFatal(pt.x >= ptDraw.x, "How did this happen?");
|
||||
PROFILE_END();
|
||||
return pt.x - ptDraw.x;
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
// Drawing primitives
|
||||
|
||||
void dglDrawLine(S32 x1, S32 y1, S32 x2, S32 y2, const ColorI &color)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glColor4ub(color.red, color.green, color.blue, color.alpha);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f((F32)x1 + 0.5, (F32)y1 + 0.5);
|
||||
glVertex2f((F32)x2 + 0.5, (F32)y2 + 0.5);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void dglDrawLine(const Point2I &startPt, const Point2I &endPt, const ColorI &color)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glColor4ub(color.red, color.green, color.blue, color.alpha);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f((F32)startPt.x + 0.5, (F32)startPt.y + 0.5);
|
||||
glVertex2f((F32)endPt.x + 0.5, (F32)endPt.y + 0.5);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void dglDrawRect(const Point2I &upperL, const Point2I &lowerR, const ColorI &color)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glColor4ub(color.red, color.green, color.blue, color.alpha);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2f((F32)upperL.x + 0.5, (F32)upperL.y + 0.5);
|
||||
glVertex2f((F32)lowerR.x + 0.5, (F32)upperL.y + 0.5);
|
||||
glVertex2f((F32)lowerR.x + 0.5, (F32)lowerR.y + 0.5);
|
||||
glVertex2f((F32)upperL.x + 0.5, (F32)lowerR.y + 0.5);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void dglDrawRect(const RectI &rect, const ColorI &color)
|
||||
{
|
||||
Point2I lowerR(rect.point.x + rect.extent.x - 1, rect.point.y + rect.extent.y - 1);
|
||||
dglDrawRect(rect.point, lowerR, color);
|
||||
}
|
||||
|
||||
void dglDrawRectFill(const Point2I &upperL, const Point2I &lowerR, const ColorI &color)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glColor4ub(color.red, color.green, color.blue, color.alpha);
|
||||
glRecti((F32)upperL.x, (F32)upperL.y, (F32)lowerR.x, (F32)lowerR.y);
|
||||
}
|
||||
void dglDrawRectFill(const RectI &rect, const ColorI &color)
|
||||
{
|
||||
Point2I lowerR(rect.point.x + rect.extent.x - 1, rect.point.y + rect.extent.y - 1);
|
||||
dglDrawRectFill(rect.point, lowerR, color);
|
||||
}
|
||||
|
||||
void dglDraw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle )
|
||||
{
|
||||
width *= 0.5;
|
||||
|
||||
MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) );
|
||||
|
||||
Point3F offset( screenPoint.x, screenPoint.y, 0.0 );
|
||||
Point3F points[4];
|
||||
|
||||
points[0] = Point3F(-width, -width, 0.0);
|
||||
points[1] = Point3F(-width, width, 0.0);
|
||||
points[2] = Point3F( width, width, 0.0);
|
||||
points[3] = Point3F( width, -width, 0.0);
|
||||
|
||||
for( int i=0; i<4; i++ )
|
||||
{
|
||||
rotMatrix.mulP( points[i] );
|
||||
points[i] += offset;
|
||||
}
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex2fv(points[0]);
|
||||
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
glVertex2fv(points[1]);
|
||||
|
||||
glTexCoord2f(1.0, 1.0);
|
||||
glVertex2fv(points[2]);
|
||||
|
||||
glTexCoord2f(1.0, 0.0);
|
||||
glVertex2fv(points[3]);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void dglDrawBillboard( const Point3F &position, F32 width, F32 spinAngle )
|
||||
{
|
||||
MatrixF modelview;
|
||||
dglGetModelview( &modelview );
|
||||
modelview.transpose();
|
||||
|
||||
|
||||
width *= 0.5;
|
||||
Point3F points[4];
|
||||
points[0] = Point3F(-width, 0.0, -width);
|
||||
points[1] = Point3F(-width, 0.0, width);
|
||||
points[2] = Point3F( width, 0.0, width);
|
||||
points[3] = Point3F( width, 0.0, -width);
|
||||
|
||||
|
||||
MatrixF rotMatrix( EulerF( 0.0, spinAngle, 0.0 ) );
|
||||
|
||||
for( int i=0; i<4; i++ )
|
||||
{
|
||||
rotMatrix.mulP( points[i] );
|
||||
modelview.mulP( points[i] );
|
||||
points[i] += position;
|
||||
}
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex3fv(points[0]);
|
||||
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
glVertex3fv(points[1]);
|
||||
|
||||
glTexCoord2f(1.0, 1.0);
|
||||
glVertex3fv(points[2]);
|
||||
|
||||
glTexCoord2f(1.0, 0.0);
|
||||
glVertex3fv(points[3]);
|
||||
glEnd();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dglSetClipRect(const RectI &clipRect)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
U32 screenWidth = Platform::getWindowSize().x;
|
||||
U32 screenHeight = Platform::getWindowSize().y;
|
||||
|
||||
glOrtho(clipRect.point.x, clipRect.point.x + clipRect.extent.x,
|
||||
clipRect.extent.y, 0,
|
||||
0, 1);
|
||||
glTranslatef(0, -clipRect.point.y, 0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glViewport(clipRect.point.x, screenHeight - (clipRect.point.y + clipRect.extent.y),
|
||||
clipRect.extent.x, clipRect.extent.y);
|
||||
|
||||
sgCurrentClipRect = clipRect;
|
||||
}
|
||||
|
||||
const RectI& dglGetClipRect()
|
||||
{
|
||||
return sgCurrentClipRect;
|
||||
}
|
||||
|
||||
bool dglPointToScreen( Point3F &point3D, Point3F &screenPoint )
|
||||
{
|
||||
GLdouble glMV[16];
|
||||
GLdouble glPR[16];
|
||||
GLint glVP[4];
|
||||
|
||||
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, glPR);
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, glMV);
|
||||
|
||||
RectI viewport;
|
||||
dglGetViewport(&viewport);
|
||||
|
||||
glVP[0] = viewport.point.x;
|
||||
glVP[1] = viewport.point.y + viewport.extent.y;
|
||||
glVP[2] = viewport.extent.x;
|
||||
glVP[3] = -viewport.extent.y;
|
||||
|
||||
MatrixF mv;
|
||||
dglGetModelview(&mv);
|
||||
MatrixF pr;
|
||||
dglGetProjection(&pr);
|
||||
|
||||
F64 x, y, z;
|
||||
int result = gluProject( point3D.x, point3D.y, point3D.z, (const F64 *)&glMV, (const F64 *)&glPR, (const S32 *)&glVP, &x, &y, &z );
|
||||
screenPoint.x = x;
|
||||
screenPoint.y = y;
|
||||
screenPoint.z = z;
|
||||
|
||||
|
||||
return (result == GL_TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool dglIsInCanonicalState()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
// Canonical state:
|
||||
// BLEND disabled
|
||||
// TEXTURE_2D disabled on both texture units.
|
||||
// ActiveTexture set to 0
|
||||
// LIGHTING off
|
||||
// winding : clockwise ?
|
||||
// cullface : disabled
|
||||
|
||||
ret &= glIsEnabled(GL_BLEND) == GL_FALSE;
|
||||
ret &= glIsEnabled(GL_CULL_FACE) == GL_FALSE;
|
||||
GLint temp;
|
||||
|
||||
if (dglDoesSupportARBMultitexture() == true) {
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
ret &= glIsEnabled(GL_TEXTURE_2D) == GL_FALSE;
|
||||
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &temp);
|
||||
ret &= temp == GL_REPLACE;
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
ret &= glIsEnabled(GL_TEXTURE_2D) == GL_FALSE;
|
||||
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &temp);
|
||||
ret &= temp == GL_REPLACE;
|
||||
|
||||
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
ret &= glIsEnabled(GL_TEXTURE_COORD_ARRAY) == GL_FALSE;
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
ret &= glIsEnabled(GL_TEXTURE_COORD_ARRAY) == GL_FALSE;
|
||||
} else {
|
||||
ret &= glIsEnabled(GL_TEXTURE_2D) == GL_FALSE;
|
||||
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &temp);
|
||||
ret &= temp == GL_REPLACE;
|
||||
|
||||
ret &= glIsEnabled(GL_TEXTURE_COORD_ARRAY) == GL_FALSE;
|
||||
}
|
||||
|
||||
ret &= glIsEnabled(GL_LIGHTING) == GL_FALSE;
|
||||
|
||||
ret &= glIsEnabled(GL_COLOR_ARRAY) == GL_FALSE;
|
||||
ret &= glIsEnabled(GL_VERTEX_ARRAY) == GL_FALSE;
|
||||
ret &= glIsEnabled(GL_NORMAL_ARRAY) == GL_FALSE;
|
||||
if (dglDoesSupportFogCoord())
|
||||
ret &= glIsEnabled(GL_FOG_COORDINATE_ARRAY_EXT) == GL_FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void dglSetCanonicalState()
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glDisable(GL_LIGHTING);
|
||||
if (dglDoesSupportARBMultitexture() == true) {
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
} else {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (dglDoesSupportFogCoord())
|
||||
glDisableClientState(GL_FOG_COORDINATE_ARRAY_EXT);
|
||||
}
|
||||
|
||||
void dglGetTransformState(S32* mvDepth,
|
||||
S32* pDepth,
|
||||
S32* t0Depth,
|
||||
F32* t0Matrix,
|
||||
S32* t1Depth,
|
||||
F32* t1Matrix,
|
||||
S32* vp)
|
||||
{
|
||||
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, mvDepth);
|
||||
glGetIntegerv(GL_PROJECTION_STACK_DEPTH, pDepth);
|
||||
|
||||
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, t0Depth);
|
||||
glGetFloatv(GL_TEXTURE_MATRIX, t0Matrix);
|
||||
if (dglDoesSupportARBMultitexture())
|
||||
{
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, t1Depth);
|
||||
glGetFloatv(GL_TEXTURE_MATRIX, t1Matrix);
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
}
|
||||
else
|
||||
{
|
||||
*t1Depth = 0;
|
||||
for (U32 i = 0; i < 16; i++)
|
||||
t1Matrix[i] = 0;
|
||||
}
|
||||
|
||||
RectI v;
|
||||
dglGetViewport(&v);
|
||||
vp[0] = v.point.x;
|
||||
vp[1] = v.point.y;
|
||||
vp[2] = v.extent.x;
|
||||
vp[3] = v.extent.y;
|
||||
}
|
||||
|
||||
|
||||
bool dglCheckState(const S32 mvDepth, const S32 pDepth,
|
||||
const S32 t0Depth, const F32* t0Matrix,
|
||||
const S32 t1Depth, const F32* t1Matrix,
|
||||
const S32* vp)
|
||||
{
|
||||
GLint md, pd;
|
||||
RectI v;
|
||||
|
||||
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &md);
|
||||
glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &pd);
|
||||
|
||||
GLint t0d, t1d;
|
||||
GLfloat t0m[16], t1m[16];
|
||||
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &t0d);
|
||||
glGetFloatv(GL_TEXTURE_MATRIX, t0m);
|
||||
if (dglDoesSupportARBMultitexture())
|
||||
{
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &t1d);
|
||||
glGetFloatv(GL_TEXTURE_MATRIX, t1m);
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
}
|
||||
else
|
||||
{
|
||||
t1d = 0;
|
||||
for (U32 i = 0; i < 16; i++)
|
||||
t1m[i] = 0;
|
||||
}
|
||||
|
||||
dglGetViewport(&v);
|
||||
|
||||
return ((md == mvDepth) &&
|
||||
(pd == pDepth) &&
|
||||
(t0d == t0Depth) &&
|
||||
(dMemcmp(t0m, t0Matrix, sizeof(F32) * 16) == 0) &&
|
||||
(t1d == t1Depth) &&
|
||||
(dMemcmp(t1m, t1Matrix, sizeof(F32) * 16) == 0) &&
|
||||
((v.point.x == vp[0]) &&
|
||||
(v.point.y == vp[1]) &&
|
||||
(v.extent.x == vp[2]) &&
|
||||
(v.extent.y == vp[3])));
|
||||
}
|
||||
|
||||
120
dgl/dgl.h
Normal file
120
dgl/dgl.h
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _DGL_H_
|
||||
#define _DGL_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _PLATFORMGL_H_
|
||||
#include "PlatformWin32/platformGL.h"
|
||||
#endif
|
||||
|
||||
class TextureObject;
|
||||
class GFont;
|
||||
class MatrixF;
|
||||
class RectI;
|
||||
class ColorI;
|
||||
class ColorF;
|
||||
class Point2I;
|
||||
class Point2F;
|
||||
class Point3F;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- Bitmap Drawing
|
||||
//
|
||||
static const U32 GFlip_None = 0;
|
||||
static const U32 GFlip_X = 1 << 0;
|
||||
static const U32 GFlip_Y = 1 << 1;
|
||||
static const U32 GFlip_XY = GFlip_X | GFlip_Y;
|
||||
|
||||
void dglSetBitmapModulation(const ColorF& in_rColor);
|
||||
void dglGetBitmapModulation(ColorF* color);
|
||||
void dglGetBitmapModulation(ColorI* color);
|
||||
void dglClearBitmapModulation();
|
||||
|
||||
// Note that you must call this _after_ SetBitmapModulation if the two are different
|
||||
// SetBMod sets the text anchor to the modulation color
|
||||
void dglSetTextAnchorColor(const ColorF&);
|
||||
|
||||
void dglDrawBitmap(TextureObject* texObject,
|
||||
const Point2I& in_rAt,
|
||||
const U32 in_flip = GFlip_None);
|
||||
void dglDrawBitmapStretch(TextureObject* texObject,
|
||||
const RectI& in_rStretch,
|
||||
const U32 in_flip = GFlip_None);
|
||||
void dglDrawBitmapSR(TextureObject* texObject,
|
||||
const Point2I& in_rAt,
|
||||
const RectI& in_rSubRegion,
|
||||
const U32 in_flip = GFlip_None);
|
||||
void dglDrawBitmapStretchSR(TextureObject* texObject,
|
||||
const RectI& in_rStretch,
|
||||
const RectI& in_rSubRegion,
|
||||
const U32 in_flip = GFlip_None);
|
||||
|
||||
// Returns the number of x pixels traversed
|
||||
U32 dglDrawText(GFont *font, const Point2I &ptDraw, const void *in_string, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9);
|
||||
U32 dglDrawTextN(GFont *font, const Point2I &ptDraw, const void *in_string, U32 n, const ColorI *colorTable = NULL, const U32 maxColorIndex = 9);
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
// Drawing primitives
|
||||
|
||||
void dglDrawLine(S32 x1, S32 y1, S32 x2, S32 y2, const ColorI &color);
|
||||
void dglDrawLine(const Point2I &startPt, const Point2I &endPt, const ColorI &color);
|
||||
void dglDrawRect(const Point2I &upperL, const Point2I &lowerR, const ColorI &color);
|
||||
void dglDrawRect(const RectI &rect, const ColorI &color);
|
||||
void dglDrawRectFill(const Point2I &upperL, const Point2I &lowerR, const ColorI &color);
|
||||
void dglDrawRectFill(const RectI &rect, const ColorI &color);
|
||||
void dglDraw2DSquare( const Point2F &screenPoint, F32 width, F32 spinAngle );
|
||||
void dglDrawBillboard( const Point3F &position, F32 width, F32 spinAngle );
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
// Matrix functions
|
||||
|
||||
void dglLoadMatrix(const MatrixF *m);
|
||||
void dglMultMatrix(const MatrixF *m);
|
||||
void dglGetModelview(MatrixF *m);
|
||||
void dglGetProjection(MatrixF *m);
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
// Camera functions
|
||||
|
||||
F32 dglGetPixelScale();
|
||||
F32 dglGetWorldToScreenScale();
|
||||
F32 dglProjectRadius(F32 dist, F32 radius);
|
||||
|
||||
void dglSetViewport(const RectI &aViewPort);
|
||||
void dglGetViewport(RectI* outViewport);
|
||||
void dglSetFrustum(F64 left, F64 right, F64 bottom, F64 top, F64 nearDist, F64 farDist, bool ortho = false);
|
||||
void dglGetFrustum(F64 *left, F64 *right, F64 *bottom, F64 *top, F64 *nearDist, F64 *farDist);
|
||||
bool dglIsOrtho();
|
||||
void dglSetClipRect(const RectI &clipRect);
|
||||
const RectI& dglGetClipRect();
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
// Misc
|
||||
bool dglPointToScreen( Point3F &point3D, Point3F &screenPoint );
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Debug stuff
|
||||
bool dglIsInCanonicalState();
|
||||
void dglSetCanonicalState();
|
||||
|
||||
void dglGetTransformState(S32* mvDepth,
|
||||
S32* pDepth,
|
||||
S32* t0Depth,
|
||||
F32* t0Matrix,
|
||||
S32* t1Depth,
|
||||
F32* t1Matrix,
|
||||
S32* vp);
|
||||
bool dglCheckState(const S32 mvDepth, const S32 pDepth,
|
||||
const S32 t0Depth, const F32* t0Matrix,
|
||||
const S32 t1Depth, const F32* t1Matrix,
|
||||
const S32* vp);
|
||||
|
||||
#endif // _H_DGL
|
||||
146
dgl/dglMatrix.cc
Normal file
146
dgl/dglMatrix.cc
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Math/mMatrix.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/console.h"
|
||||
|
||||
void dglLoadMatrix(const MatrixF *m)
|
||||
{
|
||||
//F32 mat[16];
|
||||
//m->transposeTo(mat);
|
||||
const_cast<MatrixF*>(m)->transpose();
|
||||
glLoadMatrixf(*m);
|
||||
const_cast<MatrixF*>(m)->transpose();
|
||||
}
|
||||
|
||||
void dglMultMatrix(const MatrixF *m)
|
||||
{
|
||||
//F32 mat[16];
|
||||
//m->transposeTo(mat);
|
||||
// const F32* mp = *m;
|
||||
// Con::errorf(ConsoleLogEntry::General, "Mult: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g",
|
||||
// mp[0],
|
||||
// mp[1],
|
||||
// mp[2],
|
||||
// mp[3],
|
||||
// mp[4],
|
||||
// mp[5],
|
||||
// mp[6],
|
||||
// mp[7],
|
||||
// mp[8],
|
||||
// mp[9],
|
||||
// mp[10],
|
||||
// mp[11],
|
||||
// mp[12],
|
||||
// mp[13],
|
||||
// mp[14],
|
||||
// mp[15]);
|
||||
|
||||
|
||||
const_cast<MatrixF*>(m)->transpose();
|
||||
glMultMatrixf(*m);
|
||||
const_cast<MatrixF*>(m)->transpose();
|
||||
}
|
||||
|
||||
void dglGetModelview(MatrixF *m)
|
||||
{
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, *m);
|
||||
m->transpose();
|
||||
}
|
||||
|
||||
void dglGetProjection(MatrixF *m)
|
||||
{
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, *m);
|
||||
m->transpose();
|
||||
}
|
||||
|
||||
static F64 frustLeft = 0, frustRight = 1, frustBottom, frustTop, frustNear, frustFar;
|
||||
static RectI viewPort;
|
||||
static F32 pixelScale;
|
||||
static F32 worldToScreenScale;
|
||||
static bool isOrtho;
|
||||
|
||||
void dglSetFrustum(F64 left, F64 right, F64 bottom, F64 top, F64 nearPlane, F64 farPlane, bool ortho)
|
||||
{
|
||||
// this converts from a coord system looking down the pos-y axis
|
||||
// to ogl's down neg z axis.
|
||||
// it's stored in OGL matrix form
|
||||
static F32 darkToOGLCoord[16] = { 1, 0, 0, 0,
|
||||
0, 0, -1, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 0, 1 };
|
||||
|
||||
frustLeft = left;
|
||||
frustRight = right;
|
||||
frustBottom = bottom;
|
||||
frustTop = top;
|
||||
frustNear = nearPlane;
|
||||
frustFar = farPlane;
|
||||
isOrtho = ortho;
|
||||
if (ortho)
|
||||
{
|
||||
glOrtho(left, right, bottom, top, nearPlane, farPlane);
|
||||
worldToScreenScale = viewPort.extent.x / (frustRight - frustLeft);
|
||||
}
|
||||
else
|
||||
{
|
||||
glFrustum(left, right, bottom, top, nearPlane, farPlane);
|
||||
worldToScreenScale = (frustNear * viewPort.extent.x) / (frustRight - frustLeft);
|
||||
}
|
||||
glMultMatrixf(darkToOGLCoord);
|
||||
}
|
||||
|
||||
void dglGetFrustum(F64 *left, F64 *right, F64 *bottom, F64 *top, F64 *nearPlane, F64 *farPlane)
|
||||
{
|
||||
*left = frustLeft;
|
||||
*right = frustRight;
|
||||
*bottom = frustBottom;
|
||||
*top = frustTop;
|
||||
*nearPlane = frustNear;
|
||||
*farPlane = frustFar;
|
||||
}
|
||||
|
||||
bool dglIsOrtho()
|
||||
{
|
||||
return isOrtho;
|
||||
}
|
||||
|
||||
void dglSetViewport(const RectI &aViewPort)
|
||||
{
|
||||
viewPort = aViewPort;
|
||||
U32 screenHeight = Platform::getWindowSize().y;
|
||||
//glViewport(viewPort.point.x, viewPort.point.y + viewPort.extent.y,
|
||||
// viewPort.extent.x, -viewPort.extent.y);
|
||||
|
||||
glViewport(viewPort.point.x, screenHeight - (viewPort.point.y + viewPort.extent.y),
|
||||
viewPort.extent.x, viewPort.extent.y);
|
||||
pixelScale = viewPort.extent.x / 640.0;
|
||||
worldToScreenScale = (frustNear * viewPort.extent.x) / (frustRight - frustLeft);
|
||||
}
|
||||
|
||||
void dglGetViewport(RectI* outViewport)
|
||||
{
|
||||
AssertFatal(outViewport != NULL, "Error, bad point in GetViewport");
|
||||
*outViewport = viewPort;
|
||||
}
|
||||
|
||||
F32 dglGetPixelScale()
|
||||
{
|
||||
return pixelScale;
|
||||
}
|
||||
|
||||
F32 dglGetWorldToScreenScale()
|
||||
{
|
||||
return worldToScreenScale;
|
||||
}
|
||||
|
||||
F32 dglProjectRadius(F32 dist, F32 radius)
|
||||
{
|
||||
return (radius / dist) * worldToScreenScale;
|
||||
}
|
||||
|
||||
771
dgl/gBitmap.cc
Normal file
771
dgl/gBitmap.cc
Normal file
|
|
@ -0,0 +1,771 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Core/stream.h"
|
||||
#include "Core/fileStream.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "dgl/gPalette.h"
|
||||
#include "Core/resManager.h"
|
||||
#include "Platform/platform.h"
|
||||
|
||||
#include "console/console.h"
|
||||
|
||||
const U32 GBitmap::csFileVersion = 3;
|
||||
U32 GBitmap::sBitmapIdSource = 0;
|
||||
|
||||
|
||||
GBitmap::GBitmap()
|
||||
: internalFormat(RGB),
|
||||
pBits(NULL),
|
||||
byteSize(0),
|
||||
width(0),
|
||||
height(0),
|
||||
numMipLevels(0),
|
||||
bytesPerPixel(0),
|
||||
pPalette(NULL)
|
||||
{
|
||||
for (U32 i = 0; i < c_maxMipLevels; i++)
|
||||
mipLevelOffsets[i] = 0xffffffff;
|
||||
}
|
||||
|
||||
GBitmap::GBitmap(const GBitmap& rCopy)
|
||||
{
|
||||
AssertFatal(rCopy.pPalette == NULL, "Cant copy bitmaps with palettes");
|
||||
|
||||
internalFormat = rCopy.internalFormat;
|
||||
|
||||
byteSize = rCopy.byteSize;
|
||||
pBits = new U8[byteSize];
|
||||
dMemcpy(pBits, rCopy.pBits, byteSize);
|
||||
|
||||
width = rCopy.width;
|
||||
height = rCopy.height;
|
||||
bytesPerPixel = rCopy.bytesPerPixel;
|
||||
numMipLevels = rCopy.numMipLevels;
|
||||
dMemcpy(mipLevelOffsets, rCopy.mipLevelOffsets, sizeof(mipLevelOffsets));
|
||||
|
||||
pPalette = NULL;
|
||||
}
|
||||
|
||||
|
||||
GBitmap::GBitmap(const U32 in_width,
|
||||
const U32 in_height,
|
||||
const bool in_extrudeMipLevels,
|
||||
const BitmapFormat in_format)
|
||||
: pBits(NULL),
|
||||
byteSize(0),
|
||||
pPalette(NULL)
|
||||
{
|
||||
for (U32 i = 0; i < c_maxMipLevels; i++)
|
||||
mipLevelOffsets[i] = 0xffffffff;
|
||||
|
||||
allocateBitmap(in_width, in_height, in_extrudeMipLevels, in_format);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GBitmap::~GBitmap()
|
||||
{
|
||||
deleteImage();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GBitmap::deleteImage()
|
||||
{
|
||||
delete [] pBits;
|
||||
pBits = NULL;
|
||||
byteSize = 0;
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
numMipLevels = 0;
|
||||
|
||||
delete pPalette;
|
||||
pPalette = NULL;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GBitmap::setPalette(GPalette* in_pPalette)
|
||||
{
|
||||
delete pPalette;
|
||||
|
||||
pPalette = in_pPalette;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GBitmap::allocateBitmap(const U32 in_width, const U32 in_height, const bool in_extrudeMipLevels, const BitmapFormat in_format)
|
||||
{
|
||||
//-------------------------------------- Some debug checks...
|
||||
U32 svByteSize = byteSize;
|
||||
U8 *svBits = pBits;
|
||||
|
||||
AssertFatal(in_width != 0 && in_height != 0, "GBitmap::allocateBitmap: width or height is 0");
|
||||
|
||||
if (in_extrudeMipLevels == true) {
|
||||
//AssertFatal(in_width <= 256 && in_height <= 256, "GBitmap::allocateBitmap: width or height is too large");
|
||||
AssertFatal(isPow2(in_width) == true && isPow2(in_height) == true, "GBitmap::GBitmap: in order to extrude miplevels, bitmap w/h must be pow2");
|
||||
}
|
||||
|
||||
internalFormat = in_format;
|
||||
width = in_width;
|
||||
height = in_height;
|
||||
|
||||
bytesPerPixel = 1;
|
||||
switch (internalFormat) {
|
||||
case Alpha:
|
||||
case Palettized:
|
||||
case Luminance:
|
||||
case Intensity: bytesPerPixel = 1;
|
||||
break;
|
||||
case RGB: bytesPerPixel = 3;
|
||||
break;
|
||||
case RGBA: bytesPerPixel = 4;
|
||||
break;
|
||||
case RGB565:
|
||||
case RGB5551: bytesPerPixel = 2;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "GBitmap::GBitmap: misunderstood format specifier");
|
||||
break;
|
||||
}
|
||||
|
||||
// Set up the mip levels, if necessary...
|
||||
numMipLevels = 1;
|
||||
U32 allocPixels = in_width * in_height * bytesPerPixel;
|
||||
mipLevelOffsets[0] = 0;
|
||||
|
||||
|
||||
if (in_extrudeMipLevels == true) {
|
||||
U32 currWidth = in_width;
|
||||
U32 currHeight = in_height;
|
||||
|
||||
do {
|
||||
mipLevelOffsets[numMipLevels] = mipLevelOffsets[numMipLevels - 1] +
|
||||
(currWidth * currHeight * bytesPerPixel);
|
||||
currWidth >>= 1;
|
||||
currHeight >>= 1;
|
||||
if (currWidth == 0) currWidth = 1;
|
||||
if (currHeight == 0) currHeight = 1;
|
||||
|
||||
numMipLevels++;
|
||||
allocPixels += currWidth * currHeight * bytesPerPixel;
|
||||
} while (currWidth != 1 || currHeight != 1);
|
||||
}
|
||||
AssertFatal(numMipLevels <= c_maxMipLevels, "GBitmap::allocateBitmap: too many miplevels");
|
||||
|
||||
// Set up the memory...
|
||||
byteSize = allocPixels;
|
||||
pBits = new U8[byteSize];
|
||||
dMemset(pBits, 0xFF, byteSize);
|
||||
|
||||
if(svBits != NULL)
|
||||
{
|
||||
dMemcpy(pBits, svBits, getMin(byteSize, svByteSize));
|
||||
delete[] svBits;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void bitmapExtrude5551_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
|
||||
{
|
||||
const U16 *src = (const U16 *) srcMip;
|
||||
U16 *dst = (U16 *) mip;
|
||||
U32 stride = srcHeight != 1 ? srcWidth : 0;
|
||||
|
||||
U32 width = srcWidth >> 1;
|
||||
U32 height = srcHeight >> 1;
|
||||
if (width == 0) width = 1;
|
||||
if (height == 0) height = 1;
|
||||
|
||||
if (srcWidth != 1) {
|
||||
for(U32 y = 0; y < height; y++)
|
||||
{
|
||||
for(U32 x = 0; x < width; x++)
|
||||
{
|
||||
U32 a = src[0];
|
||||
U32 b = src[1];
|
||||
U32 c = src[stride];
|
||||
U32 d = src[stride+1];
|
||||
dst[x] = ((( (a >> 11) + (b >> 11) + (c >> 11) + (d >> 11)) >> 2) << 11) |
|
||||
((( ((a >> 6) & 0x1f) + ((b >> 6) & 0x1f) + ((c >> 6) & 0x1f) + ((d >> 6) & 0x1F)) >> 2) << 6) |
|
||||
((( ((a >> 1) & 0x1F) + ((b >> 1) & 0x1F) + ((c >> 1) & 0x1f) + ((d >> 1) & 0x1f)) >> 2) << 1);
|
||||
src += 2;
|
||||
}
|
||||
src += stride;
|
||||
dst += width;
|
||||
}
|
||||
} else {
|
||||
for(U32 y = 0; y < height; y++)
|
||||
{
|
||||
U32 a = src[0];
|
||||
U32 c = src[stride];
|
||||
dst[y] = ((( (a >> 11) + (c >> 11)) >> 1) << 11) |
|
||||
((( ((a >> 6) & 0x1f) + ((c >> 6) & 0x1f)) >> 1) << 6) |
|
||||
((( ((a >> 1) & 0x1F) + ((c >> 1) & 0x1f)) >> 1) << 1);
|
||||
src += 1 + stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void bitmapExtrudeRGB_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
|
||||
{
|
||||
const U8 *src = (const U8 *) srcMip;
|
||||
U8 *dst = (U8 *) mip;
|
||||
U32 stride = srcHeight != 1 ? (srcWidth) * 3 : 0;
|
||||
|
||||
U32 width = srcWidth >> 1;
|
||||
U32 height = srcHeight >> 1;
|
||||
if (width == 0) width = 1;
|
||||
if (height == 0) height = 1;
|
||||
|
||||
if (srcWidth != 1) {
|
||||
for(U32 y = 0; y < height; y++)
|
||||
{
|
||||
for(U32 x = 0; x < width; x++)
|
||||
{
|
||||
*dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3])) >> 2;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3])) >> 2;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3])) >> 2;
|
||||
src += 4;
|
||||
}
|
||||
src += stride; // skip
|
||||
}
|
||||
} else {
|
||||
for(U32 y = 0; y < height; y++)
|
||||
{
|
||||
*dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
src += 4;
|
||||
|
||||
src += stride; // skip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void bitmapExtrudePaletted_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
|
||||
{
|
||||
const U8 *src = (const U8 *) srcMip;
|
||||
U8 *dst = (U8 *) mip;
|
||||
U32 stride = srcHeight != 1 ? (srcWidth) * 3 : 0;
|
||||
|
||||
U32 width = srcWidth >> 1;
|
||||
U32 height = srcHeight >> 1;
|
||||
if (width == 0) width = 1;
|
||||
if (height == 0) height = 1;
|
||||
|
||||
dMemset(mip, 0, width * height);
|
||||
|
||||
// if (srcWidth != 1) {
|
||||
// for(U32 y = 0; y < height; y++)
|
||||
// {
|
||||
// for(U32 x = 0; x < width; x++)
|
||||
// {
|
||||
// *dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3])) >> 2;
|
||||
// src++;
|
||||
// *dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3])) >> 2;
|
||||
// src++;
|
||||
// *dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3])) >> 2;
|
||||
// src += 4;
|
||||
// }
|
||||
// src += stride; // skip
|
||||
// }
|
||||
// } else {
|
||||
// for(U32 y = 0; y < height; y++)
|
||||
// {
|
||||
// *dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
// src++;
|
||||
// *dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
// src++;
|
||||
// *dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
// src += 4;
|
||||
|
||||
// src += stride; // skip
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void bitmapExtrudeRGBA_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
|
||||
{
|
||||
const U8 *src = (const U8 *) srcMip;
|
||||
U8 *dst = (U8 *) mip;
|
||||
U32 stride = srcHeight != 1 ? (srcWidth) * 4 : 0;
|
||||
|
||||
U32 width = srcWidth >> 1;
|
||||
U32 height = srcHeight >> 1;
|
||||
if (width == 0) width = 1;
|
||||
if (height == 0) height = 1;
|
||||
|
||||
if (srcWidth != 1) {
|
||||
for(U32 y = 0; y < height; y++)
|
||||
{
|
||||
for(U32 x = 0; x < width; x++)
|
||||
{
|
||||
*dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4])) >> 2;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4])) >> 2;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4])) >> 2;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4])) >> 2;
|
||||
src += 5;
|
||||
}
|
||||
src += stride; // skip
|
||||
}
|
||||
} else {
|
||||
for(U32 y = 0; y < height; y++)
|
||||
{
|
||||
*dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
src++;
|
||||
*dst++ = (U32(*src) + U32(src[stride])) >> 1;
|
||||
src += 5;
|
||||
|
||||
src += stride; // skip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void (*bitmapExtrude5551)(const void *srcMip, void *mip, U32 height, U32 width) = bitmapExtrude5551_c;
|
||||
void (*bitmapExtrudeRGB)(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth) = bitmapExtrudeRGB_c;
|
||||
void (*bitmapExtrudeRGBA)(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth) = bitmapExtrudeRGBA_c;
|
||||
void (*bitmapExtrudePaletted)(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth) = bitmapExtrudePaletted_c;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GBitmap::extrudeMipLevels(bool clearBorders)
|
||||
{
|
||||
if(numMipLevels == 1)
|
||||
allocateBitmap(getWidth(), getHeight(), true, getFormat());
|
||||
|
||||
// AssertFatal(getFormat() != Palettized, "Cannot calc miplevels for palettized bitmaps yet");
|
||||
|
||||
switch (getFormat())
|
||||
{
|
||||
case RGB5551:
|
||||
{
|
||||
for(U32 i = 1; i < numMipLevels; i++)
|
||||
bitmapExtrude5551(getBits(i - 1), getWritableBits(i), getHeight(i), getWidth(i));
|
||||
break;
|
||||
}
|
||||
|
||||
case RGB:
|
||||
{
|
||||
for(U32 i = 1; i < numMipLevels; i++)
|
||||
bitmapExtrudeRGB(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
|
||||
break;
|
||||
}
|
||||
|
||||
case RGBA:
|
||||
{
|
||||
for(U32 i = 1; i < numMipLevels; i++)
|
||||
bitmapExtrudeRGBA(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
|
||||
break;
|
||||
}
|
||||
|
||||
case Palettized:
|
||||
{
|
||||
for(U32 i = 1; i < numMipLevels; i++)
|
||||
bitmapExtrudePaletted(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (clearBorders)
|
||||
{
|
||||
for (U32 i = 1; i<numMipLevels; i++)
|
||||
{
|
||||
U32 width = getWidth(i);
|
||||
U32 height = getHeight(i);
|
||||
if (height<3 || width<3)
|
||||
// bmp is all borders at this mip level
|
||||
dMemset(getWritableBits(i),0,width*height*bytesPerPixel);
|
||||
else
|
||||
{
|
||||
width *= bytesPerPixel;
|
||||
U8 * bytes = getWritableBits(i);
|
||||
U8 * end = bytes + (height-1)*width - bytesPerPixel; // end = last row, 2nd column
|
||||
// clear first row sans the last pixel
|
||||
dMemset(bytes,0,width-bytesPerPixel);
|
||||
bytes -= bytesPerPixel;
|
||||
while (bytes<end)
|
||||
{
|
||||
// clear last pixel of row N-1 and first pixel of row N
|
||||
bytes += width;
|
||||
dMemset(bytes,0,bytesPerPixel*2);
|
||||
}
|
||||
// clear last row sans the first pixel
|
||||
dMemset(bytes+2*bytesPerPixel,0,width-bytesPerPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GBitmap::extrudeMipLevelsDetail()
|
||||
{
|
||||
AssertFatal(getFormat() == GBitmap::RGB, "Error, only handles RGB for now...");
|
||||
U32 i,j;
|
||||
|
||||
if(numMipLevels == 1)
|
||||
allocateBitmap(getWidth(), getHeight(), true, getFormat());
|
||||
|
||||
for (i = 1; i < numMipLevels; i++) {
|
||||
bitmapExtrudeRGB(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
|
||||
}
|
||||
|
||||
// Ok, now that we have the levels extruded, we need to move the lower miplevels
|
||||
// closer to 0.5.
|
||||
for (i = 1; i < numMipLevels - 1; i++) {
|
||||
U8* pMipBits = (U8*)getWritableBits(i);
|
||||
U32 numBytes = getWidth(i) * getHeight(i) * 3;
|
||||
|
||||
U32 shift = i;
|
||||
U32 start = ((1 << i) - 1) * 0x80;
|
||||
|
||||
for (j = 0; j < numBytes; j++) {
|
||||
U32 newVal = (start + pMipBits[j]) >> shift;
|
||||
AssertFatal(newVal <= 255, "Error, oob");
|
||||
pMipBits[j] = U8(newVal);
|
||||
}
|
||||
}
|
||||
AssertFatal(getWidth(numMipLevels - 1) == 1 && getHeight(numMipLevels - 1) == 1,
|
||||
"Error, last miplevel should be 1x1!");
|
||||
((U8*)getWritableBits(numMipLevels - 1))[0] = 0x80;
|
||||
((U8*)getWritableBits(numMipLevels - 1))[1] = 0x80;
|
||||
((U8*)getWritableBits(numMipLevels - 1))[2] = 0x80;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void bitmapConvertRGB_to_5551_c(U8 *src, U32 pixels)
|
||||
{
|
||||
U16 *dst = (U16 *)src;
|
||||
for(U32 j = 0; j < pixels; j++)
|
||||
{
|
||||
U32 r = src[0] >> 3;
|
||||
U32 g = src[1] >> 3;
|
||||
U32 b = src[2] >> 3;
|
||||
|
||||
*dst++ = (b << 1) | (g << 6) | (r << 11) | 1;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void (*bitmapConvertRGB_to_5551)(U8 *src, U32 pixels) = bitmapConvertRGB_to_5551_c;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GBitmap::setFormat(BitmapFormat fmt)
|
||||
{
|
||||
if (getFormat() == fmt)
|
||||
return true;
|
||||
|
||||
// this is a nasty pointer math hack
|
||||
// is there a quick way to calc pixels of a fully mipped bitmap?
|
||||
U32 pixels = 0;
|
||||
for (U32 i=0; i < numMipLevels; i++)
|
||||
pixels += getHeight(i) * getWidth(i);
|
||||
|
||||
switch (getFormat())
|
||||
{
|
||||
case RGB:
|
||||
switch (fmt)
|
||||
{
|
||||
case RGB5551:
|
||||
bitmapConvertRGB_to_5551(pBits, pixels);
|
||||
internalFormat = RGB5551;
|
||||
bytesPerPixel = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertWarn(0, "GBitmap::setFormat: unable to convert bitmap to requested format.");
|
||||
return false;
|
||||
}
|
||||
|
||||
U32 offset = 0;
|
||||
for (U32 j=0; j < numMipLevels; j++)
|
||||
{
|
||||
mipLevelOffsets[j] = offset;
|
||||
offset += getHeight(j) * getWidth(j) * bytesPerPixel;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GBitmap::getColor(const U32 x, const U32 y, ColorI& rColor) const
|
||||
{
|
||||
if (x >= width || y >= height)
|
||||
return false;
|
||||
if (internalFormat == Palettized && pPalette == NULL)
|
||||
return false;
|
||||
|
||||
const U8* pLoc = getAddress(x, y);
|
||||
|
||||
switch (internalFormat) {
|
||||
case Palettized:
|
||||
rColor = pPalette->getColor(*pLoc);
|
||||
break;
|
||||
|
||||
case Alpha:
|
||||
case Intensity:
|
||||
case Luminance:
|
||||
rColor.red = *pLoc;
|
||||
rColor.green = *pLoc;
|
||||
rColor.blue = *pLoc;
|
||||
rColor.alpha = *pLoc;
|
||||
break;
|
||||
|
||||
case RGB:
|
||||
rColor.red = pLoc[0];
|
||||
rColor.green = pLoc[1];
|
||||
rColor.blue = pLoc[2];
|
||||
rColor.alpha = 255;
|
||||
break;
|
||||
|
||||
case RGBA:
|
||||
rColor.red = pLoc[0];
|
||||
rColor.green = pLoc[1];
|
||||
rColor.blue = pLoc[2];
|
||||
rColor.alpha = pLoc[3];
|
||||
break;
|
||||
|
||||
case RGB5551:
|
||||
rColor.red = *((U16*)pLoc) >> 11;
|
||||
rColor.green = (*((U16*)pLoc) >> 6) & 0x1f;
|
||||
rColor.blue = (*((U16*)pLoc) >> 1) & 0x1f;
|
||||
rColor.alpha = (*((U16*)pLoc) & 1) ? 255 : 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(false, "Bad internal format");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GBitmap::setColor(const U32 x, const U32 y, ColorI& rColor)
|
||||
{
|
||||
if (x >= width || y >= height)
|
||||
return false;
|
||||
if (internalFormat == Palettized && pPalette == NULL)
|
||||
return false;
|
||||
|
||||
U8* pLoc = getAddress(x, y);
|
||||
|
||||
switch (internalFormat) {
|
||||
case Palettized:
|
||||
rColor = pPalette->getColor(*pLoc);
|
||||
break;
|
||||
|
||||
case Alpha:
|
||||
case Intensity:
|
||||
case Luminance:
|
||||
*pLoc = rColor.alpha;
|
||||
break;
|
||||
|
||||
case RGB:
|
||||
pLoc[0] = rColor.red;
|
||||
pLoc[1] = rColor.green;
|
||||
pLoc[2] = rColor.blue;
|
||||
break;
|
||||
|
||||
case RGBA:
|
||||
pLoc[0] = rColor.red;
|
||||
pLoc[1] = rColor.green;
|
||||
pLoc[2] = rColor.blue;
|
||||
pLoc[3] = rColor.alpha;
|
||||
break;
|
||||
|
||||
case RGB5551:
|
||||
*((U16*)pLoc) = (rColor.blue << 1) | (rColor.green << 6) | (rColor.red << 11) | ((rColor.alpha>0) ? 1 : 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(false, "Bad internal format");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- Persistent I/O
|
||||
//
|
||||
bool GBitmap::read(Stream& io_rStream)
|
||||
{
|
||||
// Handle versioning
|
||||
U32 version;
|
||||
io_rStream.read(&version);
|
||||
AssertFatal(version == csFileVersion, "Bitmap::read: incorrect file version");
|
||||
|
||||
//-------------------------------------- Read the object
|
||||
U32 fmt;
|
||||
io_rStream.read(&fmt);
|
||||
internalFormat = BitmapFormat(fmt);
|
||||
bytesPerPixel = 1;
|
||||
switch (internalFormat) {
|
||||
case Alpha:
|
||||
case Palettized:
|
||||
case Luminance:
|
||||
case Intensity: bytesPerPixel = 1;
|
||||
break;
|
||||
case RGB: bytesPerPixel = 3;
|
||||
break;
|
||||
case RGBA: bytesPerPixel = 4;
|
||||
break;
|
||||
case RGB565:
|
||||
case RGB5551: bytesPerPixel = 2;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "GBitmap::GBitmap: misunderstood format specifier");
|
||||
break;
|
||||
}
|
||||
|
||||
io_rStream.read(&byteSize);
|
||||
|
||||
pBits = new U8[byteSize];
|
||||
io_rStream.read(byteSize, pBits);
|
||||
|
||||
io_rStream.read(&width);
|
||||
io_rStream.read(&height);
|
||||
|
||||
io_rStream.read(&numMipLevels);
|
||||
for (U32 i = 0; i < c_maxMipLevels; i++)
|
||||
io_rStream.read(&mipLevelOffsets[i]);
|
||||
|
||||
if (internalFormat == Palettized) {
|
||||
pPalette = new GPalette;
|
||||
pPalette->read(io_rStream);
|
||||
}
|
||||
|
||||
return (io_rStream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool GBitmap::write(Stream& io_rStream) const
|
||||
{
|
||||
// Handle versioning
|
||||
io_rStream.write(csFileVersion);
|
||||
|
||||
//-------------------------------------- Write the object
|
||||
io_rStream.write(U32(internalFormat));
|
||||
|
||||
io_rStream.write(byteSize);
|
||||
io_rStream.write(byteSize, pBits);
|
||||
|
||||
io_rStream.write(width);
|
||||
io_rStream.write(height);
|
||||
|
||||
io_rStream.write(numMipLevels);
|
||||
for (U32 i = 0; i < c_maxMipLevels; i++)
|
||||
io_rStream.write(mipLevelOffsets[i]);
|
||||
|
||||
if (internalFormat == Palettized) {
|
||||
AssertFatal(pPalette != NULL,
|
||||
"GBitmap::write: cannot write a palettized bitmap wo/ a palette");
|
||||
pPalette->write(io_rStream);
|
||||
}
|
||||
|
||||
return (io_rStream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------- GFXBitmap
|
||||
ResourceInstance* constructBitmapJPEG(Stream &stream)
|
||||
{
|
||||
GBitmap* bmp = new GBitmap;
|
||||
if (bmp->readJPEG(stream))
|
||||
return bmp;
|
||||
else
|
||||
{
|
||||
delete bmp;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ResourceInstance* constructBitmapPNG(Stream &stream)
|
||||
{
|
||||
GBitmap* bmp = new GBitmap;
|
||||
if (bmp->readPNG(stream))
|
||||
return bmp;
|
||||
else
|
||||
{
|
||||
delete bmp;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ResourceInstance* constructBitmapBM8(Stream &stream)
|
||||
{
|
||||
GBitmap* bmp = new GBitmap;
|
||||
if (bmp->readBmp8(stream))
|
||||
return bmp;
|
||||
else
|
||||
{
|
||||
delete bmp;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ResourceInstance* constructBitmapBMP(Stream &stream)
|
||||
{
|
||||
GBitmap *bmp = new GBitmap;
|
||||
if(bmp->readMSBmp(stream))
|
||||
return bmp;
|
||||
else
|
||||
{
|
||||
delete bmp;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ResourceInstance* constructBitmapGIF(Stream &stream)
|
||||
{
|
||||
GBitmap *bmp = new GBitmap;
|
||||
if(bmp->readGIF(stream))
|
||||
return bmp;
|
||||
else
|
||||
{
|
||||
delete bmp;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
ResourceInstance* constructBitmapDBM(Stream &stream)
|
||||
{
|
||||
GBitmap* bmp = new GBitmap;
|
||||
if (bmp->read(stream))
|
||||
return bmp;
|
||||
else
|
||||
{
|
||||
delete bmp;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
221
dgl/gBitmap.h
Normal file
221
dgl/gBitmap.h
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GBITMAP_H_
|
||||
#define _GBITMAP_H_
|
||||
|
||||
//Includes
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _RESMANAGER_H_
|
||||
#include "Core/resManager.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------- Forward decls.
|
||||
class Stream;
|
||||
class GPalette;
|
||||
|
||||
extern ResourceInstance* constructBitmapBM8(Stream& stream);
|
||||
extern ResourceInstance* constructBitmapBMP(Stream& stream);
|
||||
extern ResourceInstance* constructBitmapPNG(Stream& stream);
|
||||
extern ResourceInstance* constructBitmapJPEG(Stream& stream);
|
||||
extern ResourceInstance* constructBitmapGIF(Stream& stream);
|
||||
extern ResourceInstance* constructBitmapDBM(Stream& stream);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- GBitmap
|
||||
//
|
||||
class GBitmap: public ResourceInstance
|
||||
{
|
||||
//-------------------------------------- public enumerants and structures
|
||||
public:
|
||||
enum BitmapFormat { // BitmapFormat and UsageHint are
|
||||
Palettized = 0, // written to the stream in write(...),
|
||||
Intensity = 1, // be sure to maintain compatability
|
||||
RGB = 2, // if they are changed...
|
||||
RGBA = 3,
|
||||
Alpha = 4,
|
||||
RGB565 = 5,
|
||||
RGB5551 = 6,
|
||||
Luminance = 7
|
||||
};
|
||||
|
||||
enum Constants {
|
||||
c_maxMipLevels = 10
|
||||
};
|
||||
|
||||
public:
|
||||
GBitmap();
|
||||
GBitmap(const GBitmap&);
|
||||
GBitmap(const U32 in_width,
|
||||
const U32 in_height,
|
||||
const bool in_extrudeMipLevels = false,
|
||||
const BitmapFormat in_format = RGB);
|
||||
virtual ~GBitmap();
|
||||
|
||||
void allocateBitmap(const U32 in_width,
|
||||
const U32 in_height,
|
||||
const bool in_extrudeMipLevels = false,
|
||||
const BitmapFormat in_format = RGB);
|
||||
|
||||
void extrudeMipLevels(bool clearBorders = false);
|
||||
void extrudeMipLevelsDetail();
|
||||
|
||||
BitmapFormat getFormat() const;
|
||||
bool setFormat(BitmapFormat fmt);
|
||||
U32 getNumMipLevels() const;
|
||||
U32 getWidth(const U32 in_mipLevel = 0) const;
|
||||
U32 getHeight(const U32 in_mipLevel = 0) const;
|
||||
|
||||
U8* getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel = U32(0));
|
||||
const U8* getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel = U32(0)) const;
|
||||
|
||||
const U8* getBits(const U32 in_mipLevel = 0) const;
|
||||
U8* getWritableBits(const U32 in_mipLevel = 0);
|
||||
|
||||
bool getColor(const U32 x, const U32 y, ColorI& rColor) const;
|
||||
bool setColor(const U32 x, const U32 y, ColorI& rColor);
|
||||
|
||||
// Note that on set palette, the bitmap delete's its palette.
|
||||
GPalette const* getPalette() const;
|
||||
void setPalette(GPalette* in_pPalette);
|
||||
|
||||
//-------------------------------------- Internal data/operators
|
||||
static U32 sBitmapIdSource;
|
||||
|
||||
void deleteImage();
|
||||
|
||||
BitmapFormat internalFormat;
|
||||
public:
|
||||
|
||||
U8* pBits; // Master bytes
|
||||
U32 byteSize;
|
||||
U32 width; // Top level w/h
|
||||
U32 height;
|
||||
U32 bytesPerPixel;
|
||||
|
||||
U32 numMipLevels;
|
||||
U32 mipLevelOffsets[c_maxMipLevels];
|
||||
|
||||
GPalette* pPalette; // Note that this palette pointer is ALWAYS
|
||||
// owned by the bitmap, and will be
|
||||
// deleted on exit, or written out on a
|
||||
// write.
|
||||
|
||||
//-------------------------------------- Input/Output interface
|
||||
public:
|
||||
bool readJPEG(Stream& io_rStream); // located in bitmapJpeg.cc
|
||||
bool writeJPEG(Stream& io_rStream) const;
|
||||
|
||||
bool readPNG(Stream& io_rStream); // located in bitmapPng.cc
|
||||
bool writePNG(Stream& io_rStream, const bool compressHard = false) const;
|
||||
bool writePNGUncompressed(Stream& io_rStream) const;
|
||||
|
||||
bool readBmp8(Stream& io_rStream); // located in bitmapMS.cc
|
||||
bool writeBmp8(Stream& io_rStream); // located in bitmapMS.cc
|
||||
|
||||
bool readMSBmp(Stream& io_rStream); // located in bitmapMS.cc
|
||||
bool writeMSBmp(Stream& io_rStream) const; // located in bitmapMS.cc
|
||||
|
||||
bool readGIF(Stream& io_rStream); // located in bitmapGIF.cc
|
||||
bool writeGIF(Stream& io_rStream) const; // located in bitmapGIF.cc
|
||||
|
||||
bool read(Stream& io_rStream);
|
||||
bool write(Stream& io_rStream) const;
|
||||
|
||||
private:
|
||||
bool _writePNG(Stream& stream, const U32, const U32, const U32) const;
|
||||
|
||||
static const U32 csFileVersion;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- Inlines
|
||||
//
|
||||
|
||||
inline GBitmap::BitmapFormat GBitmap::getFormat() const
|
||||
{
|
||||
return internalFormat;
|
||||
}
|
||||
|
||||
inline U32 GBitmap::getNumMipLevels() const
|
||||
{
|
||||
return numMipLevels;
|
||||
}
|
||||
|
||||
inline U32 GBitmap::getWidth(const U32 in_mipLevel) const
|
||||
{
|
||||
AssertFatal(in_mipLevel < numMipLevels,
|
||||
avar("GBitmap::getWidth: mip level out of range: (%d, %d)",
|
||||
in_mipLevel, numMipLevels));
|
||||
|
||||
U32 retVal = width >> in_mipLevel;
|
||||
|
||||
return (retVal != 0) ? retVal : 1;
|
||||
}
|
||||
|
||||
inline U32 GBitmap::getHeight(const U32 in_mipLevel) const
|
||||
{
|
||||
AssertFatal(in_mipLevel < numMipLevels,
|
||||
avar("Bitmap::getHeight: mip level out of range: (%d, %d)",
|
||||
in_mipLevel, numMipLevels));
|
||||
|
||||
U32 retVal = height >> in_mipLevel;
|
||||
|
||||
return (retVal != 0) ? retVal : 1;
|
||||
}
|
||||
|
||||
inline const GPalette* GBitmap::getPalette() const
|
||||
{
|
||||
AssertFatal(getFormat() == Palettized,
|
||||
"Error, incorrect internal format to return a palette");
|
||||
|
||||
return pPalette;
|
||||
}
|
||||
|
||||
inline const U8* GBitmap::getBits(const U32 in_mipLevel) const
|
||||
{
|
||||
AssertFatal(in_mipLevel < numMipLevels,
|
||||
avar("GBitmap::getBits: mip level out of range: (%d, %d)",
|
||||
in_mipLevel, numMipLevels));
|
||||
|
||||
return &pBits[mipLevelOffsets[in_mipLevel]];
|
||||
}
|
||||
|
||||
inline U8* GBitmap::getWritableBits(const U32 in_mipLevel)
|
||||
{
|
||||
AssertFatal(in_mipLevel < numMipLevels,
|
||||
avar("GBitmap::getWritableBits: mip level out of range: (%d, %d)",
|
||||
in_mipLevel, numMipLevels));
|
||||
|
||||
return &pBits[mipLevelOffsets[in_mipLevel]];
|
||||
}
|
||||
|
||||
inline U8* GBitmap::getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel)
|
||||
{
|
||||
return (getWritableBits(mipLevel) + ((in_y * getWidth(mipLevel)) + in_x) * bytesPerPixel);
|
||||
}
|
||||
|
||||
inline const U8* GBitmap::getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel) const
|
||||
{
|
||||
return (getBits(mipLevel) + ((in_y * getWidth(mipLevel)) + in_x) * bytesPerPixel);
|
||||
}
|
||||
|
||||
|
||||
extern void (*bitmapExtrude5551)(const void *srcMip, void *mip, U32 height, U32 width);
|
||||
extern void (*bitmapExtrudeRGB)(const void *srcMip, void *mip, U32 height, U32 width);
|
||||
extern void (*bitmapConvertRGB_to_5551)(U8 *src, U32 pixels);
|
||||
extern void (*bitmapExtrudePaletted)(const void *srcMip, void *mip, U32 height, U32 width);
|
||||
|
||||
void bitmapExtrudeRGB_c(const void *srcMip, void *mip, U32 height, U32 width);
|
||||
|
||||
#endif //_GBITMAP_H_
|
||||
76
dgl/gChunkedTexManager.h
Normal file
76
dgl/gChunkedTexManager.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GCHUNKEDTEXMANAGER_H_
|
||||
#define _GCHUNKEDTEXMANAGER_H_
|
||||
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
|
||||
class ChunkedTextureObject
|
||||
{
|
||||
public:
|
||||
ChunkedTextureObject *next;
|
||||
StringTableEntry texFileName;
|
||||
U32 texWidthCount;
|
||||
U32 texHeightCount;
|
||||
U32 width;
|
||||
U32 height;
|
||||
TextureHandle *textureHandles;
|
||||
S32 refCount;
|
||||
GBitmap *bitmap;
|
||||
};
|
||||
|
||||
class ChunkedTextureManager
|
||||
{
|
||||
friend class ChunkedTextureHandle;
|
||||
static ChunkedTextureObject* loadTexture(const char *textureName);
|
||||
static ChunkedTextureObject* registerTexture(const char *textureName, GBitmap *data, bool keep);
|
||||
static void freeTexture(ChunkedTextureObject *to);
|
||||
static void refresh(ChunkedTextureObject *to);
|
||||
public:
|
||||
static void makeZombie();
|
||||
static void resurrect();
|
||||
};
|
||||
|
||||
class ChunkedTextureHandle
|
||||
{
|
||||
ChunkedTextureObject *object;
|
||||
void lock();
|
||||
void unlock();
|
||||
public:
|
||||
ChunkedTextureHandle() { object = NULL; }
|
||||
ChunkedTextureHandle(const ChunkedTextureHandle &th) {
|
||||
object = th.object;
|
||||
lock();
|
||||
}
|
||||
ChunkedTextureHandle(const char *textureName)
|
||||
{
|
||||
object = ChunkedTextureManager::loadTexture(textureName);
|
||||
lock();
|
||||
}
|
||||
ChunkedTextureHandle(const char *textureName, GBitmap *bmp)
|
||||
{
|
||||
object = ChunkedTextureManager::registerTexture(textureName, bmp, true);
|
||||
lock();
|
||||
}
|
||||
~ChunkedTextureHandle() { unlock(); }
|
||||
|
||||
ChunkedTextureHandle& operator=(const ChunkedTextureHandle &t) { unlock(); object = t.object; lock(); return *this; }
|
||||
void refresh() { if(object) ChunkedTextureManager::refresh(object); }
|
||||
operator ChunkedTextureObject*() { return object; }
|
||||
const char* getName() const { return (object ? object->texFileName : NULL); }
|
||||
U32 getWidth() const { return (object ? object->width : 0UL); }
|
||||
U32 getHeight() const { return (object ? object->height : 0UL); }
|
||||
GBitmap* getBitmap() { return (object ? object->bitmap : NULL); }
|
||||
TextureHandle getSubTexture(U32 x, U32 y);
|
||||
U32 getTextureCountWidth() { return (object ? object->texWidthCount : 0UL); };
|
||||
U32 getTextureCountHeight(){ return (object ? object->texHeightCount : 0UL); };
|
||||
};
|
||||
|
||||
#endif
|
||||
470
dgl/gFont.cc
Normal file
470
dgl/gFont.cc
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Core/stream.h"
|
||||
#include "dgl/gFont.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "Core/fileStream.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
|
||||
S32 GFont::smSheetIdCount = 0;
|
||||
|
||||
ResourceInstance* constructFont(Stream& stream)
|
||||
{
|
||||
GFont *ret = new GFont;
|
||||
if(!ret->read(stream))
|
||||
{
|
||||
delete ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
const U32 GFont::csm_fileVersion = 1;
|
||||
|
||||
Resource<GFont> GFont::create(const char *faceName, S32 size)
|
||||
{
|
||||
char buf[256];
|
||||
dSprintf(buf, sizeof(buf), "fonts/%s_%d.gft", faceName, size);
|
||||
|
||||
Resource<GFont> ret = ResourceManager->load(buf);
|
||||
if(bool(ret))
|
||||
return ret;
|
||||
|
||||
GFont *resFont = createFont(faceName, size);
|
||||
if (resFont == NULL) {
|
||||
AssertISV(dStricmp(faceName, "Arial") != 0, "Error, The Arial Font must always be available!");
|
||||
|
||||
// Need to handle this case better. For now, let's just return a font that we're
|
||||
// positive exists, in the correct size...
|
||||
return create("Arial", size);
|
||||
}
|
||||
|
||||
FileStream stream;
|
||||
if(ResourceManager->openFileForWrite(stream, ResourceManager->getBasePath(), buf))
|
||||
{
|
||||
resFont->write(stream);
|
||||
stream.close();
|
||||
}
|
||||
ResourceManager->add(buf, resFont, false);
|
||||
return ResourceManager->load(buf);
|
||||
}
|
||||
|
||||
GFont::GFont()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mCharInfoList);
|
||||
|
||||
for (U32 i = 0; i < 256; i++)
|
||||
mRemapTable[i] = -1;
|
||||
|
||||
mTextureSheets = NULL;
|
||||
}
|
||||
|
||||
GFont::~GFont()
|
||||
{
|
||||
delete [] mTextureSheets;
|
||||
mTextureSheets = NULL;
|
||||
}
|
||||
|
||||
void GFont::insertBitmap(U16 index, U8 *src, U32 stride, U32 width, U32 height, S32 xOrigin, S32 yOrigin, S32 xIncrement)
|
||||
{
|
||||
CharInfo c;
|
||||
c.bitmapIndex = -1;
|
||||
c.xOffset = 0;
|
||||
c.yOffset = 0;
|
||||
c.width = width;
|
||||
c.height = height;
|
||||
|
||||
c.xOrigin = xOrigin;
|
||||
c.yOrigin = yOrigin;
|
||||
c.xIncrement = xIncrement;
|
||||
|
||||
c.bitmapData = new U8[c.width * c.height];
|
||||
|
||||
for(U32 y = 0; S32(y) < c.height; y++)
|
||||
{
|
||||
U32 x;
|
||||
for(x = 0; x < width; x++)
|
||||
c.bitmapData[y * c.width + x] = src[y * stride + x];
|
||||
}
|
||||
mRemapTable[index] = mCharInfoList.size();
|
||||
mCharInfoList.push_back(c);
|
||||
}
|
||||
|
||||
static S32 QSORT_CALLBACK CharInfoCompare(const void *a, const void *b)
|
||||
{
|
||||
S32 ha = (*((GFont::CharInfo **) a))->height;
|
||||
S32 hb = (*((GFont::CharInfo **) b))->height;
|
||||
|
||||
return hb - ha;
|
||||
}
|
||||
|
||||
void GFont::pack(U32 inFontHeight, U32 inBaseLine)
|
||||
{
|
||||
mFontHeight = inFontHeight;
|
||||
mBaseLine = inBaseLine;
|
||||
|
||||
// pack all the bitmap data into sheets.
|
||||
Vector<CharInfo *> vec;
|
||||
|
||||
U32 size = mCharInfoList.size();
|
||||
U32 i;
|
||||
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
CharInfo *ch = &mCharInfoList[i];
|
||||
vec.push_back(ch);
|
||||
}
|
||||
|
||||
dQsort(vec.address(), size, sizeof(CharInfo *), CharInfoCompare);
|
||||
// sorted by height
|
||||
|
||||
Vector<Point2I> sheetSizes;
|
||||
Point2I curSheetSize(256, 256);
|
||||
|
||||
S32 curY = 0;
|
||||
S32 curX = 0;
|
||||
S32 curLnHeight = 0;
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
CharInfo *ci = vec[i];
|
||||
|
||||
if(curX + ci->width > curSheetSize.x)
|
||||
{
|
||||
curY += curLnHeight;
|
||||
curX = 0;
|
||||
curLnHeight = 0;
|
||||
}
|
||||
if(curY + ci->height > curSheetSize.y)
|
||||
{
|
||||
sheetSizes.push_back(curSheetSize);
|
||||
curX = 0;
|
||||
curY = 0;
|
||||
curLnHeight = 0;
|
||||
}
|
||||
if(ci->height > curLnHeight)
|
||||
curLnHeight = ci->height;
|
||||
ci->bitmapIndex = sheetSizes.size();
|
||||
ci->xOffset = curX;
|
||||
ci->yOffset = curY;
|
||||
curX += ci->width;
|
||||
}
|
||||
curY += curLnHeight;
|
||||
|
||||
if(curY < 64)
|
||||
curSheetSize.y = 64;
|
||||
else if(curY < 128)
|
||||
curSheetSize.y = 128;
|
||||
|
||||
sheetSizes.push_back(curSheetSize);
|
||||
|
||||
Vector<GBitmap *> bitmapArray;
|
||||
|
||||
mNumSheets = sheetSizes.size();
|
||||
mTextureSheets = new TextureHandle[mNumSheets];
|
||||
|
||||
for(i = 0; i < mNumSheets; i++)
|
||||
bitmapArray.push_back(new GBitmap(sheetSizes[i].x, sheetSizes[i].y, false, GBitmap::Alpha));
|
||||
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
CharInfo *ci = vec[i];
|
||||
GBitmap *bmp = bitmapArray[ci->bitmapIndex];
|
||||
S32 x, y;
|
||||
for(y = 0; y < ci->height; y++)
|
||||
for(x = 0; x < ci->width; x++)
|
||||
*bmp->getAddress(x + ci->xOffset, y + ci->yOffset) =
|
||||
ci->bitmapData[y * ci->width + x];
|
||||
delete[] ci->bitmapData;
|
||||
}
|
||||
for(i = 0; i < mNumSheets; i++)
|
||||
assignSheet(i, bitmapArray[i]);
|
||||
}
|
||||
|
||||
TextureHandle GFont::getTextureHandle(S32 index)
|
||||
{
|
||||
return mTextureSheets[index];
|
||||
}
|
||||
|
||||
void GFont::assignSheet(S32 sheetNum, GBitmap *bmp)
|
||||
{
|
||||
char buf[30];
|
||||
dSprintf(buf, sizeof(buf), "font_%d", smSheetIdCount++);
|
||||
mTextureSheets[sheetNum] = TextureHandle(buf, bmp);
|
||||
}
|
||||
|
||||
U32 GFont::getStrWidth(const char* in_pString) const
|
||||
{
|
||||
AssertFatal(in_pString != NULL, "GFont::getStrWidth: String is NULL, height is undefined");
|
||||
// If we ain't running debug...
|
||||
if (in_pString == NULL)
|
||||
return 0;
|
||||
|
||||
return getStrNWidth(in_pString, dStrlen(in_pString));
|
||||
}
|
||||
|
||||
U32 GFont::getStrWidthPrecise(const char* in_pString) const
|
||||
{
|
||||
AssertFatal(in_pString != NULL, "GFont::getStrWidth: String is NULL, height is undefined");
|
||||
// If we ain't running debug...
|
||||
if (in_pString == NULL)
|
||||
return 0;
|
||||
|
||||
return getStrNWidthPrecise(in_pString, dStrlen(in_pString));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
U32 GFont::getStrNWidth(const char *str, U32 n) const
|
||||
{
|
||||
AssertFatal(str != NULL, "GFont::getStrNWidth: String is NULL");
|
||||
|
||||
if (str == NULL)
|
||||
return(0);
|
||||
|
||||
U32 totWidth = 0;
|
||||
const char *curChar;
|
||||
const char *endStr;
|
||||
for (curChar = str, endStr = str + n; curChar < endStr; curChar++)
|
||||
{
|
||||
if(isValidChar(*curChar))
|
||||
{
|
||||
const CharInfo& rChar = getCharInfo(*curChar);
|
||||
totWidth += rChar.xIncrement;
|
||||
}
|
||||
else if (*curChar == '\t')
|
||||
{
|
||||
const CharInfo& rChar = getCharInfo(' ');
|
||||
totWidth += rChar.xIncrement * TabWidthInSpaces;
|
||||
}
|
||||
}
|
||||
|
||||
return(totWidth);
|
||||
}
|
||||
|
||||
U32 GFont::getStrNWidthPrecise(const char *str, U32 n) const
|
||||
{
|
||||
AssertFatal(str != NULL, "GFont::getStrNWidth: String is NULL");
|
||||
|
||||
if (str == NULL)
|
||||
return(0);
|
||||
|
||||
U32 totWidth = 0;
|
||||
const char *curChar;
|
||||
const char *endStr;
|
||||
for (curChar = str, endStr = str + n; curChar < endStr; curChar++)
|
||||
{
|
||||
if(isValidChar(*curChar))
|
||||
{
|
||||
const CharInfo& rChar = getCharInfo(*curChar);
|
||||
totWidth += rChar.xIncrement;
|
||||
}
|
||||
else if (*curChar == '\t')
|
||||
{
|
||||
const CharInfo& rChar = getCharInfo(' ');
|
||||
totWidth += rChar.xIncrement * TabWidthInSpaces;
|
||||
}
|
||||
}
|
||||
|
||||
if (n != 0) {
|
||||
// Need to check the last char to see if it has some slop...
|
||||
char endChar = str[n-1];
|
||||
if (isValidChar(endChar)) {
|
||||
const CharInfo& rChar = getCharInfo(endChar);
|
||||
if (rChar.width > rChar.xIncrement)
|
||||
totWidth += (rChar.width - rChar.xIncrement);
|
||||
}
|
||||
}
|
||||
|
||||
return(totWidth);
|
||||
}
|
||||
|
||||
U32 GFont::getBreakPos(const char *string, U32 slen, U32 width, bool breakOnWhitespace)
|
||||
{
|
||||
U32 ret = 0;
|
||||
U32 lastws = 0;
|
||||
while(ret < slen)
|
||||
{
|
||||
char c = string[ret];
|
||||
if(c == '\t')
|
||||
c = ' ';
|
||||
if(!isValidChar(c))
|
||||
{
|
||||
ret++;
|
||||
continue;
|
||||
}
|
||||
if(c == ' ')
|
||||
lastws = ret+1;
|
||||
const CharInfo& rChar = getCharInfo(c);
|
||||
if(rChar.width > width || rChar.xIncrement > width)
|
||||
{
|
||||
if(lastws && breakOnWhitespace)
|
||||
return lastws;
|
||||
return ret;
|
||||
}
|
||||
width -= rChar.xIncrement;
|
||||
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GFont::wrapString(const char *txt, U32 lineWidth, Vector<U32> &startLineOffset, Vector<U32> &lineLen)
|
||||
{
|
||||
startLineOffset.clear();
|
||||
lineLen.clear();
|
||||
|
||||
if (!txt || !txt[0] || lineWidth < getCharWidth('W')) //make sure the line width is greater then a single character
|
||||
return;
|
||||
|
||||
U32 len = dStrlen(txt);
|
||||
|
||||
U32 startLine;
|
||||
|
||||
for (U32 i = 0; i < len;)
|
||||
{
|
||||
startLine = i;
|
||||
startLineOffset.push_back(startLine);
|
||||
|
||||
// loop until the string is too large
|
||||
bool needsNewLine = false;
|
||||
U32 lineStrWidth = 0;
|
||||
for (; i < len; i++)
|
||||
{
|
||||
if(isValidChar(txt[i]))
|
||||
{
|
||||
lineStrWidth += getCharInfo(txt[i]).xIncrement;
|
||||
if ( txt[i] == '\n' || lineStrWidth > lineWidth )
|
||||
{
|
||||
needsNewLine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!needsNewLine)
|
||||
{
|
||||
// we are done!
|
||||
lineLen.push_back(i - startLine);
|
||||
return;
|
||||
}
|
||||
|
||||
// now determine where to put the newline
|
||||
// else we need to backtrack until we find a either space character
|
||||
// or \\ character to break up the line.
|
||||
S32 j;
|
||||
for (j = i - 1; j >= startLine; j--)
|
||||
{
|
||||
if (dIsspace(txt[j]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (j < startLine)
|
||||
{
|
||||
// the line consists of a single word!
|
||||
// So, just break up the word
|
||||
j = i - 1;
|
||||
}
|
||||
lineLen.push_back(j - startLine);
|
||||
i = j;
|
||||
|
||||
// now we need to increment through any space characters at the
|
||||
// beginning of the next line
|
||||
for (i++; i < len; i++)
|
||||
{
|
||||
if (!dIsspace(txt[i]) || txt[i] == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- Persist functionality
|
||||
//
|
||||
static const U32 csm_fileVersion = 1;
|
||||
|
||||
bool GFont::read(Stream& io_rStream)
|
||||
{
|
||||
// Handle versioning
|
||||
U32 version;
|
||||
io_rStream.read(&version);
|
||||
if(version != csm_fileVersion)
|
||||
return false;
|
||||
|
||||
// Read Font Information
|
||||
io_rStream.read(&mFontHeight);
|
||||
io_rStream.read(&mBaseLine);
|
||||
|
||||
U32 size = 0;
|
||||
io_rStream.read(&size);
|
||||
mCharInfoList.setSize(size);
|
||||
U32 i;
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
CharInfo *ci = &mCharInfoList[i];
|
||||
io_rStream.read(&ci->bitmapIndex);
|
||||
io_rStream.read(&ci->xOffset);
|
||||
io_rStream.read(&ci->yOffset);
|
||||
io_rStream.read(&ci->width);
|
||||
io_rStream.read(&ci->height);
|
||||
io_rStream.read(&ci->xOrigin);
|
||||
io_rStream.read(&ci->yOrigin);
|
||||
io_rStream.read(&ci->xIncrement);
|
||||
}
|
||||
io_rStream.read(&mNumSheets);
|
||||
|
||||
mTextureSheets = new TextureHandle[mNumSheets];
|
||||
for(i = 0; i < mNumSheets; i++)
|
||||
{
|
||||
GBitmap *bmp = new GBitmap;
|
||||
if(!bmp->readPNG(io_rStream))
|
||||
{
|
||||
delete bmp;
|
||||
return false;
|
||||
}
|
||||
assignSheet(i, bmp);
|
||||
}
|
||||
|
||||
// Read character remap table
|
||||
for(i = 0; i < 256; i++)
|
||||
io_rStream.read(&mRemapTable[i]);
|
||||
|
||||
return (io_rStream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool
|
||||
GFont::write(Stream& stream) const
|
||||
{
|
||||
// Handle versioning
|
||||
stream.write(csm_fileVersion);
|
||||
|
||||
// Write Font Information
|
||||
stream.write(mFontHeight);
|
||||
stream.write(mBaseLine);
|
||||
|
||||
stream.write(U32(mCharInfoList.size()));
|
||||
U32 i;
|
||||
for(i = 0; i < mCharInfoList.size(); i++)
|
||||
{
|
||||
const CharInfo *ci = &mCharInfoList[i];
|
||||
stream.write(ci->bitmapIndex);
|
||||
stream.write(ci->xOffset);
|
||||
stream.write(ci->yOffset);
|
||||
stream.write(ci->width);
|
||||
stream.write(ci->height);
|
||||
stream.write(ci->xOrigin);
|
||||
stream.write(ci->yOrigin);
|
||||
stream.write(ci->xIncrement);
|
||||
}
|
||||
stream.write(mNumSheets);
|
||||
for(i = 0; i < mNumSheets; i++)
|
||||
mTextureSheets[i].getBitmap()->writePNG(stream);
|
||||
|
||||
for(i = 0; i < 256; i++)
|
||||
stream.write(mRemapTable[i]);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
156
dgl/gFont.h
Normal file
156
dgl/gFont.h
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GFONT_H_
|
||||
#define _GFONT_H_
|
||||
|
||||
//Includes
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _GBITMAP_H_
|
||||
#include "dgl/gBitmap.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
#ifndef _MRECT_H_
|
||||
#include "Math/mRect.h"
|
||||
#endif
|
||||
#ifndef _RESMANAGER_H_
|
||||
#include "Core/resManager.h"
|
||||
#endif
|
||||
|
||||
extern ResourceInstance* constructFont(Stream& stream);
|
||||
|
||||
class TextureHandle;
|
||||
|
||||
class GFont : public ResourceInstance
|
||||
{
|
||||
static const U32 csm_fileVersion;
|
||||
static S32 smSheetIdCount;
|
||||
|
||||
// Enumerations and structs available to everyone...
|
||||
public:
|
||||
// A justification consists of a horizontal type | a vertical type.
|
||||
// Note that a justification of 0 evalutes to left/top, the default.
|
||||
// The robustness of the rendering functions should be considered
|
||||
// suspect for a while, especially the justified versions...
|
||||
//
|
||||
struct CharInfo {
|
||||
S16 bitmapIndex; // Note: -1 indicates character is NOT to be
|
||||
// rendered, i.e., \n, \r, etc.
|
||||
U8 xOffset; // x offset into bitmap sheet
|
||||
U8 yOffset; // y offset into bitmap sheet
|
||||
U8 width; // width of character (pixels)
|
||||
U8 height; // height of character (pixels)
|
||||
S8 xOrigin;
|
||||
S8 yOrigin;
|
||||
S8 xIncrement;
|
||||
U8 *bitmapData; // temp storage for bitmap data
|
||||
};
|
||||
enum Constants {
|
||||
TabWidthInSpaces = 3
|
||||
};
|
||||
|
||||
|
||||
// Enumerations and structures available to derived classes
|
||||
private:
|
||||
U32 mNumSheets;
|
||||
TextureHandle *mTextureSheets;
|
||||
|
||||
U32 mFontHeight; // ascent + descent of the font
|
||||
U32 mBaseLine; // ascent of the font (pixels above the baseline of any character in the font)
|
||||
|
||||
Vector<CharInfo> mCharInfoList; // - List of character info structures, must
|
||||
// be accessed through the getCharInfo(U32)
|
||||
// function to account for remapping...
|
||||
S16 mRemapTable[256]; // - Index remapping
|
||||
|
||||
S16 getActualIndex(const U8 in_charIndex) const;
|
||||
void assignSheet(S32 sheetNum, GBitmap *bmp);
|
||||
|
||||
public:
|
||||
GFont();
|
||||
virtual ~GFont();
|
||||
|
||||
// Queries about this font
|
||||
public:
|
||||
TextureHandle getTextureHandle(S32 index);
|
||||
U32 getCharHeight(const U8 in_charIndex) const;
|
||||
U32 getCharWidth(const U8 in_charIndex) const;
|
||||
U32 getCharXIncrement(const U8 in_charIndex) const;
|
||||
|
||||
bool isValidChar(const U8 in_charIndex) const;
|
||||
const CharInfo& getCharInfo(const U8 in_charIndex) const;
|
||||
|
||||
|
||||
// Rendering assistance functions...
|
||||
public:
|
||||
U32 getBreakPos(const char *string, U32 strlen, U32 width, bool breakOnWhitespace);
|
||||
|
||||
U32 getStrWidth(const char*) const; // Note: ignores c/r
|
||||
U32 getStrNWidth(const char*, U32 n) const;
|
||||
U32 getStrWidthPrecise(const char*) const; // Note: ignores c/r
|
||||
U32 getStrNWidthPrecise(const char*, U32 n) const;
|
||||
void wrapString(const char *string, U32 width, Vector<U32> &startLineOffset, Vector<U32> &lineLen);
|
||||
|
||||
bool read(Stream& io_rStream);
|
||||
bool write(Stream& io_rStream) const;
|
||||
|
||||
U32 getHeight() { return mFontHeight; }
|
||||
U32 getBaseline() { return mBaseLine; }
|
||||
U32 getAscent() { return mBaseLine; }
|
||||
U32 getDescent() { return mFontHeight - mBaseLine; }
|
||||
|
||||
void insertBitmap(U16 index, U8 *src, U32 stride, U32 width, U32 height, S32 xOrigin, S32 yOrigin, S32 xIncrement);
|
||||
void pack(U32 fontHeight, U32 baseLine);
|
||||
|
||||
static Resource<GFont> create(const char *face, S32 size);
|
||||
};
|
||||
|
||||
inline bool GFont::isValidChar(const U8 in_charIndex) const
|
||||
{
|
||||
return mRemapTable[in_charIndex] != -1;
|
||||
}
|
||||
|
||||
inline S16 GFont::getActualIndex(const U8 in_charIndex) const
|
||||
{
|
||||
AssertFatal(isValidChar(in_charIndex) == true,
|
||||
avar("GFont::getActualIndex: invalid character: 0x%x",
|
||||
in_charIndex));
|
||||
|
||||
return mRemapTable[in_charIndex];
|
||||
}
|
||||
|
||||
inline const GFont::CharInfo& GFont::getCharInfo(const U8 in_charIndex) const
|
||||
{
|
||||
S16 remap = getActualIndex(in_charIndex);
|
||||
AssertFatal(remap != -1, "No remap info for this character");
|
||||
|
||||
return mCharInfoList[remap];
|
||||
}
|
||||
|
||||
inline U32 GFont::getCharXIncrement(const U8 in_charIndex) const
|
||||
{
|
||||
const CharInfo& rChar = getCharInfo(in_charIndex);
|
||||
return rChar.xIncrement;
|
||||
}
|
||||
|
||||
inline U32 GFont::getCharWidth(const U8 in_charIndex) const
|
||||
{
|
||||
const CharInfo& rChar = getCharInfo(in_charIndex);
|
||||
return rChar.width;
|
||||
}
|
||||
|
||||
inline U32 GFont::getCharHeight(const U8 in_charIndex) const
|
||||
{
|
||||
const CharInfo& rChar = getCharInfo(in_charIndex);
|
||||
return rChar.height;
|
||||
}
|
||||
|
||||
#endif //_GFONT_H_
|
||||
148
dgl/gPalette.cc
Normal file
148
dgl/gPalette.cc
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Core/stream.h"
|
||||
#include "Core/fileStream.h"
|
||||
#include "dgl/gPalette.h"
|
||||
|
||||
const U32 GPalette::csm_fileVersion = 1;
|
||||
|
||||
GPalette::GPalette()
|
||||
: m_paletteType(RGB)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
GPalette::~GPalette()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------------------- Supplimentary I/O
|
||||
bool
|
||||
GPalette::readMSPalette(const char* in_pFileName)
|
||||
{
|
||||
AssertFatal(in_pFileName != NULL, "GPalette::readMSPalette: NULL FileName");
|
||||
|
||||
FileStream frs;
|
||||
if (frs.open(in_pFileName, FileStream::Read) == false) {
|
||||
return false;
|
||||
} else {
|
||||
bool success = readMSPalette(frs);
|
||||
frs.close();
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GPalette::writeMSPalette(const char* in_pFileName) const
|
||||
{
|
||||
AssertFatal(in_pFileName != NULL, "GPalette::writeMSPalette: NULL FileName");
|
||||
|
||||
FileStream fws;
|
||||
if (fws.open(in_pFileName, FileStream::Write) == false) {
|
||||
return false;
|
||||
} else {
|
||||
bool success = writeMSPalette(fws);
|
||||
fws.close();
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GPalette::readMSPalette(Stream& io_rStream)
|
||||
{
|
||||
AssertFatal(io_rStream.getStatus() != Stream::Closed,
|
||||
"GPalette::writeMSPalette: can't write to a closed stream!");
|
||||
|
||||
U32 data;
|
||||
U32 size;
|
||||
|
||||
io_rStream.read(&data);
|
||||
io_rStream.read(&size);
|
||||
|
||||
if (data == makeFourCCTag('R', 'I', 'F', 'F')) {
|
||||
io_rStream.read(&data);
|
||||
io_rStream.read(&size);
|
||||
}
|
||||
|
||||
if (data == makeFourCCTag('P', 'A', 'L', ' ')) {
|
||||
io_rStream.read(&data); // get number of colors (ignored)
|
||||
io_rStream.read(&data); // skip the version number.
|
||||
|
||||
// Read the colors...
|
||||
io_rStream.read(256 * sizeof(ColorI), m_pColors);
|
||||
|
||||
// With MS Pals, we assume that the type is RGB, clear out all the alpha
|
||||
// members so the palette keys are consistent across multiple palettes
|
||||
//
|
||||
for (U32 i = 0; i < 256; i++)
|
||||
m_pColors[i].alpha = 0;
|
||||
|
||||
m_paletteType = RGB;
|
||||
|
||||
return (io_rStream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
AssertWarn(false, "GPalette::readMSPalette: not a MS Palette");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
GPalette::writeMSPalette(Stream& io_rStream) const
|
||||
{
|
||||
AssertFatal(io_rStream.getStatus() != Stream::Closed,
|
||||
"GPalette::writeMSPalette: can't write to a closed stream!");
|
||||
|
||||
io_rStream.write(U32(makeFourCCTag('R', 'I', 'F', 'F')));
|
||||
io_rStream.write(U32((256 * sizeof(ColorI)) + 8 + 4 + 4));
|
||||
|
||||
io_rStream.write(U32(makeFourCCTag('P', 'A', 'L', ' ')));
|
||||
io_rStream.write(U32(makeFourCCTag('d', 'a', 't', 'a')));
|
||||
|
||||
io_rStream.write(U32(0x0404)); // Number of colors + 4
|
||||
|
||||
io_rStream.write(U16(0x300)); // version
|
||||
io_rStream.write(U16(256)); // num colors...
|
||||
|
||||
io_rStream.write(256 * sizeof(ColorI), m_pColors);
|
||||
|
||||
return (io_rStream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- Persistent I/O
|
||||
//
|
||||
bool
|
||||
GPalette::read(Stream& io_rStream)
|
||||
{
|
||||
// Handle versioning
|
||||
U32 version;
|
||||
io_rStream.read(&version);
|
||||
AssertFatal(version == csm_fileVersion, "Palette::read: wrong file version...");
|
||||
|
||||
U32 type;
|
||||
io_rStream.read(&type);
|
||||
m_paletteType = PaletteType(type);
|
||||
io_rStream.read(256 * sizeof(ColorI), m_pColors);
|
||||
|
||||
return (io_rStream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool
|
||||
GPalette::write(Stream& io_rStream) const
|
||||
{
|
||||
// Handle versioning...
|
||||
io_rStream.write(csm_fileVersion);
|
||||
|
||||
io_rStream.write(U32(m_paletteType));
|
||||
io_rStream.write(256 * sizeof(ColorI), m_pColors);
|
||||
|
||||
return (io_rStream.getStatus() == Stream::Ok);
|
||||
}
|
||||
101
dgl/gPalette.h
Normal file
101
dgl/gPalette.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GPALETTE_H_
|
||||
#define _GPALETTE_H_
|
||||
|
||||
//Includes
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------- Forward decls.
|
||||
class Stream;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- GPalette
|
||||
//
|
||||
class GPalette
|
||||
{
|
||||
public:
|
||||
enum PaletteType {
|
||||
RGB,
|
||||
RGBA
|
||||
};
|
||||
|
||||
protected:
|
||||
PaletteType m_paletteType;
|
||||
ColorI m_pColors[256];
|
||||
|
||||
public:
|
||||
GPalette();
|
||||
virtual ~GPalette();
|
||||
|
||||
PaletteType getPaletteType() const;
|
||||
void setPaletteType(const PaletteType pt) { m_paletteType = pt; }
|
||||
|
||||
const ColorI* getColors() const;
|
||||
ColorI* getColors();
|
||||
const ColorI& getColor(const U32 in_index) const;
|
||||
ColorI& getColor(const U32 in_index);
|
||||
|
||||
//-------------------------------------- Supplimentary output members
|
||||
public:
|
||||
bool readMSPalette(Stream& io_rStream);
|
||||
bool readMSPalette(const char* in_pFileName);
|
||||
bool writeMSPalette(Stream& io_rStream) const;
|
||||
bool writeMSPalette(const char* in_pFileName) const;
|
||||
|
||||
//-------------------------------------- Persistent members
|
||||
public:
|
||||
bool read(Stream& io_rStream);
|
||||
bool write(Stream& io_rStream) const;
|
||||
private:
|
||||
static const U32 csm_fileVersion;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- Inlines (Trust)
|
||||
//
|
||||
inline GPalette::PaletteType
|
||||
GPalette::getPaletteType() const
|
||||
{
|
||||
return m_paletteType;
|
||||
}
|
||||
|
||||
inline const ColorI*
|
||||
GPalette::getColors() const
|
||||
{
|
||||
return m_pColors;
|
||||
}
|
||||
|
||||
inline ColorI*
|
||||
GPalette::getColors()
|
||||
{
|
||||
return m_pColors;
|
||||
}
|
||||
|
||||
inline const ColorI&
|
||||
GPalette::getColor(const U32 in_index) const
|
||||
{
|
||||
AssertFatal(in_index < 256, "Out of range index");
|
||||
|
||||
return m_pColors[in_index];
|
||||
}
|
||||
|
||||
inline ColorI&
|
||||
GPalette::getColor(const U32 in_index)
|
||||
{
|
||||
AssertFatal(in_index < 256, "Out of range index");
|
||||
|
||||
return m_pColors[in_index];
|
||||
}
|
||||
|
||||
#endif //_GPALETTE_H_
|
||||
1468
dgl/gTexManager.cc
Normal file
1468
dgl/gTexManager.cc
Normal file
File diff suppressed because it is too large
Load diff
285
dgl/gTexManager.h
Normal file
285
dgl/gTexManager.h
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#define _GTEXMANAGER_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------- Forward Decls.
|
||||
class GBitmap;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- TextureHandle
|
||||
//
|
||||
|
||||
enum TextureHandleType
|
||||
{
|
||||
BitmapTexture = 0,
|
||||
BitmapKeepTexture,
|
||||
BitmapNoDownloadTexture,
|
||||
RegisteredTexture,
|
||||
MeshTexture,
|
||||
TerrainTexture,
|
||||
SkyTexture,
|
||||
InteriorTexture,
|
||||
|
||||
DetailTexture,
|
||||
ZeroBorderTexture
|
||||
};
|
||||
|
||||
class TextureObject
|
||||
{
|
||||
public:
|
||||
TextureObject *next;
|
||||
TextureObject *prev;
|
||||
TextureObject *hashNext;
|
||||
|
||||
U32 texGLName;
|
||||
U32 smallTexGLName;
|
||||
|
||||
#ifdef GATHER_METRICS
|
||||
U32 textureSpace;
|
||||
#endif
|
||||
|
||||
StringTableEntry texFileName;
|
||||
GBitmap * bitmap;
|
||||
|
||||
U32 texWidth;
|
||||
U32 texHeight;
|
||||
|
||||
U32 bitmapWidth;
|
||||
U32 bitmapHeight;
|
||||
|
||||
U32 downloadedWidth;
|
||||
U32 downloadedHeight;
|
||||
|
||||
TextureHandleType type;
|
||||
bool clamp;
|
||||
bool holding;
|
||||
S32 refCount;
|
||||
};
|
||||
|
||||
typedef void (*TextureEventCallback)(const U32 eventCode, const U32 userData);
|
||||
|
||||
struct TextureManager
|
||||
{
|
||||
// additional functions for refreshing the textures, reloading larger
|
||||
// mip levels, etc, will go in here, as well as delay-load functions.
|
||||
friend class TextureHandle;
|
||||
friend class InteriorLMManager;
|
||||
friend struct TextureDictionary;
|
||||
|
||||
private:
|
||||
static TextureObject* loadTexture(const char *textureName, TextureHandleType type, bool clampToEdge);
|
||||
static TextureObject* registerTexture(const char *textureName, const GBitmap *data, bool clampToEdge);
|
||||
static TextureObject* registerTexture(const char *textureName, GBitmap *data, TextureHandleType type, bool clampToEdge);
|
||||
static void freeTexture(TextureObject *to);
|
||||
static bool createGLName(GBitmap *pb, bool clampToEdge, U32 firstMip, TextureHandleType type, TextureObject* obj);
|
||||
static void refresh(TextureObject *to);
|
||||
static void refresh(TextureObject *to, GBitmap*);
|
||||
static GBitmap* createMipBitmap(const GBitmap* pBitmap);
|
||||
static GBitmap* createPaddedBitmap(GBitmap* pBitmap);
|
||||
|
||||
|
||||
public:
|
||||
static void create();
|
||||
static void preDestroy();
|
||||
static void destroy();
|
||||
|
||||
static void makeZombie(); // This pair of functions is a flush() equivalent. To flush
|
||||
static void resurrect(); // the cache, call:
|
||||
// makeZombie(); /* blah blah blah */ resurrect();
|
||||
// Note that NO drawing must take place until resurrect is
|
||||
// called. The manager is a stinking corpse at this point.
|
||||
// The split is necessary to support changing the OpenGL
|
||||
// device in the "right way". This way glDeleteTexture is
|
||||
// called on the original device rather than on the new
|
||||
// device, as a flush() call would necessitate.
|
||||
static void flush(); // Added for convenience when you don't need to worry about
|
||||
// the above problems.
|
||||
static bool smIsZombie;
|
||||
|
||||
#ifdef GATHER_METRICS
|
||||
static void dumpStats();
|
||||
#endif
|
||||
|
||||
enum EventCodes {
|
||||
BeginZombification = 0,
|
||||
CacheResurrected = 1
|
||||
};
|
||||
static U32 registerEventCallback(TextureEventCallback, const U32 userData);
|
||||
static void unregisterEventCallback(const U32 callbackKey);
|
||||
|
||||
private:
|
||||
static void postTextureEvent(const U32);
|
||||
static bool smUseSmallTextures;
|
||||
|
||||
public:
|
||||
static const char * csmTexturePrefix;
|
||||
|
||||
static void setSmallTexturesActive(const bool t) { smUseSmallTextures = t; }
|
||||
static bool areSmallTexturesActive() { return smUseSmallTextures; }
|
||||
|
||||
#ifdef GATHER_METRICS
|
||||
static U32 smTextureSpaceLoaded;
|
||||
static U32 smTextureCacheMisses;
|
||||
|
||||
static F32 getResidentFraction();
|
||||
#endif
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//
|
||||
// TextureHandle - this is how you access a bitmap, etc.
|
||||
//
|
||||
// Texture handles can be allocated in 2 ways - by name to be loaded
|
||||
// from disk, or by name to a dynamically generated texture
|
||||
//
|
||||
// If you create a GBitmap and register it, the Texture manager
|
||||
// owns the pointer - so if you re-register a texture with the same
|
||||
// name, the texture manager will delete the second copy.
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
|
||||
class TextureHandle
|
||||
{
|
||||
TextureObject *object;
|
||||
void lock();
|
||||
void unlock();
|
||||
public:
|
||||
TextureHandle() { object = NULL; }
|
||||
TextureHandle(const TextureHandle &th) {
|
||||
object = th.object;
|
||||
lock();
|
||||
}
|
||||
|
||||
TextureHandle(const char* textureName,
|
||||
TextureHandleType type=BitmapTexture,
|
||||
bool clampToEdge = false) {
|
||||
object = TextureManager::loadTexture(textureName, type, clampToEdge);
|
||||
lock();
|
||||
}
|
||||
|
||||
TextureHandle(const char* textureName,
|
||||
const GBitmap* bmp,
|
||||
bool clampToEdge = false) {
|
||||
object = TextureManager::registerTexture(textureName, bmp, clampToEdge);
|
||||
lock();
|
||||
}
|
||||
|
||||
TextureHandle(const char* textureName,
|
||||
GBitmap* bmp,
|
||||
TextureHandleType type,
|
||||
bool clampToEdge = false) {
|
||||
object = TextureManager::registerTexture(textureName, bmp, type, clampToEdge);
|
||||
lock();
|
||||
}
|
||||
|
||||
~TextureHandle() { unlock(); }
|
||||
|
||||
TextureHandle& operator=(const TextureHandle &t) {
|
||||
unlock();
|
||||
object = t.object;
|
||||
lock();
|
||||
return *this;
|
||||
}
|
||||
void set(const char *textureName,
|
||||
TextureHandleType type=BitmapTexture,
|
||||
bool clampToEdge = false) {
|
||||
TextureObject* newObject = TextureManager::loadTexture(textureName, type, clampToEdge);;
|
||||
if (newObject != object)
|
||||
{
|
||||
unlock();
|
||||
object = newObject;
|
||||
lock();
|
||||
}
|
||||
}
|
||||
void set(const char *textureName,
|
||||
const GBitmap *data,
|
||||
bool clampToEdge = false) {
|
||||
TextureObject* newObject = TextureManager::registerTexture(textureName, data, clampToEdge);
|
||||
if (newObject != object)
|
||||
{
|
||||
unlock();
|
||||
object = newObject;
|
||||
lock();
|
||||
}
|
||||
}
|
||||
void set(const char *textureName,
|
||||
GBitmap *bmp,
|
||||
TextureHandleType type,
|
||||
bool clampToEdge = false) {
|
||||
TextureObject* newObject = TextureManager::registerTexture(textureName, bmp, type, clampToEdge);
|
||||
if (newObject != object)
|
||||
{
|
||||
unlock();
|
||||
object = newObject;
|
||||
lock();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const TextureHandle &t) const { return t.object == object; }
|
||||
bool operator!=(const TextureHandle &t) const { return t.object != object; }
|
||||
|
||||
void setClamp(const bool);
|
||||
|
||||
void refresh();
|
||||
void refresh(GBitmap*);
|
||||
operator TextureObject*() { return object; }
|
||||
const char* getName() const { return (object ? object->texFileName : NULL); }
|
||||
U32 getWidth() const { return (object ? object->bitmapWidth : 0UL); }
|
||||
U32 getHeight() const { return (object ? object->bitmapHeight : 0UL); }
|
||||
U32 getDownloadedWidth() const { return (object ? object->downloadedWidth : 0UL); }
|
||||
U32 getDownloadedHeight() const { return (object ? object->downloadedHeight : 0UL); }
|
||||
GBitmap* getBitmap() { return (object ? object->bitmap : NULL); }
|
||||
U32 getGLName() const;
|
||||
};
|
||||
|
||||
#if defined(GATHER_METRICS) && GATHER_METRICS > 1
|
||||
#ifndef _PLATFORMGL_H_
|
||||
#include "engine/platformWIN32/platformGL.h"
|
||||
#endif
|
||||
|
||||
inline U32 TextureHandle::getGLName() const
|
||||
{
|
||||
if (!object)
|
||||
return 0;
|
||||
|
||||
U32 useName = tex->texGLName;
|
||||
if (TextureManager::areSmallTexturesActive() && object->smallTexGLName != 0)
|
||||
useName = object->smallTexGLName;
|
||||
|
||||
if (useName != 0) {
|
||||
GLboolean res;
|
||||
glAreTexturesResident(1, &useName, &res);
|
||||
if (res == GL_FALSE)
|
||||
TextureManager::smTextureCacheMisses++;
|
||||
}
|
||||
|
||||
return useName;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline U32 TextureHandle::getGLName() const
|
||||
{
|
||||
if (!object)
|
||||
return 0;
|
||||
|
||||
U32 useName = object->texGLName;
|
||||
if (TextureManager::areSmallTexturesActive() && object->smallTexGLName != 0)
|
||||
useName = object->smallTexGLName;
|
||||
|
||||
return useName;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _GTEXMANAGER_H_
|
||||
99
dgl/lensFlare.cc
Normal file
99
dgl/lensFlare.cc
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/lensFlare.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// Lens Flare
|
||||
//**************************************************************************
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Clean up
|
||||
//--------------------------------------------------------------------------
|
||||
LensFlare::~LensFlare()
|
||||
{
|
||||
for( int i=0; i<mFlareList.size(); i++ )
|
||||
{
|
||||
delete mFlareList[i];
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Add Flare
|
||||
//--------------------------------------------------------------------------
|
||||
void LensFlare::addFlare( LFlare &flare )
|
||||
{
|
||||
LFlare *newFlare = new LFlare;
|
||||
*newFlare = flare;
|
||||
|
||||
mFlareList.push_back( newFlare );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Render
|
||||
//--------------------------------------------------------------------------
|
||||
void LensFlare::render( const MatrixF &camTrans, const Point3F &lightPos )
|
||||
{
|
||||
|
||||
Point3F camPos = camTrans.getPosition();
|
||||
Point3F camDir;
|
||||
camTrans.getRow( 1, &camDir );
|
||||
|
||||
|
||||
Point3F camAdjust = camPos + camDir;
|
||||
|
||||
Point3F lensFlareLine = lightPos - ( camAdjust );
|
||||
lensFlareLine.normalize();
|
||||
|
||||
Point3F startPoint = camAdjust - lensFlareLine;
|
||||
lensFlareLine *= 2.0;
|
||||
|
||||
|
||||
for( int i=0; i<mFlareList.size(); i++ )
|
||||
{
|
||||
const LFlare *flare = mFlareList[i];
|
||||
Point3F flarePos = startPoint + lensFlareLine * flare->offset;
|
||||
renderFlare( flarePos, *flare );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Render flare
|
||||
//--------------------------------------------------------------------------
|
||||
void LensFlare::renderFlare( Point3F &pos, const LFlare &flare )
|
||||
{
|
||||
|
||||
Point3F screenPoint;
|
||||
if( !dglPointToScreen( pos, screenPoint ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
// set ortho mode
|
||||
RectI viewport;
|
||||
dglGetViewport(&viewport);
|
||||
dglSetClipRect( viewport );
|
||||
|
||||
glColor4fv( flare.color );
|
||||
glBindTexture(GL_TEXTURE_2D, flare.tex.getGLName());
|
||||
|
||||
dglDraw2DSquare( Point2F( screenPoint.x, screenPoint.y ), flare.size, 0 );
|
||||
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
}
|
||||
67
dgl/lensFlare.h
Normal file
67
dgl/lensFlare.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LENSFLARE_H_
|
||||
#define _LENSFLARE_H_
|
||||
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MMATH_H_
|
||||
#include "Math/mMath.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
|
||||
//**************************************************************************
|
||||
// Lens flare data
|
||||
//**************************************************************************
|
||||
struct LFlare
|
||||
{
|
||||
ColorF color;
|
||||
TextureHandle tex;
|
||||
F32 size; // size in screen pixels (scaled to 640x480)
|
||||
F32 offset; // offset of flare along flare line values around 0.0-1.0 are good
|
||||
|
||||
|
||||
LFlare()
|
||||
{
|
||||
dMemset( this, 0, sizeof( LFlare ) );
|
||||
color.set( 1.0, 1.0, 1.0, 1.0 );
|
||||
}
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
// Lens Flare
|
||||
//**************************************************************************
|
||||
class LensFlare
|
||||
{
|
||||
private:
|
||||
Vector <LFlare*> mFlareList;
|
||||
|
||||
void renderFlare( Point3F &pos, const LFlare &flare );
|
||||
|
||||
public:
|
||||
~LensFlare();
|
||||
void addFlare( LFlare &flare );
|
||||
void render( const MatrixF &camTrans, const Point3F &lightPos );
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
305
dgl/materialList.cc
Normal file
305
dgl/materialList.cc
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Platform/platform.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "Core/resManager.h"
|
||||
#include "Core/stream.h"
|
||||
#include "dgl/materialList.h"
|
||||
|
||||
//--------------------------------------
|
||||
MaterialList::MaterialList()
|
||||
{
|
||||
mTextureType = BitmapTexture;
|
||||
mClampToEdge = false;
|
||||
|
||||
VECTOR_SET_ASSOCIATION(mMaterialNames);
|
||||
VECTOR_SET_ASSOCIATION(mMaterials);
|
||||
}
|
||||
|
||||
MaterialList::MaterialList(const MaterialList* pCopy)
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mMaterialNames);
|
||||
VECTOR_SET_ASSOCIATION(mMaterials);
|
||||
|
||||
mClampToEdge = pCopy->mClampToEdge;
|
||||
mTextureType = pCopy->mTextureType;
|
||||
|
||||
mMaterialNames.setSize(pCopy->mMaterialNames.size());
|
||||
U32 i;
|
||||
for (i = 0; i < mMaterialNames.size(); i++) {
|
||||
if (pCopy->mMaterialNames[i]) {
|
||||
mMaterialNames[i] = new char[dStrlen(pCopy->mMaterialNames[i]) + 1];
|
||||
dStrcpy(mMaterialNames[i], pCopy->mMaterialNames[i]);
|
||||
} else {
|
||||
mMaterialNames[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
mMaterials.setSize(pCopy->mMaterials.size());
|
||||
for (i = 0; i < mMaterials.size(); i++) {
|
||||
constructInPlace(&mMaterials[i]);
|
||||
mMaterials[i] = pCopy->mMaterials[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
MaterialList::MaterialList(U32 materialCount, const char **materialNames)
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mMaterialNames);
|
||||
VECTOR_SET_ASSOCIATION(mMaterials);
|
||||
|
||||
set(materialCount, materialNames);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void MaterialList::set(U32 materialCount, const char **materialNames)
|
||||
{
|
||||
free();
|
||||
mMaterials.setSize(materialCount);
|
||||
mMaterialNames.setSize(materialCount);
|
||||
for(U32 i = 0; i < materialCount; i++)
|
||||
{
|
||||
// vectors DO NOT initialize classes so manually call the constructor
|
||||
constructInPlace(&mMaterials[i]);
|
||||
mMaterialNames[i] = new char[dStrlen(materialNames[i]) + 1];
|
||||
dStrcpy(mMaterialNames[i], materialNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
MaterialList::~MaterialList()
|
||||
{
|
||||
free();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void MaterialList::load(U32 index)
|
||||
{
|
||||
AssertFatal(index < size(), "MaterialList:: index out of range.");
|
||||
if (index < size())
|
||||
{
|
||||
TextureHandle &handle = mMaterials[index];
|
||||
if (handle.getBitmap() == NULL)
|
||||
{
|
||||
const char *name = mMaterialNames[index];
|
||||
if (name && *name)
|
||||
handle.set(name, mTextureType, mClampToEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool MaterialList::load()
|
||||
{
|
||||
AssertFatal(mMaterials.size() == mMaterials.size(), "MaterialList::load: internal vectors out of sync.");
|
||||
|
||||
for(U32 i=0; i < mMaterials.size(); i++)
|
||||
load(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void MaterialList::unload()
|
||||
{
|
||||
AssertFatal(mMaterials.size() == mMaterials.size(), "MaterialList::unload: internal vectors out of sync.");
|
||||
for(U32 i=0; i < mMaterials.size(); i++)
|
||||
mMaterials[i].~TextureHandle();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void MaterialList::free()
|
||||
{
|
||||
AssertFatal(mMaterials.size() == mMaterials.size(), "MaterialList::free: internal vectors out of sync.");
|
||||
for(U32 i=0; i < mMaterials.size(); i++)
|
||||
{
|
||||
if(mMaterialNames[i])
|
||||
delete [] mMaterialNames[i];
|
||||
mMaterials[i].~TextureHandle();
|
||||
}
|
||||
mMaterialNames.setSize(0);
|
||||
mMaterials.setSize(0);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
U32 MaterialList::push_back(TextureHandle textureHandle, const char * filename)
|
||||
{
|
||||
mMaterials.increment();
|
||||
mMaterialNames.increment();
|
||||
|
||||
// vectors DO NOT initialize classes so manually call the constructor
|
||||
constructInPlace(&mMaterials.last());
|
||||
mMaterials.last() = textureHandle;
|
||||
mMaterialNames.last() = new char[dStrlen(filename) + 1];
|
||||
dStrcpy(mMaterialNames.last(), filename);
|
||||
|
||||
// return the index
|
||||
return mMaterials.size()-1;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
U32 MaterialList::push_back(const char *filename)
|
||||
{
|
||||
mMaterials.increment();
|
||||
mMaterialNames.increment();
|
||||
|
||||
// vectors DO NOT initialize classes so manually call the constructor
|
||||
constructInPlace(&mMaterials.last());
|
||||
mMaterialNames.last() = new char[dStrlen(filename) + 1];
|
||||
dStrcpy(mMaterialNames.last(), filename);
|
||||
|
||||
// return the index
|
||||
return mMaterials.size()-1;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
U32 MaterialList::push_back(const char *filename, GBitmap *bmp, TextureHandleType type, bool clampToEdge)
|
||||
{
|
||||
mMaterials.increment();
|
||||
mMaterialNames.increment();
|
||||
|
||||
// vectors DO NOT initialize classes so manually call the constructor
|
||||
constructInPlace(&mMaterials.last());
|
||||
mMaterials.last().set(filename, bmp, type, clampToEdge);
|
||||
mMaterialNames.last() = new char[dStrlen(filename) + 1];
|
||||
dStrcpy(mMaterialNames.last(), filename);
|
||||
|
||||
// return the index
|
||||
return mMaterials.size()-1;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool MaterialList::read(Stream &stream)
|
||||
{
|
||||
free();
|
||||
|
||||
// check the stream version
|
||||
U8 version;
|
||||
if ( stream.read(&version) && version != BINARY_FILE_VERSION)
|
||||
return readText(stream,version);
|
||||
|
||||
// how many materials?
|
||||
U32 count;
|
||||
if ( !stream.read(&count) )
|
||||
return false;
|
||||
|
||||
// pre-size the vectors for efficiency
|
||||
mMaterials.reserve(count);
|
||||
mMaterialNames.reserve(count);
|
||||
|
||||
// read in the materials
|
||||
for (U32 i=0; i<count; i++)
|
||||
{
|
||||
char buffer[256];
|
||||
stream.readString(buffer);
|
||||
if( !buffer[0] )
|
||||
{
|
||||
AssertWarn(0, "MaterialList::read: error reading stream");
|
||||
return false;
|
||||
}
|
||||
|
||||
// add it to the list
|
||||
mMaterials.increment();
|
||||
mMaterialNames.increment();
|
||||
// vectors DO NOT initialize classes so manually call the constructor
|
||||
constructInPlace(&mMaterials.last());
|
||||
mMaterialNames.last() = new char[dStrlen(buffer) + 1];
|
||||
dStrcpy(mMaterialNames.last(), buffer);
|
||||
}
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool MaterialList::write(Stream &stream)
|
||||
{
|
||||
AssertFatal(mMaterials.size() == mMaterialNames.size(), "MaterialList::write: internal vectors out of sync.");
|
||||
|
||||
stream.write((U8)BINARY_FILE_VERSION); // version
|
||||
stream.write((U32)mMaterials.size()); // material count
|
||||
|
||||
for(U32 i=0; i < mMaterials.size(); i++) // material names
|
||||
stream.writeString(mMaterialNames[i]);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
bool MaterialList::readText(Stream &stream, U8 firstByte)
|
||||
{
|
||||
free();
|
||||
|
||||
if (!firstByte)
|
||||
return (stream.getStatus() == Stream::Ok || stream.getStatus() == Stream::EOS);
|
||||
|
||||
char buf[1024];
|
||||
buf[0] = firstByte;
|
||||
U32 offset = 1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
stream.readLine((U8*)(buf+offset), sizeof(buf)-offset);
|
||||
if(!buf[0])
|
||||
break;
|
||||
offset = 0;
|
||||
|
||||
mMaterials.increment();
|
||||
mMaterialNames.increment();
|
||||
|
||||
// vectors DO NOT initialize classes so manually call the constructor
|
||||
constructInPlace(&mMaterials.last());
|
||||
mMaterialNames.last() = new char[dStrlen(buf) + 1];
|
||||
|
||||
dStrcpy(mMaterialNames.last(), buf);
|
||||
}
|
||||
return (stream.getStatus() == Stream::Ok || stream.getStatus() == Stream::EOS);
|
||||
}
|
||||
|
||||
bool MaterialList::readText(Stream &stream)
|
||||
{
|
||||
U8 firstByte;
|
||||
stream.read(&firstByte);
|
||||
return readText(stream,firstByte);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
bool MaterialList::writeText(Stream &stream)
|
||||
{
|
||||
AssertFatal(mMaterials.size() == mMaterialNames.size(), "MaterialList::writeText: internal vectors out of sync.");
|
||||
|
||||
for(U32 i=0; i < mMaterials.size(); i++)
|
||||
stream.writeLine((U8*)mMaterialNames[i]);
|
||||
stream.writeLine((U8*)"");
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
ResourceInstance* constructMaterialList(Stream &stream)
|
||||
{
|
||||
MaterialList *matList = new MaterialList;
|
||||
if(matList->readText(stream))
|
||||
return matList;
|
||||
else
|
||||
{
|
||||
delete matList;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
103
dgl/materialList.h
Normal file
103
dgl/materialList.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MATERIALLIST_H_
|
||||
#define _MATERIALLIST_H_
|
||||
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _RESMANAGER_H_
|
||||
#include "Core/resManager.h"
|
||||
#endif
|
||||
#ifndef _CONSOLE_H_
|
||||
#include "console/console.h"
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
class MaterialList : public ResourceInstance
|
||||
{
|
||||
private:
|
||||
friend class TSMaterialList;
|
||||
|
||||
enum Constants { BINARY_FILE_VERSION = 1 };
|
||||
|
||||
public:
|
||||
VectorPtr<char*> mMaterialNames;
|
||||
Vector<TextureHandle> mMaterials;
|
||||
protected:
|
||||
bool mClampToEdge;
|
||||
TextureHandleType mTextureType;
|
||||
|
||||
public:
|
||||
MaterialList();
|
||||
MaterialList(U32 materialCount, const char **materialNames);
|
||||
~MaterialList();
|
||||
|
||||
// Note: this is not to be confused with MaterialList(const MaterialList&). Copying
|
||||
// a material list in the middle of it's lifetime is not a good thing, so we force
|
||||
// it to copy at construction time by retricting the copy syntax to
|
||||
// ML* pML = new ML(©);
|
||||
explicit MaterialList(const MaterialList*);
|
||||
|
||||
S32 getMaterialCount() { return mMaterials.size(); }
|
||||
const char * getMaterialName(U32 index) { return mMaterialNames[index]; }
|
||||
TextureHandle &getMaterial(U32 index)
|
||||
{
|
||||
AssertFatal(index < mMaterials.size(), "MaterialList::getMaterial: index lookup out of range.");
|
||||
return mMaterials[index];
|
||||
}
|
||||
|
||||
// material properties
|
||||
void setTextureType(TextureHandleType type) { mTextureType = type; }
|
||||
void setClampToEdge(bool tf) { mClampToEdge = tf; }
|
||||
|
||||
void set(U32 materialCount, const char **materialNames);
|
||||
U32 push_back(TextureHandle textureHandle, const char *filename);
|
||||
U32 push_back(const char *filename);
|
||||
U32 push_back(const char *filename, GBitmap *bmp, TextureHandleType type, bool clampToEdge = false);
|
||||
|
||||
virtual void load(U32 index);
|
||||
bool load();
|
||||
bool load(TextureHandleType type, bool clampToEdge = false);
|
||||
void unload();
|
||||
virtual void free();
|
||||
|
||||
typedef Vector<TextureHandle>::iterator iterator;
|
||||
typedef Vector<TextureHandle>::value_type value;
|
||||
TextureHandle& front() { return mMaterials.front(); }
|
||||
TextureHandle& first() { return mMaterials.first(); }
|
||||
TextureHandle& last() { return mMaterials.last(); }
|
||||
bool empty() { return mMaterials.empty(); }
|
||||
S32 size() { return mMaterials.size(); }
|
||||
iterator begin() { return mMaterials.begin(); }
|
||||
iterator end() { return mMaterials.end(); }
|
||||
value operator[] (S32 index) { return getMaterial(U32(index)); }
|
||||
|
||||
bool read(Stream &stream);
|
||||
bool write(Stream &stream);
|
||||
|
||||
bool readText(Stream &stream, U8 firstByte);
|
||||
bool readText(Stream &stream);
|
||||
bool writeText(Stream &stream);
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
inline bool MaterialList::load(TextureHandleType type, bool clampToEdge)
|
||||
{
|
||||
mTextureType = type;
|
||||
mClampToEdge = clampToEdge;
|
||||
return load();
|
||||
}
|
||||
|
||||
|
||||
extern ResourceInstance* constructMaterialList(Stream &stream);
|
||||
|
||||
|
||||
#endif
|
||||
189
dgl/materialPropertyMap.cc
Normal file
189
dgl/materialPropertyMap.cc
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/materialPropertyMap.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
bool cMatPropMapAddMapping(SimObject*, S32 argc, const char** argv)
|
||||
{
|
||||
MaterialPropertyMap* pMap = static_cast<MaterialPropertyMap*>(Sim::findObject("MaterialPropertyMap"));
|
||||
if (pMap == NULL) {
|
||||
Con::errorf(ConsoleLogEntry::General, "Error, cannot find the global material map object");
|
||||
return false;
|
||||
}
|
||||
|
||||
return pMap->addMapping(argc - 1, argv + 1);
|
||||
}
|
||||
|
||||
} // namespace {}
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT(MaterialPropertyMap);
|
||||
MaterialPropertyMap::MaterialPropertyMap()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mMapEntries);
|
||||
}
|
||||
|
||||
MaterialPropertyMap::~MaterialPropertyMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const MaterialPropertyMap::MapEntry* MaterialPropertyMap::getMapEntry(StringTableEntry name) const
|
||||
{
|
||||
// DMMNOTE: Really slow. Shouldn't be a problem since these are one time scans
|
||||
// for each object, but might want to replace this with a hash table
|
||||
//
|
||||
const MapEntry* ret = NULL;
|
||||
for (U32 i = 0; i < mMapEntries.size(); i++) {
|
||||
if (dStricmp(mMapEntries[i].name, name) == 0) {
|
||||
ret = &mMapEntries[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const MaterialPropertyMap::MapEntry* MaterialPropertyMap::getMapEntryFromIndex(S32 index) const
|
||||
{
|
||||
const MapEntry* ret = NULL;
|
||||
if(index < mMapEntries.size())
|
||||
ret = &mMapEntries[index];
|
||||
return ret;
|
||||
}
|
||||
|
||||
S32 MaterialPropertyMap::getIndexFromName(StringTableEntry name) const
|
||||
{
|
||||
S32 ret = -1;
|
||||
for (U32 i = 0; i < mMapEntries.size(); i++) {
|
||||
if (dStricmp(mMapEntries[i].name, name) == 0) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MaterialPropertyMap::MapEntry* MaterialPropertyMap::getNCMapEntry(StringTableEntry name)
|
||||
{
|
||||
return const_cast<MapEntry*>(getMapEntry(name));
|
||||
}
|
||||
|
||||
bool MaterialPropertyMap::addMapping(const S32 argc, const char** argv)
|
||||
{
|
||||
const char* matName = StringTable->insert(argv[0]);
|
||||
|
||||
MapEntry* pEntry = getNCMapEntry(matName);
|
||||
if (pEntry != NULL) {
|
||||
Con::warnf(ConsoleLogEntry::General, "Warning, overwriting material properties for: %s", matName);
|
||||
} else {
|
||||
mMapEntries.increment();
|
||||
pEntry = &mMapEntries.last();
|
||||
pEntry->sound = -1;
|
||||
pEntry->puffColor[0].set(0.0f, 0.0f, 0.0f);
|
||||
pEntry->puffColor[1].set(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
pEntry->name = matName;
|
||||
pEntry->detailMapName = NULL;
|
||||
pEntry->environMapName = NULL;
|
||||
pEntry->matType = Default;
|
||||
pEntry->matFlags = 0;
|
||||
|
||||
for (U32 i = 1; S32(i) < argc; i++) {
|
||||
const char* param = argv[i];
|
||||
|
||||
if (dStrnicmp(param, "detail:", dStrlen("detail:")) == 0) {
|
||||
// Set the detail map
|
||||
const char* pColon = dStrchr(param, ':');
|
||||
pColon++;
|
||||
while (*pColon == ' ' || *pColon == '\t')
|
||||
pColon++;
|
||||
|
||||
pEntry->detailMapName = StringTable->insert(pColon);
|
||||
}
|
||||
else if (dStrnicmp(param, "environment:", dStrlen("environment:")) == 0) {
|
||||
// Set the detail map
|
||||
const char* pColon = dStrchr(param, ':');
|
||||
pColon++;
|
||||
while (*pColon == ' ' || *pColon == '\t')
|
||||
pColon++;
|
||||
|
||||
const char* start = pColon;
|
||||
while (*pColon != ' ')
|
||||
pColon++;
|
||||
const char* end = pColon;
|
||||
pColon++;
|
||||
|
||||
char buffer[256];
|
||||
dStrncpy(buffer, start, end - start);
|
||||
buffer[end - start] = '\0';
|
||||
|
||||
pEntry->environMapName = StringTable->insert(buffer);
|
||||
pEntry->environMapFactor = dAtof(pColon);
|
||||
}
|
||||
else if (dStrnicmp(param, "color:", dStrlen("color:")) == 0) {
|
||||
const char* curChar = dStrchr(param, ':');
|
||||
curChar++;
|
||||
while (*curChar == ' ' || *curChar == '\t')
|
||||
curChar++;
|
||||
|
||||
char buffer[5][256];
|
||||
S32 index = 0;
|
||||
for(S32 x = 0; x < 5; ++x, index = 0)
|
||||
{
|
||||
while(*curChar != ' ' && *curChar != '\0')
|
||||
buffer[x][index++] = *curChar++;
|
||||
buffer[x][index++] = '\0';
|
||||
while(*curChar == ' ')
|
||||
++curChar;
|
||||
}
|
||||
pEntry->puffColor[0].set(dAtof(buffer[0]), dAtof(buffer[1]), dAtof(buffer[2]), dAtof(buffer[3]));
|
||||
pEntry->puffColor[1].set(dAtof(buffer[0]), dAtof(buffer[1]), dAtof(buffer[2]), dAtof(buffer[4]));
|
||||
}
|
||||
else if (dStrnicmp(param, "sound:", dStrlen("sound:")) == 0) {
|
||||
// Set the detail map
|
||||
const char* pColon = dStrchr(param, ':');
|
||||
pColon++;
|
||||
while (*pColon == ' ' || *pColon == '\t')
|
||||
pColon++;
|
||||
|
||||
const char* start = pColon;
|
||||
while(*pColon != ' ' && *pColon != '\0')
|
||||
pColon++;
|
||||
const char* end = pColon;
|
||||
pColon++;
|
||||
|
||||
char buffer[256];
|
||||
dStrncpy(buffer, start, end - start);
|
||||
buffer[end - start] = '\0';
|
||||
|
||||
pEntry->sound = dAtoi(buffer);
|
||||
}
|
||||
else if (param[0] == '\0') {
|
||||
// Empty statement allowed, does nothing
|
||||
}
|
||||
else {
|
||||
Con::warnf(ConsoleLogEntry::General, "Warning, misunderstood material parameter: %s in materialEntry %s", param, matName);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MaterialPropertyMap::consoleInit()
|
||||
{
|
||||
//-------------------------------------- Class level variables
|
||||
// Con::addVariable("pref::Interior::LightUpdatePeriod", TypeS32, &smLightUpdatePeriod);
|
||||
|
||||
//-------------------------------------- Class level commands
|
||||
Con::addCommand("addMaterialMapping", cMatPropMapAddMapping, "addMaterialMapping(\"matName\", ...)", 2, 99);
|
||||
}
|
||||
75
dgl/materialPropertyMap.h
Normal file
75
dgl/materialPropertyMap.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MATERIALPROPERTYMAP_H_
|
||||
#define _MATERIALPROPERTYMAP_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
|
||||
class MaterialPropertyMap : public SimObject
|
||||
{
|
||||
typedef SimObject Parent;
|
||||
|
||||
public:
|
||||
enum MaterialType {
|
||||
Default
|
||||
};
|
||||
|
||||
enum MaterialFlags {
|
||||
None = 0 << 0
|
||||
};
|
||||
|
||||
struct MapEntry {
|
||||
StringTableEntry name;
|
||||
StringTableEntry detailMapName;
|
||||
StringTableEntry environMapName;
|
||||
|
||||
MaterialType matType;
|
||||
U32 matFlags;
|
||||
|
||||
float environMapFactor;
|
||||
|
||||
S32 sound;
|
||||
ColorF puffColor[2];
|
||||
};
|
||||
|
||||
public:
|
||||
MaterialPropertyMap();
|
||||
~MaterialPropertyMap();
|
||||
|
||||
const MapEntry* getMapEntry(StringTableEntry) const;
|
||||
const MapEntry* getMapEntryFromIndex(S32 index) const;
|
||||
S32 getIndexFromName(StringTableEntry name) const;
|
||||
|
||||
DECLARE_CONOBJECT(MaterialPropertyMap);
|
||||
static void consoleInit();
|
||||
|
||||
// Should only be used by console functions
|
||||
public:
|
||||
bool addMapping(const S32, const char**);
|
||||
|
||||
//-------------------------------------- Internal interface
|
||||
private:
|
||||
MapEntry* getNCMapEntry(StringTableEntry);
|
||||
|
||||
//-------------------------------------- Data
|
||||
private:
|
||||
Vector<MapEntry> mMapEntries;
|
||||
};
|
||||
|
||||
#endif // _H_MATERIALPROPERTYMAPPING_
|
||||
147
dgl/rectClipper.cc
Normal file
147
dgl/rectClipper.cc
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/rectClipper.h"
|
||||
|
||||
//#pragma message "Check to make sure new RectI semantics followed"
|
||||
|
||||
namespace {
|
||||
|
||||
inline void
|
||||
swap(F32& in_one, F32& in_two)
|
||||
{
|
||||
F32 temp = in_one;
|
||||
in_one = in_two;
|
||||
in_two = temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
RectClipper::clipLine(const Point2I& in_rStart,
|
||||
const Point2I& in_rEnd,
|
||||
Point2I& out_rStart,
|
||||
Point2I& out_rEnd) const
|
||||
{
|
||||
// Check for trivial rejection
|
||||
if ((in_rStart.x < m_clipRect.point.x && in_rEnd.x < m_clipRect.point.x) ||
|
||||
(in_rStart.x >= m_clipRect.point.x + m_clipRect.extent.x &&
|
||||
in_rEnd.x >= m_clipRect.point.x + m_clipRect.extent.x))
|
||||
return false;
|
||||
if ((in_rStart.y < m_clipRect.point.y && in_rEnd.y < m_clipRect.point.y) ||
|
||||
(in_rStart.y >= m_clipRect.point.y + m_clipRect.extent.y &&
|
||||
in_rEnd.y >= m_clipRect.point.y + m_clipRect.extent.y))
|
||||
return false;
|
||||
|
||||
F32 x1 = F32(in_rStart.x);
|
||||
F32 y1 = F32(in_rStart.y);
|
||||
F32 x2 = F32(in_rEnd.x);
|
||||
F32 y2 = F32(in_rEnd.y);
|
||||
|
||||
// I'm using essentially what's in the Phoenix libs, Liang-Biarsky based, but
|
||||
// converted to FP math for greater precision on the back end...
|
||||
//
|
||||
bool flipped = false;
|
||||
if (x1 > x2) {
|
||||
swap(x1, x2);
|
||||
swap(y1, y2);
|
||||
flipped = !flipped;
|
||||
}
|
||||
|
||||
F32 dx = x2 - x1;
|
||||
F32 dy = y2 - y1;
|
||||
|
||||
// Clip x coord
|
||||
F32 t;
|
||||
if (x1 < F32(m_clipRect.point.x)) {
|
||||
t = (F32(m_clipRect.point.x) - x1) / F32(dx);
|
||||
x1 = F32(m_clipRect.point.x);
|
||||
y1 += t * dy;
|
||||
dx = x2 - x1;
|
||||
dy = y2 - y1;
|
||||
}
|
||||
if (x2 >= F32(m_clipRect.point.x + m_clipRect.extent.x))
|
||||
{
|
||||
t = (F32(m_clipRect.point.x + m_clipRect.extent.x - 1) - x1) / F32(dx);
|
||||
x2 = F32(m_clipRect.point.x + m_clipRect.extent.x - 1);
|
||||
y2 = y1 + (t * dy);
|
||||
dx = x2 - x1;
|
||||
dy = y2 - y1;
|
||||
}
|
||||
|
||||
// Recheck trivial rejection condition...
|
||||
if((y1 > F32(m_clipRect.point.y + m_clipRect.extent.y - 1) &&
|
||||
y2 > F32(m_clipRect.point.y + m_clipRect.extent.y - 1)) ||
|
||||
(y1 < F32(m_clipRect.point.y) && y2 < F32(m_clipRect.point.y)))
|
||||
return false;
|
||||
|
||||
if (y1 > y2) {
|
||||
swap(x1, x2);
|
||||
swap(y1, y2);
|
||||
flipped = !flipped;
|
||||
}
|
||||
|
||||
if (y1 < F32(m_clipRect.point.y)) {
|
||||
t = (F32(m_clipRect.point.y) - y1) / F32(dy);
|
||||
y1 = F32(m_clipRect.point.y);
|
||||
x1 += t * dx;
|
||||
dx = x2 - x1;
|
||||
dy = y2 - y1;
|
||||
}
|
||||
if (y2 > F32(m_clipRect.point.y + m_clipRect.extent.y - 1))
|
||||
{
|
||||
t = (F32(m_clipRect.point.y + m_clipRect.extent.y - 1) - y1) / F32(dy);
|
||||
y2 = F32(m_clipRect.point.y + m_clipRect.extent.y - 1);
|
||||
x2 = x1 + (t * dx);
|
||||
}
|
||||
|
||||
if (flipped == true) {
|
||||
out_rEnd.x = S32(x1 + 0.5f);
|
||||
out_rEnd.y = S32(y1 + 0.5f);
|
||||
out_rStart.x = S32(x2 + 0.5f);
|
||||
out_rStart.y = S32(y2 + 0.5f);
|
||||
} else {
|
||||
out_rStart.x = S32(x1 + 0.5f);
|
||||
out_rStart.y = S32(y1 + 0.5f);
|
||||
out_rEnd.x = S32(x2 + 0.5f);
|
||||
out_rEnd.y = S32(y2 + 0.5f);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
RectClipper::clipRect(const RectI& in_rRect,
|
||||
RectI& out_rRect) const
|
||||
{
|
||||
AssertFatal(in_rRect.isValidRect(), "Inappropriate min/max coords for rectangle");
|
||||
|
||||
if (in_rRect.point.x + in_rRect.extent.x - 1 < m_clipRect.point.x ||
|
||||
in_rRect.point.x > m_clipRect.point.x + m_clipRect.extent.x - 1)
|
||||
return false;
|
||||
if (in_rRect.point.y + in_rRect.extent.y - 1 < m_clipRect.point.y ||
|
||||
in_rRect.point.y > m_clipRect.point.y + m_clipRect.extent.y - 1)
|
||||
return false;
|
||||
|
||||
if (in_rRect.point.x < m_clipRect.point.x) out_rRect.point.x = m_clipRect.point.x;
|
||||
else out_rRect.point.x = in_rRect.point.x;
|
||||
|
||||
if (in_rRect.point.y < m_clipRect.point.y) out_rRect.point.y = m_clipRect.point.y;
|
||||
else out_rRect.point.y = in_rRect.point.y;
|
||||
|
||||
Point2I bottomR;
|
||||
bottomR.x = getMin(in_rRect.point.x + in_rRect.extent.x - 1,
|
||||
m_clipRect.point.x + m_clipRect.extent.x - 1);
|
||||
bottomR.y = getMin(in_rRect.point.y + in_rRect.extent.y - 1,
|
||||
m_clipRect.point.y + m_clipRect.extent.y - 1);
|
||||
|
||||
out_rRect.extent.x = bottomR.x - out_rRect.point.x + 1;
|
||||
out_rRect.extent.x = bottomR.y - out_rRect.point.y + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
57
dgl/rectClipper.h
Normal file
57
dgl/rectClipper.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _RECTCLIPPER_H_
|
||||
#define _RECTCLIPPER_H_
|
||||
|
||||
//Includes
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MRECT_H_
|
||||
#include "Math/mRect.h"
|
||||
#endif
|
||||
|
||||
|
||||
class RectClipper
|
||||
{
|
||||
RectI m_clipRect;
|
||||
|
||||
public:
|
||||
RectClipper(const RectI& in_rRect);
|
||||
|
||||
bool clipPoint(const Point2I& in_rPoint) const;
|
||||
bool clipLine(const Point2I& in_rStart,
|
||||
const Point2I& in_rEnd,
|
||||
Point2I& out_rStart,
|
||||
Point2I& out_rEnd) const;
|
||||
bool clipRect(const RectI& in_rRect,
|
||||
RectI& out_rRect) const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- INLINES
|
||||
//
|
||||
inline
|
||||
RectClipper::RectClipper(const RectI& in_rRect)
|
||||
: m_clipRect(in_rRect)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
inline bool
|
||||
RectClipper::clipPoint(const Point2I& in_rPoint) const
|
||||
{
|
||||
if ((in_rPoint.x < m_clipRect.point.x) ||
|
||||
(in_rPoint.y < m_clipRect.point.y) ||
|
||||
(in_rPoint.x >= m_clipRect.point.x + m_clipRect.extent.x) ||
|
||||
(in_rPoint.y >= m_clipRect.point.y + m_clipRect.extent.y))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //_RECTCLIPPER_H_
|
||||
165
dgl/splineUtil.cc
Normal file
165
dgl/splineUtil.cc
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/splineUtil.h"
|
||||
|
||||
#include "PlatformWin32/platformGL.h"
|
||||
|
||||
namespace SplineUtil{
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Draws strip of specified width along spline. Polys on strip segments are
|
||||
// front-facing (billboarded)
|
||||
//------------------------------------------------------------------------------
|
||||
void drawSplineBeam( const Point3F& camPos, U32 numSegments,
|
||||
F32 width, SplinePatch &spline, F32 uvOffset, F32 numTexRep )
|
||||
{
|
||||
|
||||
Point3F beginPoint, endPoint;
|
||||
spline.calc( 0.0, beginPoint );
|
||||
spline.calc( 1.0, endPoint );
|
||||
|
||||
F32 approxBeamLength = (beginPoint - endPoint).len();
|
||||
F32 texRepFactor = approxBeamLength * numTexRep;
|
||||
|
||||
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
|
||||
|
||||
for( int i=0; i<numSegments; i++ )
|
||||
{
|
||||
F32 t = ((F32)i) / ((F32)(numSegments - 1));
|
||||
|
||||
Point3F curPoint;
|
||||
spline.calc( t, curPoint );
|
||||
|
||||
Point3F segmentDir;
|
||||
|
||||
// handle last segment case
|
||||
Point3F nextPoint;
|
||||
if( i == (numSegments - 1) )
|
||||
{
|
||||
F32 modT = ((F32)(numSegments - 1)) / ((F32)numSegments);
|
||||
spline.calc( modT, nextPoint );
|
||||
segmentDir = curPoint - nextPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 modT = t + (1.0 / numSegments);
|
||||
spline.calc( modT, nextPoint );
|
||||
segmentDir = nextPoint - curPoint;
|
||||
}
|
||||
|
||||
if( segmentDir.isZero() ) continue;
|
||||
segmentDir.normalize();
|
||||
|
||||
|
||||
Point3F dirFromCam = curPoint - camPos;
|
||||
Point3F crossVec;
|
||||
mCross(dirFromCam, segmentDir, &crossVec);
|
||||
crossVec.normalize();
|
||||
|
||||
crossVec *= width * 0.5;
|
||||
|
||||
F32 u = uvOffset + texRepFactor * t;
|
||||
|
||||
glTexCoord2f( u, 0.0 );
|
||||
glVertex3fv( curPoint + crossVec );
|
||||
|
||||
glTexCoord2f( u, 1.0 );
|
||||
glVertex3fv( curPoint - crossVec );
|
||||
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Draws strip of specified width along spline. Polys on strip segments are
|
||||
// front-facing (billboarded)
|
||||
//------------------------------------------------------------------------------
|
||||
void drawSplineBeam( SplineBeamInfo &sbi )
|
||||
{
|
||||
if( !sbi.camPos || !sbi.spline ) return;
|
||||
|
||||
Point3F beginPoint, endPoint;
|
||||
sbi.spline->calc( 0.0, beginPoint );
|
||||
sbi.spline->calc( 1.0, endPoint );
|
||||
|
||||
F32 approxBeamLength = (beginPoint - endPoint).len();
|
||||
F32 texRepFactor = approxBeamLength * sbi.numTexRep;
|
||||
|
||||
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
|
||||
|
||||
for( int i=0; i<sbi.numSegments; i++ )
|
||||
{
|
||||
F32 t = ((F32)i) / ((F32)(sbi.numSegments - 1));
|
||||
|
||||
Point3F curPoint;
|
||||
sbi.spline->calc( t, curPoint );
|
||||
|
||||
Point3F segmentDir;
|
||||
|
||||
// handle last segment case
|
||||
Point3F nextPoint;
|
||||
if( i == (sbi.numSegments - 1) )
|
||||
{
|
||||
F32 modT = ((F32)(sbi.numSegments - 1)) / ((F32)sbi.numSegments);
|
||||
sbi.spline->calc( modT, nextPoint );
|
||||
segmentDir = curPoint - nextPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 modT = t + (1.0 / sbi.numSegments);
|
||||
sbi.spline->calc( modT, nextPoint );
|
||||
segmentDir = nextPoint - curPoint;
|
||||
}
|
||||
|
||||
if( segmentDir.isZero() ) continue;
|
||||
segmentDir.normalize();
|
||||
|
||||
|
||||
Point3F dirFromCam = curPoint - *sbi.camPos;
|
||||
Point3F crossVec;
|
||||
mCross(dirFromCam, segmentDir, &crossVec);
|
||||
crossVec.normalize();
|
||||
|
||||
crossVec *= sbi.width * 0.5;
|
||||
|
||||
F32 u = sbi.uvOffset + texRepFactor * t;
|
||||
|
||||
if( i== 0 && sbi.zeroAlphaStart )
|
||||
{
|
||||
glColor4f( sbi.color.red, sbi.color.green, sbi.color.blue, 0.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4fv( sbi.color );
|
||||
}
|
||||
|
||||
glTexCoord2f( u, 0.0 );
|
||||
glVertex3fv( curPoint + crossVec );
|
||||
|
||||
glTexCoord2f( u, 1.0 );
|
||||
glVertex3fv( curPoint - crossVec );
|
||||
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // end SplineUtil namespace
|
||||
59
dgl/splineUtil.h
Normal file
59
dgl/splineUtil.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _SPLINEUTIL_H_
|
||||
#define _SPLINEUTIL_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "Math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _MSPLINEPATCH_H_
|
||||
#include "Math/mSplinePatch.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
|
||||
namespace SplineUtil
|
||||
{
|
||||
|
||||
struct SplineBeamInfo
|
||||
{
|
||||
Point3F * camPos;
|
||||
U32 numSegments;
|
||||
F32 width;
|
||||
SplinePatch * spline;
|
||||
F32 uvOffset;
|
||||
F32 numTexRep;
|
||||
ColorF color;
|
||||
bool zeroAlphaStart; // first part of first segment has 0 alpha value
|
||||
|
||||
SplineBeamInfo()
|
||||
{
|
||||
dMemset( this, 0, sizeof( SplineBeamInfo ) );
|
||||
numTexRep = 1.0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Draws strip of specified width along spline. Polys on strip segments are front-facing (billboarded)
|
||||
//------------------------------------------------------------------------------
|
||||
void drawSplineBeam( const Point3F& camPos, U32 numSegments, F32 width,
|
||||
SplinePatch &spline, F32 uvOffset = 0.0, F32 numTexRep = 1.0 );
|
||||
|
||||
void drawSplineBeam( SplineBeamInfo &sbi );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
59
dgl/stripCache.cc
Normal file
59
dgl/stripCache.cc
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/stripCache.h"
|
||||
#include "PlatformWin32/platformGL.h"
|
||||
|
||||
void StripCache::emitStrip(const U32 start, const U32 count, const ColorI& color)
|
||||
{
|
||||
if (count < 3) {
|
||||
AssertFatal(false, "Strip count < 3");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currIndex + count >= 1024)
|
||||
flushCache();
|
||||
|
||||
// Contiguous index enforcement
|
||||
if (currIndex != 0 && start != (stripIndices[currIndex - 1]+1))
|
||||
flushCache();
|
||||
|
||||
stripStarts[currStrip] = currIndex;
|
||||
stripColors[currStrip++] = color;
|
||||
for (U32 i = start; i < start+count; i++)
|
||||
stripIndices[currIndex++] = i;
|
||||
}
|
||||
|
||||
void StripCache::flushCache()
|
||||
{
|
||||
if (currIndex == 0)
|
||||
return;
|
||||
|
||||
// We know that (for right now) the first index is the least, and the
|
||||
// last is the greatest. The commented condition in the emitStrip
|
||||
// call makes sure this range is contiguous...
|
||||
U32 first = stripIndices[0];
|
||||
U32 last = stripIndices[currIndex-1];
|
||||
|
||||
stripStarts[currStrip] = currIndex;
|
||||
|
||||
if (dglDoesSupportCompiledVertexArray())
|
||||
glLockArraysEXT(first, last - first + 1);
|
||||
|
||||
for (U32 i = 0; i < currStrip; i++) {
|
||||
glColor4ubv(stripColors[i]);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, stripStarts[i+1] - stripStarts[i],
|
||||
GL_UNSIGNED_INT, &stripIndices[stripStarts[i]]);
|
||||
}
|
||||
|
||||
if (dglDoesSupportCompiledVertexArray())
|
||||
glUnlockArraysEXT();
|
||||
|
||||
currIndex = 0;
|
||||
currStrip = 0;
|
||||
}
|
||||
|
||||
35
dgl/stripCache.h
Normal file
35
dgl/stripCache.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _STRIPCACHE_H_
|
||||
#define _STRIPCACHE_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
|
||||
|
||||
class StripCache
|
||||
{
|
||||
U32 stripIndices[1024];
|
||||
U32 stripStarts[512];
|
||||
ColorI stripColors[512];
|
||||
U32 currIndex;
|
||||
U32 currStrip;
|
||||
|
||||
public:
|
||||
StripCache() { currIndex = 0; currStrip = 0; }
|
||||
|
||||
// Cache manages locking
|
||||
void emitStrip(const U32 start, const U32 end, const ColorI& color);
|
||||
void flushCache();
|
||||
};
|
||||
|
||||
#endif // _H_STRIPCACHE_
|
||||
Loading…
Add table
Add a link
Reference in a new issue