Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VTK based implementation of extract trianglemesh #6648

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
74 changes: 74 additions & 0 deletions cpp/open3d/pipelines/integration/UniformTSDFVolume.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@
#include "open3d/utility/Helper.h"
#include "open3d/utility/Parallel.h"

#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkFlyingEdges3D.h>
#include <vtkMarchingCubes.h>
#include "open3d/t/geometry/VtkUtils.h"

#include <vtkPolyData.h>
#include <vtkImageData.h>
#include <vtkPointData.h>
#include <vtkFloatArray.h>
#include <vtkSmartPointer.h>
#include <vtkFlyingEdges3D.h>
#include <vtkMarchingCubes.h>
#include <vtkInformation.h>
#include <vtkPolyDataConnectivityFilter.h>

namespace open3d {
namespace pipelines {
namespace integration {
Expand Down Expand Up @@ -138,6 +154,64 @@ std::shared_ptr<geometry::PointCloud> UniformTSDFVolume::ExtractPointCloud() {
return pointcloud;
}

std::shared_ptr<geometry::TriangleMesh>
UniformTSDFVolume::ExtractTriangleMesh_v2() {
auto mesh = std::make_shared<geometry::TriangleMesh>();
//float *image_array = new float[resolution_ * resolution_ * resolution_];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove unused comments.

//const long r_sq = resolution_ * resolution_;
int dims[] = {resolution_, resolution_, resolution_};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use std::array or modern containers, or explicitly declare array size.

float ***values = new float **[dims[0]];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All pointers are allocated but not released. It's better to allocate a flattened std::vector and unroll the indices.

for(int i = 0; i <= dims[1]; ++i) {
values[i] = new float *[dims[2]];
for (int j = 0; j <= dims[1]; ++j) {
values[i][j] = new float[dims[2]];
}
}

for (int x = 0; x < resolution_ - 1; x++) {
for (int y = 0; y < resolution_ - 1; y++) {
for (int z = 0; z < resolution_ - 1; z++) {
Eigen::Vector3i idx0(x, y, z);
const float f = voxels_[IndexOf(idx0)].tsdf_;
values[x][y][z] = f;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only TSDF is used here, weights are not handled, see the original implementation. This is known to provide problematic mesh especially around boundaries.

}
}
}
vtkIdType totalSize = (vtkIdType)dims[0] * (vtkIdType) dims[1] * (vtkIdType) dims[2];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use static_cast.

vtkNew<vtkFloatArray> array;
array->SetArray(**values, totalSize, 1);
vtkNew<vtkInformation> info;
vtkNew<vtkImageData> imageData;
imageData->GetPointData()->SetScalars(array);
imageData->SetDimensions(dims);
imageData->SetScalarType(VTK_UNSIGNED_SHORT, info);
imageData->SetSpacing(1.0, 1.0, 1.0);
imageData->SetOrigin(0.0, 0.0, 0.0);

#ifdef USE_FLYING_EDGES
vtkNew<vtkFlyingEdges3D> surface;
#else
vtkNew<vtkMarchingCubes> surface;
#endif
surface->SetInputData(imageData);
surface->ComputeNormalsOn();
const double isoValue = 0.0;
surface->SetValue(0, isoValue);

//// To remain largest region.
//// vtkNew<vtkPolyDataConnectivityFilter> confilter;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either remove unused code or add a flag to run the code.

//// confilter->SetInputConnection(surface->GetOutputPort());
//// confilter->SetExtractionModeToLargestRegion();
//// vtkPolyData *pdata = confilter->GetOutput();
//// cout << "pdata: " << pdata << std::endl;
vtkPolyData *sdata = surface->GetOutput();
auto tmesh = open3d::t::geometry::vtkutils::CreateTriangleMeshFromVtkPolyData(sdata);
auto lmesh = tmesh.ToLegacy();
std::shared_ptr<geometry::TriangleMesh> pmesh(new geometry::TriangleMesh(lmesh.vertices_, lmesh.triangles_));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory is copied twice in the conversion. It is also unsafe to use new to initialize a shared_ptr. Please use std::make_shared and reduce redundant memory copy.

return pmesh;
}


std::shared_ptr<geometry::TriangleMesh>
UniformTSDFVolume::ExtractTriangleMesh() {
// implementation of marching cubes, based on
Expand Down
2 changes: 2 additions & 0 deletions cpp/open3d/pipelines/integration/UniformTSDFVolume.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class UniformTSDFVolume : public TSDFVolume {
const Eigen::Matrix4d &extrinsic) override;
std::shared_ptr<geometry::PointCloud> ExtractPointCloud() override;
std::shared_ptr<geometry::TriangleMesh> ExtractTriangleMesh() override;
/// Temporary function will be deleted/"merged" with ExtractTriangleMesh
std::shared_ptr<geometry::TriangleMesh> ExtractTriangleMesh_v2();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to inject the implementation as an option in ExtractTriangleMesh(bool use_vtk = False).


/// Debug function to extract the voxel data into a VoxelGrid
std::shared_ptr<geometry::PointCloud> ExtractVoxelPointCloud() const;
Expand Down
2 changes: 2 additions & 0 deletions cpp/pybind/pipelines/integration/integration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ In SIGGRAPH, 1996)");
"Debug function to inject the voxel TSDF data.", "tsdf"_a)
.def("inject_volume_color", &UniformTSDFVolume::InjectVolumeColor,
"Debug function to inject the voxel Color data.", "color"_a)
// TODO remove after debugging
.def("extract_triangle_mesh_v2", &UniformTSDFVolume::ExtractTriangleMesh_v2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, do not duplicate API.

.def_readwrite("length", &UniformTSDFVolume::length_,
"Total length, where ``voxel_length = length / "
"resolution``.")
Expand Down