Browse Source

add udf and format the project

master
lab pc 4 years ago
parent
commit
745b7cdaf7
  1. 8
      CMakeLists.txt
  2. 34
      include/Octree/AABB.h
  3. 7
      include/Octree/BaseOctree.h
  4. 52
      include/Octree/OctreeIO.h
  5. 2
      include/Octree/sdf/SDFData.h
  6. 2
      include/Octree/sdf/SDFOctree.h
  7. 2
      include/Octree/sdf/SDFTraversalSampler.h
  8. 2
      include/Octree/udf/UDFData.h
  9. 7
      include/Octree/udf/UDFOctree.h
  10. 2
      include/Octree/udf/UDFTraversalSampler.h
  11. 45
      src/AABB.cpp
  12. 29
      src/OctreeIO.cpp
  13. 2
      src/sdf/SDFData.cpp
  14. 6
      src/sdf/SDFOctree.cpp
  15. 18
      src/sdf/SDFTraversalSampler.cpp
  16. 2
      src/udf/UDFData.cpp
  17. 9
      src/udf/UDFOctree.cpp
  18. 18
      src/udf/UDFTraversalSampler.cpp
  19. 1
      tests/octree_test/.gitignore
  20. 5
      tests/octree_test/CMakeLists.txt
  21. 21
      tests/octree_test/main.cpp
  22. 16
      tests/octree_test/test-path.h.in
  23. 1
      tests/sdf_test/.gitignore
  24. 5
      tests/sdf_test/CMakeLists.txt
  25. 7
      tests/sdf_test/main.cpp
  26. 16
      tests/sdf_test/test-path.h.in
  27. 1
      tests/udf_test/.gitignore
  28. 6
      tests/udf_test/CMakeLists.txt
  29. 198
      tests/udf_test/main.cpp
  30. 16
      tests/udf_test/test-path.h.in

8
CMakeLists.txt

@ -27,13 +27,21 @@ add_library(Octree SHARED ${headers} ${sources})
target_link_libraries(Octree igl::core ${Boost_LIBRARIES} Eigen3::Eigen pMesh)
target_include_directories(Octree PUBLIC ${PROJECT_SOURCE_DIR}/include)
# --------------------- TEST --------------------
if(Octree_BUILD_TEST)
set(TEST_DATA_BASE_PATH ${PROJECT_SOURCE_DIR}/data)
endif()
if(Octree_BUILD_TEST)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests/octree_test)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests/sdf_test)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests/udf_test)
endif()
enable_testing()
if(Octree_BUILD_TEST)
add_test(NAME octree_test COMMAND $<TARGET_FILE:octree_test>)
add_test(NAME sdf_test COMMAND $<TARGET_FILE:sdf_test>)
add_test(NAME udf_test COMMAND $<TARGET_FILE:udf_test>)
endif()

34
include/Octree/AABB.h

@ -16,7 +16,7 @@
namespace Octree {
class AABB {
Eigen::Vector3d min, max;
Eigen::Vector3d _min, _max;
public:
explicit AABB(const Eigen::Vector3d &min, const Eigen::Vector3d &max);
@ -30,11 +30,11 @@ namespace Octree {
public:
Eigen::Vector3d size() const;
Eigen::Vector3d get_min() const;
Eigen::Vector3d min() const;
Eigen::Vector3d get_max() const;
Eigen::Vector3d max() const;
Eigen::Vector3d get_center() const;
Eigen::Vector3d center() const;
/**
* @reference: https://github.com/diwi/Space_Partitioning_Octree_BVH
@ -45,14 +45,36 @@ namespace Octree {
*/
bool intersect_triangle(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c) const;
/**
* If the AABB contains the point v
* @param v
* @return
*/
bool contains(const Eigen::Vector3d &v) const;
bool
fully_contains_triangle(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c) const;
/**
* If the AABB fully contains a triangle
* @param a
* @param b
* @param c
* @return
*/
bool fully_contains_triangle(const Eigen::Vector3d &a,
const Eigen::Vector3d &b,
const Eigen::Vector3d &c) const;
/**
* Divide this AABB into 8 parts
* @return
*/
std::array<AABB, 8> half_divide() const;
public:
/**
* Extend boundary with @param step
* @param step
*/
void extend(double step);
};
}

7
include/Octree/BaseOctree.h

@ -48,6 +48,8 @@ namespace Octree {
array<ocnode_sptr, 8> children;
ocnode_ptr father;
AABB aabb;
public:
set<uint32_t> tri_ids;
public:
@ -90,6 +92,11 @@ namespace Octree {
* @return
*/
ocnode_sptr map_node(const Eigen::Vector3d &pos);
public: //Getter
uint32_t get_level(){ return level; }
AABB get_aabb() { return aabb; }
};
class BaseOctree {

52
include/Octree/OctreeIO.h

@ -1,52 +0,0 @@
/**
* ------------------------------------
* @author: Weipeng Kong
* @date: 2021/11/22
* @email: yjxkwp@foxmail.com
* @site: https://donot.fit
* @description:
* ------------------------------------
**/
#ifndef OCTREE_OCTREEIO_H
#define OCTREE_OCTREEIO_H
#include <boost/filesystem.hpp>
namespace Octree {
class BaseOctree;
class OctreeNode;
class OctreeIO {
protected:
using fs_path = boost::filesystem::path;
};
class OctreeSaver : public OctreeIO {
private:
const BaseOctree &octree;
public:
explicit OctreeSaver(const BaseOctree &octree);
void save(const fs_path &path);
private:
void save_recursively(const OctreeNode &node);
};
class OctreeLoader : public OctreeIO {
private:
BaseOctree &octree;
public:
explicit OctreeLoader(BaseOctree &octree);
void load(const fs_path &path);
};
}
#endif //OCTREE_OCTREEIO_H

2
include/Octree/SDFData.h → include/Octree/sdf/SDFData.h

@ -14,7 +14,7 @@
#include <vector>
#include <Eigen/Core>
#include <Eigen/Dense>
#include "VoxelDenseData.h"
#include "Octree/VoxelDenseData.h"
namespace Octree {
class SDFData: public VoxelDenseData{

2
include/Octree/SDFOctree.h → include/Octree/sdf/SDFOctree.h

@ -11,7 +11,7 @@
#ifndef OCTREE_SDFOCTREE_H
#define OCTREE_SDFOCTREE_H
#include "BaseOctree.h"
#include "Octree/BaseOctree.h"
namespace Octree {

2
include/Octree/SDFTraversalSampler.h → include/Octree/sdf/SDFTraversalSampler.h

@ -11,7 +11,7 @@
#ifndef OCTREE_SDFTRAVERSALSAMPLER_H
#define OCTREE_SDFTRAVERSALSAMPLER_H
#include "OctreeTraverser.h"
#include "Octree/OctreeTraverser.h"
#include "SDFData.h"
#include <utility>
#include <pMesh/mesh/TriangleMesh.h>

2
include/Octree/UDFData.h → include/Octree/udf/UDFData.h

@ -14,7 +14,7 @@
#include <vector>
#include <Eigen/Core>
#include <Eigen/Dense>
#include "VoxelDenseData.h"
#include "Octree/VoxelDenseData.h"
namespace Octree {

7
include/Octree/UDFOctree.h → include/Octree/udf/UDFOctree.h

@ -12,10 +12,10 @@
#define OCTREE_UDFOCTREE_H
#include "BaseOctree.h"
#include "Octree/BaseOctree.h"
namespace Octree {
namespace Octree{
class UDFData;
class UDFOctreeNode;
@ -24,6 +24,9 @@ namespace Octree {
using ocudfnode_sptr = shared_ptr<UDFOctreeNode>;
using ocudfnode_wptr = weak_ptr<UDFOctreeNode>;
using ocudfnode_ptr = UDFOctreeNode *;
}
namespace Octree {
struct UDFOctreeNode : public OctreeNode {
public:

2
include/Octree/UDFTraversalSampler.h → include/Octree/udf/UDFTraversalSampler.h

@ -11,7 +11,7 @@
#ifndef OCTREE_SDFTRAVERSALSAMPLER_H
#define OCTREE_SDFTRAVERSALSAMPLER_H
#include "OctreeTraverser.h"
#include "Octree/OctreeTraverser.h"
#include "UDFData.h"
#include <utility>
#include <pMesh/mesh/TriangleMesh.h>

45
src/AABB.cpp

@ -47,12 +47,12 @@ namespace AABBTools {
Octree::AABB::AABB(const Eigen::Vector3d &min, const Eigen::Vector3d &max) : min(min), max(max) {
Octree::AABB::AABB(const Eigen::Vector3d &min, const Eigen::Vector3d &max) : _min(min), _max(max) {
}
Octree::AABB::AABB(double minx, double maxx, double miny, double maxy, double minz, double maxz) :
min(minx, miny, minz), max(maxx, maxy, maxz) {
_min(minx, miny, minz), _max(maxx, maxy, maxz) {
}
@ -62,28 +62,28 @@ Octree::AABB::AABB(const std::array<double, 6> &aabb) :
Eigen::Vector3d Octree::AABB::size() const {
return max - min;
return _max - _min;
}
Eigen::Vector3d Octree::AABB::get_center() const {
return (max + min) / 2.0;
Eigen::Vector3d Octree::AABB::center() const {
return (_max + _min) / 2.0;
}
Eigen::Vector3d Octree::AABB::get_min() const {
return min;
Eigen::Vector3d Octree::AABB::min() const {
return _min;
}
Eigen::Vector3d Octree::AABB::get_max() const {
return max;
Eigen::Vector3d Octree::AABB::max() const {
return _max;
}
bool Octree::AABB::intersect_triangle(const Eigen::Vector3d &a,
const Eigen::Vector3d &b,
const Eigen::Vector3d &c) const {
const Eigen::Vector3d &b,
const Eigen::Vector3d &c) const {
using Eigen::Vector3d;
Vector3d center = this->get_center();
Vector3d center = this->center();
Vector3d hs = this->size() / 2;
Vector3d v0 = a - center;
Vector3d v1 = b - center;
@ -125,7 +125,7 @@ bool Octree::AABB::intersect_triangle(const Eigen::Vector3d &a,
// Bullet 1:
// First test overlap in the {x,y,z}-directions.
// Find min, max of the triangle each direction, and test for overlap in that
// Find _min, _max of the triangle each direction, and test for overlap in that
// direction -- this is equivalent to testing a minimal AABB around the triangle against the AABB.
if (AABBTools::directionTest(v0[0], v1[0], v2[0], hs[0])) return false; // Test in X-direction.
if (AABBTools::directionTest(v0[1], v1[1], v2[1], hs[1])) return false; // Test in Y-direction.
@ -143,12 +143,13 @@ bool Octree::AABB::intersect_triangle(const Eigen::Vector3d &a,
bool Octree::AABB::contains(const Eigen::Vector3d &v) const {
return (v.x() >= min.x() && v.y() >= min.y() && v.z() >= min.z()) &&
(v.x() <= max.x() && v.y() <= max.y() && v.z() <= max.z());
return (v.x() >= _min.x() && v.y() >= _min.y() && v.z() >= _min.z()) &&
(v.x() <= _max.x() && v.y() <= _max.y() && v.z() <= _max.z());
}
bool Octree::AABB::fully_contains_triangle(const Eigen::Vector3d &a, const Eigen::Vector3d &b,
const Eigen::Vector3d &c) const {
bool Octree::AABB::fully_contains_triangle(const Eigen::Vector3d &a,
const Eigen::Vector3d &b,
const Eigen::Vector3d &c) const {
return contains(a) && contains(b) && contains(c);
}
@ -156,9 +157,9 @@ std::array<Octree::AABB, 8> Octree::AABB::half_divide() const {
std::array<AABB, 8> aabbs;
auto half_size = this->size() / 2.0;
for (int i = 0; i < 8; ++i) {
Eigen::Vector3d sub_min = {min[0] + (((i & 4) > 0) ? half_size[0] : 0),
min[1] + (((i & 2) > 0) ? half_size[1] : 0),
min[2] + (((i & 1) > 0) ? half_size[2] : 0)};
Eigen::Vector3d sub_min = {_min[0] + (((i & 4) > 0) ? half_size[0] : 0),
_min[1] + (((i & 2) > 0) ? half_size[1] : 0),
_min[2] + (((i & 1) > 0) ? half_size[2] : 0)};
Eigen::Vector3d sub_max = sub_min + half_size;
aabbs[i] = AABB(sub_min, sub_max);
}
@ -166,6 +167,6 @@ std::array<Octree::AABB, 8> Octree::AABB::half_divide() const {
}
void Octree::AABB::extend(double step) {
this->min -= Eigen::Vector3d(step, step, step);
this->max += Eigen::Vector3d(step, step, step);
this->_min -= Eigen::Vector3d(step, step, step);
this->_max += Eigen::Vector3d(step, step, step);
}

29
src/OctreeIO.cpp

@ -1,29 +0,0 @@
/**
* ------------------------------------
* @author: Weipeng Kong
* @date: 2021/11/22
* @email: yjxkwp@foxmail.com
* @site: https://donot.fit
* @description:
* ------------------------------------
**/
#include "../include/Octree/OctreeIO.h"
#include "Octree/BaseOctree.h"
namespace SerializationTool{
}
Octree::OctreeSaver::OctreeSaver(const Octree::BaseOctree &octree): octree(octree) {
}
void Octree::OctreeSaver::save(const Octree::OctreeIO::fs_path &path) {
}
void Octree::OctreeSaver::save_recursively(const Octree::OctreeNode &node) {
}

2
src/SDFData.cpp → src/sdf/SDFData.cpp

@ -8,7 +8,7 @@
* ------------------------------------
**/
#include "Octree/SDFData.h"
#include "Octree/sdf/SDFData.h"
Octree::SDFData::SDFData(const std::vector<double> &value, int _x, int _y, int _z) : VoxelDenseData(value, _x, _y, _z) {

6
src/SDFOctree.cpp → src/sdf/SDFOctree.cpp

@ -8,12 +8,12 @@
* ------------------------------------
**/
#include "Octree/SDFOctree.h"
#include "Octree/SDFData.h"
#include "Octree/sdf/SDFOctree.h"
#include "Octree/sdf/SDFData.h"
double Octree::SDFOctreeNode::get_sdf(const Eigen::Vector3d &pos) {
Eigen::Vector3d relative = pos - aabb.get_min();
Eigen::Vector3d relative = pos - aabb.min();
auto size = aabb.size();
relative.x() = relative.x() / size.x();
relative.y() = relative.y() / size.y();

18
src/SDFTraversalSampler.cpp → src/sdf/SDFTraversalSampler.cpp

@ -8,9 +8,9 @@
* ------------------------------------
**/
#include "Octree/SDFTraversalSampler.h"
#include "Octree/SDFData.h"
#include "Octree/SDFOctree.h"
#include "Octree/sdf/SDFTraversalSampler.h"
#include "Octree/sdf/SDFData.h"
#include "Octree/sdf/SDFOctree.h"
#include <igl/signed_distance.h>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time.hpp>
@ -26,9 +26,9 @@ void Octree::SDFTraversalBuilder::visit_node(Octree::OctreeNode &node) {
// if (not node.is_leaf()) return;
auto &sdf_node = (SDFOctreeNode &)node;
if (node.level >= octree.get_max_level()) {
if (node.get_level() >= octree.get_max_level()) {
// deepest voxel
auto aabb_size = node.aabb.size();
auto aabb_size = node.get_aabb().size();
#if 0
BOOST_LOG_TRIVIAL(debug) << "aabb_size = " << aabb_size.transpose();
BOOST_LOG_TRIVIAL(debug) << "\t\t\t\t = " << (aabb_size / sample_step).transpose();
@ -81,16 +81,16 @@ void Octree::SDFTraversalBuilder::build() {
int index_base = 0;
for (const auto &qbox: this->query_boxes) {
auto &sdf = *qbox.node.sdf;
auto &aabb = qbox.node.aabb;
const auto pos_base = aabb.get_min();
const auto pos_max = aabb.get_max();
auto aabb = qbox.node.get_aabb();
const auto pos_base = aabb.min();
const auto pos_max = aabb.max();
const auto aabb_size = aabb.size();
const int _x = sdf._x - 1, _y = sdf._y - 1, _z = sdf._z - 1;
const Eigen::Vector3d local_step(aabb_size.x() / _x, aabb_size.y() / _y, aabb_size.z() / _z);
for (int z = 0; z <= _z; ++z) {
// double pos_z = std::min(pos_base.z() + z * local_step.x(), pos_max.z());
// double pos_z = std::_min(pos_base.z() + z * local_step.x(), pos_max.z());
double pos_z = pos_base.z() + z * local_step.z();
for (int y = 0; y <= _y; ++y) {
double pos_y = pos_base.y() + y * local_step.y();

2
src/UDFData.cpp → src/udf/UDFData.cpp

@ -8,7 +8,7 @@
* ------------------------------------
**/
#include "Octree/UDFData.h"
#include "Octree/udf/UDFData.h"
Octree::UDFData::UDFData(const std::vector<double> &value, int _x, int _y, int _z) : VoxelDenseData(value, _x, _y, _z) {

9
src/UDFOctree.cpp → src/udf/UDFOctree.cpp

@ -8,8 +8,8 @@
* ------------------------------------
**/
#include "Octree/UDFOctree.h"
#include "Octree/UDFData.h"
#include "Octree/udf/UDFOctree.h"
#include "Octree/udf/UDFData.h"
Octree::UDFOctreeNode::UDFOctreeNode(Octree::ocnode_ptr father, const Octree::AABB &aabb, uint32_t level) : OctreeNode(
father, aabb, level) {
@ -17,7 +17,7 @@ Octree::UDFOctreeNode::UDFOctreeNode(Octree::ocnode_ptr father, const Octree::AA
}
double Octree::UDFOctreeNode::get_udf(const Eigen::Vector3d &pos) {
Eigen::Vector3d relative = pos - aabb.get_min();
Eigen::Vector3d relative = pos - aabb.min();
auto size = aabb.size();
relative.x() = relative.x() / size.x();
relative.y() = relative.y() / size.y();
@ -29,6 +29,7 @@ Octree::ocnode_sptr Octree::UDFOctreeNode::make_child(const Octree::AABB &aabb)
return std::make_shared<UDFOctreeNode>(this, aabb, level + 1);
}
Octree::UDFOctree::UDFOctree(uint32_t max_level, const Octree::AABB &aabb) : BaseOctree(max_level, aabb) {
Octree::UDFOctree::UDFOctree(uint32_t max_level, const Octree::AABB &aabb) :
BaseOctree(max_level, std::static_pointer_cast<OctreeNode>(std::make_shared<UDFOctreeNode>(nullptr, aabb, 0))) {
}

18
src/UDFTraversalSampler.cpp → src/udf/UDFTraversalSampler.cpp

@ -8,9 +8,9 @@
* ------------------------------------
**/
#include "Octree/UDFTraversalSampler.h"
#include "Octree/UDFData.h"
#include "Octree/UDFOctree.h"
#include "Octree/udf/UDFTraversalSampler.h"
#include "Octree/udf/UDFData.h"
#include "Octree/udf/UDFOctree.h"
#include <igl/signed_distance.h>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time.hpp>
@ -28,9 +28,9 @@ void Octree::UDFTraversalBuilder::visit_node(Octree::OctreeNode &node) {
auto &udf_node = (UDFOctreeNode &)node;
// if (not node.is_leaf()) return;
if (node.level >= octree.max_level) {
if (node.get_level() >= octree.max_level) {
// deepest voxel
auto aabb_size = node.aabb.size();
auto aabb_size = node.get_aabb().size();
#if 0
BOOST_LOG_TRIVIAL(debug) << "aabb_size = " << aabb_size.transpose();
BOOST_LOG_TRIVIAL(debug) << "\t\t\t\t = " << (aabb_size / sample_step).transpose();
@ -83,16 +83,16 @@ void Octree::UDFTraversalBuilder::build() {
int index_base = 0;
for (const auto &qbox: this->query_boxes) {
auto &sdf = *qbox.node.udf;
auto &aabb = qbox.node.aabb;
const auto pos_base = aabb.get_min();
const auto pos_max = aabb.get_max();
auto aabb = qbox.node.get_aabb();
const auto pos_base = aabb.min();
const auto pos_max = aabb.max();
const auto aabb_size = aabb.size();
const int _x = sdf._x - 1, _y = sdf._y - 1, _z = sdf._z - 1;
const Eigen::Vector3d local_step(aabb_size.x() / _x, aabb_size.y() / _y, aabb_size.z() / _z);
for (int z = 0; z <= _z; ++z) {
// double pos_z = std::min(pos_base.z() + z * local_step.x(), pos_max.z());
// double pos_z = std::_min(pos_base.z() + z * local_step.x(), pos_max.z());
double pos_z = pos_base.z() + z * local_step.z();
for (int y = 0; y <= _y; ++y) {
double pos_y = pos_base.y() + y * local_step.y();

1
tests/octree_test/.gitignore

@ -0,0 +1 @@
test-path.h

5
tests/octree_test/CMakeLists.txt

@ -1,3 +1,6 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/test-path.h.in"
"${CMAKE_CURRENT_SOURCE_DIR}/test-path.h"
)
add_executable(octree_test main.cpp)
target_link_libraries(octree_test Octree pMesh)

21
tests/octree_test/main.cpp

@ -9,10 +9,10 @@
**/
#include <iostream>
#include "Octree/SDFOctree.h"
#include "Octree/sdf/SDFOctree.h"
#include "Octree/OctreeBuilder.h"
#include "Octree/OctreeTraverser.h"
#include "Octree/SDFTraversalSampler.h"
#include "Octree/sdf/SDFTraversalSampler.h"
#include <igl/marching_cubes.h>
#include <igl/voxel_grid.h>
#include <igl/writeOBJ.h>
@ -27,6 +27,7 @@
#include <boost/log/trivial.hpp>
#include <pMesh/io/reader/BaseReader.h>
#include <pMesh/io/adapter/DefaultReadAdapter.h>
#include "test-path.h"
class VTKTraverser : public pMesh::io::BaseReader, public Octree::OctreeTraverser {
@ -42,8 +43,7 @@ public:
};
int main() {
BOOST_LOG_TRIVIAL(debug) << "cwd is " << boost::filesystem::current_path();
pMesh::io::fs_path data_base_path = "../../../data";
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";
@ -51,17 +51,14 @@ int main() {
auto out_mc_path = data_base_path / "stanford-bunny-mc.obj";
auto out_error_path = data_base_path / "stanford-bunny-error_points.vtk";
pMesh::Triangle3dMesh<> mesh;
pMesh::io::OBJReader(mesh_path)
>> pMesh::io::DefaultSurfaceReadAdapter<>(mesh, false)();
BOOST_LOG_TRIVIAL(info) << "Load Face #" << mesh.f_size();
// pMesh::io::VTKReader("/Users/kwp/Projects/Porous/models/v8/tris.vtk") >> pMesh::io::DefaultSurfaceReadAdapter<>(mesh)();
const int level = 4;
const double sample_step = 0.004;
const double sample_step = 0.003;
boost::timer t;
Octree::AABB aabb(mesh.aabb());
@ -72,7 +69,7 @@ int main() {
builder.build();
BOOST_LOG_TRIVIAL(debug) << "time elapse " << t.elapsed();
auto aabb_size = octree.get_root()->aabb.size();
auto aabb_size = octree.aabb().size();
BOOST_LOG_TRIVIAL(debug) << "Global AABB " << aabb_size.transpose();
auto final_aabb_size = aabb_size / pow(2, level);
@ -173,14 +170,14 @@ int main() {
void VTKTraverser::visit_node(Octree::OctreeNode &node) {
if (node.level != octree.get_max_level()) {
if (node.get_level() != octree.get_max_level()) {
// assert(!node.is_leaf());
assert(node.tri_ids.empty());
return;
}
auto min = node.aabb.get_min();
auto max = node.aabb.get_max();
auto min = node.get_aabb().min();
auto max = node.get_aabb().max();
reader_adapter->feed_vertex({min.x(), min.y(), min.z()});
reader_adapter->feed_vertex({max.x(), min.y(), min.z()});
reader_adapter->feed_vertex({max.x(), max.y(), min.z()});

16
tests/octree_test/test-path.h.in

@ -0,0 +1,16 @@
/**
* ------------------------------------
* @author: Weipeng Kong
* @date: 2021/12/1
* @email: yjxkwp@foxmail.com
* @site: https://donot.fit
* @description:
* ------------------------------------
**/
#ifndef OCTREE_SDF_TEST_PATH_H
#define OCTREE_SDF_TEST_PATH_H
#define TEST_DATA_BASE_PATH "@TEST_DATA_BASE_PATH@"
#endif //OCTREE_SDF_TEST_PATH_H

1
tests/sdf_test/.gitignore

@ -0,0 +1 @@
test-path.h

5
tests/sdf_test/CMakeLists.txt

@ -1,3 +1,6 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/test-path.h.in"
"${CMAKE_CURRENT_SOURCE_DIR}/test-path.h"
)
add_executable(sdf_test main.cpp)
target_link_libraries(sdf_test Octree pMesh)

7
tests/sdf_test/main.cpp

@ -12,7 +12,7 @@
#include "Octree/BaseOctree.h"
#include "Octree/OctreeBuilder.h"
#include "Octree/OctreeTraverser.h"
#include "Octree/SDFTraversalSampler.h"
#include "Octree/sdf/SDFTraversalSampler.h"
#include <igl/marching_cubes.h>
#include <igl/voxel_grid.h>
#include <igl/writeOBJ.h>
@ -27,11 +27,10 @@
#include <boost/log/trivial.hpp>
#include <pMesh/io/reader/BaseReader.h>
#include <pMesh/io/adapter/DefaultReadAdapter.h>
#include "test-path.h"
int main() {
BOOST_LOG_TRIVIAL(debug) << "cwd is " << boost::filesystem::current_path();
pMesh::io::fs_path data_base_path = "../../../data";
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";

16
tests/sdf_test/test-path.h.in

@ -0,0 +1,16 @@
/**
* ------------------------------------
* @author: Weipeng Kong
* @date: 2021/12/1
* @email: yjxkwp@foxmail.com
* @site: https://donot.fit
* @description:
* ------------------------------------
**/
#ifndef OCTREE_SDF_TEST_PATH_H
#define OCTREE_SDF_TEST_PATH_H
#define TEST_DATA_BASE_PATH "@TEST_DATA_BASE_PATH@"
#endif //OCTREE_SDF_TEST_PATH_H

1
tests/udf_test/.gitignore

@ -0,0 +1 @@
test-path.h

6
tests/udf_test/CMakeLists.txt

@ -0,0 +1,6 @@
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/test-path.h.in"
"${CMAKE_CURRENT_SOURCE_DIR}/test-path.h"
)
add_executable(udf_test main.cpp)
target_link_libraries(udf_test Octree pMesh)

198
tests/udf_test/main.cpp

@ -0,0 +1,198 @@
/**
* ------------------------------------
* @author: Weipeng Kong
* @date: 2021/11/17
* @email: yjxkwp@foxmail.com
* @site: https://donot.fit
* @description:
* ------------------------------------
**/
#include <iostream>
#include <igl/marching_cubes.h>
#include <igl/voxel_grid.h>
#include <igl/writeOBJ.h>
#include <pMesh/mesh/TriangleMesh.h>
#include <pMesh/mesh/HexahedronMesh.h>
#include <pMesh/io/reader/OBJReader.h>
#include <pMesh/io/writer/VTKWriter.h>
#include <pMesh/io/adapter/DefaultReadAdapter.h>
#include <pMesh/io/adapter/DefaultWriteAdapter.h>
#include <boost/timer.hpp>
#include <boost/log/trivial.hpp>
#include <pMesh/io/reader/BaseReader.h>
#include "Octree/udf/UDFOctree.h"
#include "Octree/OctreeBuilder.h"
#include "Octree/OctreeTraverser.h"
#include "Octree/udf/UDFTraversalSampler.h"
#include "test-path.h"
class VTKTraverser : public pMesh::io::BaseReader, public Octree::OctreeTraverser {
int node_cnt = 0;
public:
explicit VTKTraverser(const Octree::UDFOctree &octree, const TraverseStrategy strategy = DFS);
void visit_node(Octree::OctreeNode &node) override;
pMesh::io::ReadAdapter *reader_adapter;
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 out_octree_path = data_base_path / "stanford-bunny-octree.vtk";
auto out_mc_path = data_base_path / "stanford-bunny-mc.obj";
auto out_error_path = data_base_path / "stanford-bunny-error_points.vtk";
pMesh::Triangle3dMesh<> mesh;
pMesh::io::OBJReader(mesh_path)
>> pMesh::io::DefaultSurfaceReadAdapter<>(mesh, false)();
BOOST_LOG_TRIVIAL(info) << "Load Face #" << mesh.f_size();
const int level = 2;
const double sample_step = 0.004;
boost::timer t;
Octree::AABB aabb(mesh.aabb());
Octree::UDFOctree octree(level, aabb);
Octree::OctreeBuilder builder(mesh, octree);
builder.build();
BOOST_LOG_TRIVIAL(debug) << "time elapse " << t.elapsed();
auto aabb_size = octree.aabb().size();
BOOST_LOG_TRIVIAL(debug) << "Global AABB " << aabb_size.transpose();
auto final_aabb_size = aabb_size / pow(2, level);
BOOST_LOG_TRIVIAL(debug) << "Local AABB " << final_aabb_size.transpose();
// origin points of model
int opm = std::ceil(aabb_size.x() / sample_step) *
std::ceil(aabb_size.y() / sample_step) *
std::ceil(aabb_size.z() / sample_step);
BOOST_LOG_TRIVIAL(debug) << "Origin Points of model = " << opm;
// points per voxel
int ppv = std::ceil(final_aabb_size.x() / sample_step) *
std::ceil(final_aabb_size.y() / sample_step) *
std::ceil(final_aabb_size.z() / sample_step);
BOOST_LOG_TRIVIAL(debug) << "Points per voxel = " << ppv;
pMesh::HexahedronMesh<> hexahedron_mesh;
VTKTraverser(octree) >> pMesh::io::DefaultVolumeReadAdapter<>(hexahedron_mesh)();
pMesh::io::VTKWriter(12, out_octree_path)
<< pMesh::io::DefaultVolumeWriteAdapter<>(hexahedron_mesh)();
BOOST_LOG_TRIVIAL(debug) << "Total Points = " << hexahedron_mesh.c_size() * ppv;
BOOST_LOG_TRIVIAL(debug) << "Compression ratio = " << (double) hexahedron_mesh.c_size() * ppv / opm;
BOOST_LOG_TRIVIAL(debug) << "Calculating UDF";
Octree::UDFTraversalBuilder udf_builder(octree, mesh, sample_step);
udf_builder.build();
BOOST_LOG_TRIVIAL(debug) << "End computing UDF";
if (1) {
Eigen::MatrixXd V = Eigen::MatrixXd(mesh.v_size(), 3);
Eigen::MatrixXi F = Eigen::MatrixXi(mesh.f_size(), 3);
for (int i = 0; i < mesh.v_size(); ++i) {
V.row(i) = mesh.vertices[i].attr.coordinate;
}
for (int i = 0; i < mesh.f_size(); ++i) {
const auto &face = mesh.faces[i].attr.vertices;
F.row(i) << face[0].id(), face[1].id(), face[2].id();
}
Eigen::MatrixXd GV;
Eigen::RowVector3i res;
const int s = 100;
igl::voxel_grid(V, 0, s, 1, GV, res);
// compute values
std::cout << "Computing distances..." << std::endl;
Eigen::VectorXd S = Eigen::VectorXd(GV.rows()), B;
#if 0
pMesh::Triangle3dMesh<> error_points;
#endif
{
for (int i = 0; i < GV.rows(); ++i) {
auto node = octree.map_node(GV.row(i));
if (node == nullptr) {
S[i] = 1000;
} else {
S[i] = node->get_udf(GV.row(i));
}
}
}
#if 0
pMesh::io::VTKWriter(1, out_error_path) << pMesh::io::DefaultSurfaceWriteAdapter(error_points)();
#endif
std::cout << "Marching cubes..." << std::endl;
Eigen::MatrixXd SV, BV;
Eigen::MatrixXi SF, BF;
igl::marching_cubes(S, GV, res(0), res(1), res(2), 0, SV, SF);
igl::writeOBJ(out_mc_path.string(), SV, SF);
}
return 0;
}
void VTKTraverser::visit_node(Octree::OctreeNode &node) {
if (node.get_level() != octree.get_max_level()) {
// assert(!node.is_leaf());
assert(node.tri_ids.empty());
return;
}
auto min = node.get_aabb().min();
auto max = node.get_aabb().max();
reader_adapter->feed_vertex({min.x(), min.y(), min.z()});
reader_adapter->feed_vertex({max.x(), min.y(), min.z()});
reader_adapter->feed_vertex({max.x(), max.y(), min.z()});
reader_adapter->feed_vertex({min.x(), max.y(), min.z()});
reader_adapter->feed_vertex({min.x(), min.y(), max.z()});
reader_adapter->feed_vertex({max.x(), min.y(), max.z()});
reader_adapter->feed_vertex({max.x(), max.y(), max.z()});
reader_adapter->feed_vertex({min.x(), max.y(), max.z()});
reader_adapter->feed_collection(
{
0 + node_cnt, 1 + node_cnt, 2 + node_cnt, 3 + node_cnt, 4 + node_cnt,
5 + node_cnt, 6 + node_cnt, 7 + node_cnt
});
node_cnt += 8;
}
bool VTKTraverser::operator>>(pMesh::io::ReadAdapter &adapter) {
reader_adapter = &adapter;
node_cnt = 0;
adapter.start();
this->traverse();
adapter.end();
return true;
}
VTKTraverser::VTKTraverser(const Octree::UDFOctree &octree, const OctreeTraverser::TraverseStrategy strategy)
: OctreeTraverser(
octree, strategy) {
}

16
tests/udf_test/test-path.h.in

@ -0,0 +1,16 @@
/**
* ------------------------------------
* @author: Weipeng Kong
* @date: 2021/12/1
* @email: yjxkwp@foxmail.com
* @site: https://donot.fit
* @description:
* ------------------------------------
**/
#ifndef OCTREE_SDF_TEST_PATH_H
#define OCTREE_SDF_TEST_PATH_H
#define TEST_DATA_BASE_PATH "@TEST_DATA_BASE_PATH@"
#endif //OCTREE_SDF_TEST_PATH_H
Loading…
Cancel
Save