diff --git a/README.md b/README.md index 30d74d2..e1de6be 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -test \ No newline at end of file +Nurbs curve surface intersection calculation \ No newline at end of file diff --git a/include/bvh.hpp b/include/bvh.hpp index 7599f9d..c5e606d 100644 --- a/include/bvh.hpp +++ b/include/bvh.hpp @@ -7,50 +7,46 @@ //包围盒结构,存储盒子对角的两个点 typedef struct AABB { - glm::vec3 Bmin, Bmax; - AABB() - { - double minNum = std::numeric_limits::lowest(); - double maxNum = std::numeric_limits::max(); - Bmax = glm::vec3(minNum, minNum, minNum); - Bmin = glm::vec3(maxNum, maxNum, maxNum); - } -}AABB; - -//AABB包围盒的结点 + glm::vec3 Bmin, Bmax; + AABB() + { + double minNum = std::numeric_limits::lowest(); + double maxNum = std::numeric_limits::max(); + Bmax = glm::vec3(minNum, minNum, minNum); + Bmin = glm::vec3(maxNum, maxNum, maxNum); + } +} AABB; + +// AABB包围盒的结点 typedef struct BVH_AABB_Node { - AABB bound; //包围盒边界 - std::vector> param; //此包围盒对应的每个参数的范围 - std::vector childPtr; //把每个孩子结点指针存储到容器里 -}BVH_AABB_Node, * BVH_AABB_NodePtr; - + AABB bound; //包围盒边界 + std::vector> param; //此包围盒对应的每个参数的范围 + std::vector childPtr; //把每个孩子结点指针存储到容器里 +} BVH_AABB_Node, *BVH_AABB_NodePtr; class BVH_AABB { public: - unsigned int Hlevel; //递归层数 - unsigned int BranchNum; //每个结点的分支数 [BranchNum=2:曲线 || BranchNum=4:曲面] - double sampleNum; //采样点数--越大包围盒构造越准确 - BVH_AABB_NodePtr bvh_aabb_node = NULL; //bvh树的根指针 + unsigned int Hlevel; //递归层数 + unsigned int BranchNum; //每个结点的分支数 [BranchNum=2:曲线 || BranchNum=4:曲面] + double sampleNum; //采样点数--越大包围盒构造越准确 + BVH_AABB_NodePtr bvh_aabb_node = NULL; // bvh树的根指针 public: - BVH_AABB(unsigned int Hlevel_, unsigned int BranchNum_, double sampleNum_) :Hlevel(Hlevel_), BranchNum(BranchNum_), sampleNum(sampleNum_) - { - bvh_aabb_node = new BVH_AABB_Node; - std::cout << "BVH_AABB constructed correct!\n"; - }; - BVH_AABB_Node* GetNode() const - { - return bvh_aabb_node; - }; - BVH_AABB_NodePtr Build_NurbsCurve(tinynurbs::RationalCurve& curve, BVH_AABB_NodePtr& curNode, int curLevel, double t, double tstep); - BVH_AABB_NodePtr Build_NurbsSurface(tinynurbs::RationalSurface& surface, BVH_AABB_NodePtr& curNode, int curLevel, double u, double v, double ustep, double vstep); - AABB& UnionBound(const AABB& a, const AABB& b); - AABB& UpdateBound(const AABB& bound, const glm::vec3& p); - + BVH_AABB(unsigned int Hlevel_, unsigned int BranchNum_, double sampleNum_) : Hlevel(Hlevel_), BranchNum(BranchNum_), sampleNum(sampleNum_) + { + bvh_aabb_node = new BVH_AABB_Node; + std::cout << "BVH_AABB constructed correct!\n"; + }; + BVH_AABB_Node *GetNode() const + { + return bvh_aabb_node; + }; + BVH_AABB_NodePtr Build_NurbsCurve(tinynurbs::RationalCurve &curve, BVH_AABB_NodePtr &curNode, int curLevel, double t, double tstep); + BVH_AABB_NodePtr Build_NurbsSurface(tinynurbs::RationalSurface &surface, BVH_AABB_NodePtr &curNode, int curLevel, double u, double v, double ustep, double vstep); + AABB &UnionBound(const AABB &a, const AABB &b); + AABB &UpdateBound(const AABB &bound, const glm::vec3 &p); }; - - #endif // !BVH_H_ diff --git a/include/show_in_libigl.hpp b/include/show_in_libigl.hpp new file mode 100644 index 0000000..3509798 --- /dev/null +++ b/include/show_in_libigl.hpp @@ -0,0 +1,5 @@ +#include "bvh.hpp" +#include + +void ShowCurve_Igl(igl::opengl::glfw::Viewer viewer, tinynurbs::RationalCurve &curve, double sampleNum); +void ShowSurface_Igl(igl::opengl::glfw::Viewer viewer, tinynurbs::RationalSurface &surface, double sampleNumU, double sampleNumV); \ No newline at end of file diff --git a/src/bvh.cpp b/src/bvh.cpp index e69de29..44330a9 100644 --- a/src/bvh.cpp +++ b/src/bvh.cpp @@ -0,0 +1,93 @@ +#include "bvh.hpp" + +AABB &BVH_AABB::UnionBound(const AABB &a, const AABB &b) +{ + AABB ret; + ret.Bmin = glm::vec3(fmin(a.Bmin.x, b.Bmin.x), + fmin(a.Bmin.y, b.Bmin.y), + fmin(a.Bmin.z, b.Bmin.z)); + + ret.Bmax = glm::vec3(fmax(a.Bmax.x, b.Bmax.x), + fmax(a.Bmax.y, b.Bmax.y), + fmax(a.Bmax.z, b.Bmax.z)); + return ret; +} + +AABB &BVH_AABB::UpdateBound(const AABB &bound, const glm::vec3 &p) +{ + AABB ret; + ret.Bmin = glm::vec3(fmin(bound.Bmin.x, p.x), + fmin(bound.Bmin.y, p.y), + fmin(bound.Bmin.z, p.z)); + + ret.Bmax = glm::vec3(fmax(bound.Bmax.x, p.x), + fmax(bound.Bmax.y, p.y), + fmax(bound.Bmax.z, p.z)); + return ret; +} + +BVH_AABB_NodePtr BVH_AABB::Build_NurbsCurve(tinynurbs::RationalCurve &curve, BVH_AABB_NodePtr &curNode, int curLevel, double t, double tstep) +{ + if (curLevel == Hlevel) + { + for (double i = t; i < t + tstep; i += tstep / sampleNum) + { + curNode->bound = UpdateBound(curNode->bound, tinynurbs::curvePoint(curve, i)); + } + curNode->childPtr.clear(); + curNode->param.push_back(std::make_pair(t, t + tstep)); + + return curNode; + } + BVH_AABB_NodePtr childNode1 = new BVH_AABB_Node; + BVH_AABB_NodePtr childNode2 = new BVH_AABB_Node; + + double tstep_ = tstep / (double)BranchNum; + Build_NurbsCurve(curve, childNode1, curLevel + 1, t, tstep_); + Build_NurbsCurve(curve, childNode2, curLevel + 1, t + tstep_, tstep_); + + curNode->bound = UnionBound(curNode->bound, childNode1->bound); + curNode->bound = UnionBound(curNode->bound, childNode2->bound); + + curNode->childPtr.push_back(childNode1); + curNode->childPtr.push_back(childNode2); + + curNode->param.push_back(std::make_pair(t, t + tstep)); + + return curNode; +} +BVH_AABB_NodePtr BVH_AABB::Build_NurbsSurface(tinynurbs::RationalSurface &surface, BVH_AABB_NodePtr &curNode, int curLevel, double u, double v, double ustep, double vstep) +{ + if (curLevel == Hlevel) + { + for (double i = u; i < u + ustep; i++) + { + for (double j = v; j < v + vstep; j++) + { + curNode->bound = UpdateBound(curNode->bound, tinynurbs::surfacePoint(surface, i, j)); + } + } + curNode->childPtr.clear(); + curNode->param.push_back(std::make_pair(u, u + ustep)); + curNode->param.push_back(std::make_pair(v, v + vstep)); + + return curNode; + } + BVH_AABB_NodePtr childNode1 = new BVH_AABB_Node; + BVH_AABB_NodePtr childNode2 = new BVH_AABB_Node; + BVH_AABB_NodePtr childNode3 = new BVH_AABB_Node; + BVH_AABB_NodePtr childNode4 = new BVH_AABB_Node; + + double ustep_ = ustep / (double)BranchNum; + double vstep_ = vstep / (double)BranchNum; + + Build_NurbsSurface(surface, childNode1, curLevel + 1, u, v, ustep_, vstep_); + Build_NurbsSurface(surface, childNode2, curLevel + 1, u + ustep_, v, ustep_, vstep_); + Build_NurbsSurface(surface, childNode3, curLevel + 1, u, v + vstep_, ustep_, vstep_); + Build_NurbsSurface(surface, childNode4, curLevel + 1, u + ustep_, v + vstep_, ustep_, vstep_); + + curNode->param.push_back(std::make_pair(u, u + ustep)); + curNode->param.push_back(std::make_pair(v, v + vstep)); + + return curNode; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ac7e836..5d8283a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,33 +2,33 @@ int main(int argc, char *argv[]) { - // Inline mesh of a cube - const Eigen::MatrixXd V= (Eigen::MatrixXd(8,3)<< - 0.0,0.0,0.0, - 0.0,0.0,1.0, - 0.0,1.0,0.0, - 0.0,1.0,1.0, - 1.0,0.0,0.0, - 1.0,0.0,1.0, - 1.0,1.0,0.0, - 1.0,1.0,1.0).finished(); - const Eigen::MatrixXi F = (Eigen::MatrixXi(12,3)<< - 0,6,4, - 0,2,6, - 0,3,2, - 0,1,3, - 2,7,6, - 2,3,7, - 4,6,7, - 4,7,5, - 0,4,5, - 0,5,1, - 1,5,7, - 1,7,3).finished(); + // Inline mesh of a cube + const Eigen::MatrixXd V = (Eigen::MatrixXd(8, 3) << 0.0, 0.0, 0.0, + 0.0, 0.0, 1.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 1.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 1.0, + 1.0, 1.0, 0.0, + 1.0, 1.0, 1.0) + .finished(); + const Eigen::MatrixXi F = (Eigen::MatrixXi(12, 3) << 0, 6, 4, + 0, 2, 6, + 0, 3, 2, + 0, 1, 3, + 2, 7, 6, + 2, 3, 7, + 4, 6, 7, + 4, 7, 5, + 0, 4, 5, + 0, 5, 1, + 1, 5, 7, + 1, 7, 3) + .finished(); - // Plot the mesh - igl::opengl::glfw::Viewer viewer; - viewer.data().set_mesh(V, F); - viewer.data().set_face_based(true); - viewer.launch(); + // Plot the mesh + igl::opengl::glfw::Viewer viewer; + viewer.data().set_mesh(V, F); + viewer.data().set_face_based(true); + viewer.launch(); } diff --git a/src/show_in_libigl.cpp b/src/show_in_libigl.cpp index e69de29..91a6ffc 100644 --- a/src/show_in_libigl.cpp +++ b/src/show_in_libigl.cpp @@ -0,0 +1,25 @@ +#include "show_in_libigl.hpp" + +void ShowCurve_Igl(igl::opengl::glfw::Viewer viewer, tinynurbs::RationalCurve &curve, double sampleNum) +{ + double T = *(curve.knots.end() - 1); + + for (double i = 0; i < T; i += T / sampleNum) + { + auto point = tinynurbs::curvePoint(curve, i); + pt << point.x, point.y, point.z; + viewer.data().add_points(pt, Eigen::RowVector3d(0, 1, 0)); + } +} + +void ShowSurface_Igl(igl::opengl::glfw::Viewer viewer, tinynurbs::RationalCurve &curve, double sampleNumU, double sampleNumV) +{ + double T = *(curve.knots.end() - 1); + + for (double i = 0; i < T; i += T / sampleNum) + { + auto point = tinynurbs::curvePoint(curve, i); + pt << point.x, point.y, point.z; + viewer.data().add_points(pt, Eigen::RowVector3d(0, 1, 0)); + } +} \ No newline at end of file