|
|
#include <stdio.h>
& Q# `, z) K$ M& B#include <stdlib.h>! ^6 z+ ]$ v4 _9 W
#include <string.h>
( f/ q, W( c- K/ _% i- J5 j#include <windows.h>9 c/ \: I9 p# z
#include <GL/gl.h>" C, S, b1 {" E* _6 Y6 X+ Z1 U
) h! X* a# F1 V( k0 W- J, [4 N7 Iclass tgaImageFile/ J, M9 Z2 s# O/ l
{# o/ l5 e; E2 i# c8 b% C! I% a
public:) n" y0 E# s2 `# l) s
7 r4 T1 h1 I7 k; o' k. LtgaImageFile(void) : " a3 _, z( Z: ~2 k3 s5 _: Q5 \' k! H( Y
m_texFormat(-1),
: U* @( o2 @; f1 A" Xm_nImageWidth(0),
0 t6 C |3 u6 e' z! B( b3 lm_nImageHeight(0),8 I) q- ?4 Z/ ^) U4 p/ F7 P$ J
m_nImageBits(0),- k; p4 f# Y9 u$ i
m_nImageData(NULL) {}. o! Q, \# U, D8 v
8 P; A* W9 y* N( J2 G# q
~tgaImageFile(void);
, S( A7 y: q0 K0 E' |8 O; V3 A8 D; V0 M; Z6 u2 C
enum TGALoadError) @$ H0 r8 `5 g+ ?
{- Q) u9 X4 Q* E$ b6 A
TGA_NO_ERROR = 1, // No error+ p! i9 W( A/ x) c9 w: o
TGA_FILE_NOT_FOUND, // File was not found 9 @* @1 `* Y* M! G9 D
TGA_BAD_IMAGE_TYPE, // Color mapped image or image is not uncompressed
/ P$ }! w( p# n2 G: G8 }TGA_BAD_DIMENSION, // Dimension is not a power of 2 4 U) r7 }- I6 r- A {$ [
TGA_BAD_BITS, // Image bits is not 8, 24 or 32
( I$ z- D) f& XTGA_BAD_DATA // Image data could not be loaded
9 m. {! m3 C9 p" C; L5 L2 [ o };
' T) `, V/ w/ G8 `% s! V( J+ P: A9 I6 I
tgaImageFile::TGALoadError load( char *name );, l& J- ]4 _1 O
+ X% _ y# y" T4 s* j. g5 \
GLenum m_texFormat;' m+ N' f/ U) i. o7 ^# b
int m_nImageWidth;# h# u. Z! P- b. L
int m_nImageHeight;
9 Y4 A! {3 W2 o/ kint m_nImageBits;0 w" Y; }5 A: W. _ U
unsigned char * m_nImageData;! q1 d3 O& ]4 i {
4 S: [- k4 P3 q
private:
( O) ~ I8 k! N8 z8 R( S6 y5 A3 z0 s% _. k
bool checkSize(int x);8 |' L( O6 f* {4 _7 I
int returnError(FILE *s, int error);7 F, c0 D# |$ E- v- Z
unsigned char *getRGBA(FILE *s, int size); X2 F( y$ f8 r# m, r8 `
unsigned char *getRGB(FILE *s, int size);" d5 S, f% Q& Q2 u1 } {2 K
unsigned char *getGray(FILE *s, int size); B6 W4 M: M8 l% Z
};
* N/ y) h! q! X: T4 F/ B1 P$ F5 k/ M. I, _8 _' N" q8 D
tgaImageFile::~tgaImageFile( void ) ]+ J0 E3 {0 c( u+ O" F
{
; ^. q' }8 P6 mif( m_nImageData != NULL )
; P9 r. v% }3 g' g3 e{
% X; z# N$ \9 b* p: Ifree( m_nImageData );
4 j0 M( u: ~$ C% A0 km_nImageData = NULL;4 p. O6 H% W; g& v4 {" d! y( }9 t7 Z
}
$ ]! g7 y) ]" f% A% V1 ~7 D}& e( Z: _( z% l: b5 C& T
$ E0 x8 U- Q3 U/ |# U4 J
bool tgaImageFile::checkSize( int x ), U- f+ y1 g Q P2 }. D
{
) t% O0 N. S$ c1 W// Make sure its a power of 2.
3 j+ i7 w+ f5 u. j9 t/ Yif( x == 2 || x == 4 ||
. U6 l' g0 t+ j! X8 |1 Qx == 8 || x == 16 ||
1 W7 ^8 ?0 ^$ wx == 32 || x == 64 ||
, G$ A) M( ]; g& E) b% W# Wx == 128 || x == 256 ||
0 O1 d2 s/ y) ?1 i& ?( wx == 512 )" C# k9 v( e: i D9 q6 V* F
return true;: c5 F; z& h. ^+ r z. C
0 q0 D3 X, }) D, Z, ]/ e
return false;+ h/ W* S0 g3 i
}( j! `! q* p3 f3 M3 I% z
. \$ w c6 G* U( Z: ^int tgaImageFile::returnError( FILE *s, int error )
$ Z/ p; z5 e5 I/ d. R4 D6 g{( N. u' p1 j% H* E
// Called when there is an error loading the .tga texture file. X# ?; b5 W8 D
fclose( s );
; B0 y! d- r2 n9 ]5 W9 y; Rreturn error;2 K# g: B. d1 n. H' B' p$ k
}
6 f6 ~- T6 y9 h. R7 X# k# {9 ^7 }- O: w/ H" [" l- _
unsigned char *tgaImageFile::getRGBA( FILE *s, int size )' p+ v' O, F5 O& K: N& o
{! i+ k, ?# Y# v/ f# M+ q; |
// Read in RGBA data for a 32bit image.
2 C( j) a5 E$ [" |( Iunsigned char *rgba;- p: A/ {, Q! A
unsigned char temp;6 v2 y7 f* u# x6 u8 ?
int bread;
5 O; G% l# W1 R3 ^int i;# z4 P; g& V/ ?/ p
* k- |; H8 F, q- g
rgba = (unsigned char *)malloc( size * 4 );7 L! W, j S7 v) e! B! ?2 O
/ O( |% q) @& ^if( rgba == NULL )- [, \1 g* E6 D5 r/ m7 m
return 0;
8 \* I+ s4 X8 W9 S) j, i9 r4 r! `6 p
bread = fread( rgba, sizeof (unsigned char), size * 4, s ); ( c8 u" l. p# A7 X* X x. U* l
$ V; @4 A" j8 r% n0 t. t
// TGA is stored in BGRA, make it RGBA 0 w0 z6 k, E7 i' l1 }2 f
if( bread != size * 4 )
8 y/ y/ g1 ] F; X7 l' W{
: K& N6 ?+ n+ L' Hfree( rgba );# a' I9 N- K/ G& j z& V I4 a; C
return 0;
6 O& k1 k( h2 ] B}
. }) j2 F' t& s9 g* ~8 D& w9 S. u6 _! U
for( i = 0; i < size * 4; i += 4 )) j" C, w* N9 t- ?
{
; r" X$ f' S$ ]+ q5 U4 [temp = rgba[i];
1 e4 i1 z; {0 s- w L0 @3 S' srgba[i] = rgba[i + 2];
. H9 j* a9 g( W/ F2 G* z* }# H frgba[i + 2] = temp;; n" }; G) Q5 {' V9 j
}
+ Q& F) Z& m; J6 L D0 `5 V7 z/ [- N( R
, Q7 M8 p& w( z um_texFormat = GL_RGBA;
: V; p. R8 s5 b" n nreturn rgba;
1 J: u+ @; T. w( Q: F! C. u: S3 z}, M8 b: v5 u- f4 m
" ? v1 y4 w& D% u2 c4 j
unsigned char *tgaImageFile::getRGB( FILE *s, int size )7 q+ t& z) l" T; u% F9 ?
{
1 B1 \7 Q. `& [// Read in RGB data for a 24bit image. * c: ^% p$ |% c+ A; D- S0 a
unsigned char *rgb;3 E; N6 ~; j1 C: f/ Y
unsigned char temp;
: m- T/ g3 W* R+ K% E; K& ?& }' oint bread;
I5 X# P+ }/ s2 m' Q7 t3 y- l! cint i;
' y1 N0 _, L: v8 T& q
/ z, T. y4 O4 }* z4 Orgb = (unsigned char*)malloc( size * 3 );9 O$ s% x b# j6 }
/ |! {8 W4 u' C* X Y& H- h
if( rgb == NULL )
) D* O* A: l) Y; q0 R2 }return 0;
4 J% d1 u5 F8 Z, a4 G8 J( q% ? ]4 {$ P! b
bread = fread( rgb, sizeof (unsigned char), size * 3, s );
+ j/ m( g9 k5 x, e, u0 u( J" v6 C9 b5 n9 ~8 j. ]# q
if(bread != size * 3)
. Y, l9 I' G$ @3 Q }8 G. q l{
+ U+ i3 {/ p/ e- j& r$ ?& |free( rgb );
- w: I$ V- a5 c. Freturn 0;8 P1 ^/ A0 R, ~3 M) c
}
$ P) C; V' Y: h3 f& x/ j8 L! M3 u2 v1 `5 l
// TGA is stored in BGR, make it RGB . b( x% r* M) d! s8 ?. M6 a/ ?! ]
for( i = 0; i < size * 3; i += 3 )
9 p6 ?5 z, g8 i9 L' l8 i{& G b3 v0 x" i7 L9 @
temp = rgb[i];
0 y, T. Z+ e- x- ]3 Crgb[i] = rgb[i + 2];+ q3 S3 L* y$ a4 T$ L
rgb[i + 2] = temp;7 D% M" V6 {/ W( M: f
}& H* U; w, s" i$ x& k
( `7 R/ B0 {$ H" ~m_texFormat = GL_RGB;. ], z* i3 D7 |% `& g8 m+ J
+ }% S" S0 J. s7 C' J* J% Hreturn rgb;5 I( G3 ]2 a' R
}
- p* \0 x1 @2 H4 J/ O0 b& p f/ ]9 _" ?; t* U6 V7 L: r0 H
unsigned char *tgaImageFile::getGray( FILE *s, int size )
( M7 I& \3 h$ M$ B. r{
A8 C+ {( G, Q// Gets the grayscale image data. Used as an alpha channel.
4 K( I# p8 z( X4 Gunsigned char *grayData;
, M' y$ f- ^ e3 bint bread;
# \3 z: v5 b' }3 U. |5 ^% p3 K9 E2 X$ F5 l( Q; G: x \
grayData = (unsigned char*)malloc( size );
" x/ e' E( }8 }5 E# Y9 {: w p S' m2 G( P: m8 ^- _; Q5 [) q. C
if( grayData == NULL )2 t; N7 S' _; W: e( ~
return 0;' c2 G- H$ k" ^. w6 f. U% s
' h$ k: l7 o4 h/ K" k5 {: D, \
bread = fread( grayData, sizeof (unsigned char), size, s );" z' c! a m) o! Y7 K
" z" S! M. @3 Q t
if( bread != size )
; _; [+ f0 e- F: `) I( c0 Q/ F{0 v5 @' M' z! p! }, e- l$ \% d) Z
free( grayData );" h' [7 A* v n/ N G* c5 z
return 0;
4 L2 x1 e; g. J+ ]- k2 ?$ Q; t}
. s$ Y* p0 C8 F4 G5 y
( u5 y/ F4 S. P3 `) A# A; Y3 F0 im_texFormat = GL_ALPHA;5 C4 [/ A0 Y4 B/ Q" b
6 N. h' v2 v" F- S9 i+ Preturn grayData;2 U8 U) M# A2 z/ v1 a7 J, c
}% c- }; i7 i8 e* t A* K' R
! m- o' C) O: i7 U1 [tgaImageFile::TGALoadError tgaImageFile::load( char *name )
$ m. q) n$ J4 e$ n" L' Q, n& a. s{# P' x6 G& m+ a1 A
// Loads up a targa file. Supported types are 8, 24 and 32 3 c1 V4 A* a% D( F5 u
// uncompressed images.6 l% u" r( J/ P) M
unsigned char type[4];$ l+ Z+ q2 K3 B7 c
unsigned char info[7];
5 \: ]7 i! r' O7 BFILE *s = NULL;7 Q! x0 T- A' d* L8 n
int size = 0;
- W* H& _. j+ q2 k% d. ?
# }. F' P5 m; f9 c( M5 ]if( !(s = fopen( name, "rb" )) )2 M- _" T( ^, M! b* Z
return TGA_FILE_NOT_FOUND;
1 Q% _3 L/ x8 u. m: s/ c7 _7 Y) E! q' |
fread( &type, sizeof (char), 3, s ); // Read in colormap info and image type, byte 0 ignored2 V+ U7 ^9 @3 T8 I2 c/ e8 t9 B
fseek( s, 12, SEEK_SET); // Seek past the header and useless info0 R. T+ H- T" m+ E
fread( &info, sizeof (char), 6, s );
6 Y" n4 P' p+ X; J/ U y N6 a8 s) n( i& E: i# j0 k* P0 G. g
if( type[1] != 0 || (type[2] != 2 && type[2] != 3) )
- ]0 B4 q) d8 Q6 A7 z" sreturnError( s, TGA_BAD_IMAGE_TYPE );
% J; e7 Z- v2 }4 }4 Z- i! G% C5 \' G1 r, m* x u" d
m_nImageWidth = info[0] + info[1] * 256; ; ?; M0 L$ V. }6 M
m_nImageHeight = info[2] + info[3] * 256;
* F$ x5 I0 |& L. q$ L Ym_nImageBits = info[4]; " }3 }* o) i. f
) w- H$ P, q) G1 Y; i) K/ psize = m_nImageWidth * m_nImageHeight;
- W' P7 U2 |/ R2 g T+ R& W; ^
- N2 k k9 o4 Q" F7 v; P j// Make sure dimension is a power of 2 - y) x E' } ^/ D4 ^9 V; B, S
if( !checkSize(m_nImageWidth) || !checkSize(m_nImageHeight))2 L7 Y. R& K- z7 _$ Z
returnError( s, TGA_BAD_DIMENSION);4 e0 W& h, v* i
4 [- O3 l$ Z: Y' C% u
// Make sure we are loading a supported type
r& c* p2 f7 x; O9 [if( m_nImageBits != 32 && m_nImageBits != 24 && m_nImageBits != 8 ): x" V5 E& ]. V. e5 @# [, a
returnError( s, TGA_BAD_BITS );" l$ J% b" L; ~3 a( V
' K0 c8 o! @- l
if( m_nImageBits == 32 )
9 M, P- A) H! v6 S" n6 Cm_nImageData = getRGBA( s, size );! o" l# Q/ d; g$ @6 q
else if( m_nImageBits == 24 ), `: |7 _: \) L6 W
m_nImageData = getRGB( s, size ); 8 Q& ]5 Y* {* Z: M$ x
else if( m_nImageBits == 8 )0 e. a/ K( \ D' a& q
m_nImageData = getGray( s, size );* i$ j% O/ _1 n# ], b
0 T; G# k( `1 m/ a o// No image data ' ]: h+ D g5 q4 l4 L" l
if( m_nImageData == NULL )
: z. L$ X8 G7 L* u8 R! FreturnError( s, TGA_BAD_DATA );
. z% ?' a8 J( T4 N+ T
& |! e5 X9 O# ~4 P9 M" lfclose( s );
' @7 f- g, s% [+ [2 \& A) G& W( E' m8 t& d' a+ P) G
return TGA_NO_ERROR;1 t. ^2 E: q* P8 u1 A) K" Q) W
}
$ c9 Q4 s b1 t1 n( x# J( ^, ~
( H G, ]. ]. d
9 V, K% d. B" ~/ G' `调用举例:1 X! ^# Z3 ~- g1 }
//
% r# [* q1 i' \; H" n// For the billboard poly, load a texture of a steel sphere. We'll use a 3 o* F- L, R {7 Z
// .tga file for this image so we can use an alpha channel.. n* j4 d2 w% s* D
//
# g1 r$ a* c3 G x3 j( p
' z' x0 ^& T" p& [7 jtgaImageFile tgaImage;: b) u/ h. ? N( ^, L( l3 S, O
tgaImage.load( "steel_sphere.tga" );
1 d$ C. z r$ t0 V0 D
/ \( E! ?& x/ E! B" l/ h cglGenTextures( 1, &g_sphereTextureID );# D& F$ `! S! [: Q/ @+ I; k/ [4 |
- V/ D+ L9 [7 X) s ~glBindTexture( GL_TEXTURE_2D, g_sphereTextureID );( ^, V l/ i' S4 L
8 {6 `/ {3 b2 z% r% aglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
8 J& X4 H, b7 v, L3 _8 uglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
# C8 p S3 Y# ]4 p. |
S0 H K' l) s+ F0 B# j8 LglTexImage2D( GL_TEXTURE_2D, 0, tgaImage.m_texFormat, . D; R k: F9 O/ d* I$ B8 ?: J9 {3 ^
tgaImage.m_nImageWidth, tgaImage.m_nImageHeight,
; [# S' {9 \: R- W0, tgaImage.m_texFormat, GL_UNSIGNED_BYTE, 5 o5 x7 n, E( H1 u3 c$ W, w
tgaImage.m_nImageData );[/i][/i][/i][/i] |
|