--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/huim3gmesh.cpp Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,691 @@
+/*
+* Copyright (c) 2007 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: Definition of CHuiM3GMesh, an interface enabling usage of M3G
+ * scene graphs within Hitchcock UI Toolkit user interfaces.
+ *
+*/
+
+
+
+#include <uiacceltk/huim3gmesh.h>
+#include <uiacceltk/HuiStatic.h>
+#include <uiacceltk/HuiEnv.h>
+
+// Force softfp linkage until included header has its own definitions
+#if defined(__ARMCC_VERSION)
+#pragma push
+#pragma softfp_linkage
+#endif
+#include <M3G/m3g_core.h>
+#if defined(__ARMCC_VERSION)
+#pragma pop
+#endif
+
+#include <s32file.h>
+#include <e32math.h>
+#include <cstack.h>
+
+// ======== LOCAL FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// A static function to destroy an M3G object if associated clean up item
+// is popped from the cleanup stack.
+// ---------------------------------------------------------------------------
+//
+void DestroyM3GObject(TAny* aObject)
+ {
+ m3gDeleteObject( (M3GObject)aObject );
+ }
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Default constructor.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CHuiM3GMesh::CHuiM3GMesh()
+: CHuiMesh(EHuiMeshTypeM3G)
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// 2nd phase constructor.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::ConstructL()
+ {
+ iCamRotation[0] = 0;
+ iCamRotation[1] = 0;
+ iCamRotation[2] = 0;
+ iCamRotation[3] = 0;
+ iCamTranslation[0] = 0;
+ iCamTranslation[1] = 0;
+ iCamTranslation[2] = 0;
+ iCamTranslation[3] = 0;
+ }
+
+// ---------------------------------------------------------------------------
+// Load scene from file.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::LoadSceneL(const TDesC& /*aFileName*/)
+ {
+ }
+
+EXPORT_C void CHuiM3GMesh::LoadSceneL(const TDesC& aFileName, M3GInterface aInterface)
+ {
+ // Release the previously loaded M3G scene graph
+ ReleaseScene();
+
+ // Load the new scene graph
+ TRAPD( err, DoLoadSceneL( aFileName, aInterface ) );
+
+ // If an error occured during the scene loading release the scene and
+ // re-leave.
+ if( err != KErrNone )
+ {
+ ReleaseScene();
+ User::Leave( err );
+ }
+ }
+
+void CHuiM3GMesh::DoLoadSceneL(const TDesC& aFileName, M3GInterface aInterface)
+ {
+ // Load M3G content from same path as images
+ TFileName fileName;
+ fileName = CHuiStatic::Env().TextureManager().ImagePath();
+ fileName += aFileName;
+
+ // Create M3G loader to load the scene from memory buffer.
+ M3GLoader loader = m3gCreateLoader(aInterface);
+ if (loader == NULL)
+ {
+ User::Leave(KErrNoMemory);
+ }
+ TCleanupItem loaderCleaner( &DestroyM3GObject, loader);
+ CleanupStack::PushL(loaderCleaner);
+
+ // Read the file contents to the memory buffer
+ RFs fs;
+ CleanupClosePushL(fs);
+ RFileReadStream reader;
+ CleanupClosePushL(reader);
+ User::LeaveIfError(fs.Connect() );
+ TInt errorCode = reader.Open(fs, fileName, EFileRead);
+ if (errorCode != KErrNone)
+ {
+ User::Leave(errorCode);
+ }
+
+ // Read the contents of the file to a buffer.
+ TInt sceneSize = reader.Source()->SizeL();
+ TUint chunkSize = 1024;
+ TUint8 *buf = new (ELeave) TUint8[chunkSize];
+ CleanupStack::PushL(buf);
+ TInt i = 0;
+ M3Gsizei reqBytes = 1;
+ while (i < sceneSize && reqBytes > 0 ){
+ TInt j = 0;
+ for( j = 0; j < chunkSize && i < sceneSize; j++ )
+ {
+ buf[j] = reader.ReadUint8L();
+ i++;
+ }
+ reqBytes = m3gDecodeData( loader, j, buf );
+ }
+
+// Get number of loaded objects
+iNumObjects = m3gGetLoadedObjects( loader, NULL );
+
+// The input buffer from the file is not needed anymore
+CleanupStack::PopAndDestroy( buf );
+CleanupStack::PopAndDestroy( &reader );
+CleanupStack::PopAndDestroy( &fs );
+
+// Leave with KErrCorrupt if there were no M3G objects within the file (corrupted file).
+if( iNumObjects == 0 )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+// Add loaded objects to an object array.
+iObjects = new (ELeave) M3GObject[iNumObjects];
+m3gGetLoadedObjects( loader, iObjects );
+
+// Add references and find the first world object
+for( TInt ii = 0; ii < iNumObjects; ii++ )
+ {
+ m3gAddRef( iObjects[ii] );
+ if( m3gGetClass( iObjects[ii] ) == M3G_CLASS_WORLD && !iWorld )
+ {
+ iWorld = (M3GWorld)iObjects[ii];
+ break;
+ }
+ }
+
+// Fetch animation controllers from world
+PopulateAnimationControllerArrayL( (M3GObject)iWorld );
+
+iUpdateCamera = EFalse;
+iCamera = m3gGetActiveCamera(iWorld);
+if ( !iCamera )
+ {
+ // Create camera if it doesn't exist
+ // The camera is updated according to hitchcock projection and model view matrices
+ iUpdateCamera = ETrue;
+ iCamera = m3gCreateCamera(aInterface);
+ if( iCamera == NULL )
+ {
+ User::Leave( KErrNoMemory );
+ }
+ m3gAddChild( (M3GGroup)iWorld, (M3GNode)iCamera );
+ m3gSetActiveCamera( iWorld, iCamera );
+ M3GMatrix identity;
+ m3gIdentityMatrix( &identity );
+ m3gSetTransform( (M3GTransformable)iCamera, &identity );
+ m3gTranslate( (M3GTransformable)iCamera, 0.f, 0.f, 1.f );
+ m3gSetPerspective( iCamera,90.f, 1.f, 0.1f, 100.f );
+ }
+
+// Init background
+M3GBackground bg = m3gGetBackground( iWorld );
+if (!bg)
+ {
+ bg = m3gCreateBackground( aInterface );
+ if( bg == NULL )
+ {
+ User::Leave( KErrNoMemory );
+ }
+ m3gSetBackground( iWorld, bg );
+ }
+m3gSetBgEnable( bg, M3G_SETGET_COLORCLEAR, M3G_FALSE );
+m3gSetBgEnable( bg, M3G_SETGET_DEPTHCLEAR, M3G_FALSE );
+
+// Release the loader
+CleanupStack::PopAndDestroy( loader );
+}
+
+// ---------------------------------------------------------------------------
+// Object destructor.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CHuiM3GMesh::~CHuiM3GMesh()
+ {
+ ReleaseScene();
+ iControllers.Close();
+ }
+
+// ---------------------------------------------------------------------------
+// Set viewport rect
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::SetViewportRect( const THuiRealRect& aRect )
+ {
+ iViewportRect = aRect;
+ }
+
+// ---------------------------------------------------------------------------
+// Draw scene
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::Draw(CHuiGc& /*aGc*/, const THuiImage* /*aImage*/,
+ const THuiImage* /*aSecondaryImage*/,
+ TReal32 /*aSecondaryAlpha*/) const __SOFTFP
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// Release scene
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::ReleaseScene()
+ {
+ if (iObjects)
+ {
+ for (TInt i = 0; i < iNumObjects; i++)
+ {
+ m3gDeleteRef(iObjects[i]);
+ iObjects[i] = NULL;
+ }
+ delete [] iObjects;
+ iNumObjects = 0;
+ iObjects = NULL;
+ iWorld = NULL;
+ }
+ iControllers.Reset();
+ }
+
+// ---------------------------------------------------------------------------
+// Rotate world around Y axis
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::RotateYaw(TReal32 aAngle) __SOFTFP
+ {
+ RotateObjects(aAngle, 0.0f, 1.0f, 0.0f);
+ }
+
+// ---------------------------------------------------------------------------
+// Rotate world around X axis
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::RotatePitch(TReal32 aAngle) __SOFTFP
+ {
+ RotateObjects(aAngle, 1.0f, 0.0f, 0.0f);
+ }
+
+// ---------------------------------------------------------------------------
+// Find the center point of the group
+// ---------------------------------------------------------------------------
+//
+void CHuiM3GMesh::FindObjectCenter(M3GGroup aGroup, TReal32 aTrans[4],
+ TBool aFirst)
+ {
+ TReal32 objectTrans[4];
+ TInt numChildren = m3gGetChildCount(aGroup);
+ for (TInt i = 0; i < numChildren; ++i)
+ {
+ M3GNode child = m3gGetChild((M3GGroup)aGroup, i);
+ M3GClass m3gClass = m3gGetClass((M3GObject)child);
+ M3GMesh mesh = (M3GMesh)child;
+
+ if (m3gClass == M3G_CLASS_SKINNED_MESH || m3gClass == M3G_CLASS_MESH
+ || m3gClass == M3G_CLASS_MORPHING_MESH)
+ {
+
+ // Set blending and culling
+ M3GAppearance hApp = m3gGetAppearance(mesh, 0);
+
+ /*
+ M3GCompositingMode cm = m3gGetCompositingMode(hApp);
+ m3gSetBlending(cm, M3G_REPLACE);
+ m3gSetAlphaWriteEnable(cm, 0);
+ m3gSetCompositingMode(hApp, cm);
+ m3gSetAppearance( mesh, 0, hApp );
+ */
+
+ M3GPolygonMode pm = m3gGetPolygonMode(hApp);
+ m3gSetCulling(pm, M3G_CULL_NONE);
+ m3gSetPolygonMode(hApp, pm);
+
+ m3gGetTranslation((M3GTransformable)mesh, objectTrans);
+ if (!aFirst)
+ {
+ aTrans[0] = (aTrans[0] + objectTrans[0]) / 2;
+ aTrans[1] = (aTrans[1] + objectTrans[1]) / 2;
+ aTrans[2] = (aTrans[2] + objectTrans[2]) / 2;
+ aTrans[3] = (aTrans[3] + objectTrans[3]) / 2;
+ }
+ else
+ {
+ aTrans[0] = objectTrans[0];
+ aTrans[1] = objectTrans[1];
+ aTrans[2] = objectTrans[2];
+ aTrans[3] = objectTrans[3];
+ aFirst = EFalse;
+ }
+ }
+ else
+ if (m3gClass == M3G_CLASS_GROUP || m3gClass == M3G_CLASS_WORLD)
+ {
+ m3gGetTranslation((M3GTransformable)mesh, objectTrans);
+ if (!aFirst)
+ {
+ aTrans[0] = (aTrans[0] + objectTrans[0]) / 2;
+ aTrans[1] = (aTrans[1] + objectTrans[1]) / 2;
+ aTrans[2] = (aTrans[2] + objectTrans[2]) / 2;
+ aTrans[3] = (aTrans[3] + objectTrans[3]) / 2;
+ }
+ else
+ {
+ aTrans[0] = objectTrans[0];
+ aTrans[1] = objectTrans[1];
+ aTrans[2] = objectTrans[2];
+ aTrans[3] = objectTrans[3];
+ aFirst = EFalse;
+ }
+ FindObjectCenter((M3GGroup)child, aTrans, aFirst);
+ }
+ else
+ {
+ // For PC-lint
+ }
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// Rotates camera around worlds objects.
+// ---------------------------------------------------------------------------
+//
+void CHuiM3GMesh::RotateObjects(TReal32 aAngle, TReal32 aAxisX,
+ TReal32 aAxisY, TReal32 aAxisZ)
+__SOFTFP {
+ if(iWorld != 0)
+ {
+
+ // Find the center of the objects
+ TReal32 objectTrans[4];
+ objectTrans[0] = 0;
+ objectTrans[1] = 0;
+ objectTrans[2] = 0;
+ objectTrans[3] = 0;
+ FindObjectCenter((M3GGroup)iWorld,objectTrans);
+
+ // Get camera position
+ M3GCamera cam = iCamera;
+ TReal32 trans[4];
+ m3gGetTranslation((M3GTransformable)cam, trans);
+
+ // Calculate distance of objects center point and camera
+ objectTrans[0] = objectTrans[0]-trans[0];
+ objectTrans[1] = objectTrans[1]-trans[1];
+ objectTrans[2] = objectTrans[2]-trans[2];
+ objectTrans[3] = objectTrans[3]-trans[3];
+ TReal dist;
+ Math().Sqrt(dist,(TReal)objectTrans[0]*objectTrans[0]+objectTrans[1]*objectTrans[1]+objectTrans[2]*objectTrans[2]);
+
+ // Get orientation of camera
+ TReal32 rot[4];
+ m3gGetOrientation((M3GTransformable)cam, rot);
+
+ // Create new camera vector
+ M3GVec4 camZ;
+ camZ.x = 0;
+ camZ.y = 0;
+ camZ.z = -dist;
+ camZ.w = 1;
+
+ // Create rotation matrix for camera (old position)
+ M3GMatrix rotmtx;
+ m3gIdentityMatrix(&rotmtx);
+ m3gPostRotateMatrix(&rotmtx, rot[0], rot[1], rot[2], rot[3]);
+
+ // Create rotation matrix for camera (new position)
+ M3GMatrix mtx;
+ m3gIdentityMatrix(&mtx);
+ m3gPostRotateMatrix(&mtx, aAngle, aAxisX, aAxisY, aAxisZ);
+
+ // Translate camera vector
+ m3gTransformVec4(&rotmtx,&camZ);
+
+ // Store this position
+ M3GVec4 trans2;
+ trans2.x = camZ.x;
+ trans2.y = camZ.y;
+ trans2.z = camZ.z;
+ trans2.w = camZ.w;
+
+ // create new camera vector
+ camZ.x = 0;
+ camZ.y = 0;
+ camZ.z = -dist;
+ camZ.w = 1;
+
+ // transform this vector with new position matrix
+ m3gTransformVec4(&mtx,&camZ);
+
+ // transform with old position matrix
+ m3gTransformVec4(&rotmtx,&camZ);
+
+ // move and rotate camerea based on these calculations
+ m3gPostRotate((M3GTransformable)cam,aAngle, aAxisX, aAxisY, aAxisZ);
+ m3gTranslate((M3GTransformable)cam, -camZ.x+trans2.x, -camZ.y+trans2.y, -camZ.z+trans2.z);
+
+ m3gAlignNode((M3GNode)cam,NULL);
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // Store camera transformations
+ // ---------------------------------------------------------------------------
+ //
+EXPORT_C void CHuiM3GMesh::StoreCamera()
+ {
+ if(iWorld != 0)
+ {
+ m3gGetOrientation((M3GTransformable)iCamera, iCamRotation);
+ m3gGetTranslation((M3GTransformable)iCamera, iCamTranslation);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Restore camera transformations
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::RestoreCamera()
+ {
+ if(iWorld != 0)
+ {
+ m3gSetOrientation((M3GTransformable)iCamera, iCamRotation[0],iCamRotation[1],iCamRotation[2],iCamRotation[3]);
+ m3gSetTranslation((M3GTransformable)iCamera, iCamTranslation[0],iCamTranslation[1],iCamTranslation[2]);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Fetch animation controllers from any M3G object (recursively).
+// ---------------------------------------------------------------------------
+//
+void CHuiM3GMesh::PopulateAnimationControllerArrayL(const M3GObject aObject)
+ {
+ // Array for storing the already visited M3G object pointers.
+ RPointerArray<M3GObjectImpl> visited;
+ CleanupClosePushL(visited);
+
+ // Stack for iteratively traversing through the object reference net.
+ CStack<M3GObjectImpl, EFalse>* stack = new ( ELeave ) CStack<M3GObjectImpl, EFalse>();
+ CleanupStack::PushL(stack);
+
+ // Push the initial M3G object to the iteration stack
+ stack->PushL(aObject);
+
+ // Iterate through all objects in the iteration stack
+ while ( !stack->IsEmpty() )
+ {
+ // Pop the current M3G object
+ M3GObject current = stack->Pop();
+
+ // If animation controller, add to array
+ M3GClass m3gClass = m3gGetClass(current);
+ if (m3gClass == M3G_CLASS_ANIMATION_CONTROLLER)
+ {
+ M3GAnimationController controller =
+ (M3GAnimationController)current;
+
+ THuiM3GMeshAnimationController newController;
+ newController.iController = controller;
+ newController.iPosition = THuiTimedValue( 0,
+ EHuiTimedValueStyleLinear);
+ newController.iAnimating = EFalse;
+ newController.iTimeOffset = 0;
+ newController.iPreviousTime
+ = CHuiStatic::MilliSecondsSinceStart();
+ iControllers.AppendL(newController);
+ }
+
+ // Traverse graph
+ const TInt count = m3gGetReferences(current, NULL, 0);
+ if (count)
+ {
+ visited.ReserveL(visited.Count() + count);
+ M3GObject* refs = new M3GObject[count];
+ User::LeaveIfNull(refs);
+ CleanupArrayDeletePushL(refs);
+
+ m3gGetReferences(current, refs, count);
+ for (TInt i = 0; i < count; i++)
+ {
+ TInt index = 0;
+ TInt err = visited.FindInAddressOrder(refs[i], index);
+ if (err != KErrNone)
+ {
+ visited.InsertL(refs[i], index);
+ stack->PushL(refs[i]);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(refs);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(stack);
+ CleanupStack::PopAndDestroy( &visited);
+ }
+
+// ---------------------------------------------------------------------------
+// Returns number of (hitchcock) animation controllers
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CHuiM3GMesh::AnimationControllerCount() const
+ {
+ TInt baseAnimations = CHuiMesh::AnimationControllerCount();
+ TInt count = iControllers.Count();
+ return baseAnimations + count;
+ }
+
+// ---------------------------------------------------------------------------
+// Set position of animation in animation controller.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::SetAnimationPosition(TInt aControllerId, TReal32 aTarget, TInt aTime) __SOFTFP
+ {
+ if(iWorld != 0)
+ {
+ // Animate every controller
+ if(aControllerId == KHuiM3GAnimateAllControllers )
+ {
+ for(int i = 0; i < iControllers.Count(); i++)
+ {
+ ((iControllers[i]).iPosition).Set(aTarget-((iControllers[i]).iTimeOffset), aTime);
+ }
+ }
+ else // Animate only aControllerId:s controller
+
+ {
+ for(int i = 0; i < iControllers.Count(); i++)
+ {
+ if(aControllerId == m3gGetUserID((M3GObject)(iControllers[i].iController)))
+ {
+ ((iControllers[i]).iPosition).Set(aTarget-((iControllers[i]).iTimeOffset), aTime);
+ }
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Go through animation controllers and does animations.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::AnimateControllers()
+ {
+ if(iWorld != 0)
+ {
+ TInt currentTime = CHuiStatic::MilliSecondsSinceStart();
+ for(TInt i = 0; i < iControllers.Count(); i++)
+ {
+ M3GAnimationController controller = (iControllers[i]).iController;
+ if( ( (iControllers[i]).iPosition).Changed())
+ {
+ ((iControllers[i]).iPosition).ClearChanged();
+ }
+ else
+ {
+ if ( (iControllers[i]).iAnimating )
+ {
+ TInt timeChanged = currentTime-((iControllers[i]).iPreviousTime);
+ ((iControllers[i]).iTimeOffset) += timeChanged;
+ }
+ }
+ ((iControllers[i]).iPreviousTime) = currentTime;
+ m3gSetPosition(controller, ((iControllers[i]).iPosition).Now() + ((iControllers[i]).iTimeOffset), currentTime);
+ m3gSetActiveInterval(controller, currentTime, currentTime);
+ }
+ m3gAnimate((M3GObject)iWorld, currentTime);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Start animation of the controller
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::StartAnimationController(TInt aControllerId)
+ {
+ if(iWorld != 0)
+ {
+ // Start every animation controller
+ if(aControllerId == KHuiM3GAnimateAllControllers )
+ {
+ for(int i = 0; i < iControllers.Count(); i++)
+ {
+ iControllers[i].iAnimating = ETrue;
+ TInt currentTime = CHuiStatic::MilliSecondsSinceStart();
+ m3gSetActiveInterval((iControllers[i]).iController, currentTime, currentTime);
+ }
+ }
+ else // Start only aControllerId:s controller
+
+ {
+ for(int i = 0; i < iControllers.Count(); i++)
+ {
+ if(aControllerId == m3gGetUserID((M3GObject)(iControllers[i].iController)))
+ {
+ iControllers[i].iAnimating = ETrue;
+ TInt currentTime = CHuiStatic::MilliSecondsSinceStart();
+ m3gSetActiveInterval((iControllers[i]).iController, currentTime, currentTime);
+ }
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Stop animation of the controller
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CHuiM3GMesh::StopAnimationController(TInt aControllerId)
+ {
+ if(iWorld != 0)
+ {
+ // Stop every animation controller
+ if(aControllerId == KHuiM3GAnimateAllControllers )
+ {
+ for(int i = 0; i < iControllers.Count(); i++)
+ {
+ iControllers[i].iAnimating = EFalse;
+ TInt currentTime = CHuiStatic::MilliSecondsSinceStart();
+ m3gSetActiveInterval((iControllers[i]).iController, currentTime-2, currentTime-1);
+ }
+ }
+ else // Stop only aControllerId:s controller
+
+ {
+ for(int i = 0; i < iControllers.Count(); i++)
+ {
+ if(aControllerId == m3gGetUserID((M3GObject)(iControllers[i].iController)))
+ {
+ iControllers[i].iAnimating = EFalse;
+ TInt currentTime = CHuiStatic::MilliSecondsSinceStart();
+ m3gSetActiveInterval((iControllers[i]).iController, currentTime-2, currentTime-1);
+ }
+ }
+ }
+ }
+ }
+
+EXPORT_C void CHuiM3GMesh::M3GMeshExtension(const TUid& /*aExtensionUid*/, TAny** aExtensionParams)
+ {
+ // If no extension with given UID was found, indicate it by returning null
+ *aExtensionParams = NULL;
+ }
+