examples/Graphics/coverflow/src/openvgengine.cpp

Go to the documentation of this file.
00001 // openvgengine.cpp
00002 //
00003 // Copyright (c) 2005-2008 Symbian Ltd.  All rights reserved.
00004 //
00009 #include <eikenv.h>
00010 #include "openvgengine.h"
00011 #include "eglrendering.h"
00012 #include <e32math.h>
00013 
00018 GLDEF_D VGUErrorCode vguComputeWarpQuadToQuadProxy(VGfloat aDx0, VGfloat aDy0,
00019                                                    VGfloat aDx1, VGfloat aDy1,
00020                                                    VGfloat aDx2, VGfloat aDy2,
00021                                                    VGfloat aDx3, VGfloat aDy3,
00022                                                    VGfloat aSx0, VGfloat aSy0,
00023                                                    VGfloat aSx1, VGfloat aSy1,
00024                                                    VGfloat aSx2, VGfloat aSy2,
00025                                                    VGfloat aSx3, VGfloat aSy3,
00026                                                    VGfloat* aMatrix)
00027         {
00028         // sets the entries of aMatrix to the projective transformation
00029         // This maps:
00030         // (aSx0,aSy0) to (aDx0,aDy0)
00031         // (aSx1,aSy1) to (aDx1,aDy1)
00032         // (aSx2,aSy2) to (aDx2,aDy2)
00033         // (aSx3,aSy3) to (aDx3,aDy3)
00034         vguComputeWarpQuadToQuad(
00035                                                    aSx0, aSy0,
00036                                                    aSx1, aSy1,
00037                                                    aSx2, aSy2,
00038                                                    aSx3, aSy3,
00039                                                    aDx0, aDy0,
00040                                                    aDx1, aDy1,
00041                                                    aDx2, aDy2,
00042                                                    aDx3, aDy3,
00043                                                    aMatrix);
00044         return VGU_NO_ERROR;
00045         }
00046 
00055 COpenVGEngine* COpenVGEngine::NewL(TSize aWindowSize,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext)
00056         {
00057         COpenVGEngine* self = new(ELeave) COpenVGEngine(aWindowSize,aDisplay,aSurface,aContext);
00058         return self;
00059         }
00060 
00064 COpenVGEngine::~COpenVGEngine()
00065         {
00066         Deactivate();
00067         }
00068 
00073 TInt COpenVGEngine::GetSpeed()
00074         {
00075         return static_cast<TInt>(iSpeed*100000);
00076         }
00077 
00082 TBool COpenVGEngine::IsPending()
00083         {
00084         return iHasPendingDraw;
00085         }
00086 
00090 void COpenVGEngine::ActivateL()
00091         {
00092         // Setup initial OpenVG context state.
00093         VGfloat clearColour[] = { 0.1f, 0.1f, 0.2f, 1.0f };
00094         // Set the value of  VG_CLEAR_COLOR to clearcolour.
00095         vgSetfv(VG_CLEAR_COLOR, 4, clearColour);
00096         // Set the image quality mode setting to VG_IMAGE_QUALITY_NONANTIALIASED.
00097         vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
00098         // Set the rendering quality mode setting to VG_RENDERING_QUALITY_NONANTIALIASED.
00099         vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
00100         vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
00101 
00102         //Load and create the VGImage.
00103 #ifdef __WINS__
00104         _LIT(KCoverBitmaps,"z:\\resource\\apps\\covers.mbm");
00105 #else
00106         _LIT(KCoverBitmaps,"e:\\resource\\apps\\covers.mbm");
00107 #endif
00108         // Create a bitmap image.
00109         // This is used to load all bitmap images to display them on the screen.
00110         CFbsBitmap* bitmap = new(ELeave) CFbsBitmap();
00111         CleanupStack::PushL(bitmap);
00112         TInt i = 0;
00113         // Load cover images.
00114         while(bitmap->Load(KCoverBitmaps,i++) == KErrNone)
00115                 {
00116                 TSize coverSize = bitmap->SizeInPixels();
00117 
00118                 // Set the pixel format and colour to  VG_sRGB_565.s
00119                 VGImageFormat dataFormat = VG_sRGB_565;
00120                 VGint width = coverSize.iWidth;
00121                 VGint height = coverSize.iHeight;
00122                 // Get the amount of bytes per scanline.
00123                 VGint dataStride = bitmap->ScanLineLength(coverSize.iWidth,bitmap->DisplayMode());
00124 
00125                 // Create the VGImage.
00126                 VGImage image = vgCreateImage(dataFormat, width, height,VG_IMAGE_QUALITY_NONANTIALIASED);
00127                 CEGLRendering::VGCheckError();
00128 
00129                 // Load Symbian bitmap into VGImage.
00130                 vgImageSubData (image, bitmap->DataAddress(), dataStride, dataFormat, 0, 0, width, height );
00131                 CEGLRendering::VGCheckError();
00132 
00133                 // Add the image to the iImages array.
00134                 iImages.AppendL(image);
00135                 iHasPendingDraw = ETrue;
00136                 }
00137 
00138         CleanupStack::Pop(bitmap);
00139         delete bitmap;
00140 
00141         // Check if no image is loaded.
00142         if(iImages.Count() == 0)
00143                 {
00144                 User::Leave(KErrNotFound);
00145                 }
00146 
00147         iImage = iImages[0];
00148 
00149         // Create a new paint object.
00150         iShadowPaint = vgCreatePaint();
00151         if (iShadowPaint != VG_INVALID_HANDLE)
00152                 {
00153                 VGfloat paintColour[4] = { 0.4f, 0.4f, 0.6f, 1.0f };
00154                 // Passing paintColour to the paint object.
00155                 vgSetParameterfv(iShadowPaint, VG_PAINT_COLOR, 4, paintColour);
00156                 CEGLRendering::VGCheckError();
00157                 }
00158         }
00159 
00163 void COpenVGEngine::Deactivate()
00164         {
00165         TInt coverIndex=iImages.Count()-1;
00166         for (;coverIndex>=0;coverIndex--)
00167                 {
00168                 // De allocate the resources of all images in the iImages array.
00169                 vgDestroyImage(iImages[coverIndex]);
00170                 }
00171 
00172         // Destroy the paint object.
00173         vgDestroyPaint(iShadowPaint);
00174         eglWaitClient();
00175 
00176         // Reset the RArray.
00177         iImages.Reset();
00178         iHasPendingDraw = EFalse;
00179         }
00180 
00184 void COpenVGEngine::Step()
00185         {
00186 #ifdef PORTRAIT_MODE
00187         vgClear(0, 0, iSurfaceSize.iHeight, iSurfaceSize.iWidth);
00188 #else
00189         vgClear(0, 0, iSurfaceSize.iWidth, iSurfaceSize.iHeight);
00190 #endif
00191         // Calculate the speed of movement of the cover
00192         // depending on its current location.
00193         if (Abs(iCoverLocation[iWantedCover]) < 0.03)
00194                 {
00195                 iSpeed = 0.0f;
00196                 iHasPendingDraw = EFalse;
00197                 }
00198         else if (Abs(iCoverLocation[iWantedCover]) < 0.5)
00199                 {
00200                 iSpeed*=0.7;
00201                 }
00202         else
00203                 {
00204                 iSpeed = 0.05*(2+ Abs(iCoverLocation[iWantedCover]) + (Abs(iCoverLocation[iWantedCover])+1) * (Abs(iCoverLocation[iWantedCover])+1) / 2);
00205                 }
00206         // For each Cover, update its location in the correct direction.
00207         // Check if the wanted cover is already at the CenterStage point.
00208         VGfloat moveEachCover = iSpeed;
00209         if (iCoverLocation[iWantedCover] > 0.0)
00210                 {
00211                 moveEachCover *= -1;
00212                 }
00213 
00214         TInt coverIndex;
00215         // Update the location of each cover.
00216         for (coverIndex = 0; coverIndex < KMaxCoversExample3; ++coverIndex)
00217                 {
00218                 iCoverLocation[coverIndex] += moveEachCover;
00219                 }
00220 
00221         TInt coverClippingCount = 10;
00222         TInt middleCoverPos=0;
00223         VGfloat threshold = 0.50f;
00224 
00225         while(Abs(iCoverLocation[middleCoverPos])>threshold)
00226                 {
00227                 ++middleCoverPos;
00228                 }
00229 
00230 
00231         //left.
00232         TInt cutOff = middleCoverPos-coverClippingCount;
00233         if (cutOff<0)
00234                 {
00235                 cutOff=0;
00236                 }
00237         for (TInt i=cutOff; i<middleCoverPos;i++)
00238                 {
00239                 DrawCover(i);
00240                 }
00241 
00242         //right.
00243         cutOff = coverClippingCount + middleCoverPos;
00244         if (cutOff>=KMaxCoversExample3)
00245                 {
00246                 cutOff=KMaxCoversExample3-1;
00247                 }
00248 
00249         for (TInt j = cutOff; j>=middleCoverPos ; --j)
00250                 {
00251                 DrawCover(j);
00252                 }
00253 
00254 #ifdef ENABLE_LOOP
00255         static TInt dir = 1;
00256         if (iWantedCover == (KMaxCoversExample3-1))
00257                 {
00258                 dir = -1;
00259                 }
00260         else if (iWantedCover == 0)
00261                 {
00262                 dir = 1;
00263                 }
00264 
00265         iWantedCover += dir;
00266         iHasPendingDraw = ETrue;
00267 #endif
00268         }
00269 
00273 void COpenVGEngine::DrawCover(TInt aCoverIndex)
00274         {
00275         VGImage image = iImages[aCoverIndex%iImages.Count()];
00276         // Starting at the outside, render each visible (+/-  KMaxDisplayCoversExample3/2) Cover.
00277         // Calculate its path.
00278 
00279         // Set the current matrix to the identity matrix.
00280         vgLoadIdentity();
00281 
00282 #ifdef PORTRAIT_MODE
00283         vgTranslate(iSurfaceSize.iHeight, 0);
00284         vgRotate(90);
00285 #endif
00286 
00287         VGfloat coverPosition = iCoverLocation[aCoverIndex];
00288 
00289         VGfloat tempMatrix[3][3];
00290         //flip coordinates.
00291         VGfloat flipmatrix[] =
00292                 {
00293                 1.0f, 0.0f, 0.0f,
00294                 0.0f, -1.0f, 0.0f,
00295                 0.0f, 0.0f, 1.0f
00296                 };
00297         vgMultMatrix(flipmatrix);
00298 
00299         VGint imageWidth = vgGetParameteri (image, VG_IMAGE_WIDTH);
00300         VGint imageHeight = vgGetParameteri (image, VG_IMAGE_HEIGHT);
00301 
00302         VGint yTrans = -200;
00303 
00304         // Factors which must be multiplied with side of image which will be projected towards back.
00305         // Valid if projecting right image side to back.
00306         // Opposite is (1 - factor) for projecting left image side.
00307 
00308         VGfloat bottomProjectXFactor= (0.75f);
00309         VGfloat bottomProjectYFactor = (0.20f);
00310 
00311         VGfloat topProjectXFactor = (0.75f);
00312         VGfloat topProjectYFactor = (0.90f);
00313 
00314         VGfloat imageSpacingFactor = 0.16;
00315 
00316         VGfloat translationOffset = 0.0;
00317 
00318         VGfloat middleTranslationOffset = KImageSize /2;
00319         VGfloat coverProjectionLimit = 10;
00320 
00321         if (coverPosition>=1)
00322                 {
00323                 // If considering an image on the right side, this is offset from middle to place image on screen.
00324                 translationOffset = middleTranslationOffset- KImageSize/2 + KImageSize*imageSpacingFactor * (coverPosition -1);
00325 
00326                 // Left side of image goes back.
00327                 vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f,
00328                                    imageWidth, 0.0f,
00329                                    0.0f, imageHeight,
00330                                    imageWidth, imageHeight,
00331 
00332                                    KImageSize * (1 - bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)),KImageSize * bottomProjectYFactor,// left vertex.
00333                                    KImageSize, 0.0f,
00334                                    KImageSize * (1 - topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)), KImageSize * topProjectYFactor,// left vertex.
00335                                    KImageSize, KImageSize,
00336 
00337                                    &tempMatrix[0][0]);
00338                 }
00339         else if (coverPosition<-1)
00340                 {
00341                 // Must move an extra image width from centre , as coordinates from bottom left corner of image.
00342                 translationOffset = - (middleTranslationOffset + (KImageSize * imageSpacingFactor) * ( -coverPosition - 1) + KImageSize/2) ;
00343 
00344                 vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f,
00345                                    imageWidth, 0.0f,
00346                                    0.0f, imageHeight,
00347                                    imageWidth, imageHeight,
00348 
00349                                    0.0f, 0.0f,
00350                                    (bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit))* KImageSize, bottomProjectYFactor * KImageSize, //Right Vertex.
00351                                    0.0f, (KImageSize),
00352                                    (topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)) * KImageSize, topProjectYFactor * KImageSize, //Right Vertex
00353 
00354                                    &tempMatrix[0][0]);
00355                 }
00356         else if((coverPosition > -1) && (coverPosition <= 0))// -0.07))
00357                 {
00358                 translationOffset = -middleTranslationOffset * Abs(coverPosition) - KImageSize/2 ;
00359 
00360                 vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f,
00361                                                            imageWidth, 0.0f,
00362                                                            0.0f, imageHeight,
00363                                                            imageWidth, imageHeight,
00364 
00365                                                            0.0f, 0.0f,
00366                                                            KImageSize * (1 - (1-bottomProjectXFactor) * Abs(coverPosition)), KImageSize * bottomProjectYFactor * Abs(coverPosition),
00367                                                            0.0f, KImageSize,
00368                                                            (KImageSize * (1 - ( 1 - topProjectXFactor) * Abs(coverPosition))) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)),
00369 
00370                                                            &tempMatrix[0][0]);
00371 
00372                 }
00373 
00374         else if ((coverPosition >=0) && (coverPosition <= 1))
00375                 {
00376 
00377                 translationOffset = middleTranslationOffset * Abs(coverPosition) - KImageSize/2 ;
00378 
00379                 vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f,
00380                                                            imageWidth, 0.0f,
00381                                                            0.0f, imageHeight,
00382                                                            imageWidth, imageHeight,
00383 
00384                                                            KImageSize * (1-bottomProjectXFactor)* (coverPosition), KImageSize * (bottomProjectYFactor) * (coverPosition),
00385                                                            KImageSize, 0,
00386                                                            KImageSize * ( 1 - topProjectXFactor) * (coverPosition) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)),
00387                                                            KImageSize, KImageSize,
00388 
00389                                                            &tempMatrix[0][0]);
00390                 }
00391 
00392 
00393         iSpeedOffset = 140*(iSpeed)*(iSpeed);
00394 
00395                         if (iCoverLocation[iWantedCover]<0)
00396                                 {
00397                                 iSpeedOffset *=-1;
00398                                 }
00399 
00400         // Apply transformations to the current matrix.
00401         vgTranslate(iSurfaceSize.iWidth/2 + translationOffset + iSpeedOffset,yTrans);
00402 
00403         vgMultMatrix(&tempMatrix[0][0]);
00404         if (Abs(coverPosition)<=1)
00405                 {
00406                 VGfloat scale = GetMiddleCoverScalingFactor(coverPosition);
00407                 vgScale(scale,scale);
00408 
00409                 vgTranslate(-(scale-1)/2 * KImageSize,-(scale-1)/2 * KImageSize);
00410                 }
00411 
00412         // Draw the image on the surface.
00413         vgDrawImage(image);
00414         CEGLRendering::VGCheckError();
00415 
00416         // Check if mirror images of covers have to be displayed.
00417         if(iShowMirror)
00418                 {
00419                 // Scale the current matrix to create inverted images.
00420                 vgScale(1,-1);
00421                 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
00422                 vgTranslate(0,-4*KImageSize+226);
00423 
00424                 // Draw the image on the surface.
00425                 vgSetPaint(iShadowPaint, VG_FILL_PATH);
00426                 vgDrawImage(image);
00427                 CEGLRendering::VGCheckError();
00428 
00429                 vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);
00430                 }
00431         }
00432 
00437 TKeyResponse COpenVGEngine::HandleKeyEventL(const TKeyEvent& aKeyEvent)
00438         {
00439         TKeyResponse response = EKeyWasConsumed;
00440         switch (aKeyEvent.iCode)
00441                 {
00442         case EKeyRightArrow:
00443         // Move to the next cover if right arrow key is pressed.
00444                 NextCover();
00445                 break;
00446 
00447         case EKeyLeftArrow:
00448         // Move to the previous cover if left arrow key is pressed.
00449         PreviousCover();
00450                 break;
00451 
00452         case EKeyBackspace:
00453         // Toggle the cover reflection flag.
00454                 ToggleCoverReflection();
00455                 break;
00456         default:
00457                 response = EKeyWasNotConsumed;
00458                 break;
00459                 };
00460         return response;
00461         }
00462 
00466 COpenVGEngine::COpenVGEngine(TSize aWindowSize,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext) :
00467         iDisplay(aDisplay),iSurface(aSurface),iContext(aContext),iWantedCover(20),iHasPendingDraw(EFalse),
00468         iShowMirror(ETrue)
00469         {
00470 #ifdef PORTRAIT_MODE
00471         iSurfaceSize.iWidth = aWindowSize.iHeight;
00472         iSurfaceSize.iHeight = aWindowSize.iWidth;
00473 #else
00474         iSurfaceSize = aWindowSize;
00475 #endif
00476         // Initiate the location of each cover & make the wanted one the cover at the opposite end
00477         for(TInt i=0; i<KMaxCoversExample3; ++i)
00478                 {
00479                 iCoverLocation[i] = i;
00480                 }
00481         }
00482 
00486 void COpenVGEngine::NextCover()
00487         {
00488         if (iWantedCover < (KMaxCoversExample3-1))
00489                 {
00490                 ++iWantedCover;
00491                 }
00492         iHasPendingDraw = ETrue;
00493         }
00494 
00498 void COpenVGEngine::PreviousCover()
00499         {
00500 
00501         if (iWantedCover>0)
00502                 {
00503                 --iWantedCover;
00504                 }
00505         iHasPendingDraw = ETrue;
00506         }
00507 
00512 void COpenVGEngine::ToggleCoverReflection()
00513         {
00514         iShowMirror = !iShowMirror;
00515         }
00516 
00522 VGfloat COpenVGEngine::GetMiddleCoverScalingFactor(VGfloat aCoverPosition)
00523         {
00524         if(Abs(aCoverPosition)>1)
00525                 {
00526                 return 0.0f;
00527                 }
00528 
00529         return (-0.125 * Abs(aCoverPosition) + 1.125);
00530         }

Generated by  doxygen 1.6.2