|
|
#include <stdio.h>* C) G$ p0 R# L4 x3 t. C! w
#include <stdlib.h>- ]6 c% ]3 ]5 n- z) }
#include <string.h>
) Q/ M$ a8 F3 c6 r5 k#include <windows.h>1 L& o. c6 S% F5 q; u
#include <GL/gl.h>
7 z. C3 k9 Z4 O! `: r& J9 J/ o8 h( u" m3 z) u: H/ V
class tgaImageFile/ y4 x7 J+ j6 `$ N
{
7 }0 b1 F' ~: _3 |public:
5 Y0 F* ^3 A. ]% O' ~" Z; f5 J
) Q4 u5 f3 T& utgaImageFile(void) :
7 G" v) \' C+ Hm_texFormat(-1),& h& {# Q3 d( X, a( }) m8 w1 r
m_nImageWidth(0),5 w; j7 ]2 T7 o' f+ R/ B+ u
m_nImageHeight(0),5 s* I8 W N3 O& @ x
m_nImageBits(0),
( S1 @ {: Q* I; l1 g, ]1 um_nImageData(NULL) {}
5 B. e: G a& @9 X7 D: J* y( f* r) s- e5 X( C' t
~tgaImageFile(void);" `$ @$ I Y$ k$ @
- q$ y, W* G" ?6 g! N6 o' o, wenum TGALoadError
T7 r! A! y3 r' W' e& _; _{. h5 R( J3 g# E
TGA_NO_ERROR = 1, // No error
# L2 s) f5 d& qTGA_FILE_NOT_FOUND, // File was not found
9 O) k) P& D8 {5 H, uTGA_BAD_IMAGE_TYPE, // Color mapped image or image is not uncompressed% i+ Z; L+ N/ z( u* X
TGA_BAD_DIMENSION, // Dimension is not a power of 2
; j3 ^9 t; ?1 s+ W a9 ~3 jTGA_BAD_BITS, // Image bits is not 8, 24 or 32 * E5 |+ A% Y% |! z; }1 s. n: b
TGA_BAD_DATA // Image data could not be loaded % u1 ^+ ~2 J7 V* O) r# x
};* H. I# y* v3 F: `) \. A# i
/ a4 `* F* U" ~( }2 p$ a; RtgaImageFile::TGALoadError load( char *name );2 t$ v- k. H b, O% ~
; U9 \& i; J, W1 M# O- mGLenum m_texFormat;3 d- \+ I/ n8 \, u2 f
int m_nImageWidth;3 K5 n! A* O' @* \ y
int m_nImageHeight;* b6 z: h! t5 I! s O: e, E
int m_nImageBits;
% q$ f. E. K% V9 v& ?" P# Iunsigned char * m_nImageData;0 X5 W7 B2 t) ~
7 a, b* w+ p) D
private:
5 F$ ~+ i+ ^, A; [$ g) [* \" Z( H3 j: ~! G- I' n* H
bool checkSize(int x);* O. z6 i" F+ F, G! O' e3 C+ A! L( |
int returnError(FILE *s, int error);
% m8 @1 |4 C9 k8 ^unsigned char *getRGBA(FILE *s, int size);
6 Q* L$ M# v. y5 [. S+ ^unsigned char *getRGB(FILE *s, int size);! S+ T- j2 P8 u" p9 s
unsigned char *getGray(FILE *s, int size);
# a, [0 Z, @, F8 q6 K};. f( N" [- Q x5 Z# p$ z0 V
' _; R6 o6 N3 z
tgaImageFile::~tgaImageFile( void )1 _5 y, n7 I4 Q8 O1 O4 n
{ Z% {# |! C8 \; _% M$ U
if( m_nImageData != NULL )! k* H) n2 x% b7 ~/ m, P. h9 k
{
3 d* d! ~! R2 y3 ^, E( Kfree( m_nImageData );
: {/ r% J) W7 K! W" d+ z' gm_nImageData = NULL;
' @. R2 f. `3 E, I! s}3 f8 o9 d; s6 ~! A
}
6 ~4 x+ q1 V2 J) f7 k$ u
! L) P* }4 n2 a5 y) P' n4 ~/ K; Tbool tgaImageFile::checkSize( int x )
+ P" _1 O/ V0 \( x! L{' F: `. e, y2 ]. c$ B
// Make sure its a power of 2.7 e- U! l0 R" X% w7 l
if( x == 2 || x == 4 || y* F" E0 n* q3 i+ J
x == 8 || x == 16 ||
8 q/ T; P! f2 Sx == 32 || x == 64 ||: c( C0 D" ~# { I# N
x == 128 || x == 256 ||
: V% u0 `0 m4 G8 @$ j! e8 kx == 512 )
N( {- x* i& q A3 k- ?2 Y# B% _return true;
% c/ c! x' ~& r& ?7 _- J x' O; Q8 J# ?" N0 T' T
return false;
% l) t3 d9 k* h- j7 c}
7 g: X3 m/ W. p# I
, P! C0 m8 d$ _7 xint tgaImageFile::returnError( FILE *s, int error )
: t1 _! D. T b3 q7 u. i{
: k0 \2 s, M y2 m4 X, y7 n// Called when there is an error loading the .tga texture file.
7 |; L: p. p, r3 ^7 i% N, }, afclose( s );( }5 l( v; \. m4 a A7 z" @5 P
return error;
, g; h+ L! V' K2 U: b}
' |2 _9 {' U+ M/ I1 ?% j, H, d0 p$ u
unsigned char *tgaImageFile::getRGBA( FILE *s, int size )
2 x4 u, z' B9 w9 s. A) L) W- n{1 u1 J3 o; }- r: e" ]4 s# q
// Read in RGBA data for a 32bit image. 9 {4 r+ D! U6 r. J* Z% t
unsigned char *rgba;# U; y# c: ]2 {5 ^
unsigned char temp;( Y+ S5 a j( w' q0 ^) Y
int bread;6 n9 e' _ d7 T
int i;
/ Q2 b6 p2 e2 I* o- }7 Y/ u7 C1 q4 {& z+ |6 g
rgba = (unsigned char *)malloc( size * 4 );2 `0 O, f. t: e
1 K" e- F3 P8 T; u: |
if( rgba == NULL )
4 P6 F: t3 H* h- E+ x/ x7 Nreturn 0;
' H$ t! t- u" o0 L8 o' _, B5 f8 u& q% E! l
bread = fread( rgba, sizeof (unsigned char), size * 4, s ); 9 ^1 \2 g" A/ z1 t- X6 D" R6 \( }
" y' U4 F$ w) U" i0 j8 E# N' Z, f// TGA is stored in BGRA, make it RGBA
# J6 [ Q+ F+ H* S0 w; [4 Dif( bread != size * 4 )
# m! D+ C1 d# y6 E{0 v% q% ?) n/ O8 @
free( rgba );
% L& q' u' Z4 @1 g3 ~8 \return 0;% H" ^" \3 @ d2 m+ t: _: y
}
- T8 b/ ~* A& ^) x* ?& u, V7 x" p& X) F
for( i = 0; i < size * 4; i += 4 )- l! h( y# n1 f+ A6 b
{1 M M. l R9 z
temp = rgba[i];( G0 k D) T. R6 P
rgba[i] = rgba[i + 2];& v6 m+ a, b2 T: j+ g
rgba[i + 2] = temp;) ~# H: \5 Z! U
}
0 O4 R+ v4 K" p6 I# t7 o, a2 T' T5 p7 G
m_texFormat = GL_RGBA;
( r+ y4 A8 n- D, s- x. i6 ]return rgba;3 O! M$ t4 o7 P' ~4 z0 e6 J
}
! }% G9 z- U9 Y6 [. n2 @+ R/ O. w) v1 ]4 u& S0 o2 q
unsigned char *tgaImageFile::getRGB( FILE *s, int size )
; }% X* z2 d3 M2 |0 [2 t3 Y; i& r' j{$ G1 t% `& I3 P: M* e; k
// Read in RGB data for a 24bit image.
9 b2 c; ^1 ? o' H2 G1 r& Zunsigned char *rgb;
* {( W( Z, t7 ?9 C8 A' J2 B( junsigned char temp;
& s6 K6 e7 S' q l H' Z) Mint bread;
# Q8 J6 m6 x1 w* q' Y# |$ ]int i;+ q4 [* r- T, B" y) \7 l6 R' c
2 f2 J" k& |- L& T7 X g# Q
rgb = (unsigned char*)malloc( size * 3 );9 P1 o8 M6 a: W) S
2 O& S% R0 q$ m3 p7 w5 u/ r
if( rgb == NULL )
0 d/ p) q' g( p: L- Lreturn 0;
5 I# L5 [! P5 S3 Y8 G2 N1 x/ j* ?& C$ X- t6 w6 c
bread = fread( rgb, sizeof (unsigned char), size * 3, s );
2 |0 X7 ] b5 @/ P) M, h, E
7 o, e9 ~3 p6 s7 |if(bread != size * 3). W* X! L. i% G1 k
{& ?3 E: d# p, `" i+ i/ v
free( rgb );
7 } \. \9 [. n% \return 0;0 _ I; c: g4 {& ?0 _/ a- e
}* ^5 Y4 C; O. i0 I
8 U% `( m' W' v8 `5 E; p) {! {3 U// TGA is stored in BGR, make it RGB $ `" Z" O3 [! q" l
for( i = 0; i < size * 3; i += 3 )
) |1 w; F6 V8 c! _; S{
% j, N' n9 m; q% c' O4 R/ s7 _temp = rgb[i];
( V3 `3 o* k& z) N( R! c8 frgb[i] = rgb[i + 2];8 {+ }# v2 {7 E& w
rgb[i + 2] = temp;; D3 \" B! R, ]' g/ N- ?% M( D
}
8 ?# v2 W6 L# m* i0 |6 j
. }9 M: M) I' D( y6 u1 n) m9 F- Dm_texFormat = GL_RGB;
$ _' ]6 n8 C; }
/ K3 o! D! a+ m3 s- V4 creturn rgb;% ]/ q- w& c" @: A* ^$ F9 }! X
}
. U2 ^5 }& O7 {# n% G; u. B3 M! k! s0 V4 f$ V- v1 t; O4 g. W
unsigned char *tgaImageFile::getGray( FILE *s, int size )! ?4 ~4 l+ w0 b: V6 V+ J- ?
{
: ^. {" J2 ~5 E" U& G// Gets the grayscale image data. Used as an alpha channel.1 S5 ^) l; R9 t2 t
unsigned char *grayData;
/ x- [& V' a$ ?& O! ^int bread;& f6 n4 n- d9 U9 a
c$ I8 i, b) J9 QgrayData = (unsigned char*)malloc( size );
' s+ y6 X: ~& N% {# j
8 I1 f5 v; d1 l$ R0 l! rif( grayData == NULL )' P4 r5 H: u/ n0 ~
return 0;
; j( K6 M3 m$ w& t3 s0 r2 d
( {9 C7 L, L' @8 s$ mbread = fread( grayData, sizeof (unsigned char), size, s );
`5 m* R$ h `: H5 T. N% Y9 `) k k% D6 y ^
if( bread != size )( C4 ]# {! H6 N% D$ O
{. D; O( D/ k. S9 v1 z; |1 ^
free( grayData );
% I$ X3 h$ J: |, d8 O5 P6 @return 0;: O1 B% |, @; ^, _
}
v( l- V+ e1 c3 a
9 w) [ X* D% y- [6 H* Um_texFormat = GL_ALPHA; ?' i" C6 d/ t4 p
" [& \# }. {$ u* C& {! _4 Breturn grayData;( I: }9 f# ?% N( O$ H
}
8 u" B3 @- ?. y( t+ D
( d- ?( w+ ]5 ttgaImageFile::TGALoadError tgaImageFile::load( char *name )
$ ]( k# [* |+ q0 ^$ ^- C{* r" ~" \, P/ d) z, W
// Loads up a targa file. Supported types are 8, 24 and 32 ( _4 i5 y0 I" f+ l# P
// uncompressed images./ y1 N! N! e" S& c; v9 y" L% B
unsigned char type[4];
; R& J: F- k0 Z6 \: J7 a1 Cunsigned char info[7];
8 f% p5 }. q6 o4 I6 HFILE *s = NULL;$ i5 n. C4 k! Y |* V9 J
int size = 0;
! c) n; K; W. X+ ~. X
+ E: W( @% P9 e2 E/ Iif( !(s = fopen( name, "rb" )) )
4 ~' n& y2 f- O" P0 y8 l! N4 [* Sreturn TGA_FILE_NOT_FOUND;
' {4 X. R$ J J0 N6 q1 w" F" w: J9 \$ Z- ]: z
fread( &type, sizeof (char), 3, s ); // Read in colormap info and image type, byte 0 ignored
+ V9 R8 y0 G. o0 n* gfseek( s, 12, SEEK_SET); // Seek past the header and useless info) A* |5 h) t6 B- L, K7 X, }
fread( &info, sizeof (char), 6, s );4 Y6 z1 j- g# B' y# Y8 O7 v9 Y( K6 H
; p9 E5 s# A* K& T: O0 g
if( type[1] != 0 || (type[2] != 2 && type[2] != 3) )
. |) {# w" r' ]7 g6 [, `returnError( s, TGA_BAD_IMAGE_TYPE );
# |5 Z) Z6 a& Z. n f9 x& D& D
* W! i$ t' L* T9 A2 v# Vm_nImageWidth = info[0] + info[1] * 256;
% |6 ?+ a' f- m/ e- Q5 v) [ ?* bm_nImageHeight = info[2] + info[3] * 256;
$ T8 B0 N' e! Q+ n+ }+ mm_nImageBits = info[4]; 0 e+ N3 B1 u: X3 d" x( b; L
$ q; c! {4 h- U% F
size = m_nImageWidth * m_nImageHeight;2 y) ^5 A: ?2 ~2 |
# f% J6 P, \! v0 X# D// Make sure dimension is a power of 2
. z/ _! C8 C/ A) X& T2 r$ d5 B8 tif( !checkSize(m_nImageWidth) || !checkSize(m_nImageHeight))# ~2 S7 l: E+ e: \* `% s: Z2 |
returnError( s, TGA_BAD_DIMENSION);
1 P$ F/ U: D& m& ^ } y* L6 Q9 ?& t5 L4 }/ }, g* f
// Make sure we are loading a supported type / x4 a$ B# N+ H; y- u1 A# g4 p
if( m_nImageBits != 32 && m_nImageBits != 24 && m_nImageBits != 8 )
) x2 D0 \* K( {* k; I- ~returnError( s, TGA_BAD_BITS );/ \/ U- g8 j/ v
' e, M/ m5 q: N$ x
if( m_nImageBits == 32 )- c+ j# ~+ D& H2 Q) ?# p
m_nImageData = getRGBA( s, size );% K( _. @/ h7 h- `
else if( m_nImageBits == 24 )
0 n* }1 v1 K" Y6 A8 n% ?# B! ~5 ~3 bm_nImageData = getRGB( s, size );
7 i( M% S1 f) R Relse if( m_nImageBits == 8 )2 y# g' ?# o* T
m_nImageData = getGray( s, size );
2 d$ Q" y+ M6 G+ |1 m m A5 e
! Q0 k" ~% l( V( f// No image data
0 p2 J+ r' p! T1 [& \) @, xif( m_nImageData == NULL )4 q) [7 L8 e. B( F& P* O
returnError( s, TGA_BAD_DATA );* c% W5 I- d( E6 w" p- X
, a& e O4 X; ]5 q0 \1 ^fclose( s );3 n3 r- O- A. h Y. r3 \
4 d0 C/ t/ E9 j. M; wreturn TGA_NO_ERROR;
% k4 A3 E2 T3 N' F; M}
1 U, X% {6 N9 B" _: p5 z. f m1 N
' j0 f0 d" l) \7 w0 t
调用举例:( A X/ _2 ~3 c+ k4 x6 v; I
//
" d% D- B# J" S) A+ |% D& s// For the billboard poly, load a texture of a steel sphere. We'll use a 2 d& X9 T) r9 g+ V* L
// .tga file for this image so we can use an alpha channel.
) Z0 o9 i" v: X' y//3 M9 j, J; |2 }9 J* k5 {% K. Y2 C5 W
; H3 X% J5 d! E3 O; GtgaImageFile tgaImage;
. j( N8 u" }, z, \tgaImage.load( "steel_sphere.tga" );
8 X& u* C8 B! @& f( f; |. _5 w/ T7 a& ?( J* |. @
glGenTextures( 1, &g_sphereTextureID );
( @ v8 I# C3 C( i# l' O$ T, W# s9 f( k; |/ B+ h
glBindTexture( GL_TEXTURE_2D, g_sphereTextureID );4 j2 a7 Y9 G( O7 Q; F( \! x
+ k, L8 a2 `+ d b2 F4 lglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );( Z0 j. a2 ~( g+ ]' \% |* Z0 X. [; y
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
( @- O' N1 P+ ?3 A6 C( x8 P5 O w
glTexImage2D( GL_TEXTURE_2D, 0, tgaImage.m_texFormat,
4 `+ ~! y. {5 B6 E* Q9 `/ gtgaImage.m_nImageWidth, tgaImage.m_nImageHeight,
9 U% ]2 B9 \& y5 Y3 @+ c0, tgaImage.m_texFormat, GL_UNSIGNED_BYTE, 9 H% b, M, |0 m6 f
tgaImage.m_nImageData );[/i][/i][/i][/i] |
|