diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/aknphysics/src/aknphysicsengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/aknphysics/src/aknphysicsengine.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,530 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: AknPhysics engine +* +*/ + +#include +#include +#include +#include +#include +#include + +#include "aknphysicsconstants.h" +#include "aknphysicsengine.h" + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::NewL +// --------------------------------------------------------------------------- +// +CAknPhysicsEngine* CAknPhysicsEngine::NewL( CAknPhysics* aPhysics ) + { + CAknPhysicsEngine* self = CAknPhysicsEngine::NewLC( aPhysics ); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::NewLC +// --------------------------------------------------------------------------- +// +CAknPhysicsEngine* CAknPhysicsEngine::NewLC( CAknPhysics* aPhysics ) + { + CAknPhysicsEngine* self = + new ( ELeave ) CAknPhysicsEngine( aPhysics ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::~CAknPhysicsEngine +// --------------------------------------------------------------------------- +// +CAknPhysicsEngine::~CAknPhysicsEngine() + { + DeletePhysics(); + delete iAlfClient; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::WorldExists +// --------------------------------------------------------------------------- +// +TBool CAknPhysicsEngine::WorldExists() const + { + return iWorldId != NULL; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::CreateWorld +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::CreateWorld( const TInt& aGravity ) + { + dInitODE(); + iWorldId = dWorldCreate(); + dWorldSetERP( iWorldId, REAL( KErpFactor ) ); + dWorldSetCFM( iWorldId, REAL( KCfmFactor ) ); + dWorldSetGravity( iWorldId, 0, 0, -REAL( aGravity ) ); + dWorldSetAutoDisableFlag(iWorldId, 1); + iSpace = dSimpleSpaceCreate(0); + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::CreatePlanes +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::CreatePlanes( const TInt64& aIh, + const TInt64& aX, + const TInt64& aY, + const TInt64& aR ) + { + // Create bounding planes + iPlaneTop = dCreatePlane( iSpace, REAL( aX ), REAL( aY ), 0, REAL( 0 ) ); + iPlaneBottom = dCreatePlane( iSpace, REAL( -aX ), REAL( -aY ), 0, REAL( -aIh ) ); + iPlaneLeft = dCreatePlane( iSpace, REAL( aY ), REAL( aX ), 0, REAL( 0 ) ); + iPlaneRight = dCreatePlane( iSpace, REAL( -aY ), REAL( -aX ), 0, REAL( -aR ) ); + + // create z-plane to apply friction + // bottom, z axle + iPlaneFriction = dCreatePlane( iSpace, 0, 0, REAL( 1 ), REAL( -KZDepth ) ); + } + + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::CreateViewBody +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::CreateViewBody( + const TInt64& aWidth, const TInt64& aHeight, const TInt64& aMass ) + { + // create viewbox + iViewBox = dCreateBox( iSpace, REAL( aWidth ), REAL( aHeight ), REAL( KZDepth ) ); + iViewBody = dBodyCreate( iWorldId ); + + dBodySetAutoDisableFlag( iViewBody, 1 ); + dGeomSetBody( iViewBox, iViewBody ); + + // Set mass for body + dMass mass; + dMassSetBoxTotal( &mass, + REAL( aMass ), REAL( aWidth ), REAL( aHeight ), REAL( KZDepth ) ); + dBodySetMass( iViewBody, &mass ); + + // Create JointGroup to handle contacts + iContactGroup = dJointGroupCreate( 0 ); + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::SetViewBodyPosition +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::SetViewBodyPosition( const TPoint& aPosition ) + { + if ( iViewBody ) + { + iViewPosition = aPosition; + TInt64 x, y; + x = iViewPosition.iX; + y = iViewPosition.iY; + dBodySetPosition( + iViewBody, + REAL( x ), + REAL( y ), + REAL( -KZDepth/2 ) ); + } + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::GetViewBodyPosition +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::GetViewBodyPosition( TPoint& aPosition ) + { + const dReal *pos = dBodyGetPosition( iViewBody ); + iViewPosition.iX = dFLOAT( pos[0] ); + iViewPosition.iY = dFLOAT( pos[1] ); + aPosition = iViewPosition; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::ResetViewBodyForceAndVelocity +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::ResetViewBodyForceAndVelocity() + { + if ( iViewBody ) + { + dBodySetForce( iViewBody, 0, 0, 0); + dBodySetLinearVel( iViewBody, 0, 0, 0 ); + } + } + + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::EnableViewBody +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::EnableViewBody() + { + if ( iViewBody ) + { + dBodyEnable( iViewBody ); + } + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::IsViewBodyEnabled +// --------------------------------------------------------------------------- +// +TBool CAknPhysicsEngine::IsViewBodyEnabled() const + { + if ( iViewBody ) + { + return dBodyIsEnabled( iViewBody ); + } + return EFalse; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::ApplyDragForce +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::ApplyDragForce( + const TPoint& aDrag, const TInt& aMoveTime ) + { + if ( iViewBody ) + { + TReal step = aMoveTime * KStepFactor; + // calculate and apply force from drag + dVector3 force; + dWorldImpulseToForce( + iWorldId, + REAL( step ), + REAL( TInt64( aDrag.iX / 3 ) ), + REAL( TInt64( aDrag.iY / 3 ) ), + 0, + force ); + dBodyAddForce( iViewBody, force[0], force[1], force[2] ); + } + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::CollisionState +// --------------------------------------------------------------------------- +// +const CAknPhysicsEngine::TAknPhysicsCollision& CAknPhysicsEngine::CollisionState() + { + return iCollision; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::ResetCollisionState +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::ResetCollisionState() + { + iCollision = EAknPhysicsNoCollision; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::TakePhysicsStep +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::TakePhysicsStep() + { + // Call collision detection (step + dSpaceCollide ( iSpace, this , &CAknPhysicsEngine::CallbackFunc ); + + // Take a simulation step + dWorldQuickStep( iWorldId, REAL( 0.1 ) ); + + // Remove all joints in the contact + dJointGroupEmpty( iContactGroup ); + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::DeletePhysics +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::DeletePhysics() + { + if(iWorldId) + { + // Remove all joints in the contact + dJointGroupEmpty( iContactGroup ); + + dJointGroupDestroy( iContactGroup ); + iContactGroup = NULL; + dBodyDestroy( iViewBody ); + iViewBody = NULL; + + dGeomDestroy( iPlaneTop ); + iPlaneTop = NULL; + dGeomDestroy( iPlaneBottom ); + iPlaneBottom = NULL; + dGeomDestroy( iPlaneLeft ); + iPlaneLeft = NULL; + dGeomDestroy( iPlaneRight ); + iPlaneRight = NULL; + dGeomDestroy( iPlaneFriction ); + iPlaneFriction = NULL; + dGeomDestroy( iViewBox ); + iViewBox = NULL; + + dSpaceDestroy( iSpace ); + iSpace = NULL; + dWorldDestroy( iWorldId ); + iWorldId = NULL; + dCloseODE(); // final clean-up; + } + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::SetFriction +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::SetFriction( TReal aFriction ) + { + iFriction = aFriction; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::ResetFriction +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::ResetFriction() + { + iFriction = KDefaultFriction; + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::StartFpsLogging +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::StartFpsLogging() + { + if ( !iAlfClient ) + { + TRAP_IGNORE( iAlfClient = new ( ELeave ) RAlfDirectClient ); + } + + if ( iAlfClient ) + { + if ( iLogUid == KNullUid ) + { + CEikonEnv* env = CEikonEnv::Static(); + + if ( env ) + { + CEikAppUi* appUi = static_cast( env->AppUi() ); + + if ( appUi && appUi->Application() ) + { + iLogUid = appUi->Application()->AppDllUid(); + } + } + } + + iAlfClient->MeasureFPS( iLogUid.iUid, ETrue ); + } + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::StopFpsLogging +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::StopFpsLogging() + { + if ( iAlfClient ) + { + iAlfClient->MeasureFPS( iLogUid.iUid, EFalse ); + } + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::CAknPhysicsEngine +// --------------------------------------------------------------------------- +// +CAknPhysicsEngine::CAknPhysicsEngine( CAknPhysics* aPhysics ) + : iWorldId( NULL ), + iFriction( KDefaultFriction ), + iPhysics( aPhysics ), + iLogUid( KNullUid ) + { + } + + +// --------------------------------------------------------------------------- +// CAknPhysicsEngine::ConstructL +// --------------------------------------------------------------------------- +// +void CAknPhysicsEngine::ConstructL() + { + } + + +// ----------------------------------------------------------------------------- +// CAknPhysicsEngine::CallbackFunc() +// ----------------------------------------------------------------------------- +// +void CAknPhysicsEngine::CallbackFunc( void* aData, dGeomID o0, dGeomID o1 ) + { + static_cast( aData )->HandleCollisionBetween( o0,o1 ); + } + + +// ----------------------------------------------------------------------------- +// CAknPhysicsEngine::HandleCollisionBetween() +// ----------------------------------------------------------------------------- +// +void CAknPhysicsEngine::HandleCollisionBetween( + dGeomID aObject1, dGeomID aObject2 ) + { + + TSize viewSize( iPhysics->ViewSize() ); + TSize worldSize( iPhysics->WorldSize() ); + TInt surfaceErp( iPhysics->SurfaceErp() ); + TInt surfaceCfm( iPhysics->SurfaceCfm() ); + + + dBodyID b1 = dGeomGetBody(aObject1); + dBodyID b2 = dGeomGetBody(aObject2); + dContact contacts[KMaxContacts]; + TInt numc = dCollide(aObject1, + aObject2, + KMaxContacts, + &contacts[0].geom, + sizeof(dContact)); + + for (TInt i = 0 ; i < numc; i++) + { + contacts[i].surface.mode = dContactApprox1; + + if(aObject1 == iPlaneFriction || aObject2 == iPlaneFriction) + { + if( iCollision == EAknPhysicsNoCollision ) + { + contacts[i].surface.mu = REAL( iFriction ); + } + else + { + contacts[i].surface.mu = 0; + } + } + else if(aObject1 == iPlaneTop + || aObject2 == iPlaneTop) + { + contacts[i].surface.mu = 0; // No friction + TInt offScreen = 0; + if( iPhysics->Landscape() ) + { + offScreen = -(iViewPosition.iX - viewSize.iWidth/2); + offScreen = + offScreen > viewSize.iWidth ? viewSize.iWidth : offScreen; + } + else + { + offScreen = -(iViewPosition.iY - viewSize.iHeight/2); + offScreen = + offScreen > viewSize.iHeight ? viewSize.iHeight : offScreen; + } + if( offScreen ) + { + contacts[i].surface.mode |= dContactSoftCFM | dContactSoftERP; + contacts[i].surface.soft_erp = + REAL( TReal( surfaceErp )/offScreen ); + contacts[i].surface.soft_cfm = + REAL( TReal( surfaceCfm )/offScreen); + iCollision = EAknPhysicsTopCollision; + } + else + iCollision = EAknPhysicsNoCollision; + + RDebug::Print(_L("TOP COLLISION")); + } + else if(aObject1 == iPlaneBottom + || aObject2 == iPlaneBottom ) + { + contacts[i].surface.mu = 0; // No friction + TInt offScreen = 0; + if(iPhysics->Landscape()) + { + offScreen = + (iViewPosition.iX + viewSize.iWidth/2) - viewSize.iWidth; + offScreen = + offScreen > viewSize.iWidth ? viewSize.iWidth : offScreen; + } + else + { + offScreen = + (iViewPosition.iY + viewSize.iHeight/2) - worldSize.iHeight; + offScreen = + offScreen > viewSize.iHeight ? viewSize.iHeight : offScreen; + } + + if( offScreen ) + { + contacts[i].surface.mode |= dContactSoftCFM | dContactSoftERP; + contacts[i].surface.soft_erp = + REAL( TReal( surfaceErp )/offScreen ); + contacts[i].surface.soft_cfm = + REAL( TReal( surfaceCfm )/offScreen); + iCollision = EAknPhysicsBottomCollision; + } + else + iCollision = EAknPhysicsNoCollision; + + RDebug::Print(_L("BOTTOM COLLISION")); + } + else + { + iCollision = EAknPhysicsNoCollision; + contacts[i].surface.mu = 0; // No friction + contacts[i].surface.mode |= + dContactBounce | dContactSoftCFM | dContactSoftERP; + contacts[i].surface.soft_cfm = REAL(KCfmSoftFactor); + contacts[i].surface.soft_erp = REAL(KErpFactor); + contacts[i].surface.bounce = REAL(KBounceFactor); // small bounce + } + + dJointID c = dJointCreateContact(iWorldId, iContactGroup, &contacts[i]); + dJointAttach(c,b1,b2); + } + }