Updated to include tests for Gentoo installation
[crack-attack.git] / src / TextureLoader.cxx
blobe7b61278067f16ab02a2e0f9b6bdfc2de5df917f
1 /*
2 * TextureLoader.cxx
3 * Daniel Nelson - 9/14/0
5 * Copyright (C) 2000 Daniel Nelson
6 * Copyright (C) 2004 Andrew Sayman
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * Daniel Nelson - aluminumangel.org
23 * 174 W. 18th Ave.
24 * Columbus, OH 43210
26 * Loads textures from uncompressed TGA files.
29 #include <GL/glut.h>
30 #include <fstream>
31 #include <iostream>
32 #include <cstring>
33 #include <sys/stat.h>
35 #ifndef _WIN32
36 # include <unistd.h>
37 #endif
39 #include "glext.h"
41 using namespace std;
43 #include "TextureLoader.h"
44 #include "Game.h"
46 // the header of an uncompressed TGA file
47 const GLubyte header_image[11] = { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
49 GLubyte *TextureLoader::loadAlphaTGA ( const char *tga_file_name, int _height,
50 int _width )
52 GLubyte *full_texture = loadTGA(tga_file_name, _height, _width);
54 int texture_size = _width * _height;
56 GLubyte *alpha_texture = new GLubyte[texture_size];
58 for (int n = 0; n < texture_size; n++)
59 alpha_texture[n] = full_texture[4 * n + 3];
61 if (full_texture != null) {
62 delete [] full_texture;
63 full_texture = null;
66 return alpha_texture;
69 GLubyte *TextureLoader::loadNoAlphaTGA ( const char *tga_file_name, int _height,
70 int _width )
72 GLubyte *full_texture = loadTGA(tga_file_name, _height, _width);
74 int texture_size = _width * _height;
76 GLubyte *no_alpha_texture = new GLubyte[texture_size * 3];
78 for (int n = 0; n < texture_size; n++) {
79 float alpha = full_texture[4 * n + 3] * (1.0f / 255.0f);
80 no_alpha_texture[3 * n + 0] = (GLubyte) (alpha * full_texture[4 * n + 0]);
81 no_alpha_texture[3 * n + 1] = (GLubyte) (alpha * full_texture[4 * n + 1]);
82 no_alpha_texture[3 * n + 2] = (GLubyte) (alpha * full_texture[4 * n + 2]);
85 if (full_texture != null) {
86 delete [] full_texture;
87 full_texture = null;
90 return no_alpha_texture;
93 GLubyte *TextureLoader::loadTGA ( const char *tga_file_name, int _height,
94 int _width, int _color_depth )
96 #ifndef _WIN32
97 ifstream file(tga_file_name);
98 #else
99 ifstream file(tga_file_name, ios::binary);
100 #endif
101 if (file.fail()) {
102 cerr << "Error opening texture file '" << tga_file_name << "'." << endl;
103 exit(1);
106 GLubyte id_length;
107 file.read((char *) &id_length, 1);
109 GLubyte static_header[11];
110 file.read((char *) static_header, sizeof(static_header));
111 if (memcmp(static_header, header_image, sizeof(static_header)) != 0) {
112 cerr << "Texture file '" << tga_file_name << "' is not in uncompressed "
113 "TGA format." << endl;
114 exit(1);
117 GLubyte header[6];
118 file.read((char *) header, sizeof(header));
120 int width = header[1] * 256 + header[0];
121 int height = header[3] * 256 + header[2];
123 if (width != _width || height != _height) {
124 cerr << "Texture file '" << tga_file_name << "' does not have the expected "
125 "height and width. [" << height << 'x' << width << "] vs expected ["
126 << _height << 'x' << _width << "]." << endl;
127 exit(1);
130 int color_depth = header[4];
131 if (color_depth != 24 && color_depth != 32) {
132 cerr << "Texture file '" << tga_file_name << "' has an unsupported color "
133 "depth." << endl;
134 exit(1);
136 if (_color_depth != 0 && _color_depth != color_depth) {
137 cerr << "Texture file '" << tga_file_name << "' does not have the expected "
138 "color depth." << endl;
139 exit(1);
142 GLubyte b;
143 while (id_length--)
144 file.read((char *) &b, 1);
146 int texture_size = width * height * color_depth / 8;
148 GLubyte *texture = new GLubyte[texture_size];
150 file.read((char *) texture, texture_size);
152 // tga is BGR
153 for (int n = 0; n < texture_size; n += color_depth / 8) {
154 GLubyte swap = texture[n];
155 texture[n] = texture[n + 2];
156 texture[n + 2] = swap;
159 return texture;
162 void TextureLoader::createTGA ( const char *tga_file_name, GLubyte *texture,
163 int _height, int _width, const char *tga_id )
165 #ifndef _WIN32
166 ofstream file(tga_file_name);
167 #else
168 ofstream file(tga_file_name, ios::binary);
169 #endif
170 if (file.fail()) {
171 cerr << "Error creating texture file '" << tga_file_name << "'." << endl;
172 exit(1);
175 GLubyte tga_id_length = strlen(tga_id);
176 file.write((char *) &tga_id_length, 1);
178 file.write((char *) header_image, sizeof(header_image));
180 GLubyte header[6];
181 header[1] = _width / 256;
182 header[0] = _width - 256 * header[1];
183 header[3] = _height / 256;
184 header[2] = _height - 256 * header[3];
185 header[4] = 32;
186 header[5] = 40;
187 file.write((char *) header, sizeof(header));
189 file.write((char *) tga_id, tga_id_length);
191 // tga is BGR
192 for (int n = 0; n < _width * _height * 4; n += 4) {
193 GLubyte swap = texture[n];
194 texture[n] = texture[n + 2];
195 texture[n + 2] = swap;
198 file.write((char *) texture, _width * _height * 4);
200 for (int n = 0; n < _width * _height * 4; n += 4) {
201 GLubyte swap = texture[n];
202 texture[n] = texture[n + 2];
203 texture[n + 2] = swap;
207 bool TextureLoader::fileExists ( const char *file_name )
209 struct stat file_stats;
211 #ifndef _WIN32
212 #else // stat fails to find directories with trailing delimiters in _WIN32
213 if (file_name[strlen(file_name) - 1] == GC_DD[0]) {
214 char truncated_file_name[256];
215 strncpy(truncated_file_name, file_name, 256);
216 truncated_file_name[strlen(file_name) - 1] = '\0';
217 return !stat(truncated_file_name, &file_stats);
219 #endif
220 return !stat(file_name, &file_stats);
223 unsigned long TextureLoader::determineTGACheckSum ( const char *tga_file_name,
224 int _height, int _width )
226 GLubyte *texture = loadTGA(tga_file_name, _height, _width);
228 unsigned long check_sum = 0;
229 for (int n = _width * _height * 4; n--; )
230 check_sum += texture[n];
232 if (texture != null) {
233 delete [] texture;
234 texture = null;
237 return check_sum;
240 void TextureLoader::determineTGASize ( const char *tga_file_name, int &height,
241 int &width )
243 #ifndef _WIN32
244 ifstream file(tga_file_name);
245 #else
246 ifstream file(tga_file_name, ios::binary);
247 #endif
248 if (file.fail()) {
249 cerr << "Error opening texture file '" << tga_file_name << "'." << endl;
250 exit(1);
253 GLubyte id_length;
254 file.read((char *) &id_length, 1);
256 GLubyte static_header[11];
257 file.read((char *) static_header, sizeof(static_header));
258 if (memcmp(static_header, header_image, sizeof(static_header)) != 0) {
259 cerr << "Texture file '" << tga_file_name << "' is not in uncompressed "
260 "TGA format." << endl;
261 exit(1);
264 GLubyte header[6];
265 file.read((char *) header, sizeof(header));
267 width = header[1] * 256 + header[0];
268 height = header[3] * 256 + header[2];