examples/Graphics/coverflow/src/openvgengine.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2005-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008 � list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010 � this list of conditions and the following disclaimer in the documentation
00011 � and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013 � may be used to endorse or promote products derived from this software
00014 � without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description:� 
00028 */
00033 #include <eikenv.h>
00034 #include "openvgengine.h"
00035 #include "eglrendering.h"
00036 #include <e32math.h>
00037 
00042 GLDEF_D VGUErrorCode vguComputeWarpQuadToQuadProxy(VGfloat aDx0, VGfloat aDy0,
00043                                                    VGfloat aDx1, VGfloat aDy1,
00044                                                    VGfloat aDx2, VGfloat aDy2,
00045                                                    VGfloat aDx3, VGfloat aDy3,
00046                                                    VGfloat aSx0, VGfloat aSy0,
00047                                                    VGfloat aSx1, VGfloat aSy1,
00048                                                    VGfloat aSx2, VGfloat aSy2,
00049                                                    VGfloat aSx3, VGfloat aSy3,
00050                                                    VGfloat* aMatrix)
00051         {
00052         // sets the entries of aMatrix to the projective transformation
00053         // This maps:
00054         // (aSx0,aSy0) to (aDx0,aDy0)
00055         // (aSx1,aSy1) to (aDx1,aDy1)
00056         // (aSx2,aSy2) to (aDx2,aDy2)
00057         // (aSx3,aSy3) to (aDx3,aDy3)
00058         vguComputeWarpQuadToQuad(
00059                                                    aSx0, aSy0,
00060                                                    aSx1, aSy1,
00061                                                    aSx2, aSy2,
00062                                                    aSx3, aSy3,
00063                                                    aDx0, aDy0,
00064                                                    aDx1, aDy1,
00065                                                    aDx2, aDy2,
00066                                                    aDx3, aDy3,
00067                                                    aMatrix);
00068         return VGU_NO_ERROR;
00069         }
00070 
00079 COpenVGEngine* COpenVGEngine::NewL(TSize aWindowSize,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext)
00080         {
00081         COpenVGEngine* self = new(ELeave) COpenVGEngine(aWindowSize,aDisplay,aSurface,aContext);
00082         return self;
00083         }
00084 
00088 COpenVGEngine::~COpenVGEngine()
00089         {
00090         Deactivate();
00091         }
00092 
00097 TInt COpenVGEngine::GetSpeed()
00098         {
00099         return static_cast<TInt>(iSpeed*100000);
00100         }
00101 
00106 TBool COpenVGEngine::IsPending()
00107         {
00108         return iHasPendingDraw;
00109         }
00110 
00114 void COpenVGEngine::ActivateL()
00115         {
00116         // Setup initial OpenVG context state.
00117         VGfloat clearColour[] = { 0.1f, 0.1f, 0.2f, 1.0f };
00118         // Set the value of  VG_CLEAR_COLOR to clearcolour.
00119         vgSetfv(VG_CLEAR_COLOR, 4, clearColour);
00120         // Set the image quality mode setting to VG_IMAGE_QUALITY_NONANTIALIASED.
00121         vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
00122         // Set the rendering quality mode setting to VG_RENDERING_QUALITY_NONANTIALIASED.
00123         vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
00124         vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
00125 
00126         //Load and create the VGImage.
00127 #ifdef __WINS__
00128         _LIT(KCoverBitmaps,"z:\\resource\\apps\\covers.mbm");
00129 #else
00130         _LIT(KCoverBitmaps,"e:\\resource\\apps\\covers.mbm");
00131 #endif
00132         // Create a bitmap image.
00133         // This is used to load all bitmap images to display them on the screen.
00134         CFbsBitmap* bitmap = new(ELeave) CFbsBitmap();
00135         CleanupStack::PushL(bitmap);
00136         TInt i = 0;
00137         // Load cover images.
00138         while(bitmap->Load(KCoverBitmaps,i++) == KErrNone)
00139                 {
00140                 TSize coverSize = bitmap->SizeInPixels();
00141 
00142                 // Set the pixel format and colour to  VG_sRGB_565.s
00143                 VGImageFormat dataFormat = VG_sRGB_565;
00144                 VGint width = coverSize.iWidth;
00145                 VGint height = coverSize.iHeight;
00146                 // Get the amount of bytes per scanline.
00147                 VGint dataStride = bitmap->ScanLineLength(coverSize.iWidth,bitmap->DisplayMode());
00148 
00149                 // Create the VGImage.
00150                 VGImage image = vgCreateImage(dataFormat, width, height,VG_IMAGE_QUALITY_NONANTIALIASED);
00151                 CEGLRendering::VGCheckError();
00152 
00153                 // Load Symbian bitmap into VGImage.
00154                 vgImageSubData (image, bitmap->DataAddress(), dataStride, dataFormat, 0, 0, width, height );
00155                 CEGLRendering::VGCheckError();
00156 
00157                 // Add the image to the iImages array.
00158                 iImages.AppendL(image);
00159                 iHasPendingDraw = ETrue;
00160                 }
00161 
00162         CleanupStack::Pop(bitmap);
00163         delete bitmap;
00164 
00165         // Check if no image is loaded.
00166         if(iImages.Count() == 0)
00167                 {
00168                 User::Leave(KErrNotFound);
00169                 }
00170 
00171         iImage = iImages[0];
00172 
00173         // Create a new paint object.
00174         iShadowPaint = vgCreatePaint();
00175         if (iShadowPaint != VG_INVALID_HANDLE)
00176                 {
00177                 VGfloat paintColour[4] = { 0.4f, 0.4f, 0.6f, 1.0f };
00178                 // Passing paintColour to the paint object.
00179                 vgSetParameterfv(iShadowPaint, VG_PAINT_COLOR, 4, paintColour);
00180                 CEGLRendering::VGCheckError();
00181                 }
00182         }
00183 
00187 void COpenVGEngine::Deactivate()
00188         {
00189         TInt coverIndex=iImages.Count()-1;
00190         for (;coverIndex>=0;coverIndex--)
00191                 {
00192                 // De allocate the resources of all images in the iImages array.
00193                 vgDestroyImage(iImages[coverIndex]);
00194                 }
00195 
00196         // Destroy the paint object.
00197         vgDestroyPaint(iShadowPaint);
00198         eglWaitClient();
00199 
00200         // Reset the RArray.
00201         iImages.Reset();
00202         iHasPendingDraw = EFalse;
00203         }
00204 
00208 void COpenVGEngine::Step()
00209         {
00210 #ifdef PORTRAIT_MODE
00211         vgClear(0, 0, iSurfaceSize.iHeight, iSurfaceSize.iWidth);
00212 #else
00213         vgClear(0, 0, iSurfaceSize.iWidth, iSurfaceSize.iHeight);
00214 #endif
00215         // Calculate the speed of movement of the cover
00216         // depending on its current location.
00217         if (Abs(iCoverLocation[iWantedCover]) < 0.03)
00218                 {
00219                 iSpeed = 0.0f;
00220                 iHasPendingDraw = EFalse;
00221                 }
00222         else if (Abs(iCoverLocation[iWantedCover]) < 0.5)
00223                 {
00224                 iSpeed*=0.7;
00225                 }
00226         else
00227                 {
00228                 iSpeed = 0.05*(2+ Abs(iCoverLocation[iWantedCover]) + (Abs(iCoverLocation[iWantedCover])+1) * (Abs(iCoverLocation[iWantedCover])+1) / 2);
00229                 }
00230         // For each Cover, update its location in the correct direction.
00231         // Check if the wanted cover is already at the CenterStage point.
00232         VGfloat moveEachCover = iSpeed;
00233         if (iCoverLocation[iWantedCover] > 0.0)
00234                 {
00235                 moveEachCover *= -1;
00236                 }
00237 
00238         TInt coverIndex;
00239         // Update the location of each cover.
00240         for (coverIndex = 0; coverIndex < KMaxCoversExample3; ++coverIndex)
00241                 {
00242                 iCoverLocation[coverIndex] += moveEachCover;
00243                 }
00244 
00245         TInt coverClippingCount = 10;
00246         TInt middleCoverPos=0;
00247         VGfloat threshold = 0.50f;
00248 
00249         while(Abs(iCoverLocation[middleCoverPos])>threshold)
00250                 {
00251                 ++middleCoverPos;
00252                 }
00253 
00254 
00255         //left.
00256         TInt cutOff = middleCoverPos-coverClippingCount;
00257         if (cutOff<0)
00258                 {
00259                 cutOff=0;
00260                 }
00261         for (TInt i=cutOff; i<middleCoverPos;i++)
00262                 {
00263                 DrawCover(i);
00264                 }
00265 
00266         //right.
00267         cutOff = coverClippingCount + middleCoverPos;
00268         if (cutOff>=KMaxCoversExample3)
00269                 {
00270                 cutOff=KMaxCoversExample3-1;
00271                 }
00272 
00273         for (TInt j = cutOff; j>=middleCoverPos ; --j)
00274                 {
00275                 DrawCover(j);
00276                 }
00277 
00278 #ifdef ENABLE_LOOP
00279         static TInt dir = 1;
00280         if (iWantedCover == (KMaxCoversExample3-1))
00281                 {
00282                 dir = -1;
00283                 }
00284         else if (iWantedCover == 0)
00285                 {
00286                 dir = 1;
00287                 }
00288 
00289         iWantedCover += dir;
00290         iHasPendingDraw = ETrue;
00291 #endif
00292         }
00293 
00297 void COpenVGEngine::DrawCover(TInt aCoverIndex)
00298         {
00299         VGImage image = iImages[aCoverIndex%iImages.Count()];
00300         // Starting at the outside, render each visible (+/-  KMaxDisplayCoversExample3/2) Cover.
00301         // Calculate its path.
00302 
00303         // Set the current matrix to the identity matrix.
00304         vgLoadIdentity();
00305 
00306 #ifdef PORTRAIT_MODE
00307         vgTranslate(iSurfaceSize.iHeight, 0);
00308         vgRotate(90);
00309 #endif
00310 
00311         VGfloat coverPosition = iCoverLocation[aCoverIndex];
00312 
00313         VGfloat tempMatrix[3][3];
00314         //flip coordinates.
00315         VGfloat flipmatrix[] =
00316                 {
00317                 1.0f, 0.0f, 0.0f,
00318                 0.0f, -1.0f, 0.0f,
00319                 0.0f, 0.0f, 1.0f
00320                 };
00321         vgMultMatrix(flipmatrix);
00322 
00323         VGint imageWidth = vgGetParameteri (image, VG_IMAGE_WIDTH);
00324         VGint imageHeight = vgGetParameteri (image, VG_IMAGE_HEIGHT);
00325 
00326         VGint yTrans = -200;
00327 
00328         // Factors which must be multiplied with side of image which will be projected towards back.
00329         // Valid if projecting right image side to back.
00330         // Opposite is (1 - factor) for projecting left image side.
00331 
00332         VGfloat bottomProjectXFactor= (0.75f);
00333         VGfloat bottomProjectYFactor = (0.20f);
00334 
00335         VGfloat topProjectXFactor = (0.75f);
00336         VGfloat topProjectYFactor = (0.90f);
00337 
00338         VGfloat imageSpacingFactor = 0.16;
00339 
00340         VGfloat translationOffset = 0.0;
00341 
00342         VGfloat middleTranslationOffset = KImageSize /2;
00343         VGfloat coverProjectionLimit = 10;
00344 
00345         if (coverPosition>=1)
00346                 {
00347                 // If considering an image on the right side, this is offset from middle to place image on screen.
00348                 translationOffset = middleTranslationOffset- KImageSize/2 + KImageSize*imageSpacingFactor * (coverPosition -1);
00349 
00350                 // Left side of image goes back.
00351                 vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f,
00352                                    imageWidth, 0.0f,
00353                                    0.0f, imageHeight,
00354                                    imageWidth, imageHeight,
00355 
00356                                    KImageSize * (1 - bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)),KImageSize * bottomProjectYFactor,// left vertex.
00357                                    KImageSize, 0.0f,
00358                                    KImageSize * (1 - topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)), KImageSize * topProjectYFactor,// left vertex.
00359                                    KImageSize, KImageSize,
00360 
00361                                    &tempMatrix[0][0]);
00362                 }
00363         else if (coverPosition<-1)
00364                 {
00365                 // Must move an extra image width from centre , as coordinates from bottom left corner of image.
00366                 translationOffset = - (middleTranslationOffset + (KImageSize * imageSpacingFactor) * ( -coverPosition - 1) + KImageSize/2) ;
00367 
00368                 vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f,
00369                                    imageWidth, 0.0f,
00370                                    0.0f, imageHeight,
00371                                    imageWidth, imageHeight,
00372 
00373                                    0.0f, 0.0f,
00374                                    (bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit))* KImageSize, bottomProjectYFactor * KImageSize, //Right Vertex.
00375                                    0.0f, (KImageSize),
00376                                    (topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)) * KImageSize, topProjectYFactor * KImageSize, //Right Vertex
00377 
00378                                    &tempMatrix[0][0]);
00379                 }
00380         else if((coverPosition > -1) && (coverPosition <= 0))// -0.07))
00381                 {
00382                 translationOffset = -middleTranslationOffset * Abs(coverPosition) - KImageSize/2 ;
00383 
00384                 vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f,
00385                                                            imageWidth, 0.0f,
00386                                                            0.0f, imageHeight,
00387                                                            imageWidth, imageHeight,
00388 
00389                                                            0.0f, 0.0f,
00390                                                            KImageSize * (1 - (1-bottomProjectXFactor) * Abs(coverPosition)), KImageSize * bottomProjectYFactor * Abs(coverPosition),
00391                                                            0.0f, KImageSize,
00392                                                            (KImageSize * (1 - ( 1 - topProjectXFactor) * Abs(coverPosition))) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)),
00393 
00394                                                            &tempMatrix[0][0]);
00395 
00396                 }
00397 
00398         else if ((coverPosition >=0) && (coverPosition <= 1))
00399                 {
00400 
00401                 translationOffset = middleTranslationOffset * Abs(coverPosition) - KImageSize/2 ;
00402 
00403                 vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f,
00404                                                            imageWidth, 0.0f,
00405                                                            0.0f, imageHeight,
00406                                                            imageWidth, imageHeight,
00407 
00408                                                            KImageSize * (1-bottomProjectXFactor)* (coverPosition), KImageSize * (bottomProjectYFactor) * (coverPosition),
00409                                                            KImageSize, 0,
00410                                                            KImageSize * ( 1 - topProjectXFactor) * (coverPosition) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)),
00411                                                            KImageSize, KImageSize,
00412 
00413                                                            &tempMatrix[0][0]);
00414                 }
00415 
00416 
00417         iSpeedOffset = 140*(iSpeed)*(iSpeed);
00418 
00419                         if (iCoverLocation[iWantedCover]<0)
00420                                 {
00421                                 iSpeedOffset *=-1;
00422                                 }
00423 
00424         // Apply transformations to the current matrix.
00425         vgTranslate(iSurfaceSize.iWidth/2 + translationOffset + iSpeedOffset,yTrans);
00426 
00427         vgMultMatrix(&tempMatrix[0][0]);
00428         if (Abs(coverPosition)<=1)
00429                 {
00430                 VGfloat scale = GetMiddleCoverScalingFactor(coverPosition);
00431                 vgScale(scale,scale);
00432 
00433                 vgTranslate(-(scale-1)/2 * KImageSize,-(scale-1)/2 * KImageSize);
00434                 }
00435 
00436         // Draw the image on the surface.
00437         vgDrawImage(image);
00438         CEGLRendering::VGCheckError();
00439 
00440         // Check if mirror images of covers have to be displayed.
00441         if(iShowMirror)
00442                 {
00443                 // Scale the current matrix to create inverted images.
00444                 vgScale(1,-1);
00445                 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
00446                 vgTranslate(0,-4*KImageSize+226);
00447 
00448                 // Draw the image on the surface.
00449                 vgSetPaint(iShadowPaint, VG_FILL_PATH);
00450                 vgDrawImage(image);
00451                 CEGLRendering::VGCheckError();
00452 
00453                 vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);
00454                 }
00455         }
00456 
00461 TKeyResponse COpenVGEngine::HandleKeyEventL(const TKeyEvent& aKeyEvent)
00462         {
00463         TKeyResponse response = EKeyWasConsumed;
00464         switch (aKeyEvent.iCode)
00465                 {
00466         case EKeyRightArrow:
00467         // Move to the next cover if right arrow key is pressed.
00468                 NextCover();
00469                 break;
00470 
00471         case EKeyLeftArrow:
00472         // Move to the previous cover if left arrow key is pressed.
00473         PreviousCover();
00474                 break;
00475 
00476         case EKeyBackspace:
00477         // Toggle the cover reflection flag.
00478                 ToggleCoverReflection();
00479                 break;
00480         default:
00481                 response = EKeyWasNotConsumed;
00482                 break;
00483                 };
00484         return response;
00485         }
00486 
00490 COpenVGEngine::COpenVGEngine(TSize aWindowSize,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext) :
00491         iDisplay(aDisplay),iSurface(aSurface),iContext(aContext),iWantedCover(20),iHasPendingDraw(EFalse),
00492         iShowMirror(ETrue)
00493         {
00494 #ifdef PORTRAIT_MODE
00495         iSurfaceSize.iWidth = aWindowSize.iHeight;
00496         iSurfaceSize.iHeight = aWindowSize.iWidth;
00497 #else
00498         iSurfaceSize = aWindowSize;
00499 #endif
00500         // Initiate the location of each cover & make the wanted one the cover at the opposite end
00501         for(TInt i=0; i<KMaxCoversExample3; ++i)
00502                 {
00503                 iCoverLocation[i] = i;
00504                 }
00505         }
00506 
00510 void COpenVGEngine::NextCover()
00511         {
00512         if (iWantedCover < (KMaxCoversExample3-1))
00513                 {
00514                 ++iWantedCover;
00515                 }
00516         iHasPendingDraw = ETrue;
00517         }
00518 
00522 void COpenVGEngine::PreviousCover()
00523         {
00524 
00525         if (iWantedCover>0)
00526                 {
00527                 --iWantedCover;
00528                 }
00529         iHasPendingDraw = ETrue;
00530         }
00531 
00536 void COpenVGEngine::ToggleCoverReflection()
00537         {
00538         iShowMirror = !iShowMirror;
00539         }
00540 
00546 VGfloat COpenVGEngine::GetMiddleCoverScalingFactor(VGfloat aCoverPosition)
00547         {
00548         if(Abs(aCoverPosition)>1)
00549                 {
00550                 return 0.0f;
00551                 }
00552 
00553         return (-0.125 * Abs(aCoverPosition) + 1.125);
00554         }

Generated by  doxygen 1.6.2