Fixes for datatype size on amd64.
[crack-attack.git] / src / TextureLoader.cxx
blobbc55d19be825fe99219f9da934e8be9978e8ff13
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 "TextureLoader.h"
31 #include <GL/glut.h>
32 #include <fstream>
33 #include <iostream>
34 #include <cstring>
35 #include <sys/stat.h>
36 #include <SDL/SDL_image.h>
38 #ifndef _WIN32
39 # include <unistd.h>
40 #endif
42 #include "glext.h"
44 #include "Game.h"
46 using namespace std;
48 // the header of an uncompressed TGA file
49 const GLubyte header_image[11] = { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
51 GLubyte *TextureLoader::loadImageAlpha ( const char *file_name, int _height,
52 int _width )
54 GLubyte *full_texture = loadImage(file_name, _height, _width);
56 int texture_size = _width * _height;
58 GLubyte *alpha_texture = new GLubyte[texture_size];
60 for (int n = 0; n < texture_size; n++)
61 alpha_texture[n] = full_texture[4 * n + 3];
63 if (full_texture != null) {
64 delete [] full_texture;
65 full_texture = null;
68 return alpha_texture;
71 GLubyte *TextureLoader::loadImageNoAlpha ( const char *file_name,
72 int _height, int _width )
74 GLubyte *full_texture = loadImage(file_name, _height, _width);
76 int texture_size = _width * _height;
78 GLubyte *no_alpha_texture = new GLubyte[texture_size * 3];
80 for (int n = 0; n < texture_size; n++) {
81 float alpha = full_texture[4 * n + 3] * (1.0f / 255.0f);
82 no_alpha_texture[3 * n + 0] = (GLubyte) (alpha * full_texture[4 * n + 0]);
83 no_alpha_texture[3 * n + 1] = (GLubyte) (alpha * full_texture[4 * n + 1]);
84 no_alpha_texture[3 * n + 2] = (GLubyte) (alpha * full_texture[4 * n + 2]);
87 if (full_texture != null) {
88 delete [] full_texture;
89 full_texture = null;
92 return no_alpha_texture;
95 GLubyte *TextureLoader::loadImage ( const char *file_name, int _height,
96 int _width)
98 SDL_Surface *img = IMG_Load(file_name);
100 if (!img) {
101 cerr << "Error opening texture file '" << file_name << "'." << endl;
102 exit(1);
105 int width = img->w;
106 int height = img->h;
108 if (width != _width || height != _height) {
109 cerr << "Texture file '" << file_name << "' does not have the expected "
110 "height and width. [" << height << 'x' << width << "] vs expected ["
111 << _height << 'x' << _width << "]." << endl;
112 exit(1);
115 // Convert the loaded image to a standard 32 bit format
117 Uint32 rmask, gmask, bmask, amask;
118 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
119 rmask = 0xff000000;
120 gmask = 0x00ff0000;
121 bmask = 0x0000ff00;
122 amask = 0x000000ff;
123 #else
124 rmask = 0x000000ff;
125 gmask = 0x0000ff00;
126 bmask = 0x00ff0000;
127 amask = 0xff000000;
128 #endif
130 SDL_Surface *formatImg = SDL_CreateRGBSurface(
131 SDL_SWSURFACE, 0, 0, 32, rmask, gmask, bmask, amask);
133 if (formatImg == NULL) {
134 cerr << "Out of memory while opening texture file '" << file_name
135 << "'." << endl;
136 SDL_FreeSurface(img);
137 exit(1);
140 SDL_Surface *tmp = SDL_ConvertSurface(img, formatImg->format, SDL_SWSURFACE);
142 SDL_FreeSurface(img);
143 SDL_FreeSurface(formatImg);
145 // TODO: This memcpy is rather pointless. Maybe find a way to avoid it.
147 int texture_size = width * height * 32 / 8;
148 GLubyte *texture = new GLubyte[texture_size];
149 memcpy(texture, tmp->pixels, texture_size);
151 SDL_FreeSurface(tmp);
153 //cout << "Succesfully loaded '" << file_name << "'." << endl;
155 return texture;
158 void TextureLoader::createTGA ( const char *tga_file_name, GLubyte *texture,
159 int _height, int _width, const char *tga_id )
161 #ifndef _WIN32
162 ofstream file(tga_file_name);
163 #else
164 ofstream file(tga_file_name, ios::binary);
165 #endif
166 if (file.fail()) {
167 cerr << "Error creating texture file '" << tga_file_name << "'." << endl;
168 exit(1);
171 GLubyte tga_id_length = strlen(tga_id);
172 file.write((char *) &tga_id_length, 1);
174 file.write((char *) header_image, sizeof(header_image));
176 GLubyte header[6];
177 header[1] = _width / 256;
178 header[0] = _width - 256 * header[1];
179 header[3] = _height / 256;
180 header[2] = _height - 256 * header[3];
181 header[4] = 32;
182 header[5] = 40;
183 file.write((char *) header, sizeof(header));
185 file.write(tga_id, tga_id_length);
187 // tga is BGR
188 for (int n = 0; n < _width * _height * 4; n += 4) {
189 GLubyte swap = texture[n];
190 texture[n] = texture[n + 2];
191 texture[n + 2] = swap;
194 file.write((char *) texture, _width * _height * 4);
196 for (int n = 0; n < _width * _height * 4; n += 4) {
197 GLubyte swap = texture[n];
198 texture[n] = texture[n + 2];
199 texture[n + 2] = swap;
203 bool TextureLoader::fileExists ( const char *file_name )
205 struct stat file_stats;
207 // stat fails to find directories with trailing delimiters in _WIN32
208 #ifdef _WIN32
209 if (file_name[strlen(file_name) - 1] == GC_DD[0]) {
210 char truncated_file_name[256];
211 strncpy(truncated_file_name, file_name, 256);
212 truncated_file_name[strlen(file_name) - 1] = '\0';
213 return !stat(truncated_file_name, &file_stats);
215 #endif
216 return !stat(file_name, &file_stats);
219 unsigned long TextureLoader::determineImageCheckSum ( const char *file_name,
220 int _height, int _width )
222 GLubyte *texture = loadImage(file_name, _height, _width);
224 unsigned long check_sum = 0;
225 for (int n = _width * _height * 4; n--; )
226 check_sum += texture[n];
228 if (texture != null) {
229 delete [] texture;
230 texture = null;
233 return check_sum;
236 void TextureLoader::determineImageSize ( const char *file_name, int &height,
237 int &width )
239 SDL_Surface *img = IMG_Load(file_name);
241 if (!img) {
242 cerr << "Error opening texture file '" << file_name << "'." << endl;
243 exit(1);
246 width = img->w;
247 height = img->h;
249 SDL_FreeSurface(img);