windows-nt/Source/XPSP1/NT/multimedia/opengl/toolkits/libmtk/texture.cxx
2020-09-26 16:20:57 +08:00

1079 lines
27 KiB
C++

/******************************Module*Header*******************************\
* Module Name: texture.c
*
* Texture handling functions
*
* Copyright (c) 1994 Microsoft Corporation
*
\**************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <time.h>
#include <windows.h>
#include <scrnsave.h>
#include <commdlg.h>
#include "mtk.h"
#include "texture.hxx"
#include "glutil.hxx"
//static int VerifyTextureFile( TEXFILE *pTexFile );
static int GetTexFileType( TEXFILE *pTexFile );
static PFNGLCOLORTABLEEXTPROC pfnColorTableEXT;
static PFNGLCOLORSUBTABLEEXTPROC pfnColorSubTableEXT;
/******************************Public*Routine******************************\
*
* TEXTURE
*
* Create a texture from a BMP or RGB file
*
\**************************************************************************/
TEXTURE::TEXTURE( TEXFILE *pTexFile )
{
TK_RGBImageRec *image = (TK_RGBImageRec *) NULL;
LPTSTR pszBmpfile = pTexFile->szPathName;
int type;
Init();
// Verify file / set type
if( !(type = mtk_VerifyTextureFileData( pTexFile )) )
return;
// While we're still calling into the tk routines, disable popups
// Eventually should pull tk code in here - all that's required is the
// file parsing code.
tkErrorPopups( FALSE );
//mf: I guess can't have TEX_A8 type file ?
if( type == TEX_BMP ) {
#ifdef UNICODE
image = tkDIBImageLoadAW( (char *) pszBmpfile, TRUE );
#else
image = tkDIBImageLoadAW( (char *) pszBmpfile, FALSE );
#endif
} else {
#ifdef UNICODE
image = tkRGBImageLoadAW( (char *) pszBmpfile, TRUE );
#else
image = tkRGBImageLoadAW( (char *) pszBmpfile, FALSE );
#endif
}
if( !image ) {
return;
}
ProcessTkTexture( image );
}
TEXTURE::TEXTURE( LPTSTR pszBmpFile )
{
TK_RGBImageRec *image = (TK_RGBImageRec *) NULL;
int type;
TEXFILE texFile; // path name, plus offset to file name
Init();
//mf: this VerifyFile stuff needs some work
// Look for file, and set nOffset if found
lstrcpy( texFile.szPathName, pszBmpFile );
if( ! mtk_VerifyTextureFilePath( &texFile ) )
return;
// Now determine the file type (this also aborts if size is too big)
if( !(type = mtk_VerifyTextureFileData( &texFile )) )
return;
// Now the bmp file should point to the full path for tk
pszBmpFile = texFile.szPathName;
//mf: I guess can't have TEX_A8 type file ?
if( type == TEX_BMP ) {
#ifdef UNICODE
image = tkDIBImageLoadAW( (char *) pszBmpFile, TRUE );
#else
image = tkDIBImageLoadAW( (char *) pszBmpFile, FALSE );
#endif
} else {
#ifdef UNICODE
image = tkRGBImageLoadAW( (char *) pszBmpFile, TRUE );
#else
image = tkRGBImageLoadAW( (char *) pszBmpFile, FALSE );
#endif
}
if( !image ) {
return;
}
ProcessTkTexture( image );
}
/******************************Public*Routine******************************\
*
* TEXTURE
*
* Create a texture from a BMP or other resource (RGB , A8, etc. )
*
\**************************************************************************/
TEXTURE::TEXTURE( TEX_RES *pTexRes, HINSTANCE hInst )
{
HMODULE hModule;
Init();
if( hInst )
hModule = hInst;
else
hModule = GetModuleHandle(NULL);
if( pTexRes->type == TEX_BMP )
LoadBitmapResource( MAKEINTRESOURCE( pTexRes->name ), hModule );
else
LoadOtherResource( pTexRes, hModule );
}
/******************************Public*Routine******************************\
*
* TEXTURE
*
* Create a texture from an HBITMAP
*
\**************************************************************************/
TEXTURE::TEXTURE( HBITMAP hBitmap )
{
if (hBitmap == NULL)
{
SS_ERROR( "TEXTURE::TEXTURE : hBitmap is NULL\n" );
return;
}
Init();
LoadFromBitmap( hBitmap );
}
/******************************Public*Routine******************************\
*
* Load a bitmap texture resource, creating the HBITMAP from the resource
* identifier
*
\**************************************************************************/
BOOL
TEXTURE::LoadBitmapResource( LPTSTR pRes, HINSTANCE hInst )
{
HBITMAP hBitmap = LoadBitmap( hInst, pRes );
if( hBitmap == NULL ) {
SS_ERROR( "TEXTURE::LoadBitmapResource : LoadBitmap failure\n" );
return FALSE;
}
LoadFromBitmap( hBitmap );
DeleteObject( hBitmap );
return TRUE;
}
/******************************Public*Routine******************************\
*
* Load a non-bmp texture resource
*
\**************************************************************************/
BOOL
TEXTURE::LoadOtherResource( TEX_RES *pTexRes, HINSTANCE hInst )
{
HRSRC hr;
HGLOBAL hg;
LPVOID pv;
LPCTSTR lpType;
BOOL fLoaded = FALSE;
switch(pTexRes->type)
{
case TEX_RGB:
lpType = MAKEINTRESOURCE(RT_RGB);
break;
case TEX_A8:
lpType = MAKEINTRESOURCE(RT_A8);
break;
default :
return FALSE;
}
hr = FindResource(hInst, MAKEINTRESOURCE(pTexRes->name), lpType);
if (hr == NULL)
{
SS_ERROR( "TEXTURE::LoadOtherResource() : Can't find texture resource\n" );
goto EH_NotFound;
}
hg = LoadResource(hInst, hr);
if (hg == NULL)
{
SS_ERROR( "TEXTURE::LoadOtherResource() : Error loading texture resource\n" );
goto EH_FreeResource;
}
pv = (PSZ)LockResource(hg);
if (pv == NULL)
{
SS_ERROR( "TEXTURE::LoadOtherResource() : Error locking texture resource\n" );
goto EH_FreeResource;
}
switch(pTexRes->type)
{
case TEX_RGB:
fLoaded = RGBImageLoad( pv );
break;
case TEX_A8:
fLoaded = A8ImageLoad( pv );
break;
}
EH_FreeResource:
FreeResource(hr);
EH_NotFound:
if( !fLoaded ) {
SS_ERROR( "TEXTURE::LoadOtherResource() : Texture resource did not load\n" );
return FALSE;
}
Process();
return TRUE;
}
/******************************Public*Routine******************************\
*
* Load a bitmap texture resource from an HBITMAP
*
\**************************************************************************/
BOOL
TEXTURE::LoadFromBitmap( HBITMAP hBitmap )
{
BOOL fLoaded = DIBImageLoad( hBitmap );
if( !fLoaded ) {
SS_ERROR( "TEXTURE::LoadFromBitmap : bitmap texture did not load\n" );
return FALSE;
}
Process();
return TRUE;
}
/******************************Public*Routine******************************\
*
* Init
*
* Common constructor intialization
*
\**************************************************************************/
void
TEXTURE::Init()
{
width = 0;
height = 0;
data = NULL;
pal_size = 0;
pal = NULL;
texObj = 0;
iPalRot = 0;
bMipmap = FALSE;
}
/******************************Public*Routine******************************\
*
* ValidateTextureSize
*
* - Scales the texture to powers of 2
*
\**************************************************************************/
BOOL
TEXTURE::ValidateSize()
{
double xPow2, yPow2;
int ixPow2, iyPow2;
int xSize2, ySize2;
float fxFact, fyFact;
GLint glMaxTexDim;
if( (width <= 0) || (height <= 0) ) {
SS_WARNING( "ValidateTextureSize : invalid texture dimensions\n" );
return FALSE;
}
// origAspectRatio = (float) height / (float) width;
//mf: changed this to standard x/y
origAspectRatio = (float) width / (float) height;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim);
if( glMaxTexDim <= 0 )
return FALSE;
if( format != GL_COLOR_INDEX ) {
// We limit the max dimension here for performance reasons
glMaxTexDim = min(256, glMaxTexDim);
if (width <= glMaxTexDim)
xPow2 = log((double)width) / log((double)2.0);
else
xPow2 = log((double)glMaxTexDim) / log((double)2.0);
if (height <= glMaxTexDim)
yPow2 = log((double)height) / log((double)2.0);
else
yPow2 = log((double)glMaxTexDim) / log((double)2.0);
ixPow2 = (int)xPow2;
iyPow2 = (int)yPow2;
// Always scale to higher nearest power
if (xPow2 != (double)ixPow2)
ixPow2++;
if (yPow2 != (double)iyPow2)
iyPow2++;
xSize2 = 1 << ixPow2;
ySize2 = 1 << iyPow2;
if (xSize2 != width ||
ySize2 != height)
{
BYTE *pData;
pData = (BYTE *) malloc(xSize2 * ySize2 * components * sizeof(BYTE));
if (!pData) {
SS_WARNING( "ValidateTextureSize : can't alloc pData\n" );
return FALSE;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if( gluScaleImage(format, width, height,
GL_UNSIGNED_BYTE, data,
xSize2, ySize2, GL_UNSIGNED_BYTE,
pData) )
{
// glu failure
SS_WARNING( "ValidateTextureSize : gluScaleImage failure\n" );
return FALSE;
}
// set the new width,height,data
width = xSize2;
height = ySize2;
free(data);
data = pData;
}
} else { // paletted texture case
//mf
// paletted texture: must be power of 2 - but might need to enforce
// here if not done in a8 load. Also have to check against
// GL_MAX_TEXTURE_SIZE. Could then clip it to power of 2 size
}
return TRUE;
}
/******************************Public*Routine******************************\
*
* SetDefaultTextureParams
*
\**************************************************************************/
void
TEXTURE::SetDefaultParams()
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if( bMipmap )
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
/******************************Public*Routine******************************\
*
* ProcessTexture
*
* - Verifies texture size
* - Fills out TEXTURE structure with required data
* - Creates a texture object if extension exists
*
\**************************************************************************/
int
TEXTURE::Process()
{
// Enforce proper texture size (power of 2, etc.)
if( !ValidateSize() )
return 0;
// if texturing objects available, init the object
if( gGLCaps.bTextureObjects ) {
glGenTextures( 1, &texObj );
glBindTexture( GL_TEXTURE_2D, texObj );
//mf: mipmap stuff
// Default attributes for texObj
SetDefaultParams();
if( bMipmap )
//mf: error return...
gluBuild2DMipmaps( GL_TEXTURE_2D, components,
width, height, format,
GL_UNSIGNED_BYTE, data );
else
glTexImage2D( GL_TEXTURE_2D, 0, components,
width, height, 0, format,
GL_UNSIGNED_BYTE, data );
if (gGLCaps.bPalettedTexture && pal != NULL)
{
pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pal_size,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, pal);
}
} else
texObj = 0;
return 1;
}
/******************************Public*Routine******************************\
*
* ProcessTkTexture
*
* Simple wrapper for ProcessTexture which fills out a TEXTURE
* from a TK_RGBImageRec
*
* Frees the ImageRec if ProcessTexture succeeds
*
\**************************************************************************/
int
TEXTURE::ProcessTkTexture( TK_RGBImageRec *image )
{
width = image->sizeX;
height = image->sizeY;
format = GL_RGB;
components = 3;
data = image->data;
pal_size = 0;
pal = NULL;
if( Process() )
{
//mf: ?? don't understand this freeing stuff...
free(image);
return 1;
}
else
{
return 0;
}
}
/******************************Public*Routine******************************\
*
* MakeCurrent
*
\**************************************************************************/
void
TEXTURE::MakeCurrent()
{
if( texObj ) {
glBindTexture( GL_TEXTURE_2D, texObj );
return;
}
if( bMipmap )
gluBuild2DMipmaps( GL_TEXTURE_2D, components,
width, height, format,
GL_UNSIGNED_BYTE, data );
else
glTexImage2D( GL_TEXTURE_2D, 0, components,
width, height, 0, format,
GL_UNSIGNED_BYTE, data );
//mf: ? no rotation if no tex objs ?
if( pal )
{
pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pal_size,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, pal);
}
}
#if 0
/******************************Public*Routine******************************\
*
* ss_CopyTexture
*
* Make a copy of a texture.
*
\**************************************************************************/
BOOL
TEXTURE::ss_CopyTexture( TEXTURE *pTexDst, TEXTURE *pTexSrc )
{
int size;
if( (pTexDst == NULL) || (pTexSrc == NULL) )
return FALSE;
*pTexDst = *pTexSrc;
if( gGLCaps.bTextureObjects && pTexSrc->texObj ) {
glGenTextures( 1, &pTexDst->texObj );
}
// copy image data
size = pTexSrc->width * pTexSrc->height;
if( pTexSrc->components != GL_COLOR_INDEX8_EXT )
size *= pTexSrc->components; // since data format always UNSIGNED_BYTE
pTexDst->data = (unsigned char *) malloc( size );
if( pTexDst->pal == NULL )
return FALSE;
memcpy( pTexDst->data, pTexSrc->data, size );
// copy palette data
if( gGLCaps.bPalettedTexture && pTexSrc->pal != NULL )
{
size = pTexSrc->pal_size*sizeof(RGBQUAD);
pTexDst->pal = (RGBQUAD *) malloc(size);
if( pTexDst->pal == NULL )
{
free(pTexDst->data);
return FALSE;
}
memcpy( pTexDst->pal, pTexSrc->pal, size );
}
if( pTexDst->texObj ) {
glBindTexture( GL_TEXTURE_2D, pTexDst->texObj );
// Default attributes for texObj
SetDefaultTextureParams( pTexDst );
if( pTexDst->bMipmap )
gluBuild2DMipmaps( GL_TEXTURE_2D, pTexDst->components,
pTexDst->width, pTexDst->height, pTexDst->format,
GL_UNSIGNED_BYTE, pTexDst->data );
else
glTexImage2D( GL_TEXTURE_2D, 0, pTexDst->components,
pTexDst->width, pTexDst->height, 0, pTexDst->format,
GL_UNSIGNED_BYTE, pTexDst->data );
if( pTexDst->pal )
{
pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pTexDst->pal_size,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, pTexDst->pal);
}
}
return TRUE;
}
#endif
/******************************Public*Routine******************************\
*
* ss_SetTexturePalette
*
* Set a texture's palette according to the supplied index. This index
* indicates the start of the palette, which then wraps around if necessary.
* Of course this only works on paletted textures.
*
\**************************************************************************/
void
TEXTURE::SetPaletteRotation( int index )
{
if( index == iPalRot )
return;
if( pal && pal_size ) {
iPalRot = index & (pal_size - 1);
MakeCurrent();
SetPalette();
}
}
void
TEXTURE::IncrementPaletteRotation()
{
if( pal && pal_size ) {
iPalRot = ++iPalRot & (pal_size - 1);
MakeCurrent();
SetPalette();
}
}
void
TEXTURE::SetPalette()
{
int start, count;
start = iPalRot & (pal_size - 1);
count = pal_size - start;
pfnColorSubTableEXT(GL_TEXTURE_2D, 0, count, GL_BGRA_EXT,
GL_UNSIGNED_BYTE, pal + start);
if (start != 0)
{
pfnColorSubTableEXT(GL_TEXTURE_2D, count, start, GL_BGRA_EXT,
GL_UNSIGNED_BYTE, pal);
}
}
/******************************Public*Routine******************************\
*
* SetTextureAlpha
*
* Set a constant alpha value for the texture
* Again, don't overwrite any existing 0 alpha values, as explained in
* ss_SetTextureTransparency
*
\**************************************************************************/
void
TEXTURE::SetAlpha( float fAlpha )
{
int i;
unsigned char *pData = data;
RGBA8 *pColor = (RGBA8 *) data;
BYTE bAlpha = (BYTE) (fAlpha * 255.0f);
if( components != 4 )
return;
for( i = 0; i < width*height; i ++, pColor++ ) {
if( pColor->a != 0 )
pColor->a = bAlpha;
}
}
/******************************Public*Routine******************************\
*
* ConvertToRGBA
*
* Convert RGB texture to RGBA
*
\**************************************************************************/
BOOL
TEXTURE::ConvertToRGBA( float fAlpha )
{
unsigned char *pNewData;
int count = width * height;
unsigned char *src, *dst;
BYTE bAlpha = (BYTE) (fAlpha * 255.0f);
int i;
if( components != 3 ) {
SS_ERROR( "TEXTURE::ConvertToRGBA : Can't convert, components != 3\n" );
return FALSE;
}
pNewData = (unsigned char *) LocalAlloc(LMEM_FIXED, count * sizeof(RGBA8));
if( !pNewData ) {
SS_ERROR( "TEXTURE::ConvertToRGBA : memory failure\n" );
return FALSE;
}
src = data;
dst = pNewData;
if( format == GL_RGB ) {
// R is lsb, A will be msb
for( i = 0; i < count; i ++ ) {
*((RGB8 *)dst) = *((RGB8 *)src);
dst += sizeof(RGB8);
src += sizeof(RGB8);
*dst++ = bAlpha;
}
format = GL_RGBA;
} else { // format == GL_BGR_EXT
// R is msb, A will be msb
for( i = 0; i < count; i ++ ) {
*dst++ = bAlpha;
*((RGB8 *)dst) = *((RGB8 *)src);
dst += sizeof(RGB8);
src += sizeof(RGB8);
}
format = GL_BGRA_EXT;
}
LocalFree( data );
data = pNewData;
components = 4;
return TRUE;
}
/******************************Public*Routine******************************\
*
* ss_SetTextureTransparency
*
* Set transparency for a texture by adding or modifying the alpha data.
* Transparency value must be between 0.0 (opaque) and 1.0 (fully transparent)
* If the texture data previously had no alpha, add it in.
* If bSet is TRUE, make this the current texture.
*
* Note: Currently fully transparent pixels (alpha=0) will not be altered, since
* it is assumed these should be permanently transparent (could make this an
* option? - bPreserveTransparentPixels )
*
\**************************************************************************/
BOOL
TEXTURE::SetTransparency( float fTransp, BOOL bSet )
{
int i;
float fAlpha;
SS_CLAMP_TO_RANGE2( fTransp, 0.0f, 1.0f );
fAlpha = 1 - fTransp;
if( format == GL_COLOR_INDEX )
{
// just need to modify the palette
RGBQUAD *pPal = pal;
BYTE bAlpha = (BYTE) (fAlpha * 255.0f);
if( !pPal )
return FALSE;
for( i = 0; i < pal_size; i ++, pPal++ ) {
if( pPal->rgbReserved != 0 )
pPal->rgbReserved = bAlpha;
}
// need to send down the new palette for texture objects
if( texObj && pal )
{
glBindTexture( GL_TEXTURE_2D, texObj );
pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pal_size,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, pal);
}
}
else {
// Need to setup new texture data
if( components != 4 ) {
// Make room for alpha component
//mf: ? change to byte Alpha ?
if( !ConvertToRGBA( fAlpha ) )
return FALSE;
} else {
// Set alpha component
SetAlpha( fAlpha );
}
// Send down new data if texture objects
if( texObj )
{
glBindTexture( GL_TEXTURE_2D, texObj );
if( bMipmap )
//mf: inefficient !!!
gluBuild2DMipmaps( GL_TEXTURE_2D, components,
width, height, format,
GL_UNSIGNED_BYTE, data );
else
glTexImage2D( GL_TEXTURE_2D, 0, components,
width, height, 0, format,
GL_UNSIGNED_BYTE, data );
}
}
if( bSet )
MakeCurrent();
return TRUE;
}
/******************************Public*Routine******************************\
*
* ss_DeleteTexture
*
\**************************************************************************/
TEXTURE::~TEXTURE()
{
if( texObj ) {
glDeleteTextures( 1, &texObj );
}
if (pal != NULL)
{
free(pal);
}
if( data )
free( data );
}
/******************************Public*Routine******************************\
*
* ss_TextureObjectsEnabled
*
* Returns BOOL set by ss_QueryGLVersion (Texture Objects only supported on
* GL v.1.1 or greater)
*
\**************************************************************************/
BOOL
mtk_TextureObjectsEnabled( void )
{
return gGLCaps.bTextureObjects;
}
/******************************Public*Routine******************************\
*
* ss_PalettedTextureEnabled
*
* Returns result from ss_QueryPalettedTextureEXT
*
\**************************************************************************/
BOOL
mtk_PalettedTextureEnabled( void )
{
return gGLCaps.bPalettedTexture;
}
/******************************Public*Routine******************************\
*
* ss_QueryPalettedTextureEXT
*
* Queries the OpenGL implementation to see if paletted texture is supported
* Typically called once at app startup.
*
\**************************************************************************/
BOOL
mtk_QueryPalettedTextureEXT( void )
{
PFNGLGETCOLORTABLEPARAMETERIVEXTPROC pfnGetColorTableParameterivEXT;
int size;
pfnColorTableEXT = (PFNGLCOLORTABLEEXTPROC)
wglGetProcAddress("glColorTableEXT");
if (pfnColorTableEXT == NULL)
return FALSE;
pfnColorSubTableEXT = (PFNGLCOLORSUBTABLEEXTPROC)
wglGetProcAddress("glColorSubTableEXT");
if (pfnColorSubTableEXT == NULL)
return FALSE;
// Check color table size
pfnGetColorTableParameterivEXT = (PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)
wglGetProcAddress("glGetColorTableParameterivEXT");
if (pfnGetColorTableParameterivEXT == NULL)
return FALSE;
// For now, the only paletted textures supported in this lib are TEX_A8,
// with 256 color table entries. Make sure the device supports this.
pfnColorTableEXT(GL_PROXY_TEXTURE_2D, GL_RGBA, 256,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL );
pfnGetColorTableParameterivEXT( GL_PROXY_TEXTURE_2D,
GL_COLOR_TABLE_WIDTH_EXT, &size );
if( size != 256 )
// The device does not support a color table size of 256, so we don't
// enable paletted textures in general.
return FALSE;
return TRUE;
}
/******************************Public*Routine******************************\
*
* ss_VerifyTextureFile
*
* Validates texture bmp or rgb file, by checking for valid pathname and
* correct format.
*
* History
* Apr. 28, 95 : [marcfo]
* - Wrote it
*
* Jul. 25, 95 : [marcfo]
* - Suppress warning dialog box in child preview mode, as it will
* be continuously brought up.
*
* Dec. 12, 95 : [marcfo]
* - Support .rgb files as well
*
* Dec. 14, 95 : [marcfo]
* - Change to have it only check the file path
*
\**************************************************************************/
//mf: this can become a standard file function
BOOL
mtk_VerifyTextureFilePath( TEXFILE *ptf )
{
// Make sure the selected texture file is OK.
ISIZE size;
TCHAR szFileName[MAX_PATH];
PTSTR pszString;
TCHAR szString[MAX_PATH];
lstrcpy(szFileName, ptf->szPathName);
if ( SearchPath(NULL, szFileName, NULL, MAX_PATH,
ptf->szPathName, &pszString)
)
{
ptf->nOffset = pszString - ptf->szPathName;
return TRUE;
}
else
{
lstrcpy(ptf->szPathName, szFileName); // restore
return FALSE;
}
}
/******************************Public*Routine******************************\
*
* VerifyTextureFile
*
* Verify that a bitmap or rgb file is valid
*
* Returns:
* File type (RGB or BMP) if valid file; otherwise, 0.
*
* History
* Dec. 12, 95 : [marcfo]
* - Creation
*
\**************************************************************************/
int
mtk_VerifyTextureFileData( TEXFILE *pTexFile )
{
int type;
ISIZE size;
BOOL bValid;
TCHAR szString[2 * MAX_PATH]; // May contain a pathname
// check for 0 offset and null strings
if( (pTexFile->nOffset == 0) || (*pTexFile->szPathName == 0) )
return 0;
type = GetTexFileType( pTexFile );
switch( type ) {
case TEX_BMP:
bValid = bVerifyDIB( pTexFile->szPathName, &size );
break;
case TEX_RGB:
bValid = bVerifyRGB( pTexFile->szPathName, &size );
break;
case TEX_UNKNOWN:
default:
bValid = FALSE;
}
if( !bValid ) {
return 0;
}
// Check size ?
if ( (size.width > TEX_WIDTH_MAX) ||
(size.height > TEX_HEIGHT_MAX) )
{
return 0;
}
return type;
}
/******************************Public*Routine******************************\
*
* ss_InitAutoTexture
*
* Generate texture coordinates automatically.
* If pTexRep is not NULL, use it to set the repetition of the generated
* texture.
*
\**************************************************************************/
void
mtk_InitAutoTexture( TEX_POINT2D *pTexRep )
{
GLfloat sgenparams[] = {1.0f, 0.0f, 0.0f, 0.0f};
GLfloat tgenparams[] = {0.0f, 1.0f, 0.0f, 0.0f};
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
if( pTexRep )
sgenparams[0] = pTexRep->s;
glTexGenfv(GL_S, GL_OBJECT_PLANE, sgenparams );
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
if( pTexRep )
tgenparams[0] = pTexRep->t;
glTexGenfv(GL_T, GL_OBJECT_PLANE, tgenparams );
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable( GL_TEXTURE_2D );
}
/******************************Public*Routine******************************\
*
* GetTexFileType
*
* Determine if a texture file is rgb or bmp, based on extension. This is
* good enough, as the open texture dialog only shows files with these
* extensions.
*
\**************************************************************************/
static int
GetTexFileType( TEXFILE *pTexFile )
{
LPTSTR pszStr;
#ifdef UNICODE
pszStr = wcsrchr( pTexFile->szPathName + pTexFile->nOffset,
(USHORT) L'.' );
#else
pszStr = strrchr( pTexFile->szPathName + pTexFile->nOffset,
(USHORT) L'.' );
#endif
if( !pszStr || (lstrlen(++pszStr) == 0) )
return TEX_UNKNOWN;
if( !lstrcmpi( pszStr, TEXT("bmp") ) )
return TEX_BMP;
else if( !lstrcmpi( pszStr, TEXT("rgb") ) )
return TEX_RGB;
else
return TEX_UNKNOWN;
}