//
-------------------------------------------------------------------------
eiTexture::eiTexture(eiBool instance_type, eiBool mip_map_filter)

{
format = NONE;
type = SRC;
m_width = 0;
m_height = 0;
instance = instance_type;
use_mip_map = mip_map_filter;
bits = NULL;
}
//
-------------------------------------------------------------------------
eiTexture::
~
eiTexture()

{
}
//
-------------------------------------------------------------------------
eiBool eiTexture::load(eiChar
*
file_name)

{
CFile file;

if( !file.Open( file_name, CFile::modeRead | CFile::shareDenyWrite ) )

{
msger.print("Load texture failed.");
return false;
}

BITMAPFILEHEADER bfhHeader;

file.Read( &bfhHeader, sizeof(BITMAPFILEHEADER) );

if( bfhHeader.bfType != 0x4d42 )

{
msger.print("Load texture failed.");
return false;
}
eiUInt uBmpInfoLen = (eiUInt) bfhHeader.bfOffBits - sizeof(BITMAPFILEHEADER);

LPBITMAPINFOHEADER m_lpBMPHdr = (LPBITMAPINFOHEADER) new eiByte [ uBmpInfoLen ];

eiUInt counts = file.Read(m_lpBMPHdr, uBmpInfoLen);

if(m_lpBMPHdr->biSize != sizeof(BITMAPINFOHEADER))

{
msger.print("Texture format error.");
return false;
}

DWORD m_dwImageSize = m_lpBMPHdr->biSizeImage;

if(m_dwImageSize == 0)

{
DWORD dwBytes = ((DWORD) m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) / 32;
if(((DWORD) m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) % 32)

{
dwBytes++;
}

dwBytes *= 4;

m_dwImageSize = dwBytes * m_lpBMPHdr->biHeight;
}

bits = (eiByte*) new eiByte [ m_dwImageSize ];

counts = file.Read(bits, m_dwImageSize);

file.Close();

m_width = m_lpBMPHdr->biWidth;
m_height = m_lpBMPHdr->biHeight;

delete []m_lpBMPHdr;

format = BMP;

normalize();

inv_width = 1.0 / m_width;
inv_height = 1.0 / m_height;

if(use_mip_map)

{
make_mip_map();
}

return true;
}
//
-------------------------------------------------------------------------
eiVoid eiTexture::normalize()

{
eiByte *pbits;
eiInt n_width,n_height;
eiFloat dx,dy;
eiColor color;

pbits = bits;
n_width = (eiInt) powf( 2, (eiInt) log2f( m_width ) + 1 );
n_height = (eiInt) powf( 2, (eiInt) log2f( m_height ) + 1 );

dx = (eiFloat) m_width / (eiFloat) n_width;
dy = (eiFloat) m_height / (eiFloat) n_height;

src.resize( n_width * n_height * 3 );

std::vector<eiByte>::iterator pbyPtr = src.begin();

for(eiInt j = 0 ; j < n_height ; j++)

{
for(eiInt i = 0 ; i < n_width ; i++)

{
color = get_bilinear_color( pbits, i * dx, j * dy );

pbyPtr[0] = (eiByte) ( color.b * 255 );
pbyPtr[1] = (eiByte) ( color.g * 255 );
pbyPtr[2] = (eiByte) ( color.r * 255 );

pbyPtr += 3;
}
}
delete []pbits;
bits = NULL;

m_width = n_width;
m_height = n_height;
}
//
-------------------------------------------------------------------------
eiInt eiTexture::get_width()

{
return m_width;
}
//
-------------------------------------------------------------------------
eiInt eiTexture::get_height()

{
return m_height;
}
//
-------------------------------------------------------------------------
eiColorB eiTexture::get_color(eiByte
*
dibbits, eiInt x, eiInt y)

{
eiColorB color;

color.r = color.g = color.b = 0;

if(dibbits == NULL)
return color;

if(x < 0)
x = 0;
if(x >= m_width)
x = m_width - 1;
if(y < 0)
y = 0;
if(y >= m_height)
y = m_height - 1;

eiByte *pbyPtr;

pbyPtr = dibbits + (y * m_width + x) * 3;

color.b = pbyPtr[0];
color.g = pbyPtr[1];
color.r = pbyPtr[2];

return color;
}
//
-------------------------------------------------------------------------
eiColor eiTexture::get_bilinear_color(eiByte
*
dibbits, eiFloat x, eiFloat y)

{
eiInt u,v;

u = (eiInt) x;
v = (eiInt) y;

if( (eiFloat) u == x && (eiFloat) v == y )

{
eiColorB clr = get_color(dibbits,u,v);
return newclr( clr.r * EI_BYTE_2_FLOAT,
clr.g * EI_BYTE_2_FLOAT,
clr.b * EI_BYTE_2_FLOAT );
}

eiFloat du,dv,r1,g1,b1,r2,g2,b2;
eiColorB c1,c2,c3,c4;

du = curve( x - u );
dv = curve( y - v );

c1 = get_color(dibbits,u,v);
c2 = get_color(dibbits,u+1,v);
c3 = get_color(dibbits,u+1,v+1);
c4 = get_color(dibbits,u,v+1);

r1 = c1.r + (c2.r - c1.r) * du;
g1 = c1.g + (c2.g - c1.g) * du;
b1 = c1.b + (c2.b - c1.b) * du;

r2 = c4.r + (c3.r - c4.r) * du;
g2 = c4.g + (c3.g - c4.g) * du;
b2 = c4.b + (c3.b - c4.b) * du;

r1 = r1 + (r2 - r1) * dv;
g1 = g1 + (g2 - g1) * dv;
b1 = b1 + (b2 - b1) * dv;

r1 *= EI_BYTE_2_FLOAT;
g1 *= EI_BYTE_2_FLOAT;
b1 *= EI_BYTE_2_FLOAT;

return newclr(r1,g1,b1);
}
//
-------------------------------------------------------------------------
eiColorB eiTexture::get_src_color(eiInt x, eiInt y)

{
eiColorB color;

color.r = color.g = color.b = 0;

if(src.empty())
return color;

if(x < 0)
x = 0;
if(x >= m_width)
x = m_width - 1;
if(y < 0)
y = 0;
if(y >= m_height)
y = m_height - 1;

std::vector<eiByte>::iterator pbyPtr;

pbyPtr = src.begin() + (y * m_width + x) * 3;

color.b = pbyPtr[0];
color.g = pbyPtr[1];
color.r = pbyPtr[2];

return color;
}
//
-------------------------------------------------------------------------
eiColor eiTexture::get_src_bilinear_color(eiFloat x, eiFloat y)

{
eiInt u,v;

u = (eiInt) x;
v = (eiInt) y;

if( (eiFloat) u == x && (eiFloat) v == y )

{
eiColorB clr = get_src_color(u,v);
return newclr( clr.r * EI_BYTE_2_FLOAT,
clr.g * EI_BYTE_2_FLOAT,
clr.b * EI_BYTE_2_FLOAT );
}

eiFloat du,dv,r1,g1,b1,r2,g2,b2;
eiColorB c1,c2,c3,c4;

du = curve( x - u );
dv = curve( y - v );

c1 = get_src_color(u,v);
c2 = get_src_color(u+1,v);
c3 = get_src_color(u+1,v+1);
c4 = get_src_color(u,v+1);

r1 = c1.r + (c2.r - c1.r) * du;
g1 = c1.g + (c2.g - c1.g) * du;
b1 = c1.b + (c2.b - c1.b) * du;

r2 = c4.r + (c3.r - c4.r) * du;
g2 = c4.g + (c3.g - c4.g) * du;
b2 = c4.b + (c3.b - c4.b) * du;

r1 = r1 + (r2 - r1) * dv;
g1 = g1 + (g2 - g1) * dv;
b1 = b1 + (b2 - b1) * dv;

r1 *= EI_BYTE_2_FLOAT;
g1 *= EI_BYTE_2_FLOAT;
b1 *= EI_BYTE_2_FLOAT;

return newclr(r1,g1,b1);
}
//
-------------------------------------------------------------------------
eiVoid eiTexture::blt(eiInt x1,eiInt y1,eiInt x2,eiInt y2,
eiInt width,eiInt height)

{
eiInt c1,c2,c3,c4;
std::vector<eiByte>::iterator pbyPtr;

for( eiInt j = y1, mj = y2 ; j < (y1 + height) ; j += 2, mj++ )

{
for( eiInt i = x1, mi = x2 ; i < (x1 + width) ; i += 2, mi++ )

{
pbyPtr = mip_map.begin() + j * m_width + i;
c1 = pbyPtr[0];
c2 = pbyPtr[1];

pbyPtr += m_width;
c3 = pbyPtr[0];
c4 = pbyPtr[1];

pbyPtr = mip_map.begin() + mj * m_width + mi;
pbyPtr[0] = (eiByte) ( (eiFloat) ( c1 + c2 + c3 + c4 ) * 0.25 );
}
}
}
//
-------------------------------------------------------------------------
eiVoid eiTexture::bltB(eiInt x1,eiInt y1,eiInt x2,eiInt y2,
eiInt width,eiInt height)

{
if(width == 0 || height == 0)
return;

eiInt width2,height2;

width2 = width / 2;
height2 = height / 2;

blt( x1, y1, x2, y2, width, height);

bltB( x2, y2, x2 / 2, y2 / 2, width2, height2 );
}
//
-------------------------------------------------------------------------
eiVoid eiTexture::bltG(eiInt x1,eiInt y1,eiInt x2,eiInt y2,
eiInt width,eiInt height)

{
if(width == 0 || height == 0)
return;

eiInt width2,height2;

width2 = width / 2;
height2 = height / 2;

blt( x1, y1, x2, y2, width, height);

bltG( x2, y2, x2 / 2, y2, width2, height2 );
}
//
-------------------------------------------------------------------------
eiVoid eiTexture::bltR(eiInt x1,eiInt y1,eiInt x2,eiInt y2,
eiInt width,eiInt height)

{
if(width == 0 || height == 0)
return;

eiInt width2,height2;

width2 = width / 2;
height2 = height / 2;

blt( x1, y1, x2, y2, width, height);

bltR( x2, y2, x2, y2 / 2, width2, height2 );
}
//
-------------------------------------------------------------------------
eiBool eiTexture::make_mip_map()

{
if(format == NONE || type == MIP_MAP)
return false;

mip_map.resize( m_width * m_height );

eiColorB c1,c2,c3,c4;
eiFloat r,g,b;
std::vector<eiByte>::iterator pbyPtr;
eiInt width2,height2;

width2 = m_width / 2;
height2 = m_height / 2;

for( eiInt j = 0, mj = 0 ; j < m_height ; j += 2, mj++ )

{
for( eiInt i = 0, mi = 0 ; i < m_width ; i += 2, mi++ )

{
c1 = get_src_color( i , j );
c2 = get_src_color( i + 1 , j );
c3 = get_src_color( i + 1 , j + 1 );
c4 = get_src_color( i , j + 1 );

b = (eiFloat) ( (eiInt) c1.b + (eiInt) c2.b + (eiInt) c3.b + (eiInt) c4.b ) * 0.25;
g = (eiFloat) ( (eiInt) c1.g + (eiInt) c2.g + (eiInt) c3.g + (eiInt) c4.g ) * 0.25;
r = (eiFloat) ( (eiInt) c1.r + (eiInt) c2.r + (eiInt) c3.r + (eiInt) c4.r ) * 0.25;

// i have not considered efficiency problem in precomputing progress


/**//* mip-map is built as follow :

NEXT GREEN
RED BLUE */

pbyPtr = mip_map.begin() + ( mj + height2 ) * m_width + mi + width2;
pbyPtr[0] = (eiByte) b;

pbyPtr = mip_map.begin() + mj * m_width + mi + width2;
pbyPtr[0] = (eiByte) g;

pbyPtr = mip_map.begin() + ( mj + height2 ) * m_width + mi;
pbyPtr[0] = (eiByte) r;
}
}

bltB( width2, height2, m_width / 4, m_height / 4, width2, height2 );
bltG( width2, 0, m_width / 4, 0, width2, height2 );
bltR( 0, height2, 0, m_height / 4, width2, height2 );

type = MIP_MAP;

return true;
}
//
-------------------------------------------------------------------------
eiFloat eiTexture::get_bilinear(eiFloat x, eiFloat y)

{
eiInt u,v;
std::vector<eiByte>::iterator pbyPtr;

u = (eiInt) x;
v = (eiInt) y;

if( (eiFloat) u == x && (eiFloat) v == y )

{
pbyPtr = mip_map.begin() + m_width * v + u;

return pbyPtr[0] * EI_BYTE_2_FLOAT;
}

eiFloat du,dv,r1,r2;
eiByte f1,f2,f3,f4;

du = curve( x - u );
dv = curve( y - v );

pbyPtr = mip_map.begin() + m_width * v + u;
f1 = pbyPtr[0];
f2 = pbyPtr[1];

pbyPtr += m_width;
f3 = pbyPtr[1];
f4 = pbyPtr[0];

r1 = f1 + (f2 - f1) * du;

r2 = f4 + (f3 - f4) * du;

r1 = r1 + (r2 - r1) * dv;

return r1 * EI_BYTE_2_FLOAT;
}
//
-------------------------------------------------------------------------
eiColor eiTexture::get_pixel(eiFloat x, eiFloat y, eiInt d)

{
if(src.empty() || ( type == MIP_MAP && mip_map.empty() ) )
return newclr();

if(d == 0)

{
return get_src_bilinear_color( x, y );
}

eiFloat b,g,r,scale;

scale = 1 / powf( 2 , d );

eiFloat mx,my,width2,height2;

width2 = m_width * scale;
height2 = m_height * scale;
mx = x * scale;
my = y * scale;

b = get_bilinear( width2 + mx , height2 + my );

g = get_bilinear( width2 + mx , my );

r = get_bilinear( mx , height2 + my );

return newclr(r,g,b);
}
//
-------------------------------------------------------------------------
eiColor eiTexture::lookup(
const
eiPlane
&
uv)

{
return get_pixel(uv.x, uv.y, uv.z, uv.w);
}
//
-------------------------------------------------------------------------
eiColor eiTexture::get_pixel(eiFloat x, eiFloat y, eiFloat dx, eiFloat dy)

{
x *= m_width;
y *= m_height;

if( type == SRC || ( dx == 0.0 && dy == 0.0 ) )

{
//maybe shading for raytracing, do not use mip-map

return get_src_bilinear_color( x, y );
}

dx *= m_width;
dy *= m_height;

eiFloat d;
eiInt di;
eiColor c1,c2;

d = max(dx,dy);

d = log2f(d);
di = (eiInt) d;
d = d - (eiFloat) di;

c1 = get_pixel( x, y, di );
c2 = get_pixel( x, y, di + 1 );

return mixclr( c1, c2, d );
}
//
-------------------------------------------------------------------------
转载于:https://www.cnblogs.com/len3d/archive/2005/07/08/188838.html