📄 texture.c
字号:
pcaps = DDPCAPS_4BIT;
}
memcpy(&ddsd, &format, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | memoryflag;
ddsd.dwHeight = dwHeight;
ddsd.dwWidth = dwWidth;
ddrval = lpDD->lpVtbl->CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
if (ddrval != DD_OK) {
D3DAppISetErrorString("CreateSurface for texture failed (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return NULL;
}
/*
* Lock the surface so it can be filled with the PPM file
*/
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddrval = lpDDS->lpVtbl->Lock(lpDDS, NULL, &ddsd, 0, NULL);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Lock failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return NULL;
}
/*
* The method of loading depends on the pixel format of the dest surface
*/
if (!bQuant) {
/*
* The texture surface is not palettized
*/
unsigned long* lpLP;
unsigned short* lpSP;
unsigned char* lpCP;
unsigned long m;
int s;
int red_shift, red_scale;
int green_shift, green_scale;
int blue_shift, blue_scale;
/*
* Determine the red, green and blue masks' shift and scale.
*/
for (s = 0, m = format.ddpfPixelFormat.dwRBitMask; !(m & 1);
s++, m >>= 1);
red_shift = s;
red_scale = 255 / (format.ddpfPixelFormat.dwRBitMask >> s);
for (s = 0, m = format.ddpfPixelFormat.dwGBitMask; !(m & 1);
s++, m >>= 1);
green_shift = s;
green_scale = 255 / (format.ddpfPixelFormat.dwGBitMask >> s);
for (s = 0, m = format.ddpfPixelFormat.dwBBitMask; !(m & 1);
s++, m >>= 1);
blue_shift = s;
blue_scale = 255 / (format.ddpfPixelFormat.dwBBitMask >> s);
/*
* Each RGB bit count requires different pointers
*/
switch (format.ddpfPixelFormat.dwRGBBitCount) {
case 32 :
for (j = 0; j < (int)dwHeight; j++) {
/*
* Point to next row in texture surface
*/
lpLP = (unsigned long*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
/*
* Read each value, scale it and shift it into position
*/
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpLP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpLP++;
}
}
break;
case 16 :
for (j = 0; j < (int)dwHeight; j++) {
lpSP = (unsigned short*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpSP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpSP++;
}
}
break;
case 8:
for (j = 0; j < (int)dwHeight; j++) {
lpCP = (unsigned char*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpCP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpCP++;
}
}
break;
default:
/*
* This wasn't a format I recognize
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
fclose(fp);
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Unknown pixel format (loadtex).");
return NULL;
}
/*
* Unlock the texture and return the surface pointer
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
fclose(fp);
return (lpDDS);
}
/*
* We assume the 8-bit palettized case
*/
color_count = 0; /* number of colors in the texture */
for (j = 0; j < (int)dwHeight; j++) {
/*
* Point to next row in surface
*/
lpC = ((char*)ddsd.lpSurface) + ddsd.lPitch * j;
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b, k;
/*
* Get the next red, green and blue values and turn them into a
* D3DCOLOR
*/
r = getc(fp);
g = getc(fp);
b = getc(fp);
c = RGB_MAKE(r, g, b);
/*
* Search for this color in a table of colors in this texture
*/
for (k = 0; k < color_count; k++)
if (c == colors[k]) break;
if (k == color_count) {
/*
* This is a new color, so add it to the list
*/
color_count++;
/*
* More than 256 and we fail (8-bit)
*/
if (color_count > psize) {
color_count--;
k = color_count - 1;
//goto burst_colors;
}
colors[k] = c;
}
/*
* Set the "pixel" value on the surface to be the index into the
* color table
*/
if (psize == 16) {
if ((i & 1) == 0)
*lpC = k & 0xf;
else {
*lpC |= (k & 0xf) << 4;
lpC++;
}
} else {
*lpC = (char)k;
lpC++;
}
}
}
/*
* Close the file and unlock the surface
*/
fclose(fp);
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
//burst_colors:
if (color_count > psize) {
/*
* If there are more than 256 colors, we overran our palette
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Palette burst. (loadtex).\n");
return (NULL);
}
/*
* Create a palette with the colors in our color table
*/
memset(ppe, 0, sizeof(PALETTEENTRY) * 256);
for (i = 0; i < color_count; i++) {
ppe[i].peRed = (unsigned char)RGB_GETRED(colors[i]);
ppe[i].peGreen = (unsigned char)RGB_GETGREEN(colors[i]);
ppe[i].peBlue = (unsigned char)RGB_GETBLUE(colors[i]);
}
/*
* Set all remaining entry flags to D3DPAL_RESERVED, which are ignored by
* the renderer.
*/
for (; i < 256; i++)
ppe[i].peFlags = D3DPAL_RESERVED;
/*
* Create the palette with the DDPCAPS_ALLOW256 flag because we want to
* have access to all entries.
*/
ddrval = lpDD->lpVtbl->CreatePalette(lpDD,
DDPCAPS_INITIALIZE | pcaps,
ppe, &lpDDPal, NULL);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Create palette failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return (NULL);
}
/*
* Finally, bind the palette to the surface
*/
ddrval = lpDDS->lpVtbl->SetPalette(lpDDS, lpDDPal);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
lpDDPal->lpVtbl->Release(lpDDPal);
D3DAppISetErrorString("SetPalette failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return (NULL);
}
lpDDPal->lpVtbl->Release(lpDDPal);
return lpDDS;
}
static BOOL
ppm_getbyte(FILE *fp, char *newByte)
{
char cchar;
int cc;
/* Get a byte, and dump comments */
cchar = cc = getc(fp);
if (cc == EOF) {
return FALSE;
}
if (cchar == '#') {
/* Read until next end of line */
do {
cchar = cc = getc(fp);
if (cc == EOF)
return FALSE;
} while (cchar != '\n' && cchar != '\r');
}
*newByte = cchar;
return TRUE;
}
static BOOL
ppm_getint(FILE *fp, int *newInt)
{
int cint;
char cchar;
do {
if (!ppm_getbyte(fp, &cchar)) return FALSE;
} while (isspace(cchar));
if (!isdigit(cchar)) {
return FALSE;
}
cint = 0;
do {
cint = (cint * 10) + (cchar - '0');
if (!ppm_getbyte(fp, &cchar)) return FALSE;
} while(isdigit(cchar));
*newInt = cint;
return TRUE;
}
static BOOL
loadPPMHeader(FILE *fp, DWORD *width, DWORD *height, int *maxgrey)
{
char magic[MAGICBYTES], cchar;
/* Slurp up ppm header until we get width, height and maxgrey values */
/* Read and check the magic bytes */
if (fread(magic, MAGICBYTES, 1, fp) != 1)
return FALSE;
if (magic[0] != 'P' || magic[1] != '6')
return FALSE;
/* Now we can actually read some numbers */
if (!ppm_getint(fp, width))
return FALSE;
if (!ppm_getint(fp, height))
return FALSE;
if (!ppm_getint(fp, maxgrey))
return FALSE;
/* Slurp up rest of white space so we get to actual data */
do {
if (!ppm_getbyte(fp, &cchar))
return FALSE;
} while (cchar == ' ' || cchar == '\t' || cchar == '\n' || cchar == '\r');
fseek(fp, -1, SEEK_CUR);
return TRUE;
}
/***************************************************************************/
/* Finding Textures */
/***************************************************************************/
#define MAXPATH 256
#define PATHSEP ';'
#define FILESEP '\\'
#define MAXCONTENTS 25
#define RESPATH "Software\\Microsoft\\Direct3D"
static int PathListInitialised = FALSE;
/*
* PathList structure
* A list of directories in which to search for the texture.
*/
static struct {
int count;
char *contents[MAXCONTENTS];
} PathList;
/*
* D3DAppIAddPathList
* Add this string to the search path list
*/
static void
D3DAppIAddPathList(const char *path)
{
char *p;
char *elt;
int len;
while (path) {
p = LSTRCHR(path, PATHSEP);
if (p)
len = p - path;
else
len = lstrlen(path);
elt = (char *) malloc(len + 1);
if (elt == NULL)
return;
lstrcpyn(elt, path, len + 1);
elt[len] = '\0';
PathList.contents[PathList.count] = elt;
PathList.count++;
if (p)
path = p + 1;
else
path = NULL;
if (PathList.count == MAXCONTENTS)
return;
}
return;
}
/*
* D3DAppIInitialisePathList
* Create a search path with the D3DPATH env. var and D3D Path registry entry
*/
static void
D3DAppIInitialisePathList()
{
long result;
HKEY key;
DWORD type, size;
static char buf[512];
char* path;
if (PathListInitialised)
return;
PathListInitialised = TRUE;
PathList.count = 0;
path = getenv("D3DPATH");
D3DAppIAddPathList(".");
if (path != NULL) {
D3DAppIAddPathList(path);
return;
}
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RESPATH, 0, KEY_READ, &key);
if (result == ERROR_SUCCESS) {
size = sizeof(buf);
result = RegQueryValueEx(key, "D3D Path", NULL, &type, (LPBYTE) buf,
&size);
RegCloseKey(key);
if (result == ERROR_SUCCESS && type == REG_SZ)
D3DAppIAddPathList(buf);
}
}
/*
* D3DAppIFindFile
* Find and open a file using the current search path.
*/
static FILE*
D3DAppIFindFile(const char *name, const char *mode)
{
FILE *fp;
char buf[MAXPATH];
static char filesep[] = {FILESEP, 0};
int i;
D3DAppIInitialisePathList();
fp = fopen(name, mode);
if (fp != NULL)
return fp;
for (i = 0; i < PathList.count; i++) {
lstrcpy(buf, PathList.contents[i]);
lstrcat(buf, filesep);
lstrcat(buf, name);
fp = fopen(buf, mode);
if (fp)
return fp;
}
return NULL;
}
/*
* D3DAppIReleasePathList
* Release the path list for program termination
*/
void
D3DAppIReleasePathList(void)
{
int i;
for (i = 0; i < PathList.count; i++) {
free(PathList.contents[i]);
PathList.contents[i] = NULL;
}
PathList.count = 0;
PathListInitialised = FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -