added support of texture for mesh
authorAnatoly Baksheev <no@email>
Sun, 12 Jan 2014 20:46:24 +0000 (00:46 +0400)
committerAnatoly Baksheev <no@email>
Sun, 19 Jan 2014 14:38:58 +0000 (18:38 +0400)
modules/viz/include/opencv2/viz.hpp
modules/viz/include/opencv2/viz/types.hpp
modules/viz/src/clouds.cpp
modules/viz/src/vizcore.cpp
modules/viz/src/vtk/vtkCloudMatSource.cpp
modules/viz/src/vtk/vtkCloudMatSource.h

index 32e32a7..89810d5 100644 (file)
@@ -99,6 +99,11 @@ namespace cv
         CV_EXPORTS Mat  readCloud (const String& file, OutputArray colors = noArray(), OutputArray normals = noArray());
 
         ///////////////////////////////////////////////////////////////////////////////////////////////
+        /// Read mesh. Only ply format is supported now
+
+        CV_EXPORTS Mesh readMesh (const String& file);
+
+        ///////////////////////////////////////////////////////////////////////////////////////////////
         /// Read/write poses and trajectories
 
         CV_EXPORTS bool readPose(const String& file, Affine3d& pose, const String& tag = "pose");
index 01ddd02..cdd89d3 100644 (file)
@@ -113,6 +113,8 @@ namespace cv
             //! where n is the number of points in the poligon, and id is a zero-offset index into an associated cloud.
             Mat polygons;
 
+            Mat texture, tcoords;
+
             //! Loads mesh from a given ply file
             static Mesh load(const String& file);
         };
index d5283d4..ff81775 100644 (file)
@@ -95,8 +95,25 @@ cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud)
 
     Vec6d bounds(cloud_source->GetOutput()->GetPoints()->GetBounds());
 
-    WPaintedCloud cloud_widget(cloud, Vec3d(bounds[0], bounds[2], bounds[4]), Vec3d(bounds[1], bounds[3], bounds[5]));
-    *this = cloud_widget;
+    vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::New();
+    elevation->SetInputConnection(cloud_source->GetOutputPort());
+    elevation->SetLowPoint(bounds[0], bounds[2], bounds[4]);
+    elevation->SetHighPoint(bounds[1], bounds[3], bounds[5]);
+    elevation->SetScalarRange(0.0, 1.0);
+    elevation->Update();
+
+    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+    VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput()));
+    mapper->ImmediateModeRenderingOff();
+    mapper->ScalarVisibilityOn();
+    mapper->SetColorModeToMapScalars();
+
+    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
+    actor->GetProperty()->SetInterpolationToFlat();
+    actor->GetProperty()->BackfaceCullingOn();
+    actor->SetMapper(mapper);
+
+    WidgetAccessor::setProp(*this, actor);
 }
 
 cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2)
@@ -329,7 +346,7 @@ cv::viz::WMesh::WMesh(const Mesh &mesh)
     CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1);
 
     vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New();
-    source->SetColorCloud(mesh.cloud, mesh.colors);
+    source->SetColorCloudNormalsTCoords(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords);
     source->Update();
 
     Mat lookup_buffer(1, mesh.cloud.total(), CV_32SC1);
@@ -394,6 +411,16 @@ cv::viz::WMesh::WMesh(const Mesh &mesh)
     actor->GetProperty()->ShadingOff();
     actor->SetMapper(mapper);
 
+    if (!mesh.texture.empty())
+    {
+        vtkSmartPointer<vtkImageMatSource> image_source = vtkSmartPointer<vtkImageMatSource>::New();
+        image_source->SetImage(mesh.texture);
+
+        vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
+        texture->SetInputConnection(image_source->GetOutputPort());
+        actor->SetTexture(texture);
+    }
+
     WidgetAccessor::setProp(*this, actor);
 }
 
index a553f8d..ee74f2a 100644 (file)
@@ -205,6 +205,8 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray n
     return cloud;
 }
 
+cv::viz::Mesh cv::viz::readMesh(const String& file) { return Mesh::load(file); }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////
 /// Read/write poses and trajectories
 
index 7884f1a..9a341b7 100644 (file)
@@ -128,7 +128,34 @@ int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArr
     else if (normals.depth() == CV_64F && cloud.depth() == CV_64F)
         filterNanNormalsCopy<double, double>(normals, cloud, total);
     else
-        CV_Assert(!"Unsupported normals type");
+        CV_Assert(!"Unsupported normals/cloud type");
+
+    return total;
+}
+
+int cv::viz::vtkCloudMatSource::SetColorCloudNormalsTCoords(InputArray _cloud, InputArray _colors, InputArray _normals, InputArray _tcoords)
+{
+    int total = SetColorCloudNormals(_cloud, _colors, _normals);
+
+    if (_tcoords.empty())
+        return total;
+
+    CV_Assert(_tcoords.depth() == CV_32F || _tcoords.depth() == CV_64F);
+    CV_Assert(_tcoords.channels() == 2 && _tcoords.size() == _cloud.size());
+
+    Mat cloud = _cloud.getMat();
+    Mat tcoords = _tcoords.getMat();
+
+    if (tcoords.depth() == CV_32F && cloud.depth() == CV_32F)
+        filterNanTCoordsCopy<float, float>(tcoords, cloud, total);
+    else if (tcoords.depth() == CV_32F && cloud.depth() == CV_64F)
+        filterNanTCoordsCopy<float, double>(tcoords, cloud, total);
+    else if (tcoords.depth() == CV_64F && cloud.depth() == CV_32F)
+        filterNanTCoordsCopy<double, float>(tcoords, cloud, total);
+    else if (tcoords.depth() == CV_64F && cloud.depth() == CV_64F)
+        filterNanTCoordsCopy<double, double>(tcoords, cloud, total);
+    else
+        CV_Assert(!"Unsupported tcoords/cloud type");
 
     return total;
 }
@@ -146,6 +173,9 @@ int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request),
     if (normals)
         output->GetPointData()->SetNormals(normals);
 
+    if (tcoords)
+        output->GetPointData()->SetTCoords(tcoords);
+
     return 1;
 }
 
@@ -232,3 +262,25 @@ void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals,
                 normals->SetTuple(pos++, srow);
     }
 }
+
+template<typename _Tn, typename _Msk>
+void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total)
+{   
+    typedef Vec<_Tn, 2> Vec2;
+    tcoords = vtkSmartPointer< VtkDepthTraits<_Tn>::array_type >::New();
+    tcoords->SetName("TextureCoordinates");
+    tcoords->SetNumberOfComponents(2);
+    tcoords->SetNumberOfTuples(total);
+
+    int pos = 0;
+    for (int y = 0; y < mask.rows; ++y)
+    {
+        const Vec2* srow = _tcoords.ptr<Vec2>(y);
+        const Vec2* send = srow + _tcoords.cols;
+        const _Msk* mrow = mask.ptr<_Msk>(y);
+
+        for (; srow != send; ++srow, mrow += mask.channels())
+            if (!isNan(mrow))
+                tcoords->SetTuple(pos++, srow->val);
+    }
+}
index a7f9fff..56bd93e 100644 (file)
@@ -62,8 +62,9 @@ namespace cv
             vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm)
 
             virtual int SetCloud(InputArray cloud);
-            virtual int SetColorCloud(InputArray cloud, InputArray colors = noArray());
-            virtual int SetColorCloudNormals(InputArray cloud, InputArray colors = noArray(), InputArray normals = noArray());
+            virtual int SetColorCloud(InputArray cloud, InputArray colors);
+            virtual int SetColorCloudNormals(InputArray cloud, InputArray colors, InputArray normals);
+            virtual int SetColorCloudNormalsTCoords(InputArray cloud, InputArray colors, InputArray normals, InputArray tcoords);
 
         protected:
             vtkCloudMatSource();
@@ -75,6 +76,7 @@ namespace cv
             vtkSmartPointer<vtkCellArray> vertices;
             vtkSmartPointer<vtkUnsignedCharArray> scalars;
             vtkSmartPointer<vtkDataArray> normals;
+            vtkSmartPointer<vtkDataArray> tcoords;
         private:
             vtkCloudMatSource(const vtkCloudMatSource&);  // Not implemented.
             void operator=(const vtkCloudMatSource&);  // Not implemented.
@@ -84,6 +86,9 @@ namespace cv
 
             template<typename _Tn, typename _Msk>
             void filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total);
+
+            template<typename _Tn, typename _Msk>
+            void filterNanTCoordsCopy(const Mat& tcoords, const Mat& mask, int total);
         };
     }
 }