//-------------------------------------------------------------------------
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 );
}
//-------------------------------------------------------------------------
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 );
}
//-------------------------------------------------------------------------