Browse Source

Break Octree into SDFTree and UDFTree

master
lab pc 4 years ago
parent
commit
8f25a6c475
  1. 6
      .idea/vcs.xml
  2. 9747
      data/stanford-bunny-octree.vtk
  3. 11
      include/Octree/OctreeBase.h
  4. 7
      include/Octree/OctreeBuilder.h
  5. 22
      include/Octree/OctreeSDF.h
  6. 40
      include/Octree/OctreeUDF.h
  7. 32
      include/Octree/SDFData.h
  8. 17
      include/Octree/UDFData.h
  9. 2
      include/Octree/UDFTraversalSampler.h
  10. 53
      include/Octree/VoxelDenseData.h
  11. 33
      src/OctreeBase.cpp
  12. 20
      src/OctreeBuilder.cpp
  13. 6
      src/OctreeIO.cpp
  14. 14
      src/OctreeSDF.cpp
  15. 4
      src/OctreeTraverser.cpp
  16. 23
      src/OctreeUDF.cpp
  17. 95
      src/SDFData.cpp
  18. 2
      src/SDFTraversalSampler.cpp
  19. 5
      src/UDFData.cpp
  20. 8
      src/UDFTraversalSampler.cpp
  21. 104
      src/VoxelDenseData.cpp
  22. 2
      tests/octree_test/CMakeLists.txt
  23. 53
      tests/octree_test/main.cpp
  24. 2
      tests/sdf_test/CMakeLists.txt
  25. 30
      tests/sdf_test/main.cpp

6
.idea/vcs.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

9747
data/stanford-bunny-octree.vtk

File diff suppressed because it is too large

11
include/Octree/OctreeBase.h

@ -12,6 +12,7 @@
#define OCTREE_OCTREEBASE_H
#include <memory>
#include <utility>
#include <vector>
#include <set>
#include <array>
@ -66,6 +67,8 @@ namespace Octree {
*/
void split_if_no_children();
virtual ocnode_sptr make_child(const AABB &aabb);
bool is_leaf() const;
array<ocnode_sptr, 8> get_children() const;
@ -80,7 +83,15 @@ namespace Octree {
ocnode_sptr root;
public:
explicit OctreeBase(uint32_t max_level, const AABB &aabb);
explicit OctreeBase(uint32_t max_level, ocnode_sptr root);
ocnode_sptr map_node(const Eigen::Vector3d &pos);
ocnode_sptr get_root() const { return root; }
uint32_t get_max_level() const { return max_level; }
};
}

7
include/Octree/OctreeBuilder.h

@ -28,12 +28,11 @@ namespace Octree {
public:
const uint32_t max_depth;
const pMesh::Triangle3dMesh<> &mesh;
const AABB global_aabb;
OctreeBase &octree;
explicit OctreeBuilder(const pMesh::Triangle3dMesh<> &mesh, const uint32_t max_depth);
explicit OctreeBuilder(const pMesh::Triangle3dMesh<> &mesh, uint32_t max_depth, const AABB &aabb);
explicit OctreeBuilder(const pMesh::Triangle3dMesh<> &mesh, OctreeBase &octree);
void build(OctreeBase &octree);
void build();
private:
/**

22
include/Octree/OctreeSDF.h

@ -14,32 +14,38 @@
#include "OctreeBase.h"
namespace Octree{
namespace Octree {
class SDFData;
class OctreeSDFNode;
using sdfdata_sptr = shared_ptr<SDFData>;
using ocsdfnode_sptr = shared_ptr<OctreeSDFNode>;
using ocsdfnode_wptr = weak_ptr<OctreeSDFNode>;
using ocsdfnode_ptr = OctreeSDFNode *;
struct OctreeSDFNode : public OctreeNode{
struct OctreeSDFNode : public OctreeNode {
public:
sdfdata_sptr sdf;
public:
explicit OctreeSDFNode(ocnode_ptr father, const AABB &aabb, uint32_t level);
double get_sdf(const Eigen::Vector3d &pos);
ocnode_sptr make_child(const AABB &aabb) override;
};
}
namespace Octree{
class OctreeSDF : public OctreeBase{
namespace Octree {
class OctreeSDF : public OctreeBase {
public:
uint32_t max_level;
ocsdfnode_sptr root;
explicit OctreeSDF(uint32_t max_level, const AABB &aabb);
public:
ocsdfnode_sptr map_node(const Eigen::Vector3d &pos);
ocsdfnode_sptr map_node(const Eigen::Vector3d &pos){return std::static_pointer_cast<OctreeSDFNode>(OctreeBase::map_node(pos));}
ocsdfnode_sptr get_root() const { return std::static_pointer_cast<OctreeSDFNode>(root); }
};
}

40
include/Octree/OctreeUDF.h

@ -12,9 +12,45 @@
#define OCTREE_OCTREEUDF_H
class OctreeUDF {
};
#include "OctreeBase.h"
namespace Octree {
class UDFData;
class OctreeUDFNode;
using udfdata_sptr = shared_ptr<UDFData>;
using ocudfnode_sptr = shared_ptr<OctreeUDFNode>;
using ocudfnode_wptr = weak_ptr<OctreeUDFNode>;
using ocudfnode_ptr = OctreeUDFNode *;
struct OctreeUDFNode : public OctreeNode {
public:
udfdata_sptr udf;
public:
explicit OctreeUDFNode(ocnode_ptr father, const AABB &aabb, uint32_t level);
double get_udf(const Eigen::Vector3d &pos);
ocnode_sptr make_child(const AABB &aabb) override;
};
}
namespace Octree {
class OctreeUDF : public OctreeBase {
public:
explicit OctreeUDF(uint32_t max_level, const AABB &aabb);
ocudfnode_sptr map_node(const Eigen::Vector3d &pos) { return std::static_pointer_cast<OctreeUDFNode>(OctreeBase::map_node(pos)); }
ocudfnode_sptr get_root() const { return std::static_pointer_cast<OctreeUDFNode>(root); }
};
}
#endif //OCTREE_OCTREEUDF_H

32
include/Octree/SDFData.h

@ -14,39 +14,13 @@
#include <vector>
#include <Eigen/Core>
#include <Eigen/Dense>
#include "VoxelDenseData.h"
namespace Octree {
/**
* All SDF value will be sampled use coordinate [0, 1]^3
*/
class SDFData {
class SDFData: public VoxelDenseData{
friend class SDFTraversalBuilder;
int _x, _y, _z; // 3D range [start with 0]
std::vector<double> value;
public:
SDFData(const std::vector<double>& value, int _x, int _y, int _z);
public:
/**
* Sample from value
* @param x [0,1]
* @param y [0,1]
* @param z [0,1]
* @return sampled value
*/
double sample(double x, double y, double z) const;
/**
* Tool function: calc 1D index from 3D coordinate
* @param x
* @param y
* @param z
* @return
*/
int get_array_index(int x, int y, int z) const;
explicit SDFData(const std::vector<double>& value, int _x, int _y, int _z);
};
}

17
include/Octree/UDFData.h

@ -11,10 +11,23 @@
#ifndef OCTREE_UDFDATA_H
#define OCTREE_UDFDATA_H
#include <vector>
#include <Eigen/Core>
#include <Eigen/Dense>
#include "VoxelDenseData.h"
class UDFData {
namespace Octree {
};
/**
* All UDF value will be sampled use coordinate [0, 1]^3
*/
class UDFData : public VoxelDenseData {
friend class UDFTraversalBuilder;
public:
explicit UDFData(const std::vector<double> &value, int _x, int _y, int _z);
};
}
#endif //OCTREE_UDFDATA_H

2
include/Octree/UDFTraversalSampler.h

@ -13,6 +13,8 @@
#include "OctreeTraverser.h"
#include "SDFData.h"
#include "UDFData.h"
#include <utility>
#include <pMesh/mesh/TriangleMesh.h>
#include <Eigen/Dense>

53
include/Octree/VoxelDenseData.h

@ -0,0 +1,53 @@
/**
* ------------------------------------
* @author: Weipeng Kong
* @date: 2021/11/30
* @email: yjxkwp@foxmail.com
* @site: https://donot.fit
* @description:
* ------------------------------------
**/
#ifndef OCTREE_VOXELDENSEDATA_H
#define OCTREE_VOXELDENSEDATA_H
#include <vector>
#include <Eigen/Core>
#include <Eigen/Dense>
namespace Octree {
/**
* All Dense value will be sampled use coordinate [0, 1]^3
*/
class VoxelDenseData {
protected:
int _x, _y, _z; // 3D range [start with 0]
std::vector<double> value;
public:
VoxelDenseData(const std::vector<double> &value, int _x, int _y, int _z);
public:
/**
* Sample from value
* @param x [0,1]
* @param y [0,1]
* @param z [0,1]
* @return sampled value
*/
double sample(double x, double y, double z) const;
/**
* Tool function: calc 1D index from 3D coordinate
* @param x
* @param y
* @param z
* @return
*/
int get_array_index(int x, int y, int z) const;
};
}
#endif //OCTREE_VOXELDENSEDATA_H

33
src/OctreeBase.cpp

@ -10,6 +10,22 @@
#include "Octree/OctreeBase.h"
Octree::ocnode_sptr Octree::OctreeBase::map_node(const Eigen::Vector3d &pos) {
auto fd = (root == nullptr) ? nullptr : root->map_node(pos);
return fd;
return fd == nullptr ? root : fd;
}
Octree::OctreeBase::OctreeBase(uint32_t max_level, const Octree::AABB &aabb) :
OctreeBase(max_level, std::make_shared<OctreeNode>(nullptr, aabb, 0)) {
}
Octree::OctreeBase::OctreeBase(uint32_t max_level, Octree::ocnode_sptr root) : max_level(max_level), root(root) {
}
Octree::OctreeNode::OctreeNode(ocnode_ptr father, const Octree::AABB &aabb, uint32_t level) : father(father),
level(level),
aabb(aabb) {
@ -23,12 +39,18 @@ void Octree::OctreeNode::insert_triangle_id(uint32_t tri) {
void Octree::OctreeNode::split_if_no_children() {
if (!is_leaf()) return;
uint32_t child_level = level + 1;
std::array<Octree::AABB, 8> sub_aabbs = this->aabb.half_divide();
std::array<AABB, 8> sub_aabbs = this->aabb.half_divide();
for (int i = 0; i < 8; i++) {
children[i] = std::make_shared<OctreeNode>(this, sub_aabbs[i], child_level);
children[i] = this->make_child(sub_aabbs[i]);
}
}
Octree::ocnode_sptr Octree::OctreeNode::make_child(const Octree::AABB &aabb) {
return std::make_shared<OctreeNode>(this, aabb, level+1);
}
bool Octree::OctreeNode::is_leaf() const {
return std::all_of(children.begin(), children.end(), [](ocnode_sptr child) { return child == nullptr; });
}
@ -51,10 +73,3 @@ Octree::ocnode_sptr Octree::OctreeNode::map_node(const Eigen::Vector3d &pos) {
}
return nullptr;
}
Octree::ocnode_sptr Octree::OctreeBase::map_node(const Eigen::Vector3d &pos) {
auto fd = (root == nullptr) ? nullptr : root->map_node(pos);
return fd;
return fd == nullptr ? root : fd;
}

20
src/OctreeBuilder.cpp

@ -19,29 +19,19 @@ struct OctreeNodeBuilder{
};
#endif
Octree::OctreeBuilder::OctreeBuilder(const pMesh::Triangle3dMesh<> &mesh, const uint32_t max_depth) :
OctreeBuilder(mesh, max_depth, AABB(mesh.aabb())) {
}
Octree::OctreeBuilder::OctreeBuilder(const pMesh::Triangle3dMesh<> &mesh, const uint32_t max_depth,
const Octree::AABB &aabb) : mesh(mesh),
max_depth(max_depth),
global_aabb(aabb) {
Octree::OctreeBuilder::OctreeBuilder(const pMesh::Triangle3dMesh<> &mesh, Octree::OctreeBase &octree):
mesh(mesh), max_depth(octree.get_max_level()), octree(octree)
{
}
void Octree::OctreeBuilder::build(OctreeBase &octree) {
auto gaabb = mesh.aabb();
octree.max_level = max_depth;
octree.root = std::make_shared<OctreeNode>(nullptr,
AABB(gaabb[0], gaabb[1], gaabb[2], gaabb[3], gaabb[4], gaabb[5]), 0);
void Octree::OctreeBuilder::build() {
for (int i = 0; i < mesh.f_size(); ++i) {
this->insert_triangle(*octree.root, i);
}
clean_up(octree.root);
}

6
src/OctreeIO.cpp

@ -16,14 +16,14 @@ namespace SerializationTool{
}
Octree::OctreeSaver::OctreeSaver(const OctreeBase::OctreeBase &octree): octree(octree) {
Octree::OctreeSaver::OctreeSaver(const Octree::OctreeBase &octree): octree(octree) {
}
void Octree::OctreeSaver::save(const OctreeBase::OctreeIO::fs_path &path) {
void Octree::OctreeSaver::save(const Octree::OctreeIO::fs_path &path) {
}
void Octree::OctreeSaver::save_recursively(const OctreeBase::OctreeNode &node) {
void Octree::OctreeSaver::save_recursively(const Octree::OctreeNode &node) {
}

14
src/OctreeSDF.cpp

@ -21,6 +21,16 @@ double Octree::OctreeSDFNode::get_sdf(const Eigen::Vector3d &pos) {
return sdf->sample(relative.x(), relative.y(), relative.z());
}
Octree::ocsdfnode_sptr Octree::OctreeSDF::map_node(const Eigen::Vector3d &pos) {
return std::dynamic_pointer_cast<OctreeSDFNode>(OctreeBase::map_node(pos));
Octree::OctreeSDFNode::OctreeSDFNode(Octree::ocnode_ptr father, const Octree::AABB &aabb, uint32_t level) : OctreeNode(
father, aabb, level) {
}
Octree::ocnode_sptr Octree::OctreeSDFNode::make_child(const Octree::AABB &aabb) {
return std::make_shared<OctreeSDFNode>(this, aabb, level + 1);
}
Octree::OctreeSDF::OctreeSDF(uint32_t max_level, const Octree::AABB &aabb) :
OctreeBase(max_level, std::static_pointer_cast<OctreeNode>(std::make_shared<OctreeSDFNode>(nullptr, aabb, 0))) {
}

4
src/OctreeTraverser.cpp

@ -19,10 +19,10 @@ Octree::OctreeTraverser::OctreeTraverser(const OctreeBase &octree, const Travers
void Octree::OctreeTraverser::traverse() {
switch (strategy) {
case DFS:
dfs(octree.root);
dfs(octree.get_root());
break;
case BFS:
bfs(octree.root);
bfs(octree.get_root());
break;
}
}

23
src/OctreeUDF.cpp

@ -9,3 +9,26 @@
**/
#include "Octree/OctreeUDF.h"
#include "Octree/UDFData.h"
Octree::OctreeUDFNode::OctreeUDFNode(Octree::ocnode_ptr father, const Octree::AABB &aabb, uint32_t level) : OctreeNode(
father, aabb, level) {
}
double Octree::OctreeUDFNode::get_udf(const Eigen::Vector3d &pos) {
Eigen::Vector3d relative = pos - aabb.get_min();
auto size = aabb.size();
relative.x() = relative.x() / size.x();
relative.y() = relative.y() / size.y();
relative.z() = relative.z() / size.z();
return udf->sample(relative.x(), relative.y(), relative.z());
}
Octree::ocnode_sptr Octree::OctreeUDFNode::make_child(const Octree::AABB &aabb) {
return std::make_shared<OctreeUDFNode>(this, aabb, level + 1);
}
Octree::OctreeUDF::OctreeUDF(uint32_t max_level, const Octree::AABB &aabb) : OctreeBase(max_level, aabb) {
}

95
src/SDFData.cpp

@ -8,97 +8,8 @@
* ------------------------------------
**/
#include "../include/Octree/SDFData.h"
#include "Octree/SDFData.h"
Octree::SDFData::SDFData(const std::vector<double> &value, int _x, int _y, int _z) : VoxelDenseData(value, _x, _y, _z) {
namespace LerpTools {
inline double interpolate1D(double v1, double v2, double x1, double x2, double x) {
double t = (x - x1) / (x2 - x1);
return v1 * (1 - t) + v2 * t;
}
inline double interpolate2D(double v1, double v2, double v3, double v4,
double x1, double x2, double x,
double y1, double y2, double y) {
double s = interpolate1D(v1, v2, x1, x2, x);
double t = interpolate1D(v3, v4, x1, x2, x);
return interpolate1D(s, t, y1, y2, y);
}
inline double interpolate3D(double v1, double v2, double v3, double v4, double v5, double v6, double v7, double v8,
double x1, double x2, double x,
double y1, double y2, double y,
double z1, double z2, double z) {
double s = interpolate2D(v1, v2, v3, v4, x1, x2, x, y1, y2, y);
double t = interpolate2D(v5, v6, v7, v8, x1, x2, x, y1, y2, y);
return interpolate1D(s, t, z1, z2, z);
}
}
Octree::SDFData::SDFData(const std::vector<double> &value, int _x, int _y, int _z) : value(value),
_x(_x), _y(_y), _z(_z) {
}
#include <iostream>
double Octree::SDFData::sample(double x, double y, double z) const {
// std::cout << "x = " << x << std::endl;
// std::cout << "_x = " << _x << std::endl;
x = (_x - 1) * x;
y = (_y - 1) * y;
z = (_z - 1) * z;
#define LerpOnSDF
#ifdef LerpOnSDF
int bound[6] = {
int(x), int(x) + 1, int(y), int(y) + 1, int(z), int(z) + 1
};
// if (bound[1] >= _x) bound[1] = bound[0];
// if (bound[3] >= _y) bound[3] = bound[2];
// if (bound[5] >= _z) bound[5] = bound[4];
// std::cout << bound[0] << ", "<< bound[1] << ", "<< bound[2] << ", "<< bound[3] << ", "<< bound[4] << ", "<< bound[5] << std::endl;
// exit(0);
double v[8];
v[0] = value[get_array_index(bound[0], bound[2], bound[4])];
v[1] = value[get_array_index(bound[1], bound[2], bound[4])];
v[2] = value[get_array_index(bound[0], bound[3], bound[4])];
v[3] = value[get_array_index(bound[1], bound[3], bound[4])];
v[4] = value[get_array_index(bound[0], bound[2], bound[5])];
v[5] = value[get_array_index(bound[1], bound[2], bound[5])];
v[6] = value[get_array_index(bound[0], bound[3], bound[5])];
v[7] = value[get_array_index(bound[1], bound[3], bound[5])];
// v[0] = value[get_array_index(bound[0], bound[2], bound[4])];
// v[1] = value[get_array_index(bound[0], bound[3], bound[4])];
// v[2] = value[get_array_index(bound[1], bound[2], bound[4])];
// v[3] = value[get_array_index(bound[1], bound[3], bound[4])];
// v[4] = value[get_array_index(bound[0], bound[2], bound[5])];
// v[5] = value[get_array_index(bound[0], bound[3], bound[5])];
// v[6] = value[get_array_index(bound[1], bound[2], bound[5])];
// v[7] = value[get_array_index(bound[1], bound[3], bound[5])];
// return v[2];
// return v[7];
// return (v[0]+ v[1]+v[2]+v[3]+ v[4]+ v[5]+ v[6]+v[7]) / 8;
// return v[0];
return LerpTools::interpolate3D(
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
bound[0], bound[1], x,
bound[2], bound[3], y,
bound[4], bound[5], z
);
#else
return value[get_array_index((int) x, (int) y, (int) z)];
#endif
}
int Octree::SDFData::get_array_index(int x, int y, int z) const {
// return (x * _x * _y) + (y * _y) + z;
// return ((x * _y) + y) * _z + z;
return ((z * _y) + y) * _x + x;
}
}

2
src/SDFTraversalSampler.cpp

@ -26,7 +26,7 @@ void Octree::SDFTraversalBuilder::visit_node(Octree::OctreeNode &node) {
// if (not node.is_leaf()) return;
auto &sdf_node = (OctreeSDFNode &)node;
if (node.level >= octree.max_level) {
if (node.level >= octree.get_max_level()) {
// deepest voxel
auto aabb_size = node.aabb.size();
#if 0

5
src/UDFData.cpp

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

8
src/UDFTraversalSampler.cpp

@ -14,14 +14,16 @@
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time.hpp>
#if 0
Octree::UDFTraversalBuilder::UDFTraversalBuilder(const Octree::OctreeBase &octree,
const pMesh::Triangle3dMesh<> &mesh,
const double sample_step,
const OctreeBase::OctreeTraverser::TraverseStrategy strategy)
const Octree::OctreeTraverser::TraverseStrategy strategy)
: OctreeTraverser(octree, strategy), mesh(mesh), sample_step(sample_step) {
}
void Octree::UDFTraversalBuilder::visit_node(OctreeBase::OctreeNode &node) {
void Octree::UDFTraversalBuilder::visit_node(Octree::OctreeNode &node) {
// if (not node.is_leaf()) return;
if (node.level >= octree.max_level) {
@ -137,3 +139,5 @@ void Octree::UDFTraversalBuilder::build() {
query_boxes.clear();
}
#endif

104
src/VoxelDenseData.cpp

@ -0,0 +1,104 @@
/**
* ------------------------------------
* @author: Weipeng Kong
* @date: 2021/11/30
* @email: yjxkwp@foxmail.com
* @site: https://donot.fit
* @description:
* ------------------------------------
**/
#include "Octree/VoxelDenseData.h"
namespace LerpTools {
inline double interpolate1D(double v1, double v2, double x1, double x2, double x) {
double t = (x - x1) / (x2 - x1);
return v1 * (1 - t) + v2 * t;
}
inline double interpolate2D(double v1, double v2, double v3, double v4,
double x1, double x2, double x,
double y1, double y2, double y) {
double s = interpolate1D(v1, v2, x1, x2, x);
double t = interpolate1D(v3, v4, x1, x2, x);
return interpolate1D(s, t, y1, y2, y);
}
inline double interpolate3D(double v1, double v2, double v3, double v4, double v5, double v6, double v7, double v8,
double x1, double x2, double x,
double y1, double y2, double y,
double z1, double z2, double z) {
double s = interpolate2D(v1, v2, v3, v4, x1, x2, x, y1, y2, y);
double t = interpolate2D(v5, v6, v7, v8, x1, x2, x, y1, y2, y);
return interpolate1D(s, t, z1, z2, z);
}
}
Octree::VoxelDenseData::VoxelDenseData(const std::vector<double> &value, int _x, int _y, int _z) : value(value),
_x(_x), _y(_y),
_z(_z) {
}
double Octree::VoxelDenseData::sample(double x, double y, double z) const {
// std::cout << "x = " << x << std::endl;
// std::cout << "_x = " << _x << std::endl;
x = (_x - 1) * x;
y = (_y - 1) * y;
z = (_z - 1) * z;
#define LerpOnSDF
#ifdef LerpOnSDF
int bound[6] = {
int(x), int(x) + 1, int(y), int(y) + 1, int(z), int(z) + 1
};
// if (bound[1] >= _x) bound[1] = bound[0];
// if (bound[3] >= _y) bound[3] = bound[2];
// if (bound[5] >= _z) bound[5] = bound[4];
// std::cout << bound[0] << ", "<< bound[1] << ", "<< bound[2] << ", "<< bound[3] << ", "<< bound[4] << ", "<< bound[5] << std::endl;
// exit(0);
double v[8];
v[0] = value[get_array_index(bound[0], bound[2], bound[4])];
v[1] = value[get_array_index(bound[1], bound[2], bound[4])];
v[2] = value[get_array_index(bound[0], bound[3], bound[4])];
v[3] = value[get_array_index(bound[1], bound[3], bound[4])];
v[4] = value[get_array_index(bound[0], bound[2], bound[5])];
v[5] = value[get_array_index(bound[1], bound[2], bound[5])];
v[6] = value[get_array_index(bound[0], bound[3], bound[5])];
v[7] = value[get_array_index(bound[1], bound[3], bound[5])];
// v[0] = value[get_array_index(bound[0], bound[2], bound[4])];
// v[1] = value[get_array_index(bound[0], bound[3], bound[4])];
// v[2] = value[get_array_index(bound[1], bound[2], bound[4])];
// v[3] = value[get_array_index(bound[1], bound[3], bound[4])];
// v[4] = value[get_array_index(bound[0], bound[2], bound[5])];
// v[5] = value[get_array_index(bound[0], bound[3], bound[5])];
// v[6] = value[get_array_index(bound[1], bound[2], bound[5])];
// v[7] = value[get_array_index(bound[1], bound[3], bound[5])];
// return v[2];
// return v[7];
// return (v[0]+ v[1]+v[2]+v[3]+ v[4]+ v[5]+ v[6]+v[7]) / 8;
// return v[0];
return LerpTools::interpolate3D(
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
bound[0], bound[1], x,
bound[2], bound[3], y,
bound[4], bound[5], z
);
#else
return value[get_array_index((int) x, (int) y, (int) z)];
#endif
}
int Octree::VoxelDenseData::get_array_index(int x, int y, int z) const {
// return (x * _x * _y) + (y * _y) + z;
// return ((x * _y) + y) * _z + z;
return ((z * _y) + y) * _x + x;
}

2
tests/octree_test/CMakeLists.txt

@ -1,3 +1,3 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/)
add_executable(octree_test main.cpp)
target_link_libraries(octree_test OctreeSDF pMesh)
target_link_libraries(octree_test Octree pMesh)

53
tests/octree_test/main.cpp

@ -9,10 +9,10 @@
**/
#include <iostream>
#include "OctreeSDF/OctreeSDF.h"
#include "OctreeSDF/OctreeBuilder.h"
#include "OctreeSDF/OctreeTraverser.h"
#include "OctreeSDF/SDFTraversalSampler.h"
#include "Octree/OctreeSDF.h"
#include "Octree/OctreeBuilder.h"
#include "Octree/OctreeTraverser.h"
#include "Octree/SDFTraversalSampler.h"
#include <igl/marching_cubes.h>
#include <igl/voxel_grid.h>
#include <igl/writeOBJ.h>
@ -29,12 +29,12 @@
#include <pMesh/io/adapter/DefaultReadAdapter.h>
class VTKTraverser : public pMesh::io::BaseReader, public OctreeSDF::OctreeTraverser {
class VTKTraverser : public pMesh::io::BaseReader, public Octree::OctreeTraverser {
int node_cnt = 0;
public:
explicit VTKTraverser(const OctreeSDF::Octree &octree, const TraverseStrategy strategy = DFS);
explicit VTKTraverser(const Octree::OctreeSDF &octree, const TraverseStrategy strategy = DFS);
void visit_node(OctreeSDF::OctreeNode &node) override;
void visit_node(Octree::OctreeNode &node) override;
pMesh::io::ReadAdapter *reader_adapter;
@ -42,28 +42,37 @@ public:
};
int main() {
std::string mesh_path = "/Users/kwp/Projects/Porous/models/v8/bunny.obj";
std::string out_octree_path = "/Users/kwp/Projects/Porous/models/v8/octree_bunny.vtk";
std::string out_mc_path = "/Users/kwp/Projects/Porous/models/v8/mc_bunny.obj";
std::string out_error_path = "/Users/kwp/Projects/Porous/models/v8/error_points.vtk";
BOOST_LOG_TRIVIAL(debug) << "cwd is " << boost::filesystem::current_path();
pMesh::io::fs_path data_base_path = "../../../data";
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();
// pMesh::io::VTKReader("/Users/kwp/Projects/Porous/models/v8/tris.vtk") >> pMesh::io::DefaultSurfaceReadAdapter<>(mesh)();
const int level = 4;
const double sample_step = 0.002;
const double sample_step = 0.004;
boost::timer t;
OctreeSDF::Octree octree;
OctreeSDF::AABB aabb(mesh.aabb());
Octree::AABB aabb(mesh.aabb());
Octree::OctreeSDF octree(level, aabb);
aabb.extend(2);
OctreeSDF::OctreeBuilder builder(mesh, level, aabb);
builder.build(octree);
Octree::OctreeBuilder builder(mesh, octree);
builder.build();
BOOST_LOG_TRIVIAL(debug) << "time elapse " << t.elapsed();
auto aabb_size = octree.root->aabb.size();
auto aabb_size = octree.get_root()->aabb.size();
BOOST_LOG_TRIVIAL(debug) << "Global AABB " << aabb_size.transpose();
auto final_aabb_size = aabb_size / pow(2, level);
@ -94,7 +103,7 @@ int main() {
BOOST_LOG_TRIVIAL(debug) << "Compression ratio = " << (double) hexahedron_mesh.c_size() * ppv / opm;
BOOST_LOG_TRIVIAL(debug) << "Calculating SDF";
OctreeSDF::SDFTraversalBuilder sdf_builder(octree, mesh, sample_step);
Octree::SDFTraversalBuilder sdf_builder(octree, mesh, sample_step);
sdf_builder.build();
BOOST_LOG_TRIVIAL(debug) << "End computing SDF";
@ -155,7 +164,7 @@ int main() {
igl::marching_cubes(S, GV, res(0), res(1), res(2), 0, SV, SF);
igl::writeOBJ(out_mc_path, SV, SF);
igl::writeOBJ(out_mc_path.string(), SV, SF);
// igl::marching_cubes(B,GV,res(0),res(1),res(2),0,BV,BF);
}
@ -163,8 +172,8 @@ int main() {
}
void VTKTraverser::visit_node(OctreeSDF::OctreeNode &node) {
if (node.level != octree.max_level) {
void VTKTraverser::visit_node(Octree::OctreeNode &node) {
if (node.level != octree.get_max_level()) {
// assert(!node.is_leaf());
assert(node.tri_ids.empty());
return;
@ -201,7 +210,7 @@ bool VTKTraverser::operator>>(pMesh::io::ReadAdapter &adapter) {
}
VTKTraverser::VTKTraverser(const OctreeSDF::Octree &octree, const OctreeTraverser::TraverseStrategy strategy)
VTKTraverser::VTKTraverser(const Octree::OctreeSDF &octree, const OctreeTraverser::TraverseStrategy strategy)
: OctreeTraverser(
octree, strategy) {
}

2
tests/sdf_test/CMakeLists.txt

@ -1,3 +1,3 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/)
add_executable(sdf_test main.cpp)
target_link_libraries(sdf_test OctreeSDF pMesh)
target_link_libraries(sdf_test Octree pMesh)

30
tests/sdf_test/main.cpp

@ -30,19 +30,22 @@
int main() {
std::string mesh_path = "/Users/kwp/Projects/Porous/models/v8/V8.obj";
std::string out_octree_path = "/Users/kwp/Projects/Porous/models/v8/octree_V8.vtk";
std::string out_mc_path = "/Users/kwp/Projects/Porous/models/v8/mc_v8.obj";
BOOST_LOG_TRIVIAL(debug) << "cwd is " << boost::filesystem::current_path();
pMesh::io::fs_path data_base_path = "../../../data";
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";
pMesh::Triangle3dMesh<> mesh;
pMesh::io::OBJReader(mesh_path)
>> pMesh::io::DefaultSurfaceReadAdapter<>(mesh, false)();
// pMesh::io::VTKReader("/Users/kwp/Projects/Porous/models/v8/tris.vtk") >> pMesh::io::DefaultSurfaceReadAdapter<>(mesh)();
const int level = 5;
const double sample_step = 1;
const double sample_step = 0.0001;
if(1){
if (1) {
Eigen::MatrixXd V = Eigen::MatrixXd(mesh.v_size(), 3);
Eigen::MatrixXi F = Eigen::MatrixXi(mesh.f_size(), 3);
@ -58,22 +61,21 @@ int main() {
Eigen::MatrixXd GV;
Eigen::RowVector3i res;
const int s = 100;
igl::voxel_grid(V,0,s,1,GV,res);
igl::voxel_grid(V, 0, s, 1, GV, res);
BOOST_LOG_TRIVIAL(debug) << res(0) << ", " << res(1) << ", " << res(2);
// compute values
std::cout<<"Computing distances..."<<std::endl;
std::cout << "Computing distances..." << std::endl;
Eigen::VectorXd S = Eigen::VectorXd(GV.rows());
std::cout<<"Marching cubes..."<<std::endl;
Eigen::MatrixXd SV,BV;
Eigen::MatrixXi SF,BF;
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::marching_cubes(S, GV, res(0), res(1), res(2), 0, SV, SF);
igl::writeOBJ(out_mc_path, SV, SF);
// igl::marching_cubes(B,GV,res(0),res(1),res(2),0,BV,BF);
igl::writeOBJ(out_mc_path.string(), SV, SF);
}
return 0;

Loading…
Cancel
Save