/** Initializes AR application components. */privatevoidinitApplicationAR(){// Do application initialization in native code (e.g. registering// callbacks, etc.):initApplicationNative(mScreenWidth,mScreenHeight);// Create OpenGL ES view:intdepthSize=16;intstencilSize=0;booleantranslucent=QCAR.requiresAlpha();mGlView=newQCARSampleGLView(this);mGlView.init(mQCARFlags,translucent,depthSize,stencilSize);mRenderer=newcameraDemoRenderer();mRenderer.mActivity=this;mGlView.setRenderer(mRenderer);LayoutInflaterinflater=LayoutInflater.from(this);mUILayout=(RelativeLayout)inflater.inflate(R.layout.activity_main,null,false);mUILayout.setVisibility(View.VISIBLE);mUILayout.setBackgroundColor(Color.BLACK);// Gets a reference to the loading dialogmLoadingDialogContainer=mUILayout.findViewById(R.id.loading_indicator);// Shows the loading indicator at startloadingDialogHandler.sendEmptyMessage(SHOW_LOADING_DIALOG);// Adds the inflated layout to the viewaddContentView(mUILayout,newLayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));}
JNIEXPORTvoidJNICALLJava_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative(JNIEnv*env,jobjectobj,jintwidth,jintheight){LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative");// Store screen dimensionsscreenWidth=width;screenHeight=height;// Handle to the activity class:jclassactivityClass=env->GetObjectClass(obj);jmethodIDgetTextureCountMethodID=env->GetMethodID(activityClass,"getTextureCount","()I");if(getTextureCountMethodID==0){LOG("Function getTextureCount() not found.");return;}textureCount=env->CallIntMethod(obj,getTextureCountMethodID);if(!textureCount){LOG("getTextureCount() returned zero.");return;}textures=newTexture*[textureCount];jmethodIDgetTextureMethodID=env->GetMethodID(activityClass,"getTexture","(I)Lcom/qualcomm/QCARSamples/ImageTargets/Texture;");if(getTextureMethodID==0){LOG("Function getTexture() not found.");return;}// Register the texturesfor(inti=0;i<textureCount;++i){jobjecttextureObject=env->CallObjectMethod(obj,getTextureMethodID,i);if(textureObject==NULL){LOG("GetTexture() returned zero pointer");return;}textures[i]=Texture::create(env,textureObject);}LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative finished");}
在init完texture之後底下的工作大部份就是在初始化一些視窗元件等等,還有把View加入到addContentView()當中,我想應該可以先跳過了。接著進入updateApplicationStatus(APPSTATUS_LOAD_TRACKER);,在case APPSTATUS_LOAD_TRACKER:當中,主要就是進行mLoadTrackerTask = new LoadTrackerTask(); mLoadTrackerTask.execute();另外開個Task來讀取Tracker,在這邊主要的程式碼為:
/** An async task to load the tracker data asynchronously. */privateclassLoadTrackerTaskextendsAsyncTask<Void,Integer,Boolean>{protectedBooleandoInBackground(Void...params){// Prevent the onDestroy() method to overlap:synchronized(mShutdownLock){// Load the tracker data set:return(loadTrackerData()>0);}}protectedvoidonPostExecute(Booleanresult){DebugLog.LOGD("LoadTrackerTask::onPostExecute: execution "+(result?"successful":"failed"));if(result){// The stones and chips data set is now active:mIsStonesAndChipsDataSetActive=true;// Done loading the tracker, update application status:updateApplicationStatus(APPSTATUS_INITED);}else{// Create dialog box for display error:AlertDialogdialogError=newAlertDialog.Builder(ImageTargets.this).create();dialogError.setButton(DialogInterface.BUTTON_POSITIVE,"Close",newDialogInterface.OnClickListener(){publicvoidonClick(DialogInterfacedialog,intwhich){// Exiting application:System.exit(1);}});// Show dialog box with error message:dialogError.setMessage("Failed to load tracker data.");dialogError.show();}}}
JNIEXPORTintJNICALLJava_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_loadTrackerData(JNIEnv*,jobject){LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_loadTrackerData");// Get the image tracker:QCAR::TrackerManager&trackerManager=QCAR::TrackerManager::getInstance();QCAR::ImageTracker*imageTracker=static_cast<QCAR::ImageTracker*>(trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER));if(imageTracker==NULL){LOG("Failed to load tracking data set because the ImageTracker has not"" been initialized.");return0;}// Create the data sets:dataSetStonesAndChips=imageTracker->createDataSet();if(dataSetStonesAndChips==0){LOG("Failed to create a new tracking data.");return0;}dataSetTarmac=imageTracker->createDataSet();if(dataSetTarmac==0){LOG("Failed to create a new tracking data.");return0;}// Load the data sets:if(!dataSetStonesAndChips->load("StonesAndChips.xml",QCAR::DataSet::STORAGE_APPRESOURCE)){LOG("Failed to load data set.");return0;}if(!dataSetTarmac->load("Tarmac.xml",QCAR::DataSet::STORAGE_APPRESOURCE))//if (!dataSetTarmac->load("FunnyDB.xml", QCAR::DataSet::STORAGE_APPRESOURCE)){LOG("Failed to load data set.");return0;}// Activate the data set:if(!imageTracker->activateDataSet(dataSetStonesAndChips)){LOG("Failed to activate data set.");return0;}LOG("Successfully loaded and activated data set.");return1;}
JNIEXPORTvoidJNICALLJava_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_onQCARInitializedNative(JNIEnv*,jobject){// Register the update callback where we handle the data set swap:QCAR::registerCallback(&updateCallback);// Comment in to enable tracking of up to 2 targets simultaneously and// split the work over multiple frames:// QCAR::setHint(QCAR::HINT_MAX_SIMULTANEOUS_IMAGE_TARGETS, 2);}
結果這邊只是QCAR::registerCallback(&updateCallback);查查一下API,說明寫著void QCAR_API QCAR::registerCallback( UpdateCallback *object )以及 Registers an object to be called when new tracking data is available.然而這邊的updateCallback是一個class…
// Object to receive update callbacks from QCAR SDKclassImageTargets_UpdateCallback:publicQCAR::UpdateCallback{virtualvoidQCAR_onUpdate(QCAR::State&/*state*/){if(switchDataSetAsap){switchDataSetAsap=false;// Get the image tracker:QCAR::TrackerManager&trackerManager=QCAR::TrackerManager::getInstance();QCAR::ImageTracker*imageTracker=static_cast<QCAR::ImageTracker*>(trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER));if(imageTracker==0||dataSetStonesAndChips==0||dataSetTarmac==0||imageTracker->getActiveDataSet()==0){LOG("Failed to switch data set.");return;}if(imageTracker->getActiveDataSet()==dataSetStonesAndChips){imageTracker->deactivateDataSet(dataSetStonesAndChips);imageTracker->activateDataSet(dataSetTarmac);}else{imageTracker->deactivateDataSet(dataSetTarmac);imageTracker->activateDataSet(dataSetStonesAndChips);}}}};
JNIEXPORTvoidJNICALLJava_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_startCamera(JNIEnv*,jobject){LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_startCamera");// Select the camera to open, set this to QCAR::CameraDevice::CAMERA_FRONT // to activate the front camera instead.QCAR::CameraDevice::CAMERAcamera=QCAR::CameraDevice::CAMERA_DEFAULT;// Initialize the camera:if(!QCAR::CameraDevice::getInstance().init(camera))return;// Configure the video backgroundconfigureVideoBackground();// Select the default mode:if(!QCAR::CameraDevice::getInstance().selectVideoMode(QCAR::CameraDevice::MODE_DEFAULT))return;// Start the camera:if(!QCAR::CameraDevice::getInstance().start())return;// Uncomment to enable flash//if(QCAR::CameraDevice::getInstance().setFlashTorchMode(true))// LOG("IMAGE TARGETS : enabled torch");// Uncomment to enable infinity focus mode, or any other supported focus mode// See CameraDevice.h for supported focus modes//if(QCAR::CameraDevice::getInstance().setFocusMode(QCAR::CameraDevice::FOCUS_MODE_INFINITY))// LOG("IMAGE TARGETS : enabled infinity focus");// Start the tracker:QCAR::TrackerManager&trackerManager=QCAR::TrackerManager::getInstance();QCAR::Tracker*imageTracker=trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER);if(imageTracker!=0)imageTracker->start();}
在這裡面也有說明可以參考,那在這段code主要的設定好像只有前面4個,在mEnabled的說明為:Enables/disables rendering of the video background.看樣子是設定要不要Rendering物件?接著就是mSynchronous,說明為Enables/disables synchronization of render and camera frame rate.又有一些補充說明If synchronization is enabled the SDK will attempt to match the rendering frame rate with the camera frame rate. This may result in a performance gain as potentially redundant render calls are avoided. Enabling this is not recommended if your augmented content needs to be animated at a rate higher than the rate at which the camera delivers frames.看樣子應該是rander的物件是不是要和frame rate同步。上面寫說,如果你的物件是個超級animated很會動,可能會很吃資源,建議不要同步。假設你的動畫需要100 fps你去和30 fps的同步應該會爆炸。在這邊因為用的是靜態茶壺,應該不會怎樣才對,除非茶壺需要自體轉動,不過好像也沒差?接著就是mPosition,說明為Relative position of the video background in the render target in pixels. Describes the offset of the center of video background to the center of the screen (viewport) in pixels. A value of (0,0) centers the video background, whereas a value of (-10,15) moves the video background 10 pixels to the left and 15 pixels upwards.看樣子應該就是offset就是通常來說,物件都會Render在Target的中央,那這個offset就是可以偏移一下這樣。那在這邊是不要偏移,所以就都用0.0f了,f沒意外應該是代表float 接著好像就是設定mSize說明為Width and height of the video background in pixels.似乎就是background的寬高,然後是要pixels,底下說明了Using the device's screen size for this parameter scales the image to fullscreen. Notice that if the camera's aspect ratio is different than the screen's aspect ratio this will create a non-uniform stretched image.看樣子應該是要把camera的size能夠和screen size有著相同的比例?應該是,否則就不會去取得VideoMode了,這是VideoMode的API,果然就是取得Camera的,但是它只有三種Mode,老實說,也沒有出現每個MODE的解析度,不知道它是怎樣決定的,反正先知道它的功能就好了。最後終於結束了,這樣就可以動了?寫到這邊我只覺得,似乎可以拉出來變成Template的地方還挺多的,之後再想想要怎樣重寫或是自己寫一個這東西出來才可以比較知道整個從無到有的步驟流程該怎樣寫。
123
MODE_DEFAULT: Default camera mode.
MODE_OPTIMIZE_SPEED: Fast camera mode.
MODE_OPTIMIZE_QUALITY: High-quality camera mode.
voidconfigureVideoBackground(){// Get the default video mode:QCAR::CameraDevice&cameraDevice=QCAR::CameraDevice::getInstance();QCAR::VideoModevideoMode=cameraDevice.getVideoMode(QCAR::CameraDevice::MODE_DEFAULT);// Configure the video backgroundQCAR::VideoBackgroundConfigconfig;config.mEnabled=true;config.mSynchronous=true;config.mPosition.data[0]=0.0f;config.mPosition.data[1]=0.0f;if(isActivityInPortraitMode){//LOG("configureVideoBackground PORTRAIT");config.mSize.data[0]=videoMode.mHeight*(screenHeight/(float)videoMode.mWidth);config.mSize.data[1]=screenHeight;if(config.mSize.data[0]<screenWidth){LOG("Correcting rendering background size to handle missmatch between screen and video aspect ratios.");config.mSize.data[0]=screenWidth;config.mSize.data[1]=screenWidth*(videoMode.mWidth/(float)videoMode.mHeight);}}else{//LOG("configureVideoBackground LANDSCAPE");config.mSize.data[0]=screenWidth;config.mSize.data[1]=videoMode.mHeight*(screenWidth/(float)videoMode.mWidth);if(config.mSize.data[1]<screenHeight){LOG("Correcting rendering background size to handle missmatch between screen and video aspect ratios.");config.mSize.data[0]=screenHeight*(videoMode.mWidth/(float)videoMode.mHeight);config.mSize.data[1]=screenHeight;}}LOG("Configure Video Background : Video (%d,%d), Screen (%d,%d), mSize (%d,%d)",videoMode.mWidth,videoMode.mHeight,screenWidth,screenHeight,config.mSize.data[0],config.mSize.data[1]);// Set the config:QCAR::Renderer::getInstance().setVideoBackgroundConfig(config);}
/** * NOTE: this method is synchronized because of a potential concurrent * access by ImageTargets::onResume() and InitQCARTask::onPostExecute(). */privatesynchronizedvoidupdateApplicationStatus(intappStatus){// Exit if there is no change in status:if(mAppStatus==appStatus)return;// Store new status value:mAppStatus=appStatus;// Execute application state-specific actions:switch(mAppStatus){caseAPPSTATUS_INIT_APP:// Initialize application elements that do not rely on QCAR// initialization:initApplication();// Proceed to next application initialization status:updateApplicationStatus(APPSTATUS_INIT_QCAR);break;caseAPPSTATUS_INIT_QCAR:// Initialize QCAR SDK asynchronously to avoid blocking the// main (UI) thread.//// NOTE: This task instance must be created and invoked on the// UI thread and it can be executed only once!try{mInitQCARTask=newInitQCARTask();mInitQCARTask.execute();}catch(Exceptione){DebugLog.LOGE("cameraDemo","Initializing QCAR SDK failed");}break;caseAPPSTATUS_INIT_TRACKER:// Initialize the ImageTracker:if(initTracker()>0){// Proceed to next application initialization status:updateApplicationStatus(APPSTATUS_INIT_APP_AR);}break;caseAPPSTATUS_INIT_APP_AR:// Initialize Augmented Reality-specific application elements// that may rely on the fact that the QCAR SDK has been// already initialized:initApplicationAR();// Proceed to next application initialization status:updateApplicationStatus(APPSTATUS_LOAD_TRACKER);break;caseAPPSTATUS_LOAD_TRACKER:// Load the tracking data set://// NOTE: This task instance must be created and invoked on the// UI thread and it can be executed only once!try{mLoadTrackerTask=newLoadTrackerTask();mLoadTrackerTask.execute();}catch(Exceptione){DebugLog.LOGE("cameraDemo","Loading tracking data set failed");}break;caseAPPSTATUS_INITED:// Hint to the virtual machine that it would be a good time to// run the garbage collector://// NOTE: This is only a hint. There is no guarantee that the// garbage collector will actually be run.System.gc();// Native post initialization:onQCARInitializedNative();// Activate the renderer:mRenderer.mIsActive=true;// Now add the GL surface view. It is important// that the OpenGL ES surface view gets added// BEFORE the camera is started and video// background is configured.addContentView(mGlView,newLayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));// Sets the UILayout to be drawn in front of the camera// mUILayout.bringToFront();// Start the camera:updateApplicationStatus(APPSTATUS_CAMERA_RUNNING);break;caseAPPSTATUS_CAMERA_STOPPED:// Call the native function to stop the camera:stopCamera();break;caseAPPSTATUS_CAMERA_RUNNING:// Call the native function to start the camera:startCamera();// Hides the Loading Dialog// loadingDialogHandler.sendEmptyMessage(HIDE_LOADING_DIALOG);// Sets the layout background to transparent// mUILayout.setBackgroundColor(Color.TRANSPARENT);// Set continuous auto-focus if supported by the device,// otherwise default back to regular auto-focus mode.// This will be activated by a tap to the screen in this// application.if(!setFocusMode(FOCUS_MODE_CONTINUOUS_AUTO)){mContAutofocus=false;setFocusMode(FOCUS_MODE_NORMAL);}else{mContAutofocus=true;}break;default:thrownewRuntimeException("Invalid application state");}}