📄 textureutils.cpp
字号:
aFrustumNear, aTextureLoadingListener );
CleanupStack::Pop();
return self;
}
// -----------------------------------------------------------------------------
// CTextureManager::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CTextureManager* CTextureManager::NewL( TFileName & aTexturePath,
GLuint aScreenWidth,
GLuint aScreenHeight,
GLfloat aFrustumTop,
GLfloat aFrustumBottom,
GLfloat aFrustumRight,
GLfloat aFrustumLeft,
GLfloat aFrustumNear,
MTextureLoadingListener * aTextureLoadingListener )
{
CTextureManager* self = new (ELeave) CTextureManager();
CleanupStack::PushL( self );
self->ConstructL( aTexturePath, aScreenWidth, aScreenHeight,
aFrustumTop, aFrustumBottom, aFrustumRight, aFrustumLeft,
aFrustumNear, aTextureLoadingListener );
CleanupStack::Pop();
return self;
}
// Destructor
CTextureManager::~CTextureManager( )
{
delete iBmapUtil;
delete iBitmap;
delete iBitmapMask;
DeleteTextures();
iFs.Close();
}
// -----------------------------------------------------------------------------
// CTextureManager::DeleteTextures
// Deletes named textures by calling glDeleteTextures.
// -----------------------------------------------------------------------------
//
void CTextureManager::DeleteTextures()
{
if ( iTextureNames != NULL )
{
glDeleteTextures( iTextureNameCount, iTextureNames );
delete [] iTextureNames;
iTextureNames = NULL;
iTextureNameCount = 0;
}
}
// -----------------------------------------------------------------------------
// CTextureManager::TextureExists
// Checks if a given texture has already been loaded.
// else returns NULL
// -----------------------------------------------------------------------------
//
TTexture * CTextureManager::TextureExists( const TDesC &aTextureName )
{
TTexture * item;
iLoadingQueueIterator.SetToFirst();
while ( (item = iLoadingQueueIterator) != NULL )
{
if ( item->iTextureName.Compare( aTextureName ) == 0 )
{
return item;
}
else
{
iLoadingQueueIterator++;
}
}
return NULL;
}
// -----------------------------------------------------------------------------
// CTextureManager::RequestToLoad
// Sends a request to load a texture
// -----------------------------------------------------------------------------
//
void CTextureManager::RequestToLoad( const TDesC &aTextureName,
TTexture * aTexture,
TUint8 * aMinColorKey,
TUint8 * aMaxColorKey,
TBool aGenerateMipmaps)
{
if ( GetState() == EIdle )
{
TTexture * text;
if ( (text = TextureExists( aTextureName )) != NULL )
{
*aTexture = *text;
return;
}
aTexture->iTextureName = aTextureName;
aTexture->iTextureHasColorKey = ( aMinColorKey != NULL && aMaxColorKey != NULL);
if ( aTexture->iTextureHasColorKey )
{
aTexture->iMinColorKey[0] = aMinColorKey[0];
aTexture->iMinColorKey[1] = aMinColorKey[1];
aTexture->iMinColorKey[2] = aMinColorKey[2];
aTexture->iMaxColorKey[0] = aMaxColorKey[0];
aTexture->iMaxColorKey[1] = aMaxColorKey[1];
aTexture->iMaxColorKey[2] = aMaxColorKey[2];
}
aTexture->iGenerateMipmaps = aGenerateMipmaps;
iLoadingQueue.AddLast( *aTexture );
}
}
// -----------------------------------------------------------------------------
// CTextureManager::DoLoadL
// Starts the loading process.
// -----------------------------------------------------------------------------
//
void CTextureManager::DoLoadL()
{
switch ( GetState() )
{
case EIdle:
SetStateL( ELoading );
break;
case ELoading:
break;
default:
break;
}
}
// -----------------------------------------------------------------------------
// CTextureManager::OnEnterStateL
// Implementation of method TFiniteStateMachine::OnEnterState( TInt aState ).
// Generates the needed GL textures. Signals the listener.
// -----------------------------------------------------------------------------
//
void CTextureManager::OnEnterStateL( TInt aState)
{
switch ( aState )
{
case EIdle:
break;
case ELoading:
if ( iTextureLoadingListener != NULL )
iTextureLoadingListener->OnStartLoadingTexturesL(); //Signals the MTextureLoadingListener client
//That texture loading has started.
if ( iLoadingQueue.IsEmpty() )
SetStateL( EIdle );
else
{
DeleteTextures();
iLoadingQueueIterator.SetToFirst();
iTextureNameCount = 0;
while ( ((TTexture *)iLoadingQueueIterator) != NULL )
{
iLoadingQueueIterator++;
iTextureNameCount++;
}
iTextureNames = new (ELeave) GLuint [iTextureNameCount];
glGenTextures( iTextureNameCount, iTextureNames );
iIndex = 0;
iLoadingQueueIterator.SetToFirst();
LoadNextTextureL();
}
break;
default:
break;
}
}
// -----------------------------------------------------------------------------
// CTextureManager::OnLeaveStateL
// Implementation of method TFiniteStateMachine::OnLeaveStateL( TInt aState ).
// -----------------------------------------------------------------------------
//
void CTextureManager::OnLeaveStateL( TInt aState )
{
switch ( aState )
{
case EIdle:
break;
case ELoading:
if ( iTextureLoadingListener != NULL )
iTextureLoadingListener->OnEndLoadingTexturesL(); //Signals the MTextureLoadingListener client
//That texture loading is completed.
break;
default:
break;
}
}
// -----------------------------------------------------------------------------
// CTextureManager::LoadNextTextureL
// Loads the next texture in the loading queue.
// -----------------------------------------------------------------------------
//
void CTextureManager::LoadNextTextureL()
{
TFileName FullTextureName;
iCurrentRequest = iLoadingQueueIterator++;
if ( iCurrentRequest == NULL )
{
SetStateL( EIdle );
}
else
{
FullTextureName.Append( _L("c:\\") );//( iTexturePath );
FullTextureName.Append( iCurrentRequest->iTextureName );
iBmapUtil->LoadFileL(FullTextureName, 0);
}
}
// -----------------------------------------------------------------------------
// CTextureManager::ImageOperationCompleteL
// Implements MImageHandlerCallback::ImageOperationCompleteL.
// Converts the loaded texture data into an appropriate format
// by flipping moving from BGR order to RGB. Implements the transparent
// color keying by setting the alpha according to the key.
//
// Creates the GL texture object.
// -----------------------------------------------------------------------------
//
void CTextureManager::ImageOperationCompleteL(TInt aError)
{
_LIT(KConvErr, "Conversion failed!");
if ( aError )
{
User::Panic( KConvErr, aError );
}
glBindTexture( GL_TEXTURE_2D, iTextureNames[iIndex] );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, iCurrentRequest->iGenerateMipmaps ? GL_TRUE : GL_FALSE );
const TFrameInfo frameInfo = iBmapUtil->FrameInfo();
iCurrentRequest->iTextureWidth = frameInfo.iOverallSizeInPixels.iWidth;
iCurrentRequest->iTextureHeight = frameInfo.iOverallSizeInPixels.iHeight;
iCurrentRequest->iID = iTextureNames[iIndex];
TInt TextureSize = iCurrentRequest->iTextureWidth *
iCurrentRequest->iTextureHeight;
// Ask the bitmap heap to be locked if this is a large bitmap
iBitmap->LockHeap( EFalse );
/* The data in the texture are in RGB order but is read in BGR order.
So we have to swap the 1st and 3rd bytes. */
TUint8 * TextureData = (TUint8 *) iBitmap->DataAddress();
TUint8 * AlphaData = (TUint8 *) iBitmapMask->DataAddress();
for ( TInt i = 0; i < TextureSize; i++ )
{
TUint8 t = TextureData[i*3];
TextureData[i*3] = TextureData[i*3+2];
TextureData[i*3+2] = t;
}
if ( iCurrentRequest->iTextureHasColorKey )
{
/*
If a color key interval was specified, then we create an alpha channel.
*/
TUint8 * TextureDataWithAlphaChannel =
new (ELeave) TUint8[TextureSize * 4];
// walk through the original image and copy it over to the destination
for ( TInt i = 0, j = 0; i < TextureSize * 3; i += 3, j += 4 )
{
/*
If a pixel color is within the color key interval, we assign it an
alpha value of 0, which makes it transparent.
Otherwise the alpha value of the pixel is set to 255, full alpha.
*/
if ( TextureData[i] >= iCurrentRequest->iMinColorKey[0] &&
TextureData[i + 1] >= iCurrentRequest->iMinColorKey[1] &&
TextureData[i + 2] >= iCurrentRequest->iMinColorKey[2] &&
TextureData[i] <= iCurrentRequest->iMaxColorKey[0] &&
TextureData[i + 1] <= iCurrentRequest->iMaxColorKey[1] &&
TextureData[i + 2] <= iCurrentRequest->iMaxColorKey[2] )
{
TextureDataWithAlphaChannel[j + 3] = 0;
}
else
{
TextureDataWithAlphaChannel[j + 3] = 255;
}
TextureDataWithAlphaChannel[j ] = TextureData[i ];
TextureDataWithAlphaChannel[j + 1] = TextureData[i + 1];
TextureDataWithAlphaChannel[j + 2] = TextureData[i + 2];
}
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,
iCurrentRequest->iTextureWidth, iCurrentRequest->iTextureHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, TextureDataWithAlphaChannel );
delete [] TextureDataWithAlphaChannel;
}
else if (frameInfo.iFlags & (TFrameInfo::ETransparencyPossible | TFrameInfo::EAlphaChannel))
{
/*
If an alpha channel was present in the image, combine the bitmap and
the mask into a single RGBA texture.
*/
TUint8 * TextureDataWithAlphaChannel =
new (ELeave) TUint8[TextureSize * 4];
for ( TInt i = 0, j = 0, k = 0; i < TextureSize * 3; i += 3, j += 4, k++ )
{
TextureDataWithAlphaChannel[j + 0] = TextureData[i + 0];
TextureDataWithAlphaChannel[j + 1] = TextureData[i + 1];
TextureDataWithAlphaChannel[j + 2] = TextureData[i + 2];
TextureDataWithAlphaChannel[j + 3] = AlphaData[k];
}
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,
iCurrentRequest->iTextureWidth, iCurrentRequest->iTextureHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, TextureDataWithAlphaChannel );
delete [] TextureDataWithAlphaChannel;
}
else
{
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, iCurrentRequest->iTextureWidth,
iCurrentRequest->iTextureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
TextureData );
}
// Ask the bitmap heap to be unlocked if this is a large bitmap
iBitmap->UnlockHeap( EFalse );
iIndex++;
/* When the conversion of the current texture completes,
start loading the next one. */
LoadNextTextureL();
}
// -----------------------------------------------------------------------------
// CTextureManager::Blit
// Performs a 2D blits using OpenGL ES by rendering a textured polygon on the
// near depth clipping plane.
// This method supports alpha blending and color keying during blit operations.
// -----------------------------------------------------------------------------
//
void CTextureManager::Blit(TTexture & aTexture, GLuint aX, GLuint aY)
{
Blit(aTexture, aX, aY, aX+aTexture.iTextureWidth,
aY+aTexture.iTextureHeight);
}
// -----------------------------------------------------------------------------
// CTextureManager::Blit
// Performs a 2D blits using OpenGL ES by rendering a textured polygon on the
// near depth clipping plane.
// This method supports alpha blending and color keying during blit operations.
// Note: arbitrary stretching or shrinking will be performed for the texture to
// fit the destination rectangle (achieved using GL functions).
// -----------------------------------------------------------------------------
//
void CTextureManager::Blit( TTexture & aTexture, GLuint aX1, GLuint aY1,
GLuint aX2, GLuint aY2 )
{
GLfloat x1, y1, x2, y2, ax, bx, ay, by;
GLfloat aspectRatio = (GLfloat)(iScreenWidth) / (GLfloat)(iScreenHeight);
//Transforming screen coordinates to 3D world coordinates.
ax = aspectRatio * iFrustumWidth / iScreenWidth;
bx = aspectRatio * iFrustumLeft;
ay = (GLfloat)iFrustumHeight / iScreenHeight;
by = iFrustumTop;
x1 = ax * aX1 + bx;
y1 = ay * aY1 + by;
x2 = ax * aX2 + bx;
y2 = ay * aY2 + by;
GLfloat Vertices[4 * 3] =
{
x2, y2, -iFrustumNear,
x2, y1, -iFrustumNear,
x1, y2, -iFrustumNear,
x1, y1, -iFrustumNear,
};
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glDisable( GL_DEPTH_TEST );
glBindTexture( GL_TEXTURE_2D, aTexture.iID );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glVertexPointer( 3, GL_FLOAT, 0, Vertices );
glTexCoordPointer( 2, GL_SHORT, 0, BlitTextureCoords );
glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, BlitIndices );
glEnable( GL_DEPTH_TEST );
glPopMatrix();
}
// -----------------------------------------------------------------------------
// CTextureManager::SetScreenSize
// Sets the screen width and height. Must be called if the screen size changes during execution
// of the program and if the Blit() method are used as screen width and height values are used in the Blit() methods.
// Note: If either of the given values is zero, that value is ignored (the old width/height is used).
// -----------------------------------------------------------------------------
//
void CTextureManager::SetScreenSize( GLuint aScreenWidth, GLuint aScreenHeight )
{
if( aScreenWidth )
{
iScreenWidth = aScreenWidth;
}
if( aScreenHeight )
{
iScreenHeight = aScreenHeight;
}
}
// -----------------------------------------------------------------------------
// utilOutputText
// Returns the root directory of an application in the form <drive-letter>:\<path>\
// -----------------------------------------------------------------------------
//
static TFileName utilGetAppRootDirectoryL()
{
TFileName RootDirectory;
TParsePtrC Parse( CEikonEnv::Static()->EikAppUi()->Application()->AppFullName() );
RootDirectory = Parse.DriveAndPath();
return RootDirectory;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -