|
|
/******************************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 <GL/gl.h>
#include "tk.h"
#include "scrnsave.h" // for hMainInstance
#include "sscommon.h"
#include "texture.h"
static int ProcessTexture( TEXTURE *pTex ); static int ProcessTkTexture( TK_RGBImageRec *image, TEXTURE *pTex ); static int VerifyTextureFile( TEXFILE *pTexFile ); static int GetTexFileType( TEXFILE *pTexFile );
static TEX_STRINGS gts = {0}; BOOL gbTextureObjects = FALSE; static BOOL gbPalettedTexture = FALSE; static PFNGLCOLORTABLEEXTPROC pfnColorTableEXT; static PFNGLCOLORSUBTABLEEXTPROC pfnColorSubTableEXT;
static BOOL gbEnableErrorMsgs = FALSE;
/******************************Public*Routine******************************\
* * ss_LoadTextureResourceStrings * * Load various messages and strings that are used in processing textures, * into global TEX_STRINGS structure * \**************************************************************************/
BOOL ss_LoadTextureResourceStrings() { LPTSTR pszStr;
// title for choose texture File dialog
LoadString(hMainInstance, IDS_TEXTUREDIALOGTITLE, gts.szTextureDialogTitle, GEN_STRING_SIZE); LoadString(hMainInstance, IDS_BMP, gts.szBmp, GEN_STRING_SIZE); LoadString(hMainInstance, IDS_DOTBMP, gts.szDotBmp, GEN_STRING_SIZE);
// szTextureFilter requires a little more work. Need to assemble the file
// name filter string, which is composed of two strings separated by a NULL
// and terminated with a double NULL.
LoadString(hMainInstance, IDS_TEXTUREFILTER, gts.szTextureFilter, GEN_STRING_SIZE); pszStr = >s.szTextureFilter[lstrlen(gts.szTextureFilter)+1]; LoadString(hMainInstance, IDS_STARDOTBMP, pszStr, GEN_STRING_SIZE); pszStr += lstrlen(pszStr); *pszStr++ = TEXT(';'); LoadString(hMainInstance, IDS_STARDOTRGB, pszStr, GEN_STRING_SIZE); pszStr += lstrlen(pszStr); pszStr++; *pszStr = TEXT('\0');
LoadString(hMainInstance, IDS_WARNING, gts.szWarningMsg, MAX_PATH); LoadString(hMainInstance, IDS_SELECT_ANOTHER_BITMAP, gts.szSelectAnotherBitmapMsg, MAX_PATH );
LoadString(hMainInstance, IDS_BITMAP_INVALID, gts.szBitmapInvalidMsg, MAX_PATH ); LoadString(hMainInstance, IDS_BITMAP_SIZE, gts.szBitmapSizeMsg, MAX_PATH );
// assumed here that all above calls loaded properly (mf: fix later)
return TRUE; }
/******************************Public*Routine******************************\
* * \**************************************************************************/
void ss_DisableTextureErrorMsgs() { gbEnableErrorMsgs = FALSE; }
/******************************Public*Routine******************************\
* * ss_LoadBMPTextureFile * * Loads a BMP file and prepares it for GL usage * \**************************************************************************/
int ss_LoadBMPTextureFile( LPCTSTR pszBmpfile, TEXTURE *pTex ) { TK_RGBImageRec *image = (TK_RGBImageRec *) NULL;
#ifdef UNICODE
image = tkDIBImageLoadAW( (char *) pszBmpfile, TRUE ); #else
image = tkDIBImageLoadAW( (char *) pszBmpfile, FALSE ); #endif
if( !image ) { return 0; } return ProcessTkTexture( image, pTex ); }
/******************************Public*Routine******************************\
* * ss_LoadTextureFile * * Loads a BMP file and prepares it for GL usage * \**************************************************************************/
int ss_LoadTextureFile( TEXFILE *pTexFile, TEXTURE *pTex ) { TK_RGBImageRec *image = (TK_RGBImageRec *) NULL; LPTSTR pszBmpfile = pTexFile->szPathName; int type; LPTSTR pszStr;
// Verify file / set type
if( !(type = VerifyTextureFile( pTexFile )) ) return 0;
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 0; } return ProcessTkTexture( image, pTex ); }
/******************************Public*Routine******************************\
* * ss_LoadTextureResource * * Loads a BMP or RGB texture resource and prepares it for GL usage * \**************************************************************************/
int ss_LoadTextureResource( TEX_RES *pTexRes, TEXTURE *pTex ) { HMODULE ghmodule; HRSRC hr; HGLOBAL hg; LPVOID pv; LPCTSTR lpType; BOOL fLoaded = FALSE;
ghmodule = GetModuleHandle(NULL); switch(pTexRes->type) { case TEX_RGB: lpType = MAKEINTRESOURCE(RT_RGB); break; case TEX_BMP: lpType = MAKEINTRESOURCE(RT_MYBMP); break; case TEX_A8: lpType = MAKEINTRESOURCE(RT_A8); break; }
hr = FindResource(ghmodule, MAKEINTRESOURCE(pTexRes->name), lpType); if (hr == NULL) { goto EH_NotFound; } hg = LoadResource(ghmodule, hr); if (hg == NULL) { goto EH_FreeResource; } pv = (PSZ)LockResource(hg); if (pv == NULL) { goto EH_FreeResource; }
switch(pTexRes->type) { case TEX_RGB: fLoaded = ss_RGBImageLoad( pv, pTex ); break; case TEX_BMP: fLoaded = ss_DIBImageLoad( pv, pTex ); break; case TEX_A8: fLoaded = ss_A8ImageLoad( pv, pTex ); break; }
EH_FreeResource: FreeResource(hr); EH_NotFound: if( !fLoaded ) { return 0; }
return ProcessTexture( pTex ); }
/******************************Public*Routine******************************\
* * ValidateTextureSize * * - Scales the texture to powers of 2 * \**************************************************************************/
static BOOL ValidateTextureSize( TEXTURE *pTex ) { double xPow2, yPow2; int ixPow2, iyPow2; int xSize2, ySize2; float fxFact, fyFact; GLint glMaxTexDim;
if( (pTex->width <= 0) || (pTex->height <= 0) ) { SS_WARNING( "ValidateTextureSize : invalid texture dimensions\n" ); return FALSE; }
pTex->origAspectRatio = (float) pTex->height / (float) pTex->width;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); if( glMaxTexDim <= 0 ) return FALSE;
if( pTex->format != GL_COLOR_INDEX ) {
// We limit the max dimension here for performance reasons
glMaxTexDim = min(256, glMaxTexDim);
if (pTex->width <= glMaxTexDim) xPow2 = log((double)pTex->width) / log((double)2.0); else xPow2 = log((double)glMaxTexDim) / log((double)2.0);
if (pTex->height <= glMaxTexDim) yPow2 = log((double)pTex->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 != pTex->width || ySize2 != pTex->height) { BYTE *pData;
pData = (BYTE *) malloc(xSize2 * ySize2 * pTex->components * sizeof(BYTE)); if (!pData) { SS_WARNING( "ValidateTextureSize : can't alloc pData\n" ); return FALSE; }
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if( gluScaleImage(pTex->format, pTex->width, pTex->height, GL_UNSIGNED_BYTE, pTex->data, xSize2, ySize2, GL_UNSIGNED_BYTE, pData) ) { // glu failure
SS_WARNING( "ValidateTextureSize : gluScaleImage failure\n" ); free(pData); return FALSE; } // set the new width,height,data
pTex->width = xSize2; pTex->height = ySize2; free(pTex->data); pTex->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 * \**************************************************************************/
static void SetDefaultTextureParams() { 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); 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 * \**************************************************************************/
static int ProcessTexture( TEXTURE *pTex ) { // Enforce proper texture size (power of 2, etc.)
if( !ValidateTextureSize( pTex ) ) return 0;
// if texturing objects available, init the object
if( gbTextureObjects ) { glGenTextures( 1, &pTex->texObj ); glBindTexture( GL_TEXTURE_2D, pTex->texObj );
// Default attributes for texObj
SetDefaultTextureParams();
glTexImage2D( GL_TEXTURE_2D, 0, pTex->components, pTex->width, pTex->height, 0, pTex->format, GL_UNSIGNED_BYTE, pTex->data ); if (gbPalettedTexture && pTex->pal != NULL) { pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pTex->pal_size, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pTex->pal); } } else pTex->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 * \**************************************************************************/
static int ProcessTkTexture( TK_RGBImageRec *image, TEXTURE *pTex ) {
pTex->width = image->sizeX; pTex->height = image->sizeY; pTex->format = GL_RGB; pTex->components = 3; pTex->data = image->data; pTex->pal_size = 0; pTex->pal = NULL;
if( ProcessTexture( pTex ) ) { free(image); return 1; } else { return 0; } } /******************************Public*Routine******************************\
* * ss_SetTexture * \**************************************************************************/
void ss_SetTexture( TEXTURE *pTex ) { if( pTex == NULL ) return;
if( gbTextureObjects && pTex->texObj ) { glBindTexture( GL_TEXTURE_2D, pTex->texObj ); return; } glTexImage2D( GL_TEXTURE_2D, 0, pTex->components, pTex->width, pTex->height, 0, pTex->format, GL_UNSIGNED_BYTE, pTex->data ); if (gbPalettedTexture && pTex->pal != NULL) { pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pTex->pal_size, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pTex->pal); } }
/******************************Public*Routine******************************\
* * ss_CopyTexture * * Make a copy of a texture. * \**************************************************************************/
BOOL ss_CopyTexture( TEXTURE *pTexDst, TEXTURE *pTexSrc ) { int size;
if( (pTexDst == NULL) || (pTexSrc == NULL) ) return FALSE;
*pTexDst = *pTexSrc;
if( gbTextureObjects && 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( gbPalettedTexture && 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( gbTextureObjects ) { glBindTexture( GL_TEXTURE_2D, pTexDst->texObj );
// Default attributes for texObj
SetDefaultTextureParams();
glTexImage2D( GL_TEXTURE_2D, 0, pTexDst->components, pTexDst->width, pTexDst->height, 0, pTexDst->format, GL_UNSIGNED_BYTE, pTexDst->data ); if( gbPalettedTexture && (pTexDst->pal != NULL) ) { pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pTexDst->pal_size, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pTexDst->pal); } } return TRUE; }
/******************************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 ss_SetTexturePalette( TEXTURE *pTex, int index ) { if( pTex == NULL ) return;
if( gbTextureObjects ) ss_SetTexture( pTex );
if( gbPalettedTexture && pTex->pal != NULL ) { int start, count;
start = index & (pTex->pal_size - 1); count = pTex->pal_size - start; pfnColorSubTableEXT(GL_TEXTURE_2D, 0, count, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pTex->pal + start); if (start != 0) { pfnColorSubTableEXT(GL_TEXTURE_2D, count, start, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pTex->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 * \**************************************************************************/
static void SetTextureAlpha( TEXTURE *pTex, float fAlpha ) { int i; unsigned char *pData = pTex->data; RGBA8 *pColor = (RGBA8 *) pTex->data; BYTE bAlpha = (BYTE) (fAlpha * 255.0f);
if( pTex->components != 4 ) return;
for( i = 0; i < pTex->width*pTex->height; i ++, pColor++ ) { if( pColor->a != 0 ) pColor->a = bAlpha; } }
/******************************Public*Routine******************************\
* * ConvertTextureToRGBA * * Convert RGB texture to RGBA * \**************************************************************************/
static void ConvertTextureToRGBA( TEXTURE *pTex, float fAlpha ) { unsigned char *pNewData; int count = pTex->width * pTex->height; unsigned char *src, *dst; BYTE bAlpha = (BYTE) (fAlpha * 255.0f); int i;
pNewData = (unsigned char *) LocalAlloc(LMEM_FIXED, count * sizeof(RGBA8)); if( !pNewData ) return;
src = pTex->data; dst = pNewData; // Note: the color ordering is ABGR, where R is lsb
for( i = 0; i < count; i ++ ) { *((RGB8 *)dst) = *((RGB8 *)src); dst += sizeof(RGB8); src += sizeof(RGB8); *dst++ = bAlpha; } LocalFree( pTex->data ); pTex->data = pNewData; pTex->components = 4; pTex->format = GL_RGBA; }
/******************************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 ss_SetTextureTransparency( TEXTURE *pTex, float fTransp, BOOL bSet ) { int i; float fAlpha;
if( pTex == NULL ) return FALSE;
SS_CLAMP_TO_RANGE2( fTransp, 0.0f, 1.0f ); fAlpha = 1 - fTransp;
if( pTex->format == GL_COLOR_INDEX ) { // just need to modify the palette
RGBQUAD *pPal = pTex->pal; BYTE bAlpha = (BYTE) (fAlpha * 255.0f);
if( !pPal ) return FALSE;
for( i = 0; i < pTex->pal_size; i ++, pPal++ ) { if( pPal->rgbReserved != 0 ) pPal->rgbReserved = bAlpha; } // need to send down the new palette for texture objects
if( gbTextureObjects && gbPalettedTexture ) { glBindTexture( GL_TEXTURE_2D, pTex->texObj ); pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pTex->pal_size, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pTex->pal); } } else { // Need to setup new texture data
if( pTex->components != 4 ) { // Make room for alpha component
//mf: ? change to bAlpha ?
ConvertTextureToRGBA( pTex, fAlpha ); } else { // Set alpha component
SetTextureAlpha( pTex, fAlpha ); } // Send down new data if texture objects
if( gbTextureObjects ) { glBindTexture( GL_TEXTURE_2D, pTex->texObj ); glTexImage2D( GL_TEXTURE_2D, 0, pTex->components, pTex->width, pTex->height, 0, pTex->format, GL_UNSIGNED_BYTE, pTex->data ); } }
if( bSet ) ss_SetTexture( pTex );
return TRUE; }
/******************************Public*Routine******************************\
* * ss_DeleteTexture * \**************************************************************************/
void ss_DeleteTexture( TEXTURE *pTex ) { if( pTex == NULL ) return;
if( gbTextureObjects && pTex->texObj ) { glDeleteTextures( 1, &pTex->texObj ); pTex->texObj = 0; } if (pTex->pal != NULL) { free(pTex->pal); } if( pTex->data ) free( pTex->data ); }
/******************************Public*Routine******************************\
* * ss_TextureObjectsEnabled * * Returns BOOL set by ss_QueryGLVersion (Texture Objects only supported on * GL v.1.1 or greater) * \**************************************************************************/
BOOL ss_TextureObjectsEnabled( void ) { return gbTextureObjects; }
/******************************Public*Routine******************************\
* * ss_PalettedTextureEnabled * * Returns result from ss_QueryPalettedTextureEXT * \**************************************************************************/
BOOL ss_PalettedTextureEnabled( void ) { return gbPalettedTexture; }
/******************************Public*Routine******************************\
* * ss_QueryPalettedTextureEXT * * Queries the OpenGL implementation to see if paletted texture is supported * Typically called once at app startup. * \**************************************************************************/
BOOL ss_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 gbPalettedTexture=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 * \**************************************************************************/
BOOL ss_VerifyTextureFile( 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 = (int)((ULONG_PTR)(pszString - ptf->szPathName)); return TRUE; } else { lstrcpy(ptf->szPathName, szFileName); // restore
if( !ss_fOnWin95() && gbEnableErrorMsgs ) { wsprintf(szString, gts.szSelectAnotherBitmapMsg, ptf->szPathName); MessageBox(NULL, szString, gts.szWarningMsg, MB_OK); } return FALSE; } }
/******************************Public*Routine******************************\
* * ss_SelectTextureFile * * Use the common dialog GetOpenFileName to get the name of a bitmap file * for use as a texture. This function will not return until the user * either selects a valid bitmap or cancels. If a valid bitmap is selected * by the user, the global array szPathName will have the full path * to the bitmap file and the global value nOffset will have the * offset from the beginning of szPathName to the pathless file name. * * If the user cancels, szPathName and nOffset will remain * unchanged. * * History: * 10-May-1994 -by- Gilman Wong [gilmanw] * - Wrote it. * Apr. 28, 95 : [marcfo] * - Modified for common use * Dec. 12, 95 : [marcfo] * - Support .rgb files as well * \**************************************************************************/
BOOL ss_SelectTextureFile( HWND hDlg, TEXFILE *ptf ) { OPENFILENAME ofn; TCHAR dirName[MAX_PATH]; TEXFILE newTexFile; LPTSTR pszFileName = newTexFile.szPathName; TCHAR origPathName[MAX_PATH]; PTSTR pszString; BOOL bTryAgain, bFileSelected;
//mf:
gbEnableErrorMsgs = TRUE;
// Make a copy of the original file path name, so we can tell if
// it changed or not
lstrcpy( origPathName, ptf->szPathName );
// Make dialog look nice by parsing out the initial path and
// file name from the full pathname. If this isn't done, then
// dialog has a long ugly name in the file combo box and
// directory will end up with the default current directory.
if (ptf->nOffset) { // Separate the directory and file names.
lstrcpy(dirName, ptf->szPathName); dirName[ptf->nOffset-1] = L'\0'; lstrcpy(pszFileName, &ptf->szPathName[ptf->nOffset]); } else { // If nOffset is zero, then szPathName is not a full path.
// Attempt to make it a full path by calling SearchPath.
if ( SearchPath(NULL, ptf->szPathName, NULL, MAX_PATH, dirName, &pszString) ) { // Successful. Go ahead a change szPathName to the full path
// and compute the filename offset.
lstrcpy(ptf->szPathName, dirName); ptf->nOffset = (int)((ULONG_PTR)(pszString - dirName));
// Break the filename and directory paths apart.
dirName[ptf->nOffset-1] = TEXT('\0'); lstrcpy(pszFileName, pszString); }
// Give up and use the Windows system directory.
else { GetWindowsDirectory(dirName, MAX_PATH); lstrcpy(pszFileName, ptf->szPathName); } }
ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.hInstance = NULL; ofn.lpstrFilter = gts.szTextureFilter; ofn.lpstrCustomFilter = (LPTSTR) NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 1; ofn.lpstrFile = pszFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = (LPTSTR) NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = dirName; ofn.lpstrTitle = gts.szTextureDialogTitle; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = gts.szBmp; ofn.lCustData = 0; ofn.lpfnHook = (LPOFNHOOKPROC) NULL; ofn.lpTemplateName = (LPTSTR) NULL;
do { // Invoke the common file dialog. If it succeeds, then validate
// the bitmap file. If not valid, make user try again until either
// they pick a good one or cancel the dialog.
bTryAgain = FALSE;
if ( bFileSelected = GetOpenFileName(&ofn) ) { ISIZE size;
newTexFile.nOffset = ofn.nFileOffset; if( VerifyTextureFile( &newTexFile ) ) { // copy in new file and offset
*ptf = newTexFile; } else { bTryAgain = TRUE; } }
// If need to try again, recompute dir and file name so dialog
// still looks nice.
if (bTryAgain && ofn.nFileOffset) { lstrcpy(dirName, pszFileName); dirName[ofn.nFileOffset-1] = L'\0'; lstrcpy(pszFileName, &pszFileName[ofn.nFileOffset]); }
} while (bTryAgain);
gbEnableErrorMsgs = FALSE;
if( bFileSelected ) { if( lstrcmpi( origPathName, ptf->szPathName ) ) // a different file was selected
return TRUE; } return FALSE; }
/******************************Public*Routine******************************\
* * ss_GetDefaultBmpFile * * Determine a default bitmap file to use for texturing, if none * exists yet in the registry. * * Put default in BmpFile parameter. DotBmp parameter is the bitmap * extension (usually .bmp). * * We have to synthesise the name from the ProductType registry entry. * Currently, this can be WinNT, LanmanNT, or Server. If it is * WinNT, the bitmap is winnt.bmp. If it is LanmanNT or Server, * the bitmap is lanmannt.bmp. * * History * Apr. 28, 95 : [marcfo] * - Wrote it * * Jul. 27, 95 : [marcfo] * - Added support for win95 * * Apr. 23, 96 : [marcfo] * - Return NULL string for win95 * \**************************************************************************/
void ss_GetDefaultBmpFile( LPTSTR pszBmpFile ) { HKEY hkey; LONG cjDefaultBitmap = MAX_PATH;
if( ss_fOnWin95() ) // There is no 'nice' bmp file on standard win95 installations
lstrcpy( pszBmpFile, TEXT("") ); else { if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR) TEXT("System\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS ) {
if ( RegQueryValueEx(hkey, TEXT("ProductType"), (LPDWORD) NULL, (LPDWORD) NULL, (LPBYTE) pszBmpFile, (LPDWORD) &cjDefaultBitmap) == ERROR_SUCCESS && (cjDefaultBitmap / sizeof(TCHAR) + 4) <= MAX_PATH ) lstrcat( pszBmpFile, gts.szDotBmp ); else lstrcpy( pszBmpFile, TEXT("winnt.bmp") );
RegCloseKey(hkey); } else lstrcpy( pszBmpFile, TEXT("winnt.bmp") );
// If its not winnt.bmp, then its lanmannt.bmp. (This would be a lot
// cleaner both in the screen savers and for usersrv desktop bitmap
// initialization if the desktop bitmap name were stored in the
// registry).
if ( lstrcmpi( pszBmpFile, TEXT("winnt.bmp") ) != 0 ) lstrcpy( pszBmpFile, TEXT("lanmannt.bmp") ); } }
/******************************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 * \**************************************************************************/
static int VerifyTextureFile( 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 ) { if( gbEnableErrorMsgs ) { wsprintf(szString, gts.szSelectAnotherBitmapMsg, pTexFile->szPathName); MessageBox(NULL, szString, gts.szWarningMsg, MB_OK); } return 0; }
// Check size ?
if ( (size.width > TEX_WIDTH_MAX) || (size.height > TEX_HEIGHT_MAX) ) { if( gbEnableErrorMsgs ) { wsprintf(szString, gts.szBitmapSizeMsg, TEX_WIDTH_MAX, TEX_HEIGHT_MAX); MessageBox(NULL, szString, gts.szWarningMsg, MB_OK); } 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 ss_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; }
|