00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <iostream>
00040 #include <string>
00041
00042
00043 #include <pcl/common/time.h>
00044 #include <pcl/point_cloud.h>
00045 #include <pcl/point_types.h>
00046
00047 #include <pcl/PCLPointCloud2.h>
00048
00049 #include <pcl/io/pcd_io.h>
00050 #include <pcl/io/vtk_lib_io.h>
00051 #include <pcl/pcl_macros.h>
00052
00053 #include <pcl/console/print.h>
00054 #include <pcl/console/parse.h>
00055
00056
00057
00058 #include <pcl/visualization/common/common.h>
00059 #include <pcl/visualization/vtk/vtkVertexBufferObjectMapper.h>
00060
00061
00062
00063
00064 #include <pcl/outofcore/outofcore.h>
00065 #include <pcl/outofcore/outofcore_impl.h>
00066
00067 #include <pcl/outofcore/visualization/axes.h>
00068 #include <pcl/outofcore/visualization/camera.h>
00069 #include <pcl/outofcore/visualization/grid.h>
00070 #include <pcl/outofcore/visualization/object.h>
00071 #include <pcl/outofcore/visualization/outofcore_cloud.h>
00072 #include <pcl/outofcore/visualization/scene.h>
00073 #include <pcl/outofcore/visualization/viewport.h>
00074
00075 using namespace pcl;
00076 using namespace pcl::outofcore;
00077
00078 using pcl::console::parse_argument;
00079 using pcl::console::find_switch;
00080 using pcl::console::print_error;
00081 using pcl::console::print_warn;
00082 using pcl::console::print_info;
00083
00084
00085 typedef PointXYZ PointT;
00086
00087 typedef OutofcoreOctreeBase<OutofcoreOctreeDiskContainer<PointT>, PointT> octree_disk;
00088 typedef OutofcoreOctreeBaseNode<OutofcoreOctreeDiskContainer<PointT>, PointT> octree_disk_node;
00089
00090
00091 typedef boost::shared_ptr<octree_disk> OctreeDiskPtr;
00092
00093 typedef Eigen::aligned_allocator<PointT> AlignedPointT;
00094
00095
00096 #include <vtkActor.h>
00097 #include <vtkActorCollection.h>
00098 #include <vtkActor2DCollection.h>
00099 #include <vtkAppendPolyData.h>
00100 #include <vtkAppendFilter.h>
00101 #include <vtkCamera.h>
00102 #include <vtkCameraActor.h>
00103 #include <vtkCellArray.h>
00104 #include <vtkCellData.h>
00105 #include <vtkCommand.h>
00106 #include <vtkConeSource.h>
00107 #include <vtkCubeSource.h>
00108 #include <vtkDataSetMapper.h>
00109 #include <vtkHull.h>
00110 #include <vtkInformation.h>
00111 #include <vtkInformationStringKey.h>
00112 #include <vtkInteractorStyleTrackballCamera.h>
00113 #include <vtkLODActor.h>
00114 #include <vtkMath.h>
00115 #include <vtkMatrix4x4.h>
00116 #include <vtkMutexLock.h>
00117 #include <vtkObjectFactory.h>
00118 #include <vtkPolyData.h>
00119 #include <vtkProperty.h>
00120 #include <vtkTextActor.h>
00121 #include <vtkRectilinearGrid.h>
00122 #include <vtkRenderer.h>
00123 #include <vtkRenderWindow.h>
00124 #include <vtkRenderWindowInteractor.h>
00125 #include <vtkSmartPointer.h>
00126 #include <vtkUnsignedCharArray.h>
00127
00128 #include <vtkInteractorStyleRubberBand3D.h>
00129 #include <vtkParallelCoordinatesInteractorStyle.h>
00130
00131
00132 #include <boost/date_time.hpp>
00133 #include <boost/filesystem.hpp>
00134 #include <boost/thread.hpp>
00135
00136
00137 const int MAX_DEPTH (-1);
00138
00139
00140 vtkSmartPointer<vtkRenderWindow> window;
00141
00142
00143 class KeyboardCallback : public vtkCommand
00144 {
00145 public:
00146 vtkTypeMacro(KeyboardCallback, vtkCommand)
00147 ;
00148
00149 static KeyboardCallback *
00150 New ()
00151 {
00152 return new KeyboardCallback;
00153 }
00154
00155 void
00156 Execute (vtkObject *caller, unsigned long vtkNotUsed(eventId), void* vtkNotUsed(callData))
00157 {
00158 vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::SafeDownCast (caller);
00159 vtkRenderer *renderer = interactor->FindPokedRenderer (interactor->GetEventPosition ()[0],
00160 interactor->GetEventPosition ()[1]);
00161
00162 std::string key (interactor->GetKeySym ());
00163 bool shift_down = interactor->GetShiftKey();
00164
00165 cout << "Key Pressed: " << key << endl;
00166
00167 Scene *scene = Scene::instance ();
00168 OutofcoreCloud *cloud = static_cast<OutofcoreCloud*> (scene->getObjectByName ("my_octree"));
00169
00170 if (key == "Up" || key == "Down")
00171 {
00172 if (key == "Up" && cloud)
00173 {
00174 if (shift_down)
00175 {
00176 cloud->increaseLodPixelThreshold();
00177 }
00178 else
00179 {
00180 cloud->setDisplayDepth (cloud->getDisplayDepth () + 1);
00181 }
00182 }
00183 else if (key == "Down" && cloud)
00184 {
00185 if (shift_down)
00186 {
00187 cloud->decreaseLodPixelThreshold();
00188 }
00189 else
00190 {
00191 cloud->setDisplayDepth (cloud->getDisplayDepth () - 1);
00192 }
00193 }
00194 }
00195
00196 if (key == "o")
00197 {
00198 cloud->setDisplayVoxels(1-static_cast<int> (cloud->getDisplayVoxels()));
00199 }
00200
00201 if (key == "Escape")
00202 {
00203 Eigen::Vector3d min (cloud->getBoundingBoxMin ());
00204 Eigen::Vector3d max (cloud->getBoundingBoxMax ());
00205 renderer->ResetCamera (min.x (), max.x (), min.y (), max.y (), min.z (), max.z ());
00206 }
00207 }
00208 };
00209
00210 void
00211 renderTimerCallback(vtkObject* caller, unsigned long int vtkNotUsed(eventId), void* vtkNotUsed(clientData), void* vtkNotUsed(callData))
00212 {
00213 vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::SafeDownCast (caller);
00214 interactor->Render ();
00215 }
00216
00217 void
00218 renderStartCallback(vtkObject* vtkNotUsed(caller), unsigned long int vtkNotUsed(eventId), void* vtkNotUsed(clientData), void* vtkNotUsed(callData))
00219 {
00220
00221 }
00222
00223 void
00224 renderEndCallback(vtkObject* vtkNotUsed(caller), unsigned long int vtkNotUsed(eventId), void* vtkNotUsed(clientData), void* vtkNotUsed(callData))
00225 {
00226
00227 }
00228
00229 int
00230 outofcoreViewer (boost::filesystem::path tree_root, int depth, bool display_octree=true, unsigned int gpu_cache_size=512)
00231 {
00232 cout << boost::filesystem::absolute (tree_root) << endl;
00233
00234
00235 Scene *scene = Scene::instance ();
00236
00237
00238 OutofcoreCloud *cloud = new OutofcoreCloud ("my_octree", tree_root);
00239 cloud->setDisplayDepth (depth);
00240 cloud->setDisplayVoxels (display_octree);
00241 OutofcoreCloud::cloud_data_cache.setCapacity(gpu_cache_size*1024);
00242 scene->addObject (cloud);
00243
00244
00245
00246
00247
00248
00249
00250 Grid *grid = new Grid ("origin_grid");
00251 Axes *axes = new Axes ("origin_axes");
00252 scene->addObject (grid);
00253 scene->addObject (axes);
00254
00255
00256
00257
00258
00259
00260
00261 vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New ();
00262 window = vtkSmartPointer<vtkRenderWindow>::New ();
00263 window->SetSize (1000, 500);
00264
00265 interactor->SetRenderWindow (window);
00266 interactor->Initialize ();
00267 interactor->CreateRepeatingTimer (100);
00268
00269
00270 Viewport octree_viewport (window, 0.0, 0.0, 0.5, 1.0);
00271 Viewport persp_viewport (window, 0.5, 0.0, 1.0, 1.0);
00272
00273
00274 Camera *persp_camera = new Camera ("persp", persp_viewport.getRenderer ()->GetActiveCamera ());
00275 Camera *octree_camera = new Camera ("octree", octree_viewport.getRenderer ()->GetActiveCamera ());
00276 scene->addCamera (persp_camera);
00277 scene->addCamera (octree_camera);
00278 octree_camera->setDisplay(true);
00279
00280
00281 persp_viewport.setCamera (persp_camera);
00282 octree_viewport.setCamera (octree_camera);
00283
00284
00285 window->Render ();
00286
00287
00288 Eigen::Vector3d min (cloud->getBoundingBoxMin ());
00289 Eigen::Vector3d max (cloud->getBoundingBoxMax ());
00290 octree_viewport.getRenderer ()->ResetCamera (min.x (), max.x (), min.y (), max.y (), min.z (), max.z ());
00291 persp_viewport.getRenderer ()->ResetCamera (min.x (), max.x (), min.y (), max.y (), min.z (), max.z ());
00292
00293 cloud->setRenderCamera(octree_camera);
00294
00295
00296
00297 vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New ();
00298 style->SetAutoAdjustCameraClippingRange(false);
00299 interactor->SetInteractorStyle (style);
00300
00301
00302
00303 vtkSmartPointer<vtkCallbackCommand> render_start_callback = vtkSmartPointer<vtkCallbackCommand>::New();
00304 render_start_callback->SetCallback(renderStartCallback);
00305 window->AddObserver(vtkCommand::StartEvent, render_start_callback);
00306
00307 vtkSmartPointer<vtkCallbackCommand> render_end_callback = vtkSmartPointer<vtkCallbackCommand>::New();
00308 render_end_callback->SetCallback(renderEndCallback);
00309 window->AddObserver(vtkCommand::EndEvent, render_end_callback);
00310
00311 vtkSmartPointer<KeyboardCallback> keyboard_callback = vtkSmartPointer<KeyboardCallback>::New ();
00312 interactor->AddObserver (vtkCommand::KeyPressEvent, keyboard_callback);
00313
00314 interactor->CreateRepeatingTimer(1000);
00315 vtkSmartPointer<vtkCallbackCommand> render_timer_callback = vtkSmartPointer<vtkCallbackCommand>::New();
00316 render_timer_callback->SetCallback(renderTimerCallback);
00317 interactor->AddObserver(vtkCommand::TimerEvent, render_timer_callback);
00318
00319 interactor->Start ();
00320
00321 return 0;
00322 }
00323
00324 void
00325 print_help (int argc, char **argv)
00326 {
00327
00328 assert(argc == argc);
00329
00330 print_info ("This program is used to visualize outofcore data structure");
00331 print_info ("%s <options> <input_tree_dir> \n", argv[0]);
00332 print_info ("\n");
00333 print_info ("Options:\n");
00334 print_info ("\t -depth <depth> \t Octree depth\n");
00335 print_info ("\t -display_octree \t Toggles octree display\n");
00336
00337 print_info ("\t -gpu_cache_size <size> \t Size of pointcloud gpu cache in MB (512MB)\n");
00338 print_info ("\t -lod_threshold <pixels> \t Bounding box screen projection threshold (10000)\n");
00339 print_info ("\t -v \t Print more verbosity\n");
00340 print_info ("\t -h \t Display help\n");
00341 print_info ("\n");
00342
00343 exit (1);
00344 }
00345
00346 int
00347 main (int argc, char* argv[])
00348 {
00349
00350
00351 if (argc > 1)
00352 {
00353 if (find_switch (argc, argv, "-h"))
00354 {
00355 print_help (argc, argv);
00356 return (-1);
00357 }
00358 }
00359
00360
00361 if (argc - 1 < 1)
00362 {
00363 print_help (argc, argv);
00364 return (-1);
00365 }
00366
00367 if (find_switch (argc, argv, "-v"))
00368 console::setVerbosityLevel (console::L_DEBUG);
00369
00370
00371 int depth = 4;
00372
00373 unsigned int gpu_cache_size = 512;
00374 unsigned int lod_threshold = 10000;
00375 bool display_octree = find_switch (argc, argv, "-display_octree");
00376
00377
00378 parse_argument (argc, argv, "-depth", depth);
00379
00380 parse_argument (argc, argv, "-gpu_cache_size", gpu_cache_size);
00381 parse_argument (argc, argv, "-lod_threshold", lod_threshold);
00382
00383
00384 boost::filesystem::path tree_root (argv[argc - 1]);
00385
00386
00387 if (boost::filesystem::is_directory (tree_root))
00388 {
00389 boost::filesystem::directory_iterator diterend;
00390 for (boost::filesystem::directory_iterator diter (tree_root); diter != diterend; ++diter)
00391 {
00392 const boost::filesystem::path& file = *diter;
00393 if (!boost::filesystem::is_directory (file))
00394 {
00395 if (boost::filesystem::extension (file) == octree_disk_node::node_index_extension)
00396 {
00397 tree_root = file;
00398 }
00399 }
00400 }
00401 }
00402
00403 return outofcoreViewer (tree_root, depth, display_octree, gpu_cache_size);
00404 }