Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
aux_texture.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Daniel Horn
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 #include <stdio.h>
23 #include <assert.h>
24 #include "gfxlib.h"
25 #include <string>
26 #include "endianness.h"
27 #include "hashtable.h"
28 #include "vsfilesystem.h"
29 #include "vsimage.h"
30 #include "vs_globals.h"
31 #include "in_kb.h"
32 #include "main_loop.h"
33 #include "aux_texture.h"
34 
35 using std::string;
36 using namespace VSFileSystem;
37 
41 
42 Texture* Texture::Exists( string s, string a )
43 {
44  return Texture::Exists( s+a );
45 }
46 
47 Texture* Texture::Exists( string s )
48 {
50  if (tmp == NULL) {
51  string tmpo;
53  }
54  if (tmp)
55  return tmp->Original();
56  return tmp;
57 }
58 
59 bool Texture::operator<( const Texture &b ) const
60 {
61  return Original() < b.Original();
62 }
63 
64 bool Texture::operator==( const Texture &b ) const
65 {
66  return Original() == b.Original();
67 }
68 
70 {
71  original = other;
72  original->refcount++;
73 
74  //Copy shared attributes
75  texfilename = other->texfilename;
76  data = other->data;
77  name = other->name;
78  bound = other->bound;
79  boundSizeX = other->boundSizeX;
80  boundSizeY = other->boundSizeY;
81  boundMode = other->boundMode;
82  texture_target = other->texture_target;
83  image_target = other->image_target;
84 }
85 
86 GFXBOOL Texture::checkold( const string &s, bool shared, string &hashname )
87 {
89  Texture *oldtex = texHashTable.Get( hashname );
90  if (oldtex != NULL) {
91  //*this = *oldtex;//will be obsoleted--unpredictable results with string()
92  setReference( oldtex );
93  //cerr<<"Found cached texture : "<<s<<" with hashname="<<hashname<<endl;
94  return GFXTRUE;
95  } else {
96  return GFXFALSE;
97  }
98 }
99 
100 void Texture::modold( const string &s, bool shared, string &hashname )
101 {
103  Texture *oldtex = new Texture;
104  //oldtex->InitTexture();new calls this
105  oldtex->name = -1;
106  oldtex->refcount = 1;
107  oldtex->original = NULL;
108  oldtex->palette = NULL;
109  oldtex->data = NULL;
110  texHashTable.Put( hashname, oldtex );
111  original = oldtex;
112 }
113 
115 {
116  bound = false;
117  original = 0;
118  refcount = 0;
119  name = -1;
120  palette = NULL;
121  data = NULL;
122  mintcoord = Vector( 0.0f, 0.0f, 0.0f );
123  maxtcoord = Vector( 1.0f, 1.0f, 1.0f );
124  address_mode = DEFAULT_ADDRESS_MODE;
125 }
126 
128 {
129  //*original = *this;//will be obsoleted in new C++ standard unpredictable results when using string() (and its strangeass copy constructor)
130  *original = *this;
131  //memcpy (original, this, sizeof (Texture));
132  original->original = NULL;
133  original->refcount++;
134 }
135 
137 {
138  if (original)
139  return original->Original();
140  else
141  return this;
142 }
143 
145 {
146  if (original)
147  return original->Original();
148  else
149  return this;
150 }
151 
153 {
154  Texture *retval = new Texture();
155  Texture *target = Original();
156  *retval = *target;
157  //memcpy (this, target, sizeof (Texture));
158  if (retval->name != -1) {
159  retval->original = target;
160  retval->original->refcount++;
161  } else {
162  retval->original = NULL;
163  }
164  retval->refcount = 0;
165  return retval;
166  //assert (!original->original);
167 }
168 
169 void Texture::FileNotFound( const string &texfilename )
170 {
171  //We may need to remove from texHashTable if we found the file but it is a bad one
172  texHashTable.Delete( texfilename );
173 
174  setbad( texfilename );
175  name = -1;
176  data = NULL;
177  if (original != NULL) {
178  original->name = -1;
179  delete original;
180  original = NULL;
181  }
182  palette = NULL;
183 }
184 
185 bool Texture::checkbad( const string &s )
186 {
187  string hashname = VSFileSystem::GetSharedTextureHashName( s );
188  bool *found = NULL;
189  found = badtexHashTable.Get( hashname );
190  if (found != NULL)
191  return true;
192  hashname = VSFileSystem::GetHashName( s );
193  found = badtexHashTable.Get( hashname );
194  if (found != NULL)
195  return true;
196  return false;
197 }
198 
199 void Texture::setbad( const string &s )
200 {
201  //Put both current path+texfile and shared texfile since they both have been looked for
202  bool *b = new bool(true);
203  if (VSFileSystem::current_path.back() != "")
206 }
207 
208 Texture::Texture( int stage,
209  enum FILTER mipmap,
210  enum TEXTURE_TARGET target,
211  enum TEXTURE_IMAGE_TARGET imagetarget,
212  enum ADDRESSMODE address_mode )
213 {
214  InitTexture();
215  data = NULL;
216  ismipmapped = mipmap;
217  palette = NULL;
218  texture_target = target;
219  image_target = imagetarget;
220  this->stage = stage;
221 }
222 
224  int stage,
225  enum FILTER mipmap,
226  enum TEXTURE_TARGET target,
227  enum TEXTURE_IMAGE_TARGET imagetarget,
228  GFXBOOL force_load,
229  int maxdimension,
230  GFXBOOL detailtexture,
231  GFXBOOL nocache,
232  enum ADDRESSMODE address_mode,
233  Texture *main )
234 {
235  data = NULL;
236  ismipmapped = mipmap;
237  InitTexture();
238  palette = NULL;
239  texture_target = target;
240  image_target = imagetarget;
241  this->stage = stage;
242  data = this->ReadImage( f, NULL, true, NULL );
243  if (data) {
244  if (mode >= _DXT1 && mode <= _DXT5) {
245  if ( (int) data[0] == 0 ) {
246  detailtexture = NEAREST;
247  ismipmapped = NEAREST;
248  }
249  }
250  if (main)
251  Bind( main, maxdimension, detailtexture );
252  else
253  Bind( maxdimension, detailtexture );
254  free( data );
255  data = NULL;
256  if (!nocache) setold();
257  } else {
258  FileNotFound( texfilename );
259  }
260 }
261 
262 Texture::Texture( const char *FileName,
263  int stage,
264  enum FILTER mipmap,
265  enum TEXTURE_TARGET target,
266  enum TEXTURE_IMAGE_TARGET imagetarget,
267  GFXBOOL force_load,
268  int maxdimension,
269  GFXBOOL detailtexture,
270  GFXBOOL nocache,
271  enum ADDRESSMODE address_mode,
272  Texture *main )
273 {
274  InitTexture();
275  Load( FileName, stage, mipmap, target, imagetarget, force_load, maxdimension, detailtexture, nocache, address_mode, main );
276 }
277 
278 void Texture::Load( const char *FileName,
279  int stage,
280  enum FILTER mipmap,
281  enum TEXTURE_TARGET target,
282  enum TEXTURE_IMAGE_TARGET imagetarget,
283  GFXBOOL force_load,
284  int maxdimension,
285  GFXBOOL detailtexture,
286  GFXBOOL nocache,
287  enum ADDRESSMODE address_mode,
288  Texture *main )
289 {
290  if (data) free( data );
291  if (palette) free( palette );
292  data = NULL;
293  palette = NULL;
294  ismipmapped = mipmap;
295  texture_target = target;
296  image_target = imagetarget;
297  this->stage = stage;
298  this->address_mode = address_mode;
299  string texfn = string( FileName );
300  if ( checkbad( texfn ) )
301  return;
302  if (!nocache) {
303  string tempstr;
304  if ( checkold( texfn, false, tempstr )
305  || checkold( texfn, true, tempstr ) ) {
306  texfilename = tempstr;
307  return;
308  }
309  }
310  //VSFileSystem::vs_fprintf (stderr,"1.Loading bmp file %s ",FileName);
311  char *t = strdup( FileName );
312  int tmp = strlen( FileName );
313  if (tmp > 3) {
314  t[tmp-3] = 'a';
315  t[tmp-2] = 'l';
316  t[tmp-1] = 'p';
317  }
318  VSFile f2;
320  if (t) {
321  if (t[0] != '\0') {
322  static bool use_alphamap = parse_bool( vs_config->getVariable( "graphics",
323  "bitmap_alphamap",
324  "true" ) );
325  if (use_alphamap)
326  err2 = f2.OpenReadOnly( t, TextureFile );
327  }
328  }
329  if (err2 <= Ok) {
330  //texfilename += string(t);
331  }
332  //this->texfilename = texfilename;
333  //strcpy (filename,texfilename.c_str());
334  VSFile f;
335  VSError err; //FIXME err not always initialized before use
336  err = Ok; //FIXME this line added temporarily by chuck_starchaser
337  if (FileName)
338  if (FileName[0])
339  err = f.OpenReadOnly( FileName, TextureFile );
340  bool shared = (err == Shared);
341  free( t );
342  if (err <= Ok && g_game.use_textures == 0 && !force_load) {
343  f.Close();
344  err = Unspecified;
345  }
346  if (err > Ok) { //FIXME err not guaranteed to have been initialized!
347  FileNotFound( texfn );
348 //VSFileSystem::vs_fprintf (stderr, "\n%s, not found\n",FileName);
349  if (err2 <= Ok)
350  f2.Close();
351  return;
352  }
353  if (!nocache) {
354  string tempstr;
355  modold( texfn, shared, tempstr );
356  texfilename = tempstr;
357  }
358  if (texfn.find( "white" ) == string::npos)
359  bootstrap_draw( "Loading "+string( FileName ) );
360  //strcpy(filename, FileName);
361  if (err2 > Ok)
362  data = this->ReadImage( &f, NULL, true, NULL );
363  else
364  data = this->ReadImage( &f, NULL, true, &f2 );
365  if (data) {
366  if (mode >= _DXT1 && mode <= _DXT5) {
367  if ( (int) data[0] == 0 ) {
368  detailtexture = NEAREST;
369  ismipmapped = NEAREST;
370  }
371  }
372  if (main)
373  Bind( main, maxdimension, detailtexture );
374  else
375  Bind( maxdimension, detailtexture );
376  free( data );
377  data = NULL;
378  if (!nocache) setold();
379  } else {
380  FileNotFound( texfilename );
381  }
382  f.Close();
383  if ( f2.Valid() )
384  f2.Close();
385  //VSFileSystem::vs_fprintf (stderr," Load Success\n");
386 }
387 
388 Texture::Texture( const char *FileNameRGB,
389  const char *FileNameA,
390  int stage,
391  enum FILTER mipmap,
392  enum TEXTURE_TARGET target,
393  enum TEXTURE_IMAGE_TARGET imagetarget,
394  float alpha,
395  int zeroval,
396  GFXBOOL force_load,
397  int maxdimension,
398  GFXBOOL detailtexture,
399  GFXBOOL nocache,
400  enum ADDRESSMODE address_mode,
401  Texture *main )
402 {
403  InitTexture();
404  Load( FileNameRGB,
405  FileNameA,
406  stage,
407  mipmap,
408  target,
409  imagetarget,
410  alpha,
411  zeroval,
412  force_load,
413  maxdimension,
414  detailtexture,
415  nocache,
416  address_mode,
417  main );
418 }
419 
420 void Texture::Load( const char *FileNameRGB,
421  const char *FileNameA,
422  int stage,
423  enum FILTER mipmap,
424  enum TEXTURE_TARGET target,
425  enum TEXTURE_IMAGE_TARGET imagetarget,
426  float alpha,
427  int zeroval,
428  GFXBOOL force_load,
429  int maxdimension,
430  GFXBOOL detailtexture,
431  GFXBOOL nocache,
432  enum ADDRESSMODE address_mode,
433  Texture *main )
434 {
435  if (data) free( data );
436  if (palette) free( palette );
437  data = NULL;
438  palette = NULL;
439  ismipmapped = mipmap;
440 
441  this->stage = stage;
442  this->address_mode = address_mode;
443  texture_target = target;
444  image_target = imagetarget;
445  string texfn = string( FileNameRGB )+string( "|" )+string( FileNameA );
446  if (!nocache) {
447  string tempstr;
448  if ( checkold( texfn, false, tempstr )
449  || checkold( texfn, true, tempstr ) ) {
450  texfilename = tempstr;
451  return;
452  }
453  }
454  //VSFileSystem::vs_fprintf (stderr,"2.Loading bmp file %s alp %s ",FileNameRGB,FileNameA);
455  //this->texfilename = texfilename;
456  //strcpy (filename,texfilename.c_str());
457  VSFile f;
458  VSError err = Unspecified;
459  err = f.OpenReadOnly( FileNameRGB, TextureFile );
460  if (!nocache) {
461  bool shared = (err == Shared);
462  string tempstr;
463  modold( texfn, shared, tempstr );
464  texfilename = tempstr;
465  }
466  if (err <= Ok && g_game.use_textures == 0 && !force_load) {
467  f.Close();
468  err = Unspecified;
469  }
470  if (err > Ok) {
471  FileNotFound( texfilename );
472  return;
473  }
474  VSFile f1;
475  VSError err1 = Unspecified;
476  bool shared1;
477  if (FileNameA) {
478  static bool use_alphamap =
479  parse_bool( vs_config->getVariable( "graphics",
480  "bitmap_alphamap",
481  "true" ) );
482  if (use_alphamap) {
483  std::string tmp;
484  f1.OpenReadOnly( FileNameA, TextureFile );
485 
486  shared1 = (err1 == Shared);
487  if (err1 > Ok) {
488  data = NULL;
489  FileNameA = NULL;
490  }
491  } else {FileNameA = 0; }}
492  if (err1 > Ok)
493  data = this->ReadImage( &f, NULL, true, NULL );
494  else
495  data = this->ReadImage( &f, NULL, true, &f1 );
496  if (data) {
497  if (mode >= _DXT1 && mode <= _DXT5) {
498  if ( (int) data[0] == 0 ) {
499  detailtexture = NEAREST;
500  ismipmapped = NEAREST;
501  }
502  }
503  if (main)
504  Bind( main, maxdimension, detailtexture );
505  else
506  Bind( maxdimension, detailtexture );
507  free( data );
508  data = NULL;
509  if (!nocache) setold();
510  } else {
511  FileNotFound( texfilename );
512  }
513  f.Close();
514  if (err1 <= Ok)
515  f1.Close();
516  //VSFileSystem::vs_fprintf (stderr,"Load Success\n");
517 }
518 
520 {
521  if (original == NULL) {
530  UnBind();
531  if (palette != NULL) {
532  free( palette );
533  palette = NULL;
534  }
535  } else {
536  original->refcount--;
537  if (original->refcount == 0)
538  delete original;
539  }
540 }
541 
543 {
544  if (name != -1) {
545  texHashTable.Delete( texfilename );
546  GFXDeleteTexture( name );
547  name = -1;
548  }
549  //glDeleteTextures(1, &name);
550 }
551 
552 void Texture::Transfer( int maxdimension, GFXBOOL detailtexture )
553 {
554  //Implement this in D3D
555  //if(mode == _8BIT)
556  //glColorTable(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette);
557 
558  TEXTUREFORMAT internformat;
559  switch (mode)
560  {
561  //send DXT1,DXT3,DXT5 ...need to have the function call other glcompressedTexImage2D function
562  case _DXT1:
563  internformat = DXT1;
564  break;
565  case _DXT1RGBA:
566  internformat = DXT1RGBA;
567  break;
568  case _DXT3:
569  internformat = DXT3;
570  break;
571  case _DXT5:
572  internformat = DXT5;
573  break;
574  case _24BITRGBA:
575  internformat = RGBA32;
576  break;
577  case _24BIT:
578  internformat = RGB24;
579  break;
580  case _8BIT:
581  internformat = PALETTE8;
582  break;
583  default:
584  return;
585  }
586  if (img_sides == SIDE_SINGLE) {
587  GFXTransferTexture( data, name, sizeX, sizeY, internformat, image_target, maxdimension, detailtexture );
588  } else {
589  GFXTransferTexture( data, name, sizeX, sizeY, internformat, CUBEMAP_POSITIVE_X, maxdimension, detailtexture, 0 );
590  GFXTransferTexture( data, name, sizeX, sizeY, internformat, CUBEMAP_NEGATIVE_X, maxdimension, detailtexture, 1 );
591  GFXTransferTexture( data, name, sizeX, sizeY, internformat, CUBEMAP_POSITIVE_Y, maxdimension, detailtexture, 2 );
592  GFXTransferTexture( data, name, sizeX, sizeY, internformat, CUBEMAP_NEGATIVE_Y, maxdimension, detailtexture, 3 );
593  GFXTransferTexture( data, name, sizeX, sizeY, internformat, CUBEMAP_POSITIVE_Z, maxdimension, detailtexture, 4 );
594  GFXTransferTexture( data, name, sizeX, sizeY, internformat, CUBEMAP_NEGATIVE_Z, maxdimension, detailtexture, 5 );
595  }
596 }
597 
598 int Texture::Bind( int maxdimension, GFXBOOL detailtexture )
599 {
600  if ( !bound || (boundSizeX != sizeX) || (boundSizeY != sizeY) || (boundMode != mode) ) {
601  UnBind();
602  switch (mode)
603  {
604  case _DXT1:
605  GFXCreateTexture( sizeX, sizeY, DXT1, &name, NULL, stage, ismipmapped, texture_target, address_mode );
606  break;
607  case _DXT1RGBA:
608  GFXCreateTexture( sizeX, sizeY, DXT1RGBA, &name, NULL, stage, ismipmapped, texture_target, address_mode );
609  break;
610 
611  case _DXT3:
612  GFXCreateTexture( sizeX, sizeY, DXT3, &name, NULL, stage, ismipmapped, texture_target, address_mode );
613  break;
614  case _DXT5:
615  GFXCreateTexture( sizeX, sizeY, DXT5, &name, NULL, stage, ismipmapped, texture_target, address_mode );
616  break;
617 
618  case _24BITRGBA:
619  //GFXCreateTexture(sizeX, sizeY, RGBA32, &name, NULL, stage);
620  GFXCreateTexture( sizeX, sizeY, RGBA32, &name, NULL, stage, ismipmapped, texture_target, address_mode );
621  break;
622  case _24BIT:
623  //not supported by most cards, so i use rgba32
624  //GFXCreateTexture(sizeX, sizeY, RGB24, &name);
625  GFXCreateTexture( sizeX, sizeY, RGB24, &name, NULL, stage, ismipmapped, texture_target, address_mode );
626  break;
627  case _8BIT:
628  GFXCreateTexture( sizeX, sizeY, PALETTE8, &name, (char*) palette, stage, ismipmapped, texture_target, address_mode );
629  break;
630  }
631  }
632  boundSizeX = sizeX;
633  boundSizeY = sizeY;
634  boundMode = mode;
635  bound = true;
636  Transfer( maxdimension, detailtexture );
637  return name;
638 }
639 
640 int Texture::Bind( Texture *other, int maxdimension, GFXBOOL detailtexture )
641 {
642  UnBind();
643 
644  boundSizeX = other->boundSizeX;
645  boundSizeY = other->boundSizeY;
646  boundMode = other->boundMode;
647  bound = other->bound;
648  name = other->name;
649  Transfer( maxdimension, detailtexture );
650  return name;
651 }
652 
653 void Texture::Prioritize( float priority )
654 {
655  GFXPrioritizeTexture( name, priority );
656 }
657 
658 static void ActivateWhite( int stage )
659 {
660  static Texture *white = new Texture( "white.bmp", 0, MIPMAP, TEXTURE2D, TEXTURE_2D, 1 );
661  if ( white->LoadSuccess() )
662  white->MakeActive( stage );
663 }
664 
665 void Texture::MakeActive( int stag, int pass )
666 {
667  static bool missing = false;
668  if ( (name == -1) || (pass != 0) ) {
669  ActivateWhite( stag );
670  } else {
671  // Lazy-init default address mode
672  // So that texture_target is properly initiated
673  // by the time we do
674  if (address_mode == DEFAULT_ADDRESS_MODE) {
675  switch (texture_target)
676  {
677  case TEXTURE1D:
678  case TEXTURE2D:
679  #ifdef GL_EXT_texture3D
680  case TEXTURE3D:
681  #endif
682  default:
683  address_mode = WRAP;
684  break;
685  case TEXTURERECT:
686  case CUBEMAP:
687  address_mode = CLAMP;
688  break;
689  }
690  }
691 
692  GFXActiveTexture( stag );
693  GFXSelectTexture( name, stag );
694  GFXTextureAddressMode( address_mode, texture_target ); //In case it changed - it's possible
695  }
696 }
697