1 /*
2
3 *************************************************************************
4
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
7
8 **************************************************************************
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 ***************************************************************************
25
26 */
27
28 #include "rSDL.h"
29
30 #include "config.h"
31
32 #include "rTexture.h"
33 #include "rDisplayList.h"
34 #include "tString.h"
35 #include "rScreen.h"
36 #include "tDirectories.h"
37 #include "tLocale.h"
38 #include "tException.h"
39 #include "tResourceManager.h"
40
41 #include <sstream>
42
43 #ifndef DEDICATED
44 #include "rRender.h"
45 #include "rGL.h"
46
47 // Load the right SDL_IMAGE header
48
49 #ifdef _MSC_VER
50 #include <SDL_image.h>
51 #else
52 #ifdef __MINGW32__
53 #include <SDL_image.h>
54 #else
55 #ifdef HAVE_SDL_IMG_H
56 #include <SDL_image.h>
57 #else
58 #ifdef HAVE_SDL_SDL_IMAGE_H
59 #include <SDL/SDL_image.h>
60 #else
61 #ifdef HAVE_IMG_H
62 #include <IMG.h>
63 #else
64 #ifdef HAVE_SDL_IMG_H
65 #include <SDL/IMG.h>
66 #else
67 #ifdef HAVE_LIBSDL
68 #include <SDL_image.h>
69 #else
70 #ifdef HAVE_LIBIMG
71 #include <IMG.h>
72 #else
73 // if the following include ( or one of the earlier ones ) fails, you don't have SDL_image properly installed.
74 #include <SDL_image.h>
75 #endif
76 #endif
77 #endif
78 #endif
79 #endif
80 #endif
81 #endif
82 #endif
83 #endif
84
85
86 // ******************************************************************************************
87 // *
88 // * rSurface
89 // *
90 // ******************************************************************************************
91 //!
92 //! @param fileName name of the file to load sufrace from
93 //!
94 // ******************************************************************************************
95
rSurface(char const * fileName)96 rSurface::rSurface( char const * fileName )
97 {
98 Init();
99 Create( fileName );
100 }
101
102 // ******************************************************************************************
103 // *
104 // * ~rSurface
105 // *
106 // ******************************************************************************************
107 //!
108 //!
109 // ******************************************************************************************
110
~rSurface(void)111 rSurface::~rSurface( void )
112 {
113 Clear();
114 }
115
116 // ******************************************************************************************
117 // *
118 // * rSurface
119 // *
120 // ******************************************************************************************
121 //!
122 //!
123 // ******************************************************************************************
124
rSurface(void)125 rSurface::rSurface( void )
126 {
127 Init();
128 }
129
130 // ******************************************************************************************
131 // *
132 // * rSurface
133 // *
134 // ******************************************************************************************
135 //!
136 //! @param other source to copy from
137 //!
138 // ******************************************************************************************
139
rSurface(rSurface const & other)140 rSurface::rSurface( rSurface const & other )
141 {
142 Init();
143 CopyFrom( other );
144 }
145
146 // ******************************************************************************************
147 // *
148 // * operator =
149 // *
150 // ******************************************************************************************
151 //!
152 //! @param other
153 //! @return
154 //!
155 // ******************************************************************************************
156
operator =(rSurface const & other)157 rSurface & rSurface::operator =( rSurface const & other )
158 {
159 if ( &other != this )
160 {
161 Clear();
162 CopyFrom( other );
163 }
164
165 return *this;
166 }
167
168 // ******************************************************************************************
169 // *
170 // * Init
171 // *
172 // ******************************************************************************************
173 //!
174 //!
175 // ******************************************************************************************
176
Init(void)177 void rSurface::Init( void )
178 {
179 surface_ = 0;
180 format_ = 0;
181 }
182
183 // ******************************************************************************************
184 // *
185 // * Clear
186 // *
187 // ******************************************************************************************
188 //!
189 //!
190 // ******************************************************************************************
191
Clear(void)192 void rSurface::Clear( void )
193 {
194 #ifndef DEDICATED
195 // delete surface
196 if ( surface_ )
197 SDL_FreeSurface( surface_ );
198
199 #endif
200 surface_ = 0;
201 }
202
203 // ******************************************************************************************
204 // *
205 // * Create
206 // *
207 // ******************************************************************************************
208 //!
209 //! @param fileName name of the image file to load
210 //!
211 // ******************************************************************************************
212
Create(char const * fileName)213 void rSurface::Create( char const * fileName )
214 {
215 #ifndef DEDICATED
216 sr_LockSDL();
217
218 // find path of image
219 // tString s = tResourceManager::locateResource("", fileName);
220 tString s = tDirectories::Data().GetReadPath( fileName );
221
222 // Load image
223 IMG_InvertAlpha(true);
224 Create( IMG_Load(s) );
225
226 //if ( surface_ )
227 // std::cerr << "loaded surface " << fileName << "\n";
228
229 sr_UnlockSDL();
230 #endif
231 }
232
233 // ******************************************************************************************
234 // *
235 // * Create
236 // *
237 // ******************************************************************************************
238 //!
239 //! @param surface
240 //!
241 // ******************************************************************************************
242
Create(SDL_Surface * surface)243 void rSurface::Create( SDL_Surface * surface )
244 {
245 #ifndef DEDICATED
246 // clear previous surface
247 Clear();
248
249 // take ownership
250 surface_ = surface;
251
252 // determine texture format
253 if ( surface_ )
254 {
255 switch (surface_->format->BytesPerPixel){
256 case 1:
257 format_ = GL_LUMINANCE;
258 break;
259
260 case 2:
261 format_ = GL_LUMINANCE8_ALPHA8;
262 break;
263
264 case 3:
265 format_ = GL_RGB;
266 break;
267
268 case 4:
269 format_ = GL_RGBA;
270 break;
271
272 default:
273 {
274 // fallback: convert the texture into a known format.
275
276 SDL_Surface *dummy =
277 SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1,
278 32,
279 0x0000FF, 0x00FF00,
280 0xFF0000 ,0xFF000000);
281
282 SDL_Surface *convtex =
283 SDL_ConvertSurface(surface_, dummy->format, SDL_SWSURFACE);
284
285 SDL_FreeSurface(surface_);
286 surface_ = convtex;
287 SDL_FreeSurface(dummy);
288
289 format_ = GL_RGBA;
290 }
291 break;
292 }
293 }
294 #endif
295 }
296
297 // ******************************************************************************************
298 // *
299 // * CopyFrom
300 // *
301 // ******************************************************************************************
302 //!
303 //! @param other
304 //!
305 // ******************************************************************************************
306
CopyFrom(rSurface const & other)307 void rSurface::CopyFrom( rSurface const & other )
308 {
309 #ifndef DEDICATED
310 tASSERT( 0 == surface_ );
311 tASSERT( other.surface_ );
312
313 // copy surface
314 surface_ = SDL_ConvertSurface(other.surface_, other.surface_->format, SDL_SWSURFACE);
315
316 // copy flags
317 format_ = other.format_;
318 #endif
319 }
320
321 // ******************************************************************************************
322 // *
323 // * ~rITexture
324 // *
325 // ******************************************************************************************
326 //!
327 //!
328 // ******************************************************************************************
329
~rITexture(void)330 rITexture::~rITexture( void )
331 {
332 s_textures_.Remove(this,id_);
333 }
334
335 // ******************************************************************************************
336 // *
337 // * UnloadAll
338 // *
339 // ******************************************************************************************
340 //!
341 //!
342 // ******************************************************************************************
343
UnloadAll(void)344 void rITexture::UnloadAll( void )
345 {
346 for(int i=s_textures_.Len()-1;i>=0;i--)
347 {
348 s_textures_(i)->Unload();
349 }
350 }
351
352 // ******************************************************************************************
353 // *
354 // * LoadAll
355 // *
356 // ******************************************************************************************
357 //!
358 //!
359 // ******************************************************************************************
360
LoadAll(void)361 void rITexture::LoadAll( void )
362 {
363 // s_reportErrors=false;
364 for(int i=s_textures_.Len()-1;i>=0;i--)
365 {
366 s_textures_(i)->Select();
367 //if (i>=s_textures.Len())
368 // i=s_textures.Len()-1;
369 }
370 // s_reportErrors=true;
371 }
372
373 // ******************************************************************************************
374 // *
375 // * rITexture
376 // *
377 // ******************************************************************************************
378 //!
379 //!
380 // ******************************************************************************************
381
rITexture(void)382 rITexture::rITexture( void )
383 : id_( -1 )
384 {
385 }
386
387 // ******************************************************************************************
388 // *
389 // * OnSelect
390 // *
391 // ******************************************************************************************
392 //!
393 //! @param enforce enforce when set to true, the texture should be loaded even if the configuration says it should not
394 //!
395 // ******************************************************************************************
396
OnSelect(bool enforce)397 void rITexture::OnSelect( bool enforce )
398 {
399 if ( id_ < 0 )
400 s_textures_.Add(this,id_);
401 }
402
403 // ******************************************************************************************
404 // *
405 // * OnUnload
406 // *
407 // ******************************************************************************************
408 //!
409 //!
410 // ******************************************************************************************
411
OnUnload(void)412 void rITexture::OnUnload( void )
413 {
414 }
415
416 // ******************************************************************************************
417 // *
418 // * rISurfaceTexture
419 // *
420 // ******************************************************************************************
421 //!
422 //! @param group texture group ( floor/wall)
423 //! @param repx flag indicating the x repeat mode
424 //! @param repy flag indicating the y repeat mode
425 //! @param storeAlpha flag indicating whether the alpha channel should be stored
426 //!
427 // ******************************************************************************************
428
rISurfaceTexture(int group,bool repx,bool repy,bool storeAlpha)429 rISurfaceTexture::rISurfaceTexture( int group, bool repx, bool repy, bool storeAlpha )
430 : group_( group ), textureModeLast_( -1), tint_( 0 ), repx_( repx ), repy_( repy ), storeAlpha_( storeAlpha )
431 {
432 }
433
434 // ******************************************************************************************
435 // *
436 // * ~rISurfaceTexture
437 // *
438 // ******************************************************************************************
439 //!
440 //!
441 // ******************************************************************************************
442
~rISurfaceTexture(void)443 rISurfaceTexture::~rISurfaceTexture( void )
444 {
445 #ifndef DEDICATED
446 if (tint_ > 0)
447 {
448 rDisplayList::ClearAll();
449
450 glDeleteTextures(1,&tint_);
451 tint_ = 0;
452 }
453 #endif
454 }
455
456 // ******************************************************************************************
457 // *
458 // * ProcessImage
459 // *
460 // ******************************************************************************************
461 //!
462 //! @param surface the surface to process
463 //!
464 // ******************************************************************************************
465
ProcessImage(SDL_Surface * surface)466 void rISurfaceTexture::ProcessImage( SDL_Surface * surface )
467 {
468 }
469
470 // ******************************************************************************************
471 // *
472 // * Upload
473 // *
474 // ******************************************************************************************
475 //!
476 //! @param surface
477 //!
478 // ******************************************************************************************
479
Upload(rSurface & surface)480 void rISurfaceTexture::Upload( rSurface & surface )
481 {
482 #ifndef DEDICATED
483 sr_LockSDL();
484 GLenum texformat = surface.GetFormat();
485 SDL_Surface * tex = surface.GetSurface();
486 tASSERT( tex );
487
488 bool texalpha=tex->format->Amask;
489
490 ProcessImage(tex);
491
492 if(repx_)
493 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
494 else
495 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
496 if(repy_)
497 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
498 else
499 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
500
501 int format;
502 if (sr_texturesTruecolor)
503 if (storageHack_ || ( storeAlpha_ && texalpha ) )
504 format=GL_RGBA8;
505 else
506 format=GL_RGB8;
507 else
508 if (storageHack_ || ( storeAlpha_ && texalpha ) )
509 format=GL_RGBA4;
510 else
511 format=GL_RGB5;
512
513 gluBuild2DMipmaps(GL_TEXTURE_2D,format,tex->w,tex->h,
514 texformat,GL_UNSIGNED_BYTE,tex->pixels);
515
516 sr_UnlockSDL();
517 #endif
518 }
519
520 // ******************************************************************************************
521 // *
522 // * OnSelect
523 // *
524 // ******************************************************************************************
525 //!
526 //! @param enforce enforce when set to true, the texture should be loaded even if the configuration says it should not
527 //!
528 // ******************************************************************************************
529
OnSelect(bool enforce)530 void rISurfaceTexture::OnSelect( bool enforce )
531 {
532 #ifndef DEDICATED
533 if(sr_glOut)
534 {
535 RenderEnd(true);
536
537 int texmod=rTextureGroups::TextureMode[group_];
538 if (enforce && texmod<0) texmod=GL_NEAREST_MIPMAP_NEAREST;
539
540 if(textureModeLast_!=texmod)
541 {
542 // unload texture if the mode changed
543 if ( tint_ > 0 )
544 Unload();
545 tASSERT( tint_ == 0 );
546 // std::cerr << "loading texture " << fileName << ':' << tint << "\n";
547
548 if (texmod>0){
549 // don't generate textures inside display lists
550 rDisplayList::Cancel();
551
552 glGenTextures(1, &tint_);
553 glBindTexture(GL_TEXTURE_2D,tint_);
554
555 if (textureModeLast_<0)
556 {
557 // delegate core loading work to derived class
558 OnSelect();
559 }
560
561 //glEnable(GL_TEXTURE);
562 glEnable(GL_TEXTURE_2D);
563
564 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
565 texmod);
566
567 switch(texmod)
568 {
569 case GL_NEAREST:
570 case GL_NEAREST_MIPMAP_NEAREST:
571 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
572 GL_NEAREST);
573 break;
574 default:
575 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
576 GL_LINEAR);
577 break;
578 }
579
580 }
581 else
582 {
583 glDisable(GL_TEXTURE_2D);
584 }
585 }
586 else
587 {
588 glBindTexture(GL_TEXTURE_2D,tint_);
589 if (texmod>0)
590 {
591 glEnable(GL_TEXTURE_2D);
592 }
593 else
594 {
595 glDisable(GL_TEXTURE_2D);
596 }
597 }
598 textureModeLast_=texmod;
599 }
600 rITexture::OnSelect(enforce);
601 #endif
602 }
603
604 // ******************************************************************************************
605 // *
606 // * OnSelect
607 // *
608 // ******************************************************************************************
609 //!
610 //! In derived classes, this routine is supposed to do the work of loading the texture
611 //! into memory and using the Upload() function to upload it to OpenGL.
612 //!
613 // ******************************************************************************************
614
OnSelect()615 void rISurfaceTexture::OnSelect()
616 {
617 }
618
619 // ******************************************************************************************
620 // *
621 // * OnUnload
622 // *
623 // ******************************************************************************************
624 //!
625 //!
626 // ******************************************************************************************
627
OnUnload(void)628 void rISurfaceTexture::OnUnload( void )
629 {
630 #ifndef DEDICATED
631 if (tint_ > 0)
632 {
633 rDisplayList::ClearAll();
634
635 // std::cerr << "unloading texture " << fileName << ':' << tint_ << "\n";
636 glDeleteTextures(1,&tint_);
637 tint_ = 0;
638 }
639
640 textureModeLast_=-100;
641 rITexture::OnUnload();
642 #endif
643 }
644
645 // ******************************************************************************************
646 // *
647 // * StoreAlpha
648 // *
649 // ******************************************************************************************
650 //!
651 //!
652 // ******************************************************************************************
653
StoreAlpha(void)654 void rISurfaceTexture::StoreAlpha( void )
655 {
656 storeAlpha_ = true;
657 }
658
659 // ******************************************************************************************
660 // *
661 // * rFileTexture
662 // *
663 // ******************************************************************************************
664 //!
665 //! @param group texture group ( floor/wall)
666 //! @param fileName the filename of the picture to load
667 //! @param repx flag indicating the x repeat mode
668 //! @param repy flag indicating the y repeat mode
669 //! @param storeAlpha flag indicating whether the alpha channel should be stored
670 //!
671 // ******************************************************************************************
672
rFileTexture(int group,char const * fileName,bool repx,bool repy,bool storeAlpha)673 rFileTexture::rFileTexture( int group, char const * fileName, bool repx, bool repy, bool storeAlpha )
674 : rISurfaceTexture( group, repx, repy, storeAlpha )
675 , fileName_( fileName )
676 {
677 }
678
679 // ******************************************************************************************
680 // *
681 // * ~rFileTexture
682 // *
683 // ******************************************************************************************
684 //!
685 //!
686 // ******************************************************************************************
687
~rFileTexture(void)688 rFileTexture::~rFileTexture( void )
689 {
690 }
691
692 // ******************************************************************************************
693 // *
694 // * OnSelect
695 // *
696 // ******************************************************************************************
697 //!
698 //!
699 // ******************************************************************************************
700
OnSelect()701 void rFileTexture::OnSelect()
702 {
703 #ifndef DEDICATED
704 // std::cerr << "loading texture " << fileName_ << "\n";
705 rSurface surface( fileName_ );
706 if ( surface.GetSurface() )
707 {
708 this->Upload( surface );
709 }
710 else if (s_reportErrors_)
711 {
712 throw tGenericException( tOutput( "$texture_error_filenotfound", fileName_ ), tOutput("$texture_error_filenotfound_title") );
713 }
714 rISurfaceTexture::OnSelect();
715 #endif
716 }
717
718 // ******************************************************************************************
719 // *
720 // * rSurfaceTexture
721 // *
722 // ******************************************************************************************
723 //!
724 //! @param group texture group ( floor/wall)
725 //! @param surface
726 //! @param repx flag indicating the x repeat mode
727 //! @param repy flag indicating the y repeat mode
728 //! @param storeAlpha flag indicating whether the alpha channel should be stored
729 //!
730 // ******************************************************************************************
731
rSurfaceTexture(int group,rSurface const & surface,bool repx,bool repy,bool storeAlpha)732 rSurfaceTexture::rSurfaceTexture( int group, rSurface const & surface, bool repx, bool repy, bool storeAlpha )
733 : rISurfaceTexture( group, repx, repy, storeAlpha )
734 , surface_( surface )
735 {
736 }
737
738 // ******************************************************************************************
739 // *
740 // * ~rSurfaceTexture
741 // *
742 // ******************************************************************************************
743 //!
744 //!
745 // ******************************************************************************************
746
~rSurfaceTexture(void)747 rSurfaceTexture::~rSurfaceTexture( void )
748 {
749 }
750
751 // ******************************************************************************************
752 // *
753 // * OnSelect
754 // *
755 // ******************************************************************************************
756 //!
757 //!
758 // ******************************************************************************************
759
OnSelect()760 void rSurfaceTexture::OnSelect()
761 {
762 #ifndef DEDICATED
763 // upload a copy of the surface ( it may get modified )
764 if ( surface_.GetSurface() )
765 {
766 rSurface copy( surface_ );
767 this->Upload( copy );
768 rISurfaceTexture::OnSelect();
769 }
770 #endif
771 }
772
773
774 bool rISurfaceTexture::s_reportErrors_=false;
775 tList<rITexture> rITexture::s_textures_;
776
777 int rTextureGroups::TextureMode[rTextureGroups::TEX_GROUPS];
778
779 char const * rTextureGroups::TextureGroupDescription[rTextureGroups::TEX_GROUPS]=
780 {
781 "$texture_mode_0_help",
782 "$texture_mode_1_help",
783 "$texture_mode_2_help",
784 "$texture_mode_3_help",
785 };
786
787 bool rISurfaceTexture::storageHack_ = false;
788
789 //rTexture ArmageTron_eWall("wWall.png",1,0);
790 //rTexture ArmageTron_dir_eWall("wall.png",1,0);
791
792
793 static rCallbackBeforeScreenModeChange unload(&rITexture::UnloadAll);
794
795 // static rCallbackAfterScreenModeChange load(&rITexture::LoadAll);
796