diff --git a/area-description-jni-example/app/src/main/AndroidManifest.xml b/area-description-jni-example/app/src/main/AndroidManifest.xml index 55193849..963479f4 100644 --- a/area-description-jni-example/app/src/main/AndroidManifest.xml +++ b/area-description-jni-example/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); - env->DeleteGlobalRef(calling_activity_obj_); } int AreaLearningApp::TangoInitialize(JNIEnv* env, jobject caller_activity) { @@ -91,6 +89,14 @@ int AreaLearningApp::TangoInitialize(JNIEnv* env, jobject caller_activity) { return ret; } +void AreaLearningApp::ActivityDestroyed() { + JNIEnv* env; + java_vm_->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); + env->DeleteGlobalRef(calling_activity_obj_); + calling_activity_obj_ = nullptr; + on_saving_adf_progress_updated_ = nullptr; +} + int AreaLearningApp::TangoSetupConfig(bool is_area_learning_enabled, bool is_loading_adf) { // Here, we'll configure the service to run in the way we'd want. For this @@ -291,9 +297,9 @@ void AreaLearningApp::Render() { main_scene_.Render(cur_pose, pose_data_.IsRelocalized()); } -void AreaLearningApp::FreeContent() { +void AreaLearningApp::DeleteResources() { + main_scene_.DeleteResources(); pose_data_.ResetPoseData(); - main_scene_.FreeGLContent(); } bool AreaLearningApp::IsRelocalized() { @@ -376,6 +382,12 @@ std::string AreaLearningApp::GetTangoServiceVersion() { void AreaLearningApp::OnAdfSavingProgressChanged(int progress) { // Here, we notify the Java activity that we'd like it to update the saving // Adf progress. + if (calling_activity_obj_ == nullptr || + on_saving_adf_progress_updated_ == nullptr) { + LOGE("AreaLearningApp: Cannot reference activity on ADF saving progress changed."); + return; + } + JNIEnv* env; java_vm_->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); env->CallVoidMethod(calling_activity_obj_, on_saving_adf_progress_updated_, diff --git a/area-description-jni-example/app/src/main/jni/jni_interface.cc b/area-description-jni-example/app/src/main/jni/jni_interface.cc index 35a05c3d..95810fbc 100644 --- a/area-description-jni-example/app/src/main/jni/jni_interface.cc +++ b/area-description-jni-example/app/src/main/jni/jni_interface.cc @@ -38,6 +38,12 @@ Java_com_projecttango_experiments_nativearealearning_TangoJNINative_initialize( return app.TangoInitialize(env, activity); } +JNIEXPORT void JNICALL +Java_com_projecttango_experiments_nativearealearning_TangoJNINative_destroyActivity( + JNIEnv*, jobject) { + app.ActivityDestroyed(); +} + JNIEXPORT jint JNICALL Java_com_projecttango_experiments_nativearealearning_TangoJNINative_setupConfig( JNIEnv*, jobject, bool is_area_learningEnabled, bool is_loading_adf) { @@ -88,9 +94,9 @@ Java_com_projecttango_experiments_nativearealearning_TangoJNINative_render( } JNIEXPORT void JNICALL -Java_com_projecttango_experiments_nativearealearning_TangoJNINative_freeContent( +Java_com_projecttango_experiments_nativearealearning_TangoJNINative_deleteResources( JNIEnv*, jobject) { - app.FreeContent(); + app.DeleteResources(); } JNIEXPORT jboolean JNICALL diff --git a/area-description-jni-example/app/src/main/jni/scene.cc b/area-description-jni-example/app/src/main/jni/scene.cc index a50e1d8d..f5fe07cd 100644 --- a/area-description-jni-example/app/src/main/jni/scene.cc +++ b/area-description-jni-example/app/src/main/jni/scene.cc @@ -66,7 +66,7 @@ void Scene::InitGLContent() { tango_gl::GestureCamera::CameraType::kThirdPerson); } -void Scene::FreeGLContent() { +void Scene::DeleteResources() { delete gesture_camera_; delete axis_; delete frustum_; diff --git a/area-description-jni-example/app/src/main/jni/tango-area-learning/area_learning_app.h b/area-description-jni-example/app/src/main/jni/tango-area-learning/area_learning_app.h index f5d2e15b..c485fda4 100644 --- a/area-description-jni-example/app/src/main/jni/tango-area-learning/area_learning_app.h +++ b/area-description-jni-example/app/src/main/jni/tango-area-learning/area_learning_app.h @@ -42,6 +42,11 @@ class AreaLearningApp { // The activity object is used for checking if the API version is outdated. int TangoInitialize(JNIEnv* env, jobject caller_activity); + // When the Android activity is destroyed, signal the JNI layer to remove + // references to the activity. This should be called from the onDestroy() + // callback of the parent activity lifecycle. + void ActivityDestroyed(); + // Setup the configuration file for the Tango Service. We'll also se whether // we'd like auto-recover enabled. // @@ -119,8 +124,8 @@ class AreaLearningApp { // Main render loop. void Render(); - // Release/reset all resources that allocate from the program. - void FreeContent(); + // Reset pose data and release resources that allocate from the program. + void DeleteResources(); // Return true if Tango has relocalized to the current ADF at least once. bool IsRelocalized(); diff --git a/area-description-jni-example/app/src/main/jni/tango-area-learning/scene.h b/area-description-jni-example/app/src/main/jni/tango-area-learning/scene.h index dc5a754e..96c6e654 100644 --- a/area-description-jni-example/app/src/main/jni/tango-area-learning/scene.h +++ b/area-description-jni-example/app/src/main/jni/tango-area-learning/scene.h @@ -48,8 +48,8 @@ class Scene { // Allocate OpenGL resources for rendering. void InitGLContent(); - // Release OpenGL resources allocated. - void FreeGLContent(); + // Release non-GL resources. + void DeleteResources(); // Setup GL view port. void SetupViewPort(int w, int h); diff --git a/augmented-reality-jni-example/app/src/main/AndroidManifest.xml b/augmented-reality-jni-example/app/src/main/AndroidManifest.xml index 48890782..dfd12a28 100644 --- a/augmented-reality-jni-example/app/src/main/AndroidManifest.xml +++ b/augmented-reality-jni-example/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ android:minSdkVersion="19" android:targetSdkVersion="19" /> + diff --git a/augmented-reality-jni-example/app/src/main/java/com/projecttango/experiments/nativeaugmentedreality/AugmentedRealityActivity.java b/augmented-reality-jni-example/app/src/main/java/com/projecttango/experiments/nativeaugmentedreality/AugmentedRealityActivity.java index d6eea205..06ddd980 100644 --- a/augmented-reality-jni-example/app/src/main/java/com/projecttango/experiments/nativeaugmentedreality/AugmentedRealityActivity.java +++ b/augmented-reality-jni-example/app/src/main/java/com/projecttango/experiments/nativeaugmentedreality/AugmentedRealityActivity.java @@ -135,6 +135,9 @@ protected void onCreate(Bundle savedInstanceState) { // OpenGL view where all of the graphics are drawn mGLView = (GLSurfaceView) findViewById(R.id.gl_surface_view); + + // Configure OpenGL renderer + mGLView.setEGLContextClientVersion(2); // Set up button click listeners mMotionReset.setOnClickListener(this); @@ -165,7 +168,7 @@ protected void onCreate(Bundle savedInstanceState) { protected void onResume() { super.onResume(); mGLView.onResume(); - + // Setup the configuration for the TangoService. TangoJNINative.setupConfig(); @@ -191,7 +194,7 @@ protected void onResume() { protected void onPause() { super.onPause(); mGLView.onPause(); - TangoJNINative.freeGLContent(); + TangoJNINative.deleteResources(); // Disconnect from Tango Service, release all the resources that the app is // holding from Tango Service. diff --git a/augmented-reality-jni-example/app/src/main/java/com/projecttango/experiments/nativeaugmentedreality/TangoJNINative.java b/augmented-reality-jni-example/app/src/main/java/com/projecttango/experiments/nativeaugmentedreality/TangoJNINative.java index 420ea831..471f0cee 100644 --- a/augmented-reality-jni-example/app/src/main/java/com/projecttango/experiments/nativeaugmentedreality/TangoJNINative.java +++ b/augmented-reality-jni-example/app/src/main/java/com/projecttango/experiments/nativeaugmentedreality/TangoJNINative.java @@ -46,8 +46,8 @@ public class TangoJNINative { // holding from the Tango Service. public static native void disconnect(); - // Release all OpenGL resources that are allocated from the program. - public static native void freeGLContent(); + // Delete non-GL data structures that are allocated from the program. + public static native void deleteResources(); // Allocate OpenGL resources for rendering. public static native void initGlContent(); diff --git a/augmented-reality-jni-example/app/src/main/jni/augmented_reality_app.cc b/augmented-reality-jni-example/app/src/main/jni/augmented_reality_app.cc index 381d3364..5d214740 100644 --- a/augmented-reality-jni-example/app/src/main/jni/augmented_reality_app.cc +++ b/augmented-reality-jni-example/app/src/main/jni/augmented_reality_app.cc @@ -295,14 +295,14 @@ void AugmentedRealityApp::Render() { pose_data_.GetExtrinsicsAppliedOpenGLWorldFrame(color_camera_pose); if (status != TANGO_SUCCESS) { LOGE( - "AugmentedRealityApp: Failed to update video overlay texture with" + "AugmentedRealityApp: Failed to update video overlay texture with " "error code: %d", status); } main_scene_.Render(color_camera_pose); } -void AugmentedRealityApp::FreeGLContent() { main_scene_.FreeGLContent(); } +void AugmentedRealityApp::DeleteResources() { main_scene_.DeleteResources(); } std::string AugmentedRealityApp::GetPoseString() { std::lock_guard lock(pose_mutex_); diff --git a/augmented-reality-jni-example/app/src/main/jni/jni_interface.cc b/augmented-reality-jni-example/app/src/main/jni/jni_interface.cc index 68ede864..606b9382 100644 --- a/augmented-reality-jni-example/app/src/main/jni/jni_interface.cc +++ b/augmented-reality-jni-example/app/src/main/jni/jni_interface.cc @@ -93,9 +93,9 @@ Java_com_projecttango_experiments_nativeaugmentedreality_TangoJNINative_render( } JNIEXPORT void JNICALL -Java_com_projecttango_experiments_nativeaugmentedreality_TangoJNINative_freeGLContent( +Java_com_projecttango_experiments_nativeaugmentedreality_TangoJNINative_deleteResources( JNIEnv*, jobject) { - app.FreeGLContent(); + app.DeleteResources(); } JNIEXPORT jstring JNICALL diff --git a/augmented-reality-jni-example/app/src/main/jni/scene.cc b/augmented-reality-jni-example/app/src/main/jni/scene.cc index 332b3777..f9f345b0 100644 --- a/augmented-reality-jni-example/app/src/main/jni/scene.cc +++ b/augmented-reality-jni-example/app/src/main/jni/scene.cc @@ -73,9 +73,9 @@ void Scene::InitGLContent() { tango_gl::GestureCamera::CameraType::kThirdPerson); } -void Scene::FreeGLContent() { - delete video_overlay_; +void Scene::DeleteResources() { delete gesture_camera_; + delete video_overlay_; delete axis_; delete frustum_; delete trace_; diff --git a/augmented-reality-jni-example/app/src/main/jni/tango-augmented-reality/augmented_reality_app.h b/augmented-reality-jni-example/app/src/main/jni/tango-augmented-reality/augmented_reality_app.h index ca648150..f88484ba 100644 --- a/augmented-reality-jni-example/app/src/main/jni/tango-augmented-reality/augmented_reality_app.h +++ b/augmented-reality-jni-example/app/src/main/jni/tango-augmented-reality/augmented_reality_app.h @@ -89,8 +89,8 @@ class AugmentedRealityApp { // Main render loop. void Render(); - // Release all OpenGL resources that allocate from the program. - void FreeGLContent(); + // Release all non-OpenGL resources that allocate from the program. + void DeleteResources(); // Retrun pose debug string. std::string GetPoseString(); diff --git a/augmented-reality-jni-example/app/src/main/jni/tango-augmented-reality/scene.h b/augmented-reality-jni-example/app/src/main/jni/tango-augmented-reality/scene.h index c696b660..5757f4d5 100644 --- a/augmented-reality-jni-example/app/src/main/jni/tango-augmented-reality/scene.h +++ b/augmented-reality-jni-example/app/src/main/jni/tango-augmented-reality/scene.h @@ -50,8 +50,8 @@ class Scene { // Allocate OpenGL resources for rendering. void InitGLContent(); - // Release OpenGL resources allocated. - void FreeGLContent(); + // Release non-OpenGL resources. + void DeleteResources(); // Setup GL view port. // @param: x, left of the screen. diff --git a/hello-tango-jni-example/app/src/main/AndroidManifest.xml b/hello-tango-jni-example/app/src/main/AndroidManifest.xml index 5382a02a..415b19ac 100644 --- a/hello-tango-jni-example/app/src/main/AndroidManifest.xml +++ b/hello-tango-jni-example/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + + + lock(pose_mutex_); diff --git a/motion-tracking-jni-example/app/src/main/jni/scene.cc b/motion-tracking-jni-example/app/src/main/jni/scene.cc index c9de3ee2..f9c6d985 100644 --- a/motion-tracking-jni-example/app/src/main/jni/scene.cc +++ b/motion-tracking-jni-example/app/src/main/jni/scene.cc @@ -61,7 +61,7 @@ void Scene::InitGLContent() { tango_gl::GestureCamera::CameraType::kThirdPerson); } -void Scene::FreeGLContent() { +void Scene::DeleteResources() { delete gesture_camera_; delete axis_; delete frustum_; diff --git a/motion-tracking-jni-example/app/src/main/jni/tango-motion-tracking/motion_tracking_app.h b/motion-tracking-jni-example/app/src/main/jni/tango-motion-tracking/motion_tracking_app.h index c5832533..7cf4bab5 100644 --- a/motion-tracking-jni-example/app/src/main/jni/tango-motion-tracking/motion_tracking_app.h +++ b/motion-tracking-jni-example/app/src/main/jni/tango-motion-tracking/motion_tracking_app.h @@ -85,8 +85,8 @@ class MotiongTrackingApp { // Main render loop. void Render(); - // Release all OpenGL resources that allocate from the program. - void FreeGLContent(); + // Release all resources that allocate from the program. + void DeleteResources(); // Retrun pose debug string. std::string GetPoseString(); diff --git a/motion-tracking-jni-example/app/src/main/jni/tango-motion-tracking/scene.h b/motion-tracking-jni-example/app/src/main/jni/tango-motion-tracking/scene.h index 1d1a78ee..30cf18dd 100644 --- a/motion-tracking-jni-example/app/src/main/jni/tango-motion-tracking/scene.h +++ b/motion-tracking-jni-example/app/src/main/jni/tango-motion-tracking/scene.h @@ -49,7 +49,7 @@ class Scene { void InitGLContent(); // Release OpenGL resources allocated. - void FreeGLContent(); + void DeleteResources(); // Setup GL view port. void SetupViewPort(int w, int h); diff --git a/plane-fitting-jni-example/app/src/main/java/com/projecttango/experiments/nativeplanefitting/JNIInterface.java b/plane-fitting-jni-example/app/src/main/java/com/projecttango/experiments/nativeplanefitting/JNIInterface.java index 5836375d..33b250bc 100644 --- a/plane-fitting-jni-example/app/src/main/java/com/projecttango/experiments/nativeplanefitting/JNIInterface.java +++ b/plane-fitting-jni-example/app/src/main/java/com/projecttango/experiments/nativeplanefitting/JNIInterface.java @@ -42,8 +42,8 @@ public class JNIInterface { // camera texture. public static native int initializeGLContent(); - // Release all the OpenGL resources that are allocated. - public static native void freeGLContent(); + // Release resources that are allocated. + public static native void deleteResources(); // Display debug colors on point cloud. public static native void setRenderDebugPointCloud(boolean debugRender); diff --git a/plane-fitting-jni-example/app/src/main/java/com/projecttango/experiments/nativeplanefitting/MainActivity.java b/plane-fitting-jni-example/app/src/main/java/com/projecttango/experiments/nativeplanefitting/MainActivity.java index 692becda..bdd18534 100644 --- a/plane-fitting-jni-example/app/src/main/java/com/projecttango/experiments/nativeplanefitting/MainActivity.java +++ b/plane-fitting-jni-example/app/src/main/java/com/projecttango/experiments/nativeplanefitting/MainActivity.java @@ -63,7 +63,7 @@ public class MainActivity extends Activity { // program attempting to disconnect from the service while it is not // connected.This is especially important in the onPause() callback for the // activity class. - private boolean mIsConnectedService = false; + private boolean mIsServiceConnected = false; // GLSurfaceView and renderer, all of the graphic content is rendered // through OpenGL ES 2.0 in native code. @@ -200,9 +200,10 @@ protected void onResume() { // Setup the configuration of the Tango Service. int ret = JNIInterface.tangoSetupAndConnect(); + mIsServiceConnected = true; if (ret != TANGO_SUCCESS) { - mIsConnectedService = true; + mIsServiceConnected = false; Log.e(TAG, "Failed to set config and connect with code: " + ret); finish(); } @@ -212,13 +213,13 @@ protected void onResume() { protected void onPause() { super.onPause(); mGLView.onPause(); - JNIInterface.freeGLContent(); + JNIInterface.deleteResources(); // Disconnect from the Tango Service, release all the resources that // the app is holding from the Tango Service. - if (mIsConnectedService) { + if (mIsServiceConnected) { JNIInterface.tangoDisconnect(); - mIsConnectedService = false; + mIsServiceConnected = false; } } diff --git a/plane-fitting-jni-example/app/src/main/jni/Android.mk b/plane-fitting-jni-example/app/src/main/jni/Android.mk index 0ee8c279..b135cf98 100644 --- a/plane-fitting-jni-example/app/src/main/jni/Android.mk +++ b/plane-fitting-jni-example/app/src/main/jni/Android.mk @@ -25,7 +25,7 @@ LOCAL_C_INCLUDES := $(PROJECT_ROOT)/tango-gl/include \ LOCAL_SRC_FILES := jni_interface.cc \ plane_fitting.cc \ plane_fitting_application.cc \ - point_cloud.cc \ + point_cloud_renderer.cc \ $(PROJECT_ROOT_FROM_JNI)/tango-gl/bounding_box.cpp \ $(PROJECT_ROOT_FROM_JNI)/tango-gl/camera.cpp \ $(PROJECT_ROOT_FROM_JNI)/tango-gl/conversions.cpp \ diff --git a/plane-fitting-jni-example/app/src/main/jni/jni_interface.cc b/plane-fitting-jni-example/app/src/main/jni/jni_interface.cc index 7c8264d3..a25a8143 100644 --- a/plane-fitting-jni-example/app/src/main/jni/jni_interface.cc +++ b/plane-fitting-jni-example/app/src/main/jni/jni_interface.cc @@ -67,9 +67,9 @@ Java_com_projecttango_experiments_nativeplanefitting_JNIInterface_render( } JNIEXPORT void JNICALL -Java_com_projecttango_experiments_nativeplanefitting_JNIInterface_freeGLContent( +Java_com_projecttango_experiments_nativeplanefitting_JNIInterface_deleteResources( JNIEnv* /*env*/, jobject /*obj*/) { - app.FreeGLContent(); + app.DeleteResources(); } JNIEXPORT void JNICALL diff --git a/plane-fitting-jni-example/app/src/main/jni/plane_fitting_application.cc b/plane-fitting-jni-example/app/src/main/jni/plane_fitting_application.cc index 9be2c167..ae14b198 100644 --- a/plane-fitting-jni-example/app/src/main/jni/plane_fitting_application.cc +++ b/plane-fitting-jni-example/app/src/main/jni/plane_fitting_application.cc @@ -47,7 +47,7 @@ void OnXYZijAvailableRouter(void* context, const TangoXYZij* xyz_ij) { } // end namespace void PlaneFittingApplication::OnXYZijAvailable(const TangoXYZij* xyz_ij) { - point_cloud_->UpdateVertices(xyz_ij); + TangoSupport_updatePointCloud(point_cloud_manager_, xyz_ij); } PlaneFittingApplication::PlaneFittingApplication() @@ -60,6 +60,8 @@ PlaneFittingApplication::PlaneFittingApplication() PlaneFittingApplication::~PlaneFittingApplication() { TangoConfig_free(tango_config_); + TangoSupport_freePointCloudManager(point_cloud_manager_); + point_cloud_manager_ = nullptr; } int PlaneFittingApplication::TangoInitialize(JNIEnv* env, @@ -68,7 +70,7 @@ int PlaneFittingApplication::TangoInitialize(JNIEnv* env, // initialize the service. We will do that here, passing on the JNI // environment and jobject corresponding to the Android activity that is // calling us. - const int ret = TangoService_initialize(env, caller_activity); + int ret = TangoService_initialize(env, caller_activity); if(ret != TANGO_SUCCESS) { return ret; } @@ -78,6 +80,23 @@ int PlaneFittingApplication::TangoInitialize(JNIEnv* env, LOGE("Unable to get tango config"); return TANGO_ERROR; } + + if (point_cloud_manager_ == nullptr) { + int32_t max_point_cloud_elements; + ret = TangoConfig_getInt32(tango_config_, "max_point_cloud_elements", + &max_point_cloud_elements); + if(ret != TANGO_SUCCESS) { + LOGE("Failed to query maximum number of point cloud elements."); + return ret; + } + + ret = TangoSupport_createPointCloudManager(max_point_cloud_elements, + &point_cloud_manager_); + if(ret != TANGO_SUCCESS) { + return ret; + } + } + return TANGO_SUCCESS; } @@ -220,16 +239,8 @@ void PlaneFittingApplication::TangoDisconnect() { } int PlaneFittingApplication::InitializeGLContent() { - int32_t max_point_cloud_elements; - const int ret = TangoConfig_getInt32(tango_config_, "max_point_cloud_elements", - &max_point_cloud_elements); - if(ret != TANGO_SUCCESS) { - LOGE("Failed to query maximum number of point cloud elements."); - return ret; - } - video_overlay_ = new tango_gl::VideoOverlay(); - point_cloud_ = new PointCloud(max_point_cloud_elements); + point_cloud_renderer_ = new PointCloudRenderer(); cube_ = new tango_gl::Cube(); cube_->SetScale(glm::vec3(kCubeScale, kCubeScale, kCubeScale)); cube_->SetColor(0.7f, 0.7f, 0.7f); @@ -244,7 +255,7 @@ int PlaneFittingApplication::InitializeGLContent() { } void PlaneFittingApplication::SetRenderDebugPointCloud(bool on) { - point_cloud_->SetRenderDebugColors(on); + point_cloud_renderer_->SetRenderDebugColors(on); } void PlaneFittingApplication::SetViewPort(int width, int height) { @@ -309,8 +320,12 @@ void PlaneFittingApplication::GLRender( glEnable(GL_BLEND); video_overlay_->Render(glm::mat4(1.0), glm::mat4(1.0)); glEnable(GL_DEPTH_TEST); - point_cloud_->Render(projection_matrix_ar_, opengl_camera_T_ss, - device_T_depth_); + UpdateCurrentPointData(); + const glm::mat4 start_service_T_device_t1 = GetStartServiceTDeviceTransform(); + const glm::mat4 projection_T_depth = projection_matrix_ar_ * opengl_camera_T_ss * + start_service_T_device_t1 * device_T_depth_; + const glm::mat4 start_service_T_depth = start_service_T_device_t1 * device_T_depth_; + point_cloud_renderer_->Render(projection_T_depth, start_service_T_depth, front_cloud_); glDisable(GL_BLEND); glm::mat4 opengl_camera_T_opengl_world = @@ -319,33 +334,22 @@ void PlaneFittingApplication::GLRender( cube_->Render(projection_matrix_ar_, opengl_camera_T_opengl_world); } -void PlaneFittingApplication::FreeGLContent() { +void PlaneFittingApplication::DeleteResources() { delete video_overlay_; - delete point_cloud_; delete cube_; video_overlay_ = nullptr; - point_cloud_ = nullptr; cube_ = nullptr; } // We assume the Java layer ensures this function is called on the GL thread. void PlaneFittingApplication::OnTouchEvent(float x, float y) { - // Get the current point cloud data and transform. This assumes the data has - // been recently updated on the render thread and does not attempt to update - // again here. - const TangoXYZij* current_cloud = point_cloud_->GetCurrentPointData(); - // This transform relates the point cloud at acquisition time (t0) to the - // start of service. - const glm::mat4 start_service_T_device_t0 = - point_cloud_->GetPointCloudStartServiceTDeviceTransform(); - /// Calculate the conversion from the latest depth camera position to the /// position of the most recent color camera image. This corrects for screen /// lag between the two systems. TangoPoseData pose_color_camera_t0_T_depth_camera_t1; int ret = TangoSupport_calculateRelativePose( last_gpu_timestamp_, TANGO_COORDINATE_FRAME_CAMERA_COLOR, - current_cloud->timestamp, TANGO_COORDINATE_FRAME_CAMERA_DEPTH, + front_cloud_->timestamp, TANGO_COORDINATE_FRAME_CAMERA_DEPTH, &pose_color_camera_t0_T_depth_camera_t1); if (ret != TANGO_SUCCESS) { LOGE("%s: could not calculate relative pose", __func__); @@ -356,7 +360,7 @@ void PlaneFittingApplication::OnTouchEvent(float x, float y) { glm::dvec3 double_depth_position; glm::dvec4 double_depth_plane_equation; if (TangoSupport_fitPlaneModelNearClick( - current_cloud, &color_camera_intrinsics_, + front_cloud_, &color_camera_intrinsics_, &pose_color_camera_t0_T_depth_camera_t1, glm::value_ptr(uv), glm::value_ptr(double_depth_position), glm::value_ptr(double_depth_plane_equation)) != TANGO_SUCCESS) { @@ -369,7 +373,7 @@ void PlaneFittingApplication::OnTouchEvent(float x, float y) { static_cast(double_depth_plane_equation); const glm::mat4 opengl_world_T_depth = opengl_world_T_start_service_ * - start_service_T_device_t0 * + GetStartServiceTDeviceTransform() * device_T_depth_; // Transform to world coordinates @@ -380,7 +384,7 @@ void PlaneFittingApplication::OnTouchEvent(float x, float y) { PlaneTransform(depth_plane_equation, opengl_world_T_depth, &world_plane_equation); - point_cloud_->SetPlaneEquation(world_plane_equation); + point_cloud_renderer_->SetPlaneEquation(world_plane_equation); const glm::vec3 plane_normal(world_plane_equation); @@ -406,4 +410,23 @@ void PlaneFittingApplication::OnTouchEvent(float x, float y) { cube_->SetPosition(glm::vec3(world_position) + plane_normal * kCubeScale); } +glm::mat4 PlaneFittingApplication::GetStartServiceTDeviceTransform() { + TangoCoordinateFramePair frame_pair; + frame_pair.base = TANGO_COORDINATE_FRAME_START_OF_SERVICE; + frame_pair.target = TANGO_COORDINATE_FRAME_DEVICE; + TangoPoseData pose_start_service_T_device_t1; + + TangoService_getPoseAtTime(front_cloud_->timestamp, frame_pair, + &pose_start_service_T_device_t1); + + return tango_gl::conversions::TransformFromArrays( + pose_start_service_T_device_t1.translation, + pose_start_service_T_device_t1.orientation); +} + +void PlaneFittingApplication::UpdateCurrentPointData() { + TangoSupport_getLatestPointCloud(point_cloud_manager_, + &front_cloud_); +} + } // namespace tango_plane_fitting diff --git a/plane-fitting-jni-example/app/src/main/jni/point_cloud.cc b/plane-fitting-jni-example/app/src/main/jni/point_cloud_renderer.cc similarity index 61% rename from plane-fitting-jni-example/app/src/main/jni/point_cloud.cc rename to plane-fitting-jni-example/app/src/main/jni/point_cloud_renderer.cc index 16194ade..e36be8cb 100644 --- a/plane-fitting-jni-example/app/src/main/jni/point_cloud.cc +++ b/plane-fitting-jni-example/app/src/main/jni/point_cloud_renderer.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "tango-plane-fitting/point_cloud.h" +#include "tango-plane-fitting/point_cloud_renderer.h" #include #include @@ -55,12 +55,10 @@ const std::string kPointCloudFragmentShader = } // namespace -PointCloud::PointCloud(int32_t max_point_cloud_size) +PointCloudRenderer::PointCloudRenderer() : plane_distance_(0.05f), debug_colors_(false), plane_model_(glm::vec4(0.0, 0.0, 1.0, 0.0)) { - TangoSupport_createPointCloudManager(max_point_cloud_size, - &point_cloud_manager_); opengl_world_T_start_service_ = tango_gl::conversions::opengl_world_T_tango_world(); @@ -75,26 +73,17 @@ PointCloud::PointCloud(int32_t max_point_cloud_size) plane_distance_handle_ = glGetUniformLocation(shader_program_, "plane_distance"); - tango_gl::util::CheckGlError("Pointcloud::Construction"); + tango_gl::util::CheckGlError("PointCloudRenderer::Construction"); } -PointCloud::~PointCloud() { +PointCloudRenderer::~PointCloudRenderer() { glDeleteProgram(shader_program_); glDeleteBuffers(0, &vertex_buffer_); - TangoSupport_freePointCloudManager(point_cloud_manager_); } -void PointCloud::UpdateVertices(const TangoXYZij* cloud) { - TangoSupport_updatePointCloud(point_cloud_manager_, cloud); -} - -void PointCloud::Render(const glm::mat4& projection, - const glm::mat4& opengl_camera_T_start_service, - const glm::mat4& device_T_depth) { - // Update point data. - if(TangoSupport_getLatestPointCloud(point_cloud_manager_, &front_cloud_) == TANGO_INVALID) { - return; - } +void PointCloudRenderer::Render(const glm::mat4& projection_T_depth, + const glm::mat4&start_service_T_depth, + const TangoXYZij* point_cloud) { if (!debug_colors_) { return; @@ -102,26 +91,20 @@ void PointCloud::Render(const glm::mat4& projection, glUseProgram(shader_program_); - const size_t number_of_vertices = front_cloud_->xyz_count; + const size_t number_of_vertices = point_cloud->xyz_count; glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * number_of_vertices, - front_cloud_->xyz[0], GL_STATIC_DRAW); - - const glm::mat4 start_service_T_device_t1 = this->GetPointCloudStartServiceTDeviceTransform(); - - const glm::mat4 mvp_mat = projection * opengl_camera_T_start_service * - start_service_T_device_t1 * device_T_depth; + point_cloud->xyz[0], GL_STATIC_DRAW); const glm::mat4 depth_T_opengl = - glm::inverse(opengl_world_T_start_service_ * start_service_T_device_t1 * - device_T_depth); + glm::inverse(opengl_world_T_start_service_ * start_service_T_depth); // Transform plane into depth camera coordinates. glm::vec4 camera_plane; PlaneTransform(plane_model_, depth_T_opengl, &camera_plane); - glUniformMatrix4fv(mvp_handle_, 1, GL_FALSE, glm::value_ptr(mvp_mat)); + glUniformMatrix4fv(mvp_handle_, 1, GL_FALSE, glm::value_ptr(projection_T_depth)); glUniform4fv(plane_handle_, 1, glm::value_ptr(camera_plane)); @@ -139,30 +122,7 @@ void PointCloud::Render(const glm::mat4& projection, glBindBuffer(GL_ARRAY_BUFFER, 0); glUseProgram(0); - tango_gl::util::CheckGlError("Pointcloud::Render"); -} - -const glm::mat4 PointCloud::GetPointCloudStartServiceTDeviceTransform() { - TangoCoordinateFramePair frame_pair; - frame_pair.base = TANGO_COORDINATE_FRAME_START_OF_SERVICE; - frame_pair.target = TANGO_COORDINATE_FRAME_DEVICE; - TangoPoseData pose_start_service_T_device_t1; - - TangoService_getPoseAtTime(front_cloud_->timestamp, frame_pair, - &pose_start_service_T_device_t1); - - const glm::mat4 start_service_T_device = - tango_gl::conversions::TransformFromArrays( - pose_start_service_T_device_t1.translation, - pose_start_service_T_device_t1.orientation); - - return start_service_T_device; -} - -const TangoXYZij* PointCloud::GetCurrentPointData() { - TangoSupport_getLatestPointCloud(point_cloud_manager_, - &front_cloud_); - return front_cloud_; + tango_gl::util::CheckGlError("PointCloudRenderer::Render"); } } // namespace tango_plane_fitting diff --git a/plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/plane_fitting_application.h b/plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/plane_fitting_application.h index 66eae02c..5c1cd44e 100644 --- a/plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/plane_fitting_application.h +++ b/plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/plane_fitting_application.h @@ -24,7 +24,7 @@ #include #include -#include "tango-plane-fitting/point_cloud.h" +#include "tango-plane-fitting/point_cloud_renderer.h" namespace tango_plane_fitting { @@ -61,8 +61,8 @@ class PlaneFittingApplication { // Get current camera position and render. void Render(); - // Free the GL context when the context is deleted. - void FreeGLContent(); + // Delete the allocate resources. + void DeleteResources(); // // Callback for point clouds that come in from the Tango service. @@ -83,12 +83,19 @@ class PlaneFittingApplication { // Details of rendering to OpenGL after determining transforms. void GLRender(const glm::mat4& w_T_cc); + // Update the current point data. + void UpdateCurrentPointData(); + + // return pose for device position with respect to + // start of service. + glm::mat4 GetStartServiceTDeviceTransform(); + TangoConfig tango_config_; TangoCameraIntrinsics color_camera_intrinsics_; // Render objects tango_gl::VideoOverlay* video_overlay_; - PointCloud* point_cloud_; + PointCloudRenderer* point_cloud_renderer_; tango_gl::Cube* cube_; // The dimensions of the render window. @@ -110,6 +117,10 @@ class PlaneFittingApplication { glm::mat4 color_camera_T_opengl_camera_; // OpenGL projection matrix. glm::mat4 projection_matrix_ar_; + + // Point data manager. + TangoSupportPointCloudManager* point_cloud_manager_; + TangoXYZij* front_cloud_; }; } // namespace tango_plane_fitting diff --git a/plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/point_cloud.h b/plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/point_cloud_renderer.h similarity index 61% rename from plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/point_cloud.h rename to plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/point_cloud_renderer.h index 9e9ff805..db783309 100644 --- a/plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/point_cloud.h +++ b/plane-fitting-jni-example/app/src/main/jni/tango-plane-fitting/point_cloud_renderer.h @@ -27,28 +27,23 @@ namespace tango_plane_fitting { -// PointCloud contains the logic to maintain an updated, renderable depth -// buffer. -class PointCloud { +// PointCloudRenderer contains the OpenGL logic to render depth data. +class PointCloudRenderer { public: - PointCloud(int32_t max_point_cloud_size); - ~PointCloud(); - - // Update the point cloud data with the latest results from the - // callback. This is intended to be called from the callback thread. - void UpdateVertices(const TangoXYZij* cloud); + PointCloudRenderer(); + ~PointCloudRenderer(); // Render the point cloud colored by its location relative to the // world plane model. // - // @param projection The OpenGL projection matrix. - // @param opengl_camera_T_start_service The pose of the OpenGL camera with - // respect to start of service. - // @param device_T_depth Fixed extrinsics of pose of depth camera - // with respect to device (not time-varying). - void Render(const glm::mat4& projection, - const glm::mat4& opengl_camera_T_start_service, - const glm::mat4& device_T_depth); + // @param projection_T_depth The pose of the openGL projection with + // respect to the depth camera position. + // @param start_service_T_depth The pose of the start of service with + // respect to depth camera position. + // @param point_cloud Depth data gathered by a PointCloudManager. + void Render(const glm::mat4& projection_T_depth, + const glm::mat4& start_service_T_depth, + const TangoXYZij* point_cloud); // Render depth points with debugging colors. void SetRenderDebugColors(bool on) { debug_colors_ = on; } @@ -56,15 +51,7 @@ class PointCloud { // A plane equation in world coordinates for debug rendering. void SetPlaneEquation(const glm::vec4& plane) { plane_model_ = plane; } - // Get a reference to the current point data. - const TangoXYZij* GetCurrentPointData(); - - // Get a copy of the current point cloud transform of device with respect to - // start of service. - const glm::mat4 GetPointCloudStartServiceTDeviceTransform(); - private: - bool UpdateRenderPoints(); GLuint shader_program_; GLuint vertex_buffer_; GLuint mvp_handle_; @@ -84,10 +71,6 @@ class PointCloud { // Cached transform from opengl world to tango world. // This is initialized and never updated. glm::mat4 opengl_world_T_start_service_; - - // Point data manager. - TangoSupportPointCloudManager* point_cloud_manager_; - TangoXYZij* front_cloud_; }; } // namespace tango_plane_fitting diff --git a/point-cloud-jni-example/app/src/main/AndroidManifest.xml b/point-cloud-jni-example/app/src/main/AndroidManifest.xml index d45e71eb..95ec78db 100644 --- a/point-cloud-jni-example/app/src/main/AndroidManifest.xml +++ b/point-cloud-jni-example/app/src/main/AndroidManifest.xml @@ -9,6 +9,7 @@ android:targetSdkVersion="19" /> + lock(pose_mutex_); diff --git a/point-cloud-jni-example/app/src/main/jni/point_cloud_drawable.cc b/point-cloud-jni-example/app/src/main/jni/point_cloud_drawable.cc index be9f17eb..b73ad6ac 100644 --- a/point-cloud-jni-example/app/src/main/jni/point_cloud_drawable.cc +++ b/point-cloud-jni-example/app/src/main/jni/point_cloud_drawable.cc @@ -21,15 +21,18 @@ namespace { const std::string kPointCloudVertexShader = + "precision mediump float;\n" + "precision mediump int;\n" "attribute vec4 vertex;\n" "uniform mat4 mvp;\n" "varying vec4 v_color;\n" "void main() {\n" - " gl_PointSize = 5.0;\n" " gl_Position = mvp*vertex;\n" " v_color = vertex;\n" "}\n"; const std::string kPointCloudFragmentShader = + "precision mediump float;\n" + "precision mediump int;\n" "varying vec4 v_color;\n" "void main() {\n" " gl_FragColor = vec4(v_color);\n" @@ -43,7 +46,6 @@ const glm::mat4 kOpengGL_T_Depth = namespace tango_point_cloud { PointCloudDrawable::PointCloudDrawable() { - LOGI("PointCloudDrawable constructor"); shader_program_ = tango_gl::util::CreateProgram( kPointCloudVertexShader.c_str(), kPointCloudFragmentShader.c_str()); @@ -52,13 +54,19 @@ PointCloudDrawable::PointCloudDrawable() { glGenBuffers(1, &vertex_buffers_); } -PointCloudDrawable::~PointCloudDrawable() { glDeleteProgram(shader_program_); } +void PointCloudDrawable::DeleteGlResources() { + if (vertex_buffers_) { + glDeleteBuffers(1, &vertex_buffers_); + } + if (shader_program_) { + glDeleteShader(shader_program_); + } +} void PointCloudDrawable::Render(glm::mat4 projection_mat, glm::mat4 view_mat, glm::mat4 model_mat, const std::vector& vertices) { glUseProgram(shader_program_); - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); mvp_handle_ = glGetUniformLocation(shader_program_, "mvp"); // Calculate model view projection matrix. @@ -75,7 +83,7 @@ void PointCloudDrawable::Render(glm::mat4 projection_mat, glm::mat4 view_mat, glDrawArrays(GL_POINTS, 0, vertices.size() / 3); glUseProgram(0); - tango_gl::util::CheckGlError("Pointcloud::Render"); + tango_gl::util::CheckGlError("Pointcloud::Render()"); } } // namespace tango_point_cloud diff --git a/point-cloud-jni-example/app/src/main/jni/scene.cc b/point-cloud-jni-example/app/src/main/jni/scene.cc index dcb1093d..66032b72 100644 --- a/point-cloud-jni-example/app/src/main/jni/scene.cc +++ b/point-cloud-jni-example/app/src/main/jni/scene.cc @@ -56,7 +56,7 @@ void Scene::InitGLContent() { tango_gl::GestureCamera::CameraType::kThirdPerson); } -void Scene::FreeGLContent() { +void Scene::DeleteResources() { delete gesture_camera_; delete axis_; delete frustum_; diff --git a/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/point_cloud_app.h b/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/point_cloud_app.h index f2ee8c17..110eaec7 100644 --- a/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/point_cloud_app.h +++ b/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/point_cloud_app.h @@ -93,8 +93,8 @@ class PointCloudApp { // Main render loop. void Render(); - // Release all OpenGL resources that allocate from the program. - void FreeGLContent(); + // Release all non-OpenGL allocated resources. + void DeleteResources(); // Return pose debug string. std::string GetPoseString(); diff --git a/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/point_cloud_drawable.h b/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/point_cloud_drawable.h index 8d76790f..6a8e388d 100644 --- a/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/point_cloud_drawable.h +++ b/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/point_cloud_drawable.h @@ -27,7 +27,9 @@ namespace tango_point_cloud { class PointCloudDrawable { public: PointCloudDrawable(); - ~PointCloudDrawable(); + + // Free all GL Resources, i.e, shaders, buffers. + void DeleteGlResources(); // Update current point cloud data. // diff --git a/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/scene.h b/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/scene.h index ff98a2ce..ebde4dbd 100644 --- a/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/scene.h +++ b/point-cloud-jni-example/app/src/main/jni/tango-point-cloud/scene.h @@ -46,8 +46,8 @@ class Scene { // Allocate OpenGL resources for rendering. void InitGLContent(); - // Release OpenGL resources allocated. - void FreeGLContent(); + // Release non-OpenGL allocated resources. + void DeleteResources(); // Setup GL view port. void SetupViewPort(int w, int h); diff --git a/starter-jni-example/app/src/main/AndroidManifest.xml b/starter-jni-example/app/src/main/AndroidManifest.xml index 937ff8f2..1d3494b9 100644 --- a/starter-jni-example/app/src/main/AndroidManifest.xml +++ b/starter-jni-example/app/src/main/AndroidManifest.xml @@ -7,6 +7,8 @@ + + TANGO_SUCCESS on free. -/// Returns TANGO_INVALID if manager is NULL. TangoErrorType TangoSupport_freeImageBufferManager( TangoSupportImageBufferManager* manager); @@ -72,10 +71,14 @@ TangoErrorType TangoSupport_freeImageBufferManager( /// @param manager A handle to the image buffer manager. /// @param y_only For YUV images copy only the Y-portion (grayscale /// intensities) if value is non-zero. For zero value copy Y and UV portions. -/// @param begin_line Copy only scan lines start at this row. -/// @param end_line Copy only scan lines to this row. +/// @param begin_line Copy only scan lines start at this row. Must be less than +/// end_line. +/// @param end_line Copy only scan lines to this row. Must be greater than +/// begin_line. /// @pre 0 <= begin_line <= end_line <= image_height - 1. -/// @return Returns TANGO_SUCCESS on update of the copy region. +/// @return Returns TANGO_SUCCESS on update of the copy +/// region. Returns TANGO_INVALID if the preconditions are not +/// satisfied. TangoErrorType TangoSupport_setImageBufferCopyRegion( TangoSupportImageBufferManager* manager, int y_only, uint32_t begin_line, uint32_t end_line); @@ -150,7 +153,8 @@ TangoErrorType TangoSupport_copyXYZij(const TangoXYZij* input_point_cloud, /// /// @param point_cloud The input point cloud. Cannot be NULL and must have at /// least three points. -/// @param intrinsics The camera intrinsics for the color camera. +/// @param camera_intrinsics The camera intrinsics for the color camera. Cannot +/// be NULL. /// @param color_camera_T_point_cloud The pose of the point cloud relative to /// the color camera used to obtain uv_coordinates. /// @param uv_coordinates The UV coordinates for the user selection. This is @@ -164,7 +168,8 @@ TangoErrorType TangoSupport_copyXYZij(const TangoXYZij* input_point_cloud, /// @return TANGO_SUCCESS on success, TANGO_INVALID on /// invalid input, and TANGO_ERROR on failure. TangoErrorType TangoSupport_fitPlaneModelNearClick( - const TangoXYZij* point_cloud, const TangoCameraIntrinsics* intrinsics, + const TangoXYZij* point_cloud, + const TangoCameraIntrinsics* camera_intrinsics, const TangoPoseData* color_camera_T_point_cloud, const float uv_coordinates[2], double intersection_point[3], double plane_model[4]); @@ -216,8 +221,7 @@ TangoErrorType TangoSupport_createPointCloudManager( /// @brief Delete the point cloud manager object. /// /// @param manager A handle to the manager to delete. -/// @return A TangoErrorType value of TANGO_SUCCESS if -/// successful. Returns TANGO_INVALID if manager is NULL. +/// @return A TangoErrorType value of TANGO_SUCCESS on free. TangoErrorType TangoSupport_freePointCloudManager( TangoSupportPointCloudManager* manager); @@ -261,7 +265,6 @@ TangoErrorType TangoSupport_initializeEmptyMesh(TangoMesh_Experimental* mesh); /// /// @param mesh A pointer to the mesh to be deleted. Cannot be NULL. /// @return Returns TANGO_SUCCESS on successful free. -/// Returns TANGO_INVALID if mesh is NULL. TangoErrorType TangoSupport_freeMesh(TangoMesh_Experimental* mesh); /// @brief Creates a mesh, allocating memory for vertices, faces, and @@ -351,8 +354,8 @@ TangoErrorType TangoSupport_calculateRelativePose( /// in the order of x, y, z. /// @param orientation The camera with respect to world orientation, /// in the order of x, y, z, w. -/// @return TANGO_SUCCESS on success, TANGO_INVALID -/// on invalid input, and TANGO_ERROR on failure. +/// @return TANGO_SUCCESS on success and TANGO_INVALID +/// on invalid input. TangoErrorType TangoSupport_getWorldTCameraPose( TangoCoordinateConvention coordinate_convention, const TangoPoseData* pose_start_service_T_device, double translation[3], @@ -360,6 +363,175 @@ TangoErrorType TangoSupport_getWorldTCameraPose( /// @} +/// @defgroup DepthInterpolationSupport Depth Interpolation Support Functions +/// @brief Functions for interpolating depth. +/// @{ + +/// @brief Calculates the depth in the color camera space at a user-specified +/// location using nearest-neighbor interpolation. +/// +/// @param point_cloud The point cloud. Cannot be NULL and must have at least +/// one point. +/// @param camera_intrinsics The camera intrinsics for the color camera. Cannot +// be NULL. +/// @param color_camera_T_point_cloud The pose of the point cloud relative to +/// the color camera used to obtain uv_coordinates. +/// @param uv_coordinates The UV coordinates for the user selection. This is +/// expected to be between (0.0, 0.0) and (1.0, 1.0). Cannot be NULL. +/// @param point_cloud_point The point (x, y, z), where (x, y) is the +/// back-projection of the UV coordinates to the color camera space and z is +// the z coordinate of the point in the point cloud nearest to the user +// selection after projection onto the image plane. If there is not a point +// cloud point close to the user selection after projection onto the image +// plane, then the point will be set to (0.0, 0.0, 0.0) and is_valid_point +/// will be set to 0. +/// @param is_valid_point A flag valued 1 if there is a point cloud point close +/// to the user selection after projection onto the image plane and valued 0 +/// otherwise. +/// @return TANGO_SUCCESS on success and TANGO_INVALID +/// on invalid input. +TangoErrorType TangoSupport_getDepthAtPointNearestNeighbor( + const TangoXYZij* point_cloud, + const TangoCameraIntrinsics* camera_intrinsics, + const TangoPoseData* color_camera_T_point_cloud, + const float uv_coordinates[2], float point_cloud_point[3], + int* is_valid_point); + +/// @brief The TangoSupportDepthInterpolator contains references to camera +/// intrinsics +/// and cached data structures needed to upsample depth data to a camera image. +struct TangoSupportDepthInterpolator; + +/// @brief Create an object for depth interpolation. +/// +/// @param intrinsics The camera intrinsics for the camera to upsample. +/// @param interpolator A handle to the interpolator object. +/// @return A TangoErrorType value of TANGO_INVALID if intrinsics +/// is null. Returns TANGO_SUCCESS otherwise. +TangoErrorType TangoSupport_createDepthInterpolator( + TangoCameraIntrinsics* intrinsics, + TangoSupportDepthInterpolator** interpolator); + +/// @brief Free the depth interpolation object. +/// +/// @param A handle to the interpolator object. +/// @return TANGO_SUCCESS +TangoErrorType TangoSupport_freeDepthInterpolator( + TangoSupportDepthInterpolator* interpolator); + +/// @brief Calculates the depth in the color camera space at a user-specified +/// location using bilateral filtering weighted by both spatial distance from +/// the user coordinate and by intensity similarity. +/// +/// @param interpolator A handle to the interpolator object. The intrinsics of +/// this interpolator object must match those of the image_buffer. +/// @param point_cloud The point cloud. Cannot be NULL and must have at least +/// one point. +/// @param image_buffer The RGB image buffer. This must have intrinsics matching +/// those used to create the interpolator object. Cannot be NULL. +/// @param color_camera_T_point_cloud The pose of the point cloud relative to +/// the color camera used to obtain uv_coordinates. +/// @param uv_coordinates The UV coordinates for the user selection. This is +/// expected to be between (0.0, 0.0) and (1.0, 1.0). Cannot be NULL. +/// @param point_cloud_point The point (x, y, z), where (x, y) is the +/// back-projection of the UV coordinates to the color camera space and z is +/// the bilateral interpolation of the z coordinate of the point. If there is +/// not a point cloud point close to the user selection after projection onto +/// the image plane, then the point will be set to (0.0, 0.0, 0.0) and +/// is_valid_point will be set to 0. +/// @param is_valid_point A flag valued 1 if there is a point cloud point close +/// to the user selection after projection onto the image plane and valued 0 +/// otherwise. +/// @return TANGO_SUCCESS on success, TANGO_INVALID on +/// invalid input, and TANGO_ERROR on failure. +TangoErrorType TangoSupport_getDepthAtPointBilateral( + const TangoSupportDepthInterpolator* interpolator, + const TangoXYZij* point_cloud, const TangoImageBuffer* image_buffer, + const TangoPoseData* color_camera_T_point_cloud, + const float uv_coordinates[2], float point_cloud_point[3], + int* is_valid_point); + +/// @brief A structure to hold depth values for image upsampling. The units of +/// the depth are the same as for TangoXYZij. +struct TangoSupportDepthBuffer { + float* depths; + uint32_t width; + uint32_t height; +}; + +/// @brief Allocate memory for a depth buffer for the given image resolution. +/// +/// @param width The width of the image. This should match the width given by +/// the camera intrinsics. +/// @param height The height of the image. This should match the height given by +/// the camera intrinsics. +/// @param depth_buffer The depth buffer to initialize. +/// @return TANGO_SUCCESS on success, TANGO_INVALID on +/// invalid input, and TANGO_ERROR on failure. +TangoErrorType TangoSupport_initializeDepthBuffer( + uint32_t width, uint32_t height, TangoSupportDepthBuffer* depth_buffer); + +/// @brief Free memory for the depth buffer. +/// +/// @param depth_buffer The depth buffer to free. +/// @return TANGO_SUCCESS on success, TANGO_INVALID on +/// invalid input, and TANGO_ERROR on failure. +TangoErrorType TangoSupport_freeDepthBuffer( + TangoSupportDepthBuffer* depth_buffer); + +/// @brief Upsamples the depth data to the resolution of the color image. This +/// uses the resolution specified by the intrinsics used to construct the +/// interpolator. This function fills depth around each sample using a fixed +/// radius. The resolution of the intrinsics provided to the interpolator and +/// the the resolution of the output depth_buffer must match. +/// +/// @param interpolator A handle to the interpolator object. The intrinsics of +/// this interpolator object must match those of the image_buffer. Cannot be +/// NULL. +/// @param point_cloud The point cloud. Cannot be NULL and must have at least +/// one point. +/// @param color_camera_T_point_cloud The pose of the point cloud relative to +/// the color camera used to obtain uv_coordinates. Cannot be NULL. +/// @param depth_buffer A buffer for output of the depth data. Each pixel +/// contains a depth value (in meters) or zero if there is no depth data near +/// enough to the pixel. Cannot be NULL. +/// @return TANGO_SUCCESS on success, TANGO_INVALID on +/// invalid input, and TANGO_ERROR on failure. +TangoErrorType TangoSupport_upsampleImageNearest( + const TangoSupportDepthInterpolator* interpolator, + const TangoXYZij* point_cloud, + const TangoPoseData* color_camera_T_point_cloud, + TangoSupportDepthBuffer* depth_buffer); + +/// @brief Upsamples the depth data to the resolution of the color image. This +/// uses the resolution specified by the intrinsics used to construct the +/// interpolator. This function fills depth around using a bilateral filtering +/// approach. The resolution of the intrinsics provided to the interpolator and +/// the the resolution of the output depth_buffer must match. +/// +/// @param interpolator A handle to the interpolator object. The intrinsics of +/// this interpolator object must match those of the image_buffer. Cannot be +/// NULL. +/// @param approximate If non-zero, uses an approximation technique that is +/// faster but somewhat less accurate. If zero, use the a slower technique +/// that is slightly more accurate. +/// @param point_cloud The point cloud. Cannot be NULL and must have at least +/// one point. +/// @param color_camera_T_point_cloud The pose of the point cloud relative to +/// the color camera used to obtain uv_coordinates. Cannot be NULL. +/// @param depth_buffer A buffer for output of the depth data. Each pixel +/// contains a depth value (in meters) or zero if there is no depth data near +/// enough to the pixel. Cannot be NULL. +/// @return TANGO_SUCCESS on success, TANGO_INVALID on +/// invalid input, and TANGO_ERROR on failure. +TangoErrorType TangoSupport_upsampleImageBilateral( + const TangoSupportDepthInterpolator* interpolator, int approximate, + const TangoXYZij* point_cloud, const TangoImageBuffer* image_buffer, + const TangoPoseData* color_camera_T_point_cloud, + TangoSupportDepthBuffer* depth_buffer); + +/// @} + #ifdef __cplusplus } #endif diff --git a/tango_support_api/lib/libtango_support_api.so b/tango_support_api/lib/libtango_support_api.so index 3658fef5..5f90d03d 100644 Binary files a/tango_support_api/lib/libtango_support_api.so and b/tango_support_api/lib/libtango_support_api.so differ diff --git a/video-overlay-jni-example/app/src/main/AndroidManifest.xml b/video-overlay-jni-example/app/src/main/AndroidManifest.xml index 15c76593..83a95afe 100644 --- a/video-overlay-jni-example/app/src/main/AndroidManifest.xml +++ b/video-overlay-jni-example/app/src/main/AndroidManifest.xml @@ -8,10 +8,12 @@ android:name="android.hardware.camera.autofocus" android:required="false" /> + + DeleteDrawables(); + } video_overlay_drawable_ = new tango_gl::VideoOverlay(); yuv_drawable_ = new YUVDrawable(); @@ -182,14 +194,13 @@ void VideoOverlayApp::Render() { } } -void VideoOverlayApp::FreeGLContent() { +void VideoOverlayApp::FreeBufferData() { is_yuv_texture_available_ = false; swap_buffer_signal_ = false; rgb_buffer_.clear(); yuv_buffer_.clear(); yuv_temp_buffer_.clear(); - delete yuv_drawable_; - delete video_overlay_drawable_; + this->DeleteDrawables(); } void VideoOverlayApp::AllocateTexture(GLuint texture_id, int width,