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");
//! 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);
};
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)
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);
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);
}
return cloud;
}
+cv::viz::Mesh cv::viz::readMesh(const String& file) { return Mesh::load(file); }
+
///////////////////////////////////////////////////////////////////////////////////////////////
/// Read/write poses and trajectories
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;
}
if (normals)
output->GetPointData()->SetNormals(normals);
+ if (tcoords)
+ output->GetPointData()->SetTCoords(tcoords);
+
return 1;
}
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);
+ }
+}
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();
vtkSmartPointer<vtkCellArray> vertices;
vtkSmartPointer<vtkUnsignedCharArray> scalars;
vtkSmartPointer<vtkDataArray> normals;
+ vtkSmartPointer<vtkDataArray> tcoords;
private:
vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented.
void operator=(const vtkCloudMatSource&); // Not implemented.
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);
};
}
}