-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtexture.cpp
460 lines (380 loc) · 13.4 KB
/
texture.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
// -----------------------------------------------------------------
// Learning Team B
// Members:
// Adam LeMmon
// Faith Satterthwaite
// Tom Fletcher
// Justin Ball
// CS 4280 – 11:30 am
// Final Project
// Dr. Rague
// Due: 12/06/12
// Version: 2.4
// -----------------------------------------------------------------
// We made five major improvements to this game
// 1) New controls
// 2) Enemy attack
// 3) HUD (heads up display)
// 4) Enemy health bars
// 5) New Weapon
// -----------------------------------------------------------------
#include "texture.h"
// LoadBitmapFile
// desc: Returns a pointer to the bitmap image of the bitmap specified
// by filename. Also returns the bitmap header information.
// No support for 8-bit bitmaps.
unsigned char *CTexture::LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
FILE *filePtr; // the file pointer
BITMAPFILEHEADER bitmapFileHeader; // bitmap file header
unsigned char *bitmapImage; // bitmap image data
int imageIdx = 0; // image index counter
unsigned char tempRGB; // swap variable
// open filename in "read binary" mode
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// read the bitmap file header
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// verify that this is a bitmap by checking for the universal bitmap id
if (bitmapFileHeader.bfType != BITMAP_ID)
{
fclose(filePtr);
return NULL;
}
// read the bitmap information header
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// move file pointer to beginning of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// allocate enough memory for the bitmap image data
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
// verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
// read in the bitmap image data
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// make sure bitmap image data was read
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
// swap the R and B values to get RGB since the bitmap color format is in BGR
for (imageIdx = 0; imageIdx < (int)bitmapInfoHeader->biSizeImage; imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
// close the file and return the bitmap image data
fclose(filePtr);
return bitmapImage;
}
/*****************************************************************************
LoadBitmapFileWithAlpha
Loads a bitmap file normally, and then adds an alpha component to use for
blending
*****************************************************************************/
unsigned char *CTexture::LoadBitmapFileWithAlpha(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
unsigned char *bitmapImage = LoadBitmapFile(filename, bitmapInfoHeader);
unsigned char *bitmapWithAlpha = (unsigned char *)malloc(bitmapInfoHeader->biSizeImage * 4 / 3);
// loop through the bitmap data
for (int src = 0, dst = 0; src < (int)bitmapInfoHeader->biSizeImage; src +=3, dst +=4)
{
// if the pixel is black, set the alpha to 0. Otherwise, set it to 255.
if (bitmapImage[src] == 0 && bitmapImage[src+1] == 0 && bitmapImage[src+2] == 0)
bitmapWithAlpha[dst+3] = 0;
else
bitmapWithAlpha[dst+3] = 0xFF;
// copy pixel data over
bitmapWithAlpha[dst] = bitmapImage[src];
bitmapWithAlpha[dst+1] = bitmapImage[src+1];
bitmapWithAlpha[dst+2] = bitmapImage[src+2];
}
free(bitmapImage);
return bitmapWithAlpha;
} // end LoadBitmapFileWithAlpha()
// LoadPCXFile()
// desc: loads a PCX file into memory
unsigned char *CTexture::LoadPCXFile(char *filename, PCXHEADER *pcxHeader)
{
int idx = 0; // counter index
int c; // used to retrieve a char from the file
int i; // counter index
int numRepeat;
FILE *filePtr; // file handle
int width; // pcx width
int height; // pcx height
unsigned char *pixelData; // pcx image data
unsigned char *paletteData; // pcx palette data
// open PCX file
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// retrieve first character; should be equal to 10
c = getc(filePtr);
if (c != 10)
{
fclose(filePtr);
return NULL;
}
// retrieve next character; should be equal to 5
c = getc(filePtr);
if (c != 5)
{
fclose(filePtr);
return NULL;
}
// reposition file pointer to beginning of file
rewind(filePtr);
// read 4 characters of data to skip
fgetc(filePtr);
fgetc(filePtr);
fgetc(filePtr);
fgetc(filePtr);
// retrieve leftmost x value of PCX
pcxHeader->xMin = fgetc(filePtr); // loword
pcxHeader->xMin |= fgetc(filePtr) << 8; // hiword
// retrieve bottom-most y value of PCX
pcxHeader->yMin = fgetc(filePtr); // loword
pcxHeader->yMin |= fgetc(filePtr) << 8; // hiword
// retrieve rightmost x value of PCX
pcxHeader->xMax = fgetc(filePtr); // loword
pcxHeader->xMax |= fgetc(filePtr) << 8; // hiword
// retrieve topmost y value of PCX
pcxHeader->yMax = fgetc(filePtr); // loword
pcxHeader->yMax |= fgetc(filePtr) << 8; // hiword
// calculate the width and height of the PCX
width = pcxHeader->xMax - pcxHeader->xMin + 1;
height = pcxHeader->yMax - pcxHeader->yMin + 1;
// allocate memory for PCX image data
pixelData = (unsigned char*)malloc(width*height);
// set file pointer to 128th byte of file, where the PCX image data starts
fseek(filePtr, 128, SEEK_SET);
// decode the pixel data and store
while (idx < (width*height))
{
c = getc(filePtr);
if (c > 0xbf)
{
numRepeat = 0x3f & c;
c = getc(filePtr);
for (i = 0; i < numRepeat; i++)
{
pixelData[idx++] = c;
}
}
else
pixelData[idx++] = c;
fflush(stdout);
}
// allocate memory for the PCX image palette
paletteData = (unsigned char*)malloc(768);
// palette is the last 769 bytes of the PCX file
fseek(filePtr, -769, SEEK_END);
// verify palette; first character should be 12
c = getc(filePtr);
if (c != 12)
{
fclose(filePtr);
return NULL;
}
// read and store all of palette
for (i = 0; i < 768; i++)
{
c = getc(filePtr);
paletteData[i] = c;
}
// close file and store palette in header
fclose(filePtr);
pcxHeader->palette = paletteData;
// return the pixel image data
return pixelData;
}
// LoadPCXTexture()
// desc: loads a PCX image file as a texture
void CTexture::LoadPCXTexture(char *filename)
{
PCXHEADER texInfo; // header of texture
// texture_t *thisTexture; // the texture
unsigned char *unscaledData;// used to calculate pcx
int i; // index counter
int j; // index counter
int w; // width of texture
int h; // height of texture
// load the PCX file into the texture struct
data = LoadPCXFile(filename, &texInfo);
if (data == NULL)
{
free(data);
// return NULL;
}
// store the texture information
palette = texInfo.palette;
width = texInfo.xMax - texInfo.xMin + 1;
height = texInfo.yMax - texInfo.yMin + 1;
textureType = PCX;
w = width;
h = height;
// allocate memory for the unscaled data
unscaledData = (unsigned char*)malloc(w*h*4);
// store the unscaled data via the palette
for (j = 0; j < h; j++)
{
for (i = 0; i < w; i++)
{
unscaledData[4*(j*w+i)+0] = (unsigned char)palette[3*data[j*w+i]+0];
unscaledData[4*(j*w+i)+1] = (unsigned char)palette[3*data[j*w+i]+1];
unscaledData[4*(j*w+i)+2] = (unsigned char)palette[3*data[j*w+i]+2];
unscaledData[4*(j*w+i)+3] = (unsigned char)255;
}
}
// find width and height's nearest greater power of 2
// find width's
i = 0;
while (w)
{
w /= 2;
i++;
}
scaledHeight = (long)pow(2., i-1);
// find height's
i = 0;
while (h)
{
h /= 2;
i++;
}
scaledWidth = (long)pow(2., i-1);
// clear the texture data
if (data != NULL)
{
free(data);
data = NULL;
}
// reallocate memory for the texture data
data = (unsigned char*)malloc(scaledWidth*scaledHeight*4);
// use the GL utility library to scale the texture to the unscaled dimensions
gluScaleImage(GL_RGBA, this->width, this->height, GL_UNSIGNED_BYTE, unscaledData, scaledWidth, scaledHeight, GL_UNSIGNED_BYTE, data);
free(unscaledData);
// return thisTexture;
}
// LoadBMPTexture()
// desc: loads a texture of the BMP format
void CTexture::LoadBMPTexture(char *filename)
{
BITMAPINFOHEADER texInfo; // BMP header
// store BMP data in texture
data = LoadBitmapFileWithAlpha(filename, &texInfo);
if (data == NULL)
{
free(data);
}
// store texture information
width = texInfo.biWidth;
height = texInfo.biHeight;
palette = NULL;
scaledHeight = 0;
scaledWidth = 0;
textureType = BMP;
}
// LoadTexture()
// desc: loads a texture given the filename
void CTexture::LoadTexture(char *filename)
{
char *extStr;
// get extension from filename
extStr = strchr(filename, '.');
extStr++;
// set the texture type based on extension of filename
if ((strcmpi(extStr, "BMP") == 0) || (strcmpi(extStr, "bmp") == 0))
LoadBMPTexture(filename);
else if ((strcmpi(extStr, "PCX") == 0) || (strcmpi(extStr, "pcx") == 0) )
LoadPCXTexture(filename);
else if ((strcmpi(extStr, "TGA") == 0) || (strcmpi(extStr, "tga") == 0) )
LoadTGATexture(filename);
}
// LoadTGAFile()
// desc: loads a TGA file defined by filename
unsigned char *CTexture::LoadTGAFile(char *filename, TGAHEADER *tgaHeader)
{
FILE *filePtr;
unsigned char ucharBad; // garbage data
short int sintBad; // garbage data
long imageSize; // size of TGA image
int colorMode; // 4 for RGBA, 3 for RGB
long imageIdx; // counter variable
unsigned char colorSwap; // swap variable
unsigned char *imageData; // the TGA data
// open the TGA file
filePtr = fopen(filename, "rb");
if (!filePtr)
return NULL;
// read first two bytes of garbage
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
// read in the image type
fread(&tgaHeader->imageTypeCode, sizeof(unsigned char), 1, filePtr);
// for our purposes, the image type should be either a 2 or a 3
if ((tgaHeader->imageTypeCode != 2) && (tgaHeader->imageTypeCode != 3))
{
fclose(filePtr);
return NULL;
}
// read 13 bytes of garbage data
fread(&sintBad, sizeof(short int), 1, filePtr);
fread(&sintBad, sizeof(short int), 1, filePtr);
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
fread(&sintBad, sizeof(short int), 1, filePtr);
fread(&sintBad, sizeof(short int), 1, filePtr);
// read image dimensions
fread(&tgaHeader->imageWidth, sizeof(short int), 1, filePtr);
fread(&tgaHeader->imageHeight, sizeof(short int), 1, filePtr);
// read bit depth
fread(&tgaHeader->bitCount, sizeof(unsigned char), 1, filePtr);
// read garbage
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
// colormode -> 3 = BGR, 4 = BGRA
colorMode = tgaHeader->bitCount / 8;
imageSize = tgaHeader->imageWidth * tgaHeader->imageHeight * colorMode;
// allocate memory for image data
imageData = (unsigned char*)malloc(sizeof(unsigned char)*imageSize);
// read image data
fread(imageData, sizeof(unsigned char), imageSize, filePtr);
// change BGR to RGB so OpenGL can use the data
for (imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode)
{
colorSwap = imageData[imageIdx];
imageData[imageIdx] = imageData[imageIdx+2];
imageData[imageIdx + 2] = colorSwap;
}
// close the file
fclose(filePtr);
return imageData;
}
// LoadTGATexture()
// desc: loads a TGA as a texture
void CTexture::LoadTGATexture(char *filename)
{
TGAHEADER tga; // BMP header
// store BMP data in texture
data = LoadTGAFile(filename, &tga);
if (data == NULL)
{
free(data);
}
// store texture information
width = tga.imageWidth;
height = tga.imageHeight;
palette = NULL;
scaledHeight = 0;
scaledWidth = 0;
tgaImageCode = tga.imageTypeCode;
bitDepth = tga.bitCount;
textureType = TGA;
}