render_views_tesselated_sphere.cpp
Go to the documentation of this file.
00001 /*
00002  * render_views_tesselated_sphere.cpp
00003  *
00004  *  Created on: Dec 23, 2011
00005  *      Author: aitor
00006  */
00007 #include <pcl/point_types.h>
00008 #include <pcl/apps/render_views_tesselated_sphere.h>
00009 #include <vtkCellData.h>
00010 #include <vtkWorldPointPicker.h>
00011 #include <vtkPropPicker.h>
00012 #include <vtkPlatonicSolidSource.h>
00013 #include <vtkLoopSubdivisionFilter.h>
00014 #include <vtkTriangle.h>
00015 #include <vtkTransform.h>
00016 #include <vtkVisibleCellSelector.h>
00017 #include <vtkSelection.h>
00018 #include <vtkCellArray.h>
00019 #include <vtkTransformFilter.h>
00020 #include <vtkCamera.h>
00021 #include <vtkActor.h>
00022 #include <vtkRenderWindow.h>
00023 #include <vtkRenderer.h>
00024 #include <vtkPolyDataMapper.h>
00025 // Only available in older versions of VTK
00026 //#include <vtkHardwareSelector.h>
00027 //#include <vtkSelectionNode.h>
00028 #include <vtkPointPicker.h>
00029 
00030 void pcl::apps::RenderViewsTesselatedSphere::generateViews() {
00031   //center object
00032   double CoM[3];
00033   vtkIdType npts_com = 0, *ptIds_com = NULL;
00034   vtkSmartPointer<vtkCellArray> cells_com = polydata_->GetPolys ();
00035 
00036   double center[3], p1_com[3], p2_com[3], p3_com[3], area_com, totalArea_com = 0;
00037   double comx = 0, comy = 0, comz = 0;
00038   for (cells_com->InitTraversal (); cells_com->GetNextCell (npts_com, ptIds_com);)
00039   {
00040     polydata_->GetPoint (ptIds_com[0], p1_com);
00041     polydata_->GetPoint (ptIds_com[1], p2_com);
00042     polydata_->GetPoint (ptIds_com[2], p3_com);
00043     vtkTriangle::TriangleCenter (p1_com, p2_com, p3_com, center);
00044     area_com = vtkTriangle::TriangleArea (p1_com, p2_com, p3_com);
00045     comx += center[0] * area_com;
00046     comy += center[1] * area_com;
00047     comz += center[2] * area_com;
00048     totalArea_com += area_com;
00049   }
00050 
00051   CoM[0] = comx / totalArea_com;
00052   CoM[1] = comy / totalArea_com;
00053   CoM[2] = comz / totalArea_com;
00054 
00055   vtkSmartPointer<vtkTransform> trans_center = vtkSmartPointer<vtkTransform>::New ();
00056   trans_center->Translate (-CoM[0], -CoM[1], -CoM[2]);
00057   vtkSmartPointer<vtkMatrix4x4> matrixCenter = trans_center->GetMatrix ();
00058 
00059   vtkSmartPointer<vtkTransformFilter> trans_filter_center = vtkSmartPointer<vtkTransformFilter>::New ();
00060   trans_filter_center->SetTransform (trans_center);
00061   trans_filter_center->SetInput (polydata_);
00062   trans_filter_center->Update ();
00063 
00064   vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New ();
00065   mapper->SetInputConnection (trans_filter_center->GetOutputPort ());
00066   mapper->Update ();
00067 
00068   //scale so it fits in the unit sphere!
00069   double bb[6];
00070   mapper->GetBounds (bb);
00071   double ms = (std::max) ((std::fabs) (bb[0] - bb[1]),
00072                           (std::max) ((std::fabs) (bb[2] - bb[3]), (std::fabs) (bb[4] - bb[5])));
00073   double max_side = radius_sphere_ / 2.0;
00074   double scale_factor = max_side / ms;
00075 
00076   vtkSmartPointer<vtkTransform> trans_scale = vtkSmartPointer<vtkTransform>::New ();
00077   trans_scale->Scale (scale_factor, scale_factor, scale_factor);
00078   vtkSmartPointer<vtkMatrix4x4> matrixScale = trans_scale->GetMatrix ();
00079 
00080   vtkSmartPointer<vtkTransformFilter> trans_filter_scale = vtkSmartPointer<vtkTransformFilter>::New ();
00081   trans_filter_scale->SetTransform (trans_scale);
00082   trans_filter_scale->SetInputConnection (trans_filter_center->GetOutputPort ());
00083   trans_filter_scale->Update ();
00084 
00085   mapper->SetInputConnection (trans_filter_scale->GetOutputPort ());
00086   mapper->Update ();
00087 
00089   // * Compute area of the mesh
00091   vtkSmartPointer<vtkCellArray> cells = mapper->GetInput ()->GetPolys ();
00092   vtkIdType npts = 0, *ptIds = NULL;
00093 
00094   double p1[3], p2[3], p3[3], area, totalArea = 0;
00095   for (cells->InitTraversal (); cells->GetNextCell (npts, ptIds);)
00096   {
00097     polydata_->GetPoint (ptIds[0], p1);
00098     polydata_->GetPoint (ptIds[1], p2);
00099     polydata_->GetPoint (ptIds[2], p3);
00100     area = vtkTriangle::TriangleArea (p1, p2, p3);
00101     totalArea += area;
00102   }
00103 
00104   //create icosahedron
00105   vtkSmartPointer<vtkPlatonicSolidSource> ico = vtkSmartPointer<vtkPlatonicSolidSource>::New ();
00106   ico->SetSolidTypeToIcosahedron ();
00107   ico->Update ();
00108 
00109   //tesselate cells from icosahedron
00110   vtkSmartPointer<vtkLoopSubdivisionFilter> subdivide = vtkSmartPointer<vtkLoopSubdivisionFilter>::New ();
00111   subdivide->SetNumberOfSubdivisions (tesselation_level_);
00112   subdivide->SetInputConnection (ico->GetOutputPort ());
00113 
00114   // Get camera positions
00115   vtkPolyData *sphere = subdivide->GetOutput ();
00116   sphere->Update ();
00117 
00118   std::vector<Eigen::Vector3f> cam_positions;
00119   if (!use_vertices_)
00120   {
00121     vtkSmartPointer<vtkCellArray> cells_sphere = sphere->GetPolys ();
00122     cam_positions.resize (sphere->GetNumberOfPolys ());
00123 
00124     size_t i=0;
00125     for (cells_sphere->InitTraversal (); cells_sphere->GetNextCell (npts_com, ptIds_com);)
00126     {
00127       sphere->GetPoint (ptIds_com[0], p1_com);
00128       sphere->GetPoint (ptIds_com[1], p2_com);
00129       sphere->GetPoint (ptIds_com[2], p3_com);
00130       vtkTriangle::TriangleCenter (p1_com, p2_com, p3_com, center);
00131       cam_positions[i] = Eigen::Vector3f (float (center[0]), float (center[1]), float (center[2]));
00132       i++;
00133     }
00134 
00135   }
00136   else
00137   {
00138     cam_positions.resize (sphere->GetNumberOfPoints ());
00139     for (int i = 0; i < sphere->GetNumberOfPoints (); i++)
00140     {
00141       double cam_pos[3];
00142       sphere->GetPoint (i, cam_pos);
00143       cam_positions[i] = Eigen::Vector3f (float (cam_pos[0]), float (cam_pos[1]), float (cam_pos[2]));
00144     }
00145   }
00146 
00147   double camera_radius = radius_sphere_;
00148   double cam_pos[3];
00149   double first_cam_pos[3];
00150 
00151   first_cam_pos[0] = cam_positions[0][0] * radius_sphere_;
00152   first_cam_pos[1] = cam_positions[0][1] * radius_sphere_;
00153   first_cam_pos[2] = cam_positions[0][2] * radius_sphere_;
00154 
00155   //create renderer and window
00156   vtkSmartPointer<vtkRenderWindow> render_win = vtkSmartPointer<vtkRenderWindow>::New ();
00157   vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New ();
00158   render_win->AddRenderer (renderer);
00159   render_win->SetSize (resolution_, resolution_);
00160   renderer->SetBackground (1.0, 0, 0);
00161 
00162   //create picker
00163   vtkSmartPointer<vtkWorldPointPicker> worldPicker = vtkSmartPointer<vtkWorldPointPicker>::New ();
00164 
00165   vtkSmartPointer<vtkCamera> cam = vtkSmartPointer<vtkCamera>::New ();
00166   cam->SetFocalPoint (0, 0, 0);
00167 
00168   Eigen::Vector3f cam_pos_3f = cam_positions[0];
00169   Eigen::Vector3f perp = cam_pos_3f.cross (Eigen::Vector3f::UnitY ());
00170   cam->SetViewUp (perp[0], perp[1], perp[2]);
00171 
00172   cam->SetPosition (first_cam_pos);
00173   cam->SetViewAngle (view_angle_);
00174   cam->Modified ();
00175 
00176   //For each camera position, traposesnsform the object and render view
00177   for (size_t i = 0; i < cam_positions.size (); i++)
00178   {
00179     cam_pos[0] = cam_positions[i][0];
00180     cam_pos[1] = cam_positions[i][1];
00181     cam_pos[2] = cam_positions[i][2];
00182 
00183     //create temporal virtual camera
00184     vtkSmartPointer<vtkCamera> cam_tmp = vtkSmartPointer<vtkCamera>::New ();
00185     cam_tmp->SetViewAngle (view_angle_);
00186 
00187     Eigen::Vector3f cam_pos_3f (static_cast<float> (cam_pos[0]), static_cast<float> (cam_pos[1]), static_cast<float> (cam_pos[2]));
00188     cam_pos_3f = cam_pos_3f.normalized ();
00189     Eigen::Vector3f test = Eigen::Vector3f::UnitY ();
00190 
00191     //If the view up is parallel to ray cam_pos - focalPoint then the transformation
00192     //is singular and no points are rendered...
00193     //make sure it is perpendicular
00194     if (fabs (cam_pos_3f.dot (test)) == 1)
00195     {
00196       //parallel, create
00197       test = cam_pos_3f.cross (Eigen::Vector3f::UnitX ());
00198     }
00199 
00200     cam_tmp->SetViewUp (test[0], test[1], test[2]);
00201 
00202     for (int k = 0; k < 3; k++)
00203     {
00204       cam_pos[k] = cam_pos[k] * camera_radius;
00205     }
00206 
00207     cam_tmp->SetPosition (cam_pos);
00208     cam_tmp->SetFocalPoint (0, 0, 0);
00209     cam_tmp->Modified ();
00210 
00211     //rotate model so it looks the same as if we would look from the new position
00212     vtkSmartPointer<vtkMatrix4x4> view_trans_inverted = vtkSmartPointer<vtkMatrix4x4>::New ();
00213     vtkMatrix4x4::Invert (cam->GetViewTransformMatrix (), view_trans_inverted);
00214     vtkSmartPointer<vtkTransform> trans_rot_pose = vtkSmartPointer<vtkTransform>::New ();
00215     trans_rot_pose->Identity ();
00216     trans_rot_pose->Concatenate (view_trans_inverted);
00217     trans_rot_pose->Concatenate (cam_tmp->GetViewTransformMatrix ());
00218     vtkSmartPointer<vtkTransformFilter> trans_rot_pose_filter = vtkSmartPointer<vtkTransformFilter>::New ();
00219     trans_rot_pose_filter->SetTransform (trans_rot_pose);
00220     trans_rot_pose_filter->SetInputConnection (trans_filter_scale->GetOutputPort ());
00221 
00222     //translate model so we can place camera at (0,0,0)
00223     vtkSmartPointer<vtkTransform> translation = vtkSmartPointer<vtkTransform>::New ();
00224     translation->Translate (first_cam_pos[0] * -1, first_cam_pos[1] * -1, first_cam_pos[2] * -1);
00225     vtkSmartPointer<vtkTransformFilter> translation_filter = vtkSmartPointer<vtkTransformFilter>::New ();
00226     translation_filter->SetTransform (translation);
00227     translation_filter->SetInputConnection (trans_rot_pose_filter->GetOutputPort ());
00228 
00229     //modify camera
00230     cam_tmp->SetPosition (0, 0, 0);
00231     cam_tmp->SetFocalPoint (first_cam_pos[0] * -1, first_cam_pos[1] * -1, first_cam_pos[2] * -1);
00232     cam_tmp->Modified ();
00233 
00234     //notice transformations for final pose
00235     vtkSmartPointer<vtkMatrix4x4> matrixRotModel = trans_rot_pose->GetMatrix ();
00236     vtkSmartPointer<vtkMatrix4x4> matrixTranslation = translation->GetMatrix ();
00237 
00238     mapper->SetInputConnection (translation_filter->GetOutputPort ());
00239     mapper->Update ();
00240 
00241     //render view
00242     vtkSmartPointer<vtkActor> actor_view = vtkSmartPointer<vtkActor>::New ();
00243     actor_view->SetMapper (mapper);
00244     renderer->SetActiveCamera (cam_tmp);
00245     renderer->AddActor (actor_view);
00246     renderer->Modified ();
00247     //renderer->ResetCameraClippingRange ();
00248     render_win->Render ();
00249 
00250     //back to real scale transform
00251     vtkSmartPointer<vtkTransform> backToRealScale = vtkSmartPointer<vtkTransform>::New ();
00252     backToRealScale->PostMultiply ();
00253     backToRealScale->Identity ();
00254     backToRealScale->Concatenate (matrixScale);
00255     backToRealScale->Concatenate (matrixTranslation);
00256     backToRealScale->Inverse ();
00257     backToRealScale->Modified ();
00258     backToRealScale->Concatenate (matrixTranslation);
00259     backToRealScale->Modified ();
00260 
00261     Eigen::Matrix4f backToRealScale_eigen;
00262     backToRealScale_eigen.setIdentity ();
00263 
00264     for (int x = 0; x < 4; x++)
00265       for (int y = 0; y < 4; y++)
00266         backToRealScale_eigen (x, y) = float (backToRealScale->GetMatrix ()->GetElement (x, y));
00267 
00268     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00269 
00270     cloud->points.resize (resolution_ * resolution_);
00271     cloud->width = resolution_ * resolution_;
00272     cloud->height = 1;
00273 
00274     double coords[3];
00275     float * depth = new float[resolution_ * resolution_];
00276     render_win->GetZbufferData (0, 0, resolution_ - 1, resolution_ - 1, &(depth[0]));
00277 
00278     int count_valid_depth_pixels = 0;
00279     for (int x = 0; x < resolution_; x++)
00280     {
00281       for (int y = 0; y < resolution_; y++)
00282       {
00283         float value = depth[y * resolution_ + x];
00284         if (value == 1.0)
00285           continue;
00286 
00287         worldPicker->Pick (x, y, value, renderer);
00288         worldPicker->GetPickPosition (coords);
00289         /*cloud->points[count_valid_depth_pixels].x = static_cast<pcl::traits::datatype<pcl::PointXYZ, pcl::fields::x>::type> (coords[0]);
00290         cloud->points[count_valid_depth_pixels].y = static_cast<pcl::traits::datatype<pcl::PointXYZ, pcl::fields::x>::type> (coords[1]);
00291         cloud->points[count_valid_depth_pixels].z = static_cast<pcl::traits::datatype<pcl::PointXYZ, pcl::fields::x>::type> (coords[2]);*/
00292         cloud->points[count_valid_depth_pixels].x = static_cast<float> (coords[0]);
00293         cloud->points[count_valid_depth_pixels].y = static_cast<float> (coords[1]);
00294         cloud->points[count_valid_depth_pixels].z = static_cast<float> (coords[2]);
00295         cloud->points[count_valid_depth_pixels].getVector4fMap () = backToRealScale_eigen
00296             * cloud->points[count_valid_depth_pixels].getVector4fMap ();
00297         count_valid_depth_pixels++;
00298       }
00299     }
00300 
00301     delete[] depth;
00302 
00303     if(compute_entropy_) {
00305       // * Compute area of the mesh
00307 
00308       vtkSmartPointer<vtkPolyData> polydata = mapper->GetInput ();
00309       polydata->BuildCells ();
00310 
00311       vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys ();
00312       vtkIdType npts = 0, *ptIds = NULL;
00313 
00314       double p1[3], p2[3], p3[3], area, totalArea = 0;
00315       for (cells->InitTraversal (); cells->GetNextCell (npts, ptIds);)
00316       {
00317         polydata->GetPoint (ptIds[0], p1);
00318         polydata->GetPoint (ptIds[1], p2);
00319         polydata->GetPoint (ptIds[2], p3);
00320         area = vtkTriangle::TriangleArea (p1, p2, p3);
00321         totalArea += area;
00322       }
00323 
00325       // * Select visible cells (triangles)
00327       vtkSmartPointer<vtkVisibleCellSelector> selector = vtkSmartPointer<vtkVisibleCellSelector>::New ();
00328       vtkSmartPointer<vtkIdTypeArray> selection = vtkSmartPointer<vtkIdTypeArray>::New ();
00329 
00330       selector->SetRenderer (renderer);
00331       selector->SetArea (0, 0, resolution_ - 1, resolution_ - 1);
00332       selector->Select ();
00333       selector->GetSelectedIds (selection);
00334 
00335       double visible_area = 0;
00336       for (int sel_id = 3; sel_id < (selection->GetNumberOfTuples () * selection->GetNumberOfComponents ()); sel_id
00337           += selection->GetNumberOfComponents ())
00338       {
00339         int id_mesh = int (selection->GetValue (sel_id));
00340 
00341         if (id_mesh >= polydata->GetNumberOfCells ())
00342           continue;
00343 
00344         vtkCell * cell = polydata->GetCell (id_mesh);
00345         vtkTriangle* triangle = dynamic_cast<vtkTriangle*> (cell);
00346         double p0[3];
00347         double p1[3];
00348         double p2[3];
00349         triangle->GetPoints ()->GetPoint (0, p0);
00350         triangle->GetPoints ()->GetPoint (1, p1);
00351         triangle->GetPoints ()->GetPoint (2, p2);
00352         visible_area += vtkTriangle::TriangleArea (p0, p1, p2);
00353       }
00354 
00355       //THIS CAN BE USED WHEN VTK >= 5.4 IS REQUIRED... vtkVisibleCellSelector is deprecated from VTK5.4
00356       /*vtkSmartPointer<vtkHardwareSelector> hardware_selector = vtkSmartPointer<vtkHardwareSelector>::New ();
00357        hardware_selector->ClearBuffers();
00358        vtkSmartPointer<vtkSelection> hdw_selection = vtkSmartPointer<vtkSelection>::New ();
00359        hardware_selector->SetRenderer (renderer);
00360        hardware_selector->SetArea (0, 0, xres - 1, yres - 1);
00361        hardware_selector->SetFieldAssociation(vtkDataObject::FIELD_ASSOCIATION_CELLS);
00362        hdw_selection = hardware_selector->Select ();
00363        vtkSmartPointer<vtkIdTypeArray> ids = vtkSmartPointer<vtkIdTypeArray>::New ();
00364        ids = vtkIdTypeArray::SafeDownCast(hdw_selection->GetNode(0)->GetSelectionList());
00365        double visible_area = 0;
00366        for (int sel_id = 0; sel_id < (ids->GetNumberOfTuples ()); sel_id++)
00367        {
00368        int id_mesh = selection->GetValue (sel_id);
00369        vtkCell * cell = polydata->GetCell (id_mesh);
00370        vtkTriangle* triangle = dynamic_cast<vtkTriangle*> (cell);
00371        double p0[3];
00372        double p1[3];
00373        double p2[3];
00374        triangle->GetPoints ()->GetPoint (0, p0);
00375        triangle->GetPoints ()->GetPoint (1, p1);
00376        triangle->GetPoints ()->GetPoint (2, p2);
00377        area = vtkTriangle::TriangleArea (p0, p1, p2);
00378        visible_area += area;
00379        }*/
00380 
00381       entropies_.push_back (float (visible_area / totalArea));
00382     }
00383 
00384     cloud->points.resize (count_valid_depth_pixels);
00385     cloud->width = count_valid_depth_pixels;
00386 
00387     //transform cloud to give camera coordinates instead of world coordinates!
00388     vtkSmartPointer<vtkMatrix4x4> view_transform = cam_tmp->GetViewTransformMatrix ();
00389     Eigen::Matrix4f trans_view;
00390     trans_view.setIdentity ();
00391 
00392     for (int x = 0; x < 4; x++)
00393       for (int y = 0; y < 4; y++)
00394         trans_view (x, y) = float (view_transform->GetElement (x, y));
00395 
00396     //NOTE: vtk view coordinate system is different than the standard camera coordinates (z forward, y down, x right)
00397     //thus, the fliping in y and z
00398     for (size_t i = 0; i < cloud->points.size (); i++)
00399     {
00400       cloud->points[i].getVector4fMap () = trans_view * cloud->points[i].getVector4fMap ();
00401       cloud->points[i].y *= -1.0f;
00402       cloud->points[i].z *= -1.0f;
00403     }
00404 
00405     renderer->RemoveActor (actor_view);
00406 
00407     generated_views_.push_back (cloud);
00408 
00409     //create pose, from OBJECT coordinates to CAMERA coordinates!
00410     vtkSmartPointer<vtkTransform> transOCtoCC = vtkSmartPointer<vtkTransform>::New ();
00411     transOCtoCC->PostMultiply ();
00412     transOCtoCC->Identity ();
00413     transOCtoCC->Concatenate (matrixCenter);
00414     transOCtoCC->Concatenate (matrixRotModel);
00415     transOCtoCC->Concatenate (matrixTranslation);
00416     transOCtoCC->Concatenate (cam_tmp->GetViewTransformMatrix ());
00417 
00418     //NOTE: vtk view coordinate system is different than the standard camera coordinates (z forward, y down, x right)
00419     //thus, the fliping in y and z
00420     vtkSmartPointer<vtkMatrix4x4> cameraSTD = vtkSmartPointer<vtkMatrix4x4>::New ();
00421     cameraSTD->Identity ();
00422     cameraSTD->SetElement (0, 0, 1);
00423     cameraSTD->SetElement (1, 1, -1);
00424     cameraSTD->SetElement (2, 2, -1);
00425 
00426     transOCtoCC->Concatenate (cameraSTD);
00427     transOCtoCC->Modified ();
00428 
00429     Eigen::Matrix4f pose_view;
00430     pose_view.setIdentity ();
00431 
00432     for (int x = 0; x < 4; x++)
00433       for (int y = 0; y < 4; y++)
00434         pose_view (x, y) = float (transOCtoCC->GetMatrix ()->GetElement (x, y));
00435 
00436     poses_.push_back (pose_view);
00437 
00438   }
00439 }


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:17:39