|
|
@ -21,6 +21,7 @@ |
|
|
|
#include <pMesh/io/reader/OBJReader.h> |
|
|
|
#include <pMesh/io/reader/VTKReader.h> |
|
|
|
#include <pMesh/io/writer/VTKWriter.h> |
|
|
|
#include <pMesh/io/writer/OBJWriter.h> |
|
|
|
#include <pMesh/io/adapter/DefaultReadAdapter.h> |
|
|
|
#include <pMesh/io/adapter/DefaultWriteAdapter.h> |
|
|
|
#include <boost/timer.hpp> |
|
|
@ -30,6 +31,7 @@ |
|
|
|
#include "test-path.h" |
|
|
|
|
|
|
|
#include "Octree/voxel/SurfaceVoxelBuilder.h" |
|
|
|
#include "Octree/voxel/SolidVoxelBuilder.h" |
|
|
|
#include "Octree/voxel/Voxel.h" |
|
|
|
|
|
|
|
class VTKTraverser : public pMesh::io::BaseReader, public Octree::OctreeTraverser { |
|
|
@ -44,14 +46,15 @@ public: |
|
|
|
bool operator>>(pMesh::io::ReadAdapter &adapter) override; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
int main() { |
|
|
|
pMesh::io::fs_path data_base_path = TEST_DATA_BASE_PATH; |
|
|
|
BOOST_LOG_TRIVIAL(debug) << "base data path is " << boost::filesystem::absolute(data_base_path); |
|
|
|
|
|
|
|
auto mesh_path = data_base_path / "stanford-bunny.obj"; |
|
|
|
auto mesh_path = data_base_path / "bunny.obj"; |
|
|
|
auto out_octree_path = data_base_path / "stanford-bunny-octree.vtk"; |
|
|
|
auto out_voxel_path = data_base_path / "stanford-bunny-voxel.vtk"; |
|
|
|
auto out_voxel_surf_path = data_base_path / "stanford-bunny-voxel-surf.obj"; |
|
|
|
auto out_voxel_line_path = data_base_path / "stanford-bunny-voxel-line.obj"; |
|
|
|
auto out_error_path = data_base_path / "stanford-bunny-error_points.vtk"; |
|
|
|
|
|
|
|
pMesh::Triangle3dMesh<> mesh; |
|
|
@ -61,7 +64,7 @@ int main() { |
|
|
|
BOOST_LOG_TRIVIAL(info) << "Load Face #" << mesh.f_size(); |
|
|
|
|
|
|
|
const int level = 4; |
|
|
|
const double block_size = 0.005; |
|
|
|
const double block_size = 0.03; |
|
|
|
|
|
|
|
boost::timer t; |
|
|
|
Octree::AABB aabb(mesh.aabb()); |
|
|
@ -84,14 +87,21 @@ int main() { |
|
|
|
<< pMesh::io::DefaultVolumeWriteAdapter<>(hexahedron_mesh)(); |
|
|
|
|
|
|
|
t.restart(); |
|
|
|
Octree::Voxel voxel; |
|
|
|
Octree::SurfaceVoxelBuilder voxel_builder(octree, mesh, block_size); |
|
|
|
voxel_builder.build(voxel); |
|
|
|
Octree::Voxel surfVoxel, solidVoxel; |
|
|
|
Octree::SurfaceVoxelBuilder(octree, mesh, block_size).build(surfVoxel); |
|
|
|
BOOST_LOG_TRIVIAL(debug) << "SurfaceVoxelBuilder time elapse " << t.elapsed(); |
|
|
|
|
|
|
|
t.restart(); |
|
|
|
Octree::SolidVoxelBuilder(surfVoxel).build(solidVoxel); |
|
|
|
BOOST_LOG_TRIVIAL(debug) << "SolidVoxelBuilder time elapse " << t.elapsed(); |
|
|
|
|
|
|
|
// output voxel
|
|
|
|
pMesh::HexahedronMesh<> voxelMesh; |
|
|
|
pMesh::SurfaceMesh<> faceMesh; |
|
|
|
pMesh::SurfaceMesh<> lineMesh; |
|
|
|
{ |
|
|
|
Octree::Voxel &voxel = solidVoxel; |
|
|
|
|
|
|
|
auto aabb = voxel.aabb; |
|
|
|
int _x = voxel._x; |
|
|
|
int _y = voxel._y; |
|
|
@ -104,34 +114,97 @@ int main() { |
|
|
|
for (int k = 0; k < _z; ++k) { |
|
|
|
double base_z = aabb.min().z() + k * block_size; |
|
|
|
|
|
|
|
if(voxel.voxels[voxel.id_at(i, j, k)]){ |
|
|
|
Octree::AABB v({base_x, base_y, base_z}, {base_x + block_size, base_y + block_size, base_z + block_size}); |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(0, {v.min().x(),v.min().y(),v.min().z()})); |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(1, {v.max().x(),v.min().y(),v.min().z()})); |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(2, {v.max().x(),v.max().y(),v.min().z()})); |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(3, {v.min().x(),v.max().y(),v.min().z()})); |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(4, {v.min().x(),v.min().y(),v.max().z()})); |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(5, {v.max().x(),v.min().y(),v.max().z()})); |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(6, {v.max().x(),v.max().y(),v.max().z()})); |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(7, {v.min().x(),v.max().y(),v.max().z()})); |
|
|
|
|
|
|
|
if (voxel.voxels[voxel.id_at(i, j, k)]) { |
|
|
|
int base_id = voxelMesh.v_size(); |
|
|
|
|
|
|
|
Octree::AABB v |
|
|
|
({base_x, base_y, base_z}, {base_x + block_size, base_y + block_size, base_z + block_size}); |
|
|
|
std::vector<pMesh::Point3d> vertices = { |
|
|
|
{v.min().x(), v.min().y(), v.min().z()}, |
|
|
|
{v.max().x(), v.min().y(), v.min().z()}, |
|
|
|
{v.max().x(), v.max().y(), v.min().z()}, |
|
|
|
{v.min().x(), v.max().y(), v.min().z()}, |
|
|
|
{v.min().x(), v.min().y(), v.max().z()}, |
|
|
|
{v.max().x(), v.min().y(), v.max().z()}, |
|
|
|
{v.max().x(), v.max().y(), v.max().z()}, |
|
|
|
{v.min().x(), v.max().y(), v.max().z()} |
|
|
|
}; |
|
|
|
|
|
|
|
static std::vector<std::vector<int>> line_cell = { |
|
|
|
{0, 1}, {1, 2}, {2, 3}, {3, 0}, |
|
|
|
{4, 5}, {5, 6}, {6, 7}, {7, 4}, |
|
|
|
{0, 4}, {1, 5}, {2, 6}, {3, 7} |
|
|
|
}; |
|
|
|
|
|
|
|
static std::vector<std::vector<int>> faces = { |
|
|
|
{0, 1, 2, 3}, {4, 5, 6, 7}, {0, 1, 5, 4}, {2, 3, 7, 6}, {0, 3, 7, 4}, {1, 2, 6, 5} |
|
|
|
}; |
|
|
|
|
|
|
|
for (const auto &v : vertices) { |
|
|
|
voxelMesh.vertices.emplace_back(pMesh::Volume::Vertex(0, v)); |
|
|
|
faceMesh.vertices.emplace_back(pMesh::Surface::Vertex(0, v)); |
|
|
|
lineMesh.vertices.emplace_back(pMesh::Surface::Vertex(0, v)); |
|
|
|
} |
|
|
|
|
|
|
|
pMesh::Volume::Cell cell; |
|
|
|
using PPP = pMesh::Volume::VertexHandle; |
|
|
|
using PVP = pMesh::Volume::VertexHandle; |
|
|
|
using PSP = pMesh::Surface::VertexHandle; |
|
|
|
cell.vertices = { |
|
|
|
PPP(base_id + 0), PPP(base_id + 1), PPP(base_id + 2), PPP(base_id + 3), |
|
|
|
PPP(base_id + 4), PPP(base_id + 5), PPP(base_id + 6), PPP(base_id + 7) |
|
|
|
PVP(base_id + 0), PVP(base_id + 1), PVP(base_id + 2), PVP(base_id + 3), |
|
|
|
PVP(base_id + 4), PVP(base_id + 5), PVP(base_id + 6), PVP(base_id + 7) |
|
|
|
}; |
|
|
|
voxelMesh.cells.emplace_back(cell); |
|
|
|
|
|
|
|
for (const auto &face : faces) { |
|
|
|
pMesh::Surface::Face f; |
|
|
|
f.vertices = { |
|
|
|
PSP(base_id + face[0]), PSP(base_id + face[1]), PSP(base_id + face[2]), PSP(base_id + face[3]) |
|
|
|
}; |
|
|
|
faceMesh.faces.emplace_back(f); |
|
|
|
} |
|
|
|
|
|
|
|
for (const auto &line : line_cell) { |
|
|
|
pMesh::Surface::Face l; |
|
|
|
l.vertices = { |
|
|
|
PSP(base_id + line[0]), PSP(base_id + line[1]) |
|
|
|
}; |
|
|
|
lineMesh.faces.emplace_back(l); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pMesh::io::VTKWriter(12, out_voxel_path) |
|
|
|
<< pMesh::io::DefaultVolumeWriteAdapter<>(voxelMesh)(); |
|
|
|
|
|
|
|
{ |
|
|
|
Eigen::MatrixXd vFaceMatrix(faceMesh.v_size(), 3); |
|
|
|
Eigen::MatrixXi fFaceMatrix(faceMesh.f_size(), 4); |
|
|
|
for (int i = 0; i < faceMesh.v_size(); ++i) { |
|
|
|
vFaceMatrix.row(i) = faceMesh.vertices[i].attr.coordinate.transpose(); |
|
|
|
} |
|
|
|
for (int i = 0; i < faceMesh.f_size(); ++i) { |
|
|
|
auto ff = faceMesh.faces[i].attr.vertices; |
|
|
|
fFaceMatrix.row(i) <<ff[0].id(),ff[1].id(),ff[2].id(),ff[3].id(); |
|
|
|
} |
|
|
|
igl::writeOBJ(out_voxel_surf_path.string(), vFaceMatrix, fFaceMatrix); |
|
|
|
} |
|
|
|
|
|
|
|
{ |
|
|
|
Eigen::MatrixXd vFaceMatrix(lineMesh.v_size(), 3); |
|
|
|
Eigen::MatrixXi fFaceMatrix(lineMesh.f_size(), 2); |
|
|
|
for (int i = 0; i < lineMesh.v_size(); ++i) { |
|
|
|
vFaceMatrix.row(i) = lineMesh.vertices[i].attr.coordinate.transpose(); |
|
|
|
} |
|
|
|
for (int i = 0; i < lineMesh.f_size(); ++i) { |
|
|
|
auto ff = lineMesh.faces[i].attr.vertices; |
|
|
|
fFaceMatrix.row(i) <<ff[0].id(),ff[1].id(); |
|
|
|
} |
|
|
|
igl::writeOBJ(out_voxel_line_path.string(), vFaceMatrix, fFaceMatrix); |
|
|
|
std::cout << "Write lines" << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|