TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
grtexture.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : grtexture.cpp
4 created : Wed Jun 1 14:56:31 CET 2005
5 copyright : (C) 2005-2026 by Bernhard Wymann
6
7***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18/*
19 This classes/methods are used to handle texture compression and
20 textures which are shared among multiple objects. In the long term
21 they should obsolete parts of grutil.cpp.
22*/
23
24#include "grtexture.h"
25
26//int grManagedState::ms = 0;
27
28bool doMipMap(const char *tfname, int mipmap)
29{
30 char *buf = (char *) malloc(strlen(tfname)+1);
31 strcpy(buf, tfname);
32
33 // find the filename extension.
34 char *s = strrchr(buf, '.');
35 if (s) {
36 *s = 0;
37 }
38
39 // search for the texture parameters.
40 s = strrchr(buf, '_');
41
42 // no mipmap for "_n" and "shadow".
43 if (s) {
44 // check the "_n".
45 if (strncmp(s, "_n", 4) == 0) {
46 mipmap = FALSE;
47 }
48 }
49
50 if (mipmap == TRUE) {
51 // Check the shadow.
52 s = strrchr((char *)tfname, '/');
53 if (s == NULL) {
54 s = (char *) tfname;
55 } else {
56 s++;
57 }
58 if (strstr(s, "shadow") != NULL) {
59 mipmap = FALSE;
60 }
61 }
62 free(buf);
63 return mipmap;
64}
65
66
67void grApplyTextureAnisotropy(ssgTexture *tex)
68{
69 if (tex == NULL || tex->getHandle() == 0) {
70 return;
71 }
73 return;
74 }
75
76 GLint curTex = 0;
77 GLuint texHandle = tex->getHandle();
78 glGetIntegerv(GL_TEXTURE_BINDING_2D, &curTex);
79 if ((GLuint)curTex != texHandle) {
80 glBindTexture(GL_TEXTURE_2D, texHandle);
81 }
83 if ((GLuint)curTex != texHandle) {
84 glBindTexture(GL_TEXTURE_2D, (GLuint)curTex);
85 }
86}
87
88
89/*
90 The latter parts are derived from plib (plib.sf.net) and have this license:
91
92 PLIB - A Suite of Portable Game Libraries
93 Copyright (C) 1998,2002 Steve Baker
94
95 This library is free software; you can redistribute it and/or
96 modify it under the terms of the GNU Library General Public
97 License as published by the Free Software Foundation; either
98 version 2 of the License, or (at your option) any later version.
99
100 This library is distributed in the hope that it will be useful,
101 but WITHOUT ANY WARRANTY; without even the implied warranty of
102 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
103 Library General Public License for more details.
104
105 You should have received a copy of the GNU Library General Public
106 License along with this library; if not, write to the Free Software
107 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
108
109 For further information visit http://plib.sourceforge.net
110*/
111
112/*
113 Modifications:
114 Copyright (c) 2005 Bernhard Wymann
115*/
116
117
118// SGI texture loading function.
119bool grLoadSGI(const char *fname, ssgTextureInfo* info)
120{
121 grSGIHeader *sgihdr = new grSGIHeader(fname, info);
122 bool returnval = sgihdr->loadSGI_bool;
123 delete sgihdr;
124 return returnval;
125}
126
127
128// Register customized loader in plib.
130{
131 ssgAddTextureFormat(".rgb", grLoadSGI);
132 ssgAddTextureFormat(".rgba", grLoadSGI);
133 ssgAddTextureFormat(".int", grLoadSGI);
134 ssgAddTextureFormat(".inta", grLoadSGI);
135 ssgAddTextureFormat(".bw", grLoadSGI);
136}
137
138
139grSGIHeader::grSGIHeader(const char *fname, ssgTextureInfo* info)
140{
141 grSGIHeader *sgihdr = this;
142
143 start = NULL;
144 leng = NULL;
145
146 bool success = openFile(fname);
147
148 int mipmap = doMipMap(fname, TRUE);
149
150 if (!success) {
151 loadSGI_bool = false;
152 return;
153 }
154
155 GLubyte *image = new GLubyte [sgihdr->xsize*sgihdr->ysize*sgihdr->zsize];
156 GLubyte *ptr = image;
157
158 unsigned char *rbuf = new unsigned char[sgihdr->xsize];
159 unsigned char *gbuf = (sgihdr->zsize>1) ? new unsigned char[sgihdr->xsize] : (unsigned char *) NULL ;
160 unsigned char *bbuf = (sgihdr->zsize>2) ? new unsigned char[sgihdr->xsize] : (unsigned char *) NULL ;
161 unsigned char *abuf = (sgihdr->zsize>3) ? new unsigned char[sgihdr->xsize] : (unsigned char *) NULL ;
162
163 for (int y = 0 ; y < sgihdr->ysize ; y++) {
164 int x ;
165
166 switch (sgihdr->zsize) {
167 case 1:
168 sgihdr->getRow(rbuf, y, 0);
169 for (x = 0; x < sgihdr->xsize; x++) {
170 *ptr++ = rbuf[x];
171 }
172 break;
173
174 case 2:
175 sgihdr->getRow (rbuf, y, 0);
176 sgihdr->getRow (gbuf, y, 1);
177
178 for (x = 0; x < sgihdr->xsize; x++) {
179 *ptr++ = rbuf[x];
180 *ptr++ = gbuf[x];
181 }
182 break;
183
184 case 3:
185 sgihdr->getRow(rbuf, y, 0);
186 sgihdr->getRow(gbuf, y, 1);
187 sgihdr->getRow(bbuf, y, 2);
188
189 for (x = 0; x < sgihdr->xsize; x++) {
190 *ptr++ = rbuf[x];
191 *ptr++ = gbuf[x];
192 *ptr++ = bbuf[x];
193 }
194 break;
195
196 case 4:
197 sgihdr->getRow(rbuf, y, 0);
198 sgihdr->getRow(gbuf, y, 1);
199 sgihdr->getRow(bbuf, y, 2);
200 sgihdr->getRow(abuf, y, 3);
201
202 for (x = 0; x < sgihdr->xsize; x++ ) {
203 *ptr++ = rbuf[x];
204 *ptr++ = gbuf[x];
205 *ptr++ = bbuf[x];
206 *ptr++ = abuf[x];
207 }
208 break;
209 }
210 }
211
212 fclose(image_fd);
213 image_fd = NULL ;
214 delete [] rbuf;
215 delete [] gbuf;
216 delete [] bbuf;
217 delete [] abuf;
218
219 if (info != NULL) {
220 info->width = sgihdr->xsize;
221 info->height = sgihdr->ysize;
222 info->depth = sgihdr->zsize;
223 info->alpha = (sgihdr->zsize == 2 || sgihdr->zsize == 4);
224 }
225
226 //printf("%s: ", jn);
227
228 bool result = grMakeMipMaps(image, sgihdr->xsize, sgihdr->ysize, sgihdr->zsize, mipmap);
229
230 loadSGI_bool= result ;
231}
232
233
234bool grMakeMipMaps (GLubyte *image, int xsize, int ysize, int zsize, bool mipmap)
235{
236 if (!((xsize & (xsize-1))==0) || !((ysize & (ysize-1))==0)) {
237 ulSetError ( UL_WARNING, "Map is not a power-of-two in size!" ) ;
238 return false ;
239 }
240
241 GLubyte *texels[20]; // One element per level of MIPmap.
242
243 for (int l = 0; l < 20; l++) {
244 texels [l] = NULL;
245 }
246
247 texels[0] = image;
248
249 int lev;
250
251 for (lev = 0 ;((xsize >> (lev+1)) != 0 || (ysize >> (lev+1)) != 0); lev++) {
252 // Suffix '1' is the higher level map, suffix '2' is the lower level.
253 int l1 = lev;
254 int l2 = lev+1;
255 int w1 = xsize >> l1;
256 int h1 = ysize >> l1;
257 int w2 = xsize >> l2;
258 int h2 = ysize >> l2;
259
260 if (w1 <= 0) {
261 w1 = 1;
262 }
263 if (h1 <= 0) {
264 h1 = 1;
265 }
266 if (w2 <= 0) {
267 w2 = 1;
268 }
269 if (h2 <= 0) {
270 h2 = 1;
271 }
272
273 texels[l2] = new GLubyte[w2*h2*zsize];
274
275 for (int x2 = 0; x2 < w2; x2++) {
276 for (int y2 = 0; y2 < h2; y2++) {
277 for (int c = 0; c < zsize; c++) {
278 int x1 = x2 + x2;
279 int x1_1 = (x1 + 1) % w1;
280 int y1 = y2 + y2;
281 int y1_1 = (y1 + 1) % h1;
282 int t1 = texels[l1][(y1*w1 + x1)*zsize + c];
283 int t2 = texels[l1][(y1_1*w1 + x1)*zsize + c];
284 int t3 = texels[l1][(y1*w1 + x1_1)*zsize + c];
285 int t4 = texels[l1][(y1_1*w1 + x1_1)*zsize + c];
286
287 if (c == 3) { // Alpha.
288 int a = t1;
289 if (t2 > a) {
290 a = t2;
291 }
292 if (t3 > a) {
293 a = t3;
294 }
295 if (t4 > a) {
296 a = t4;
297 }
298 texels[l2][(y2*w2 + x2)*zsize + c] = a;
299 } else {
300 texels[l2][(y2*w2 + x2)*zsize + c] = ( t1 + t2 + t3 + t4 )/4;
301 }
302 }
303 }
304 }
305 }
306
307 texels[lev + 1] = NULL;
308
309 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
310 glHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
311 int map_level = 0;
312
313 GLint ww;
314
315 GLint textureTargetFormat;
316 if (isCompressARBEnabled()) {
317 //printf("COMPRESSOR: ");
318
319 switch (zsize) {
320 case 1:
321 textureTargetFormat = GL_COMPRESSED_LUMINANCE_ARB;
322 //printf("GL_COMPRESSED_LUMINANCE_ARB\n");
323 break;
324 case 2:
325 textureTargetFormat = GL_COMPRESSED_LUMINANCE_ALPHA_ARB;
326 //printf("GL_COMPRESSED_LUMINANCE_ALPHA_ARB\n");
327 break;
328 case 3:
329 textureTargetFormat = GL_COMPRESSED_RGB_ARB;
330 //printf("GL_COMPRESSED_RGB_ARB\n");
331 break;
332 default:
333 textureTargetFormat = GL_COMPRESSED_RGBA_ARB;
334 //printf("GL_COMPRESSED_RGBA_ARB\n");
335 break;
336 }
337 } else {
338 textureTargetFormat = zsize;
339 //printf("NON COMPRESSOR\n");
340 }
341
342 int tlimit = getUserTextureMaxSize();
343
344 do {
345 if (xsize > tlimit || ysize > tlimit) {
346 ww = 0;
347 } else {
348
349 glTexImage2D(GL_PROXY_TEXTURE_2D, map_level, textureTargetFormat, xsize, ysize, FALSE /* Border */,
350 (zsize==1)?GL_LUMINANCE:
351 (zsize==2)?GL_LUMINANCE_ALPHA:
352 (zsize==3)?GL_RGB:
353 GL_RGBA,
354 GL_UNSIGNED_BYTE, NULL);
355
356 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &ww);
357 }
358
359 if (ww == 0) {
360 delete [] texels[0];
361 xsize >>= 1;
362 ysize >>= 1;
363 for (int l = 0; texels [l] != NULL; l++) {
364 texels [l] = texels[l+1];
365 }
366
367 if (xsize < 8 && ysize < 8) {
368 //ulSetError (UL_FATAL, "SSG: OpenGL will not accept a downsized version ?!?");
369 }
370 }
371 } while (ww == 0);
372
373
374 for (int i = 0; texels[i] != NULL; i++) {
375 int w = xsize >> i;
376 int h = ysize >> i;
377
378 if (w <= 0) {
379 w = 1;
380 }
381 if (h <= 0) {
382 h = 1;
383 }
384
385 if (mipmap == TRUE || i == 0) {
386 glTexImage2D ( GL_TEXTURE_2D,
387 map_level, textureTargetFormat, w, h, FALSE /* Border */,
388 (zsize==1)?GL_LUMINANCE:
389 (zsize==2)?GL_LUMINANCE_ALPHA:
390 (zsize==3)?GL_RGB:
391 GL_RGBA,
392 GL_UNSIGNED_BYTE, (GLvoid *) texels[i] ) ;
393
394 /*int compressed;
395 glGetTexLevelParameteriv(GL_TEXTURE_2D, map_level, GL_TEXTURE_COMPRESSED_ARB, &compressed);
396 if (compressed == GL_TRUE) {
397 int csize;
398 glGetTexLevelParameteriv(GL_TEXTURE_2D, map_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &csize);
399 printf("compression ratio: %d to %d\n", csize, w*h*zsize);
400 } else {
401 printf("not compressed\n");
402 }*/
403 }
404
405 map_level++ ;
406 delete [] texels[i];
407 }
408
409 return true;
410}
411
412
static Vector y[4]
Definition Convex.cpp:56
grSGIHeader(const char *fname, ssgTextureInfo *info)
unsigned short ysize
Definition grloadsgi.h:63
unsigned short xsize
Definition grloadsgi.h:62
FILE * image_fd
Definition grloadsgi.h:68
bool openFile(const char *fname)
void getRow(unsigned char *buf, int y, int z)
unsigned int * start
Definition grloadsgi.h:59
unsigned short zsize
Definition grloadsgi.h:64
bool loadSGI_bool
Definition grloadsgi.h:72
bool isCompressARBEnabled(void)
void applyUserTextureAnisotropy(void)
int getUserTextureAnisotropy(void)
int getUserTextureMaxSize(void)
bool isTextureAnisotropyAvailable(void)
bool grMakeMipMaps(GLubyte *image, int xsize, int ysize, int zsize, bool mipmap)
bool doMipMap(const char *tfname, int mipmap)
Definition grtexture.cpp:28
void grApplyTextureAnisotropy(ssgTexture *tex)
Definition grtexture.cpp:67
bool grLoadSGI(const char *fname, ssgTextureInfo *info)
void grRegisterCustomSGILoader(void)
bool grMakeMipMaps(GLubyte *image, int xsize, int ysize, int zsize, bool mipmap)
bool doMipMap(const char *tfname, int mipmap)
Definition grtexture.cpp:28