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