--- /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 <e32debug.h>
+#include <aknphysics.h>
+#include <eikenv.h>
+#include <eikappui.h>
+#include <eikapp.h>
+#include <alf/alfdirectclient.h>
+
+#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<CEikAppUi*>( 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<CAknPhysicsEngine*>( 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);
+ }
+ }