|
|
@ -16,6 +16,7 @@ |
|
|
|
#include "blobtree.hpp" |
|
|
|
#include "quaternion.hpp" |
|
|
|
#include "factorial.hpp" |
|
|
|
#include "minimalPrimitive.hpp" |
|
|
|
#include <memory> |
|
|
|
|
|
|
|
namespace algoim::organizer |
|
|
@ -226,13 +227,13 @@ void compositePower(const std::vector<xarray<real, 3>>& powers, |
|
|
|
} |
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
class Primitive |
|
|
|
{ |
|
|
|
public: |
|
|
|
virtual void print() = 0; |
|
|
|
// class Primitive
|
|
|
|
// {
|
|
|
|
// public:
|
|
|
|
// virtual void print() = 0;
|
|
|
|
|
|
|
|
virtual real eval(const uvector3&) { return 0; } |
|
|
|
}; |
|
|
|
// virtual real eval(const uvector3&) { return 0; }
|
|
|
|
// };
|
|
|
|
|
|
|
|
template <int N> |
|
|
|
real evalPower(const xarray<real, N>& phi, const uvector<real, N>& x) |
|
|
@ -481,18 +482,18 @@ bool isInsideBernsteins(const std::vector<tensor3>& tensors, const uvector3& p) |
|
|
|
|
|
|
|
bool isInsidePower(const tensor3& t, const uvector3& p) { return evalPower(t, p) < 0; } |
|
|
|
|
|
|
|
class FRep : public Primitive |
|
|
|
{ |
|
|
|
private: |
|
|
|
std::function<real(uvector3)> f; |
|
|
|
// class FRep : public Primitive
|
|
|
|
// {
|
|
|
|
// private:
|
|
|
|
// std::function<real(uvector3)> f;
|
|
|
|
|
|
|
|
public: |
|
|
|
void print() override { std::cout << "FRep" << std::endl; } |
|
|
|
// public:
|
|
|
|
// void print() override { std::cout << "FRep" << std::endl; }
|
|
|
|
|
|
|
|
real eval(const uvector3& p) override { return f(p); } |
|
|
|
// real eval(const uvector3& p) override { return f(p); }
|
|
|
|
|
|
|
|
FRep(std::function<real(uvector3)> f_) : f(f_) {} |
|
|
|
}; |
|
|
|
// FRep(std::function<real(uvector3)> f_) : f(f_) {}
|
|
|
|
// };
|
|
|
|
|
|
|
|
enum PrimitiveType { Sphere, Cylinder, Cone, Mesh, BRep }; |
|
|
|
|
|
|
@ -698,63 +699,13 @@ public: |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
class AABB |
|
|
|
{ |
|
|
|
public: |
|
|
|
uvector3 min = uvector3(std::numeric_limits<real>::max()); |
|
|
|
uvector3 max = uvector3(std::numeric_limits<real>::lowest()); |
|
|
|
AABB() = default; |
|
|
|
|
|
|
|
AABB(const uvector3& min_, const uvector3& max_) : min(min_), max(max_) {} |
|
|
|
|
|
|
|
void extend(const uvector3& p) |
|
|
|
{ |
|
|
|
for (int i = 0; i < 3; ++i) { |
|
|
|
min(i) = std::min(min(i), p(i)); |
|
|
|
max(i) = std::max(max(i), p(i)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void extend(const AABB& aabb) |
|
|
|
{ |
|
|
|
for (int i = 0; i < 3; ++i) { |
|
|
|
min(i) = std::min(min(i), aabb.min(i)); |
|
|
|
max(i) = std::max(max(i), aabb.max(i)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
uvector3 center() const { return (min + max) / 2; } |
|
|
|
|
|
|
|
uvector3 size() const { return max - min; } |
|
|
|
|
|
|
|
real volume() const { return prod(size()); } |
|
|
|
|
|
|
|
bool intersect(const AABB& aabb) const |
|
|
|
{ |
|
|
|
for (int i = 0; i < 3; ++i) { |
|
|
|
if (min(i) > aabb.max(i) || max(i) < aabb.min(i)) { return false; } |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
void normalize(const uvector3& scale, const uvector3& boundaryMin) |
|
|
|
{ |
|
|
|
min = (min - boundaryMin) / scale; |
|
|
|
max = (max - boundaryMin) / scale; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct VisiblePrimitiveRep { |
|
|
|
std::vector<tensor3> tensors; |
|
|
|
AABB aabb; |
|
|
|
organizer::BlobTree subBlobTree; |
|
|
|
}; |
|
|
|
|
|
|
|
struct MinimalPrimitiveRep { |
|
|
|
tensor3 tensor; |
|
|
|
AABB aabb; |
|
|
|
}; |
|
|
|
|
|
|
|
// hesai
|
|
|
|
struct Scene { |
|
|
|
// std::vector<CompleteTensorRep> polys;
|
|
|
|
// std::vector<VisiblePrimitiveRep> visiblePrimitives;
|
|
|
@ -763,66 +714,6 @@ struct Scene { |
|
|
|
AABB boundary; |
|
|
|
}; |
|
|
|
|
|
|
|
void upwardGeneratingNodes(std::vector<int>& levelLeftBook, |
|
|
|
organizer::BlobTree& tree, |
|
|
|
int level, |
|
|
|
int primitiveIdx, |
|
|
|
bool isFinal) |
|
|
|
{ |
|
|
|
assert(level <= levelLeftBook.size()); |
|
|
|
if (level == levelLeftBook.size()) { levelLeftBook.emplace_back(-1); } |
|
|
|
if (levelLeftBook[level] != -1) { |
|
|
|
// 右节点
|
|
|
|
if (level == 0) { |
|
|
|
tree.primitiveNodeIdx[primitiveIdx] = tree.structure.size(); |
|
|
|
tree.structure.emplace_back(organizer::Blob{1, 0, 0, 0, 0, 0}); |
|
|
|
} else { |
|
|
|
tree.structure.emplace_back(organizer::Blob{0, organizer::OP_INTERSECTION, 0, 0, 0, 0}); |
|
|
|
} |
|
|
|
// upwards
|
|
|
|
tree.structure[levelLeftBook[level]].ancestor = tree.structure.size() - levelLeftBook[level]; |
|
|
|
levelLeftBook[level] = -1; |
|
|
|
upwardGeneratingNodes(levelLeftBook, tree, level + 1, primitiveIdx, isFinal); |
|
|
|
} else { |
|
|
|
if (isFinal) { |
|
|
|
// 不会再有同层的其它右节点了。因此该节点应作为右节点与更高层的左节点组合
|
|
|
|
if (level == 0) { |
|
|
|
tree.primitiveNodeIdx[primitiveIdx] = tree.structure.size(); |
|
|
|
tree.structure.emplace_back(organizer::Blob{1, 0, 0, 0, 0, 0}); |
|
|
|
} else { |
|
|
|
tree.structure.emplace_back(organizer::Blob{0, organizer::OP_INTERSECTION, 0, 0, 0, 0}); |
|
|
|
} |
|
|
|
// upwards
|
|
|
|
// 向上寻找第一个有记录的左节点
|
|
|
|
int i = level + 1; |
|
|
|
if (i == levelLeftBook.size()) return; |
|
|
|
for (; i < levelLeftBook.size(); ++i) { |
|
|
|
if (levelLeftBook[i] != -1) break; |
|
|
|
} |
|
|
|
assert(i < levelLeftBook.size()); |
|
|
|
tree.structure[levelLeftBook[i]].ancestor = tree.structure.size() - levelLeftBook[i]; |
|
|
|
levelLeftBook[level] = -1; |
|
|
|
upwardGeneratingNodes(levelLeftBook, tree, i + 1, primitiveIdx, isFinal); |
|
|
|
} else { |
|
|
|
// 左节点
|
|
|
|
levelLeftBook[level] = tree.structure.size(); // 标记左节点的位置
|
|
|
|
if (level == 0) { |
|
|
|
tree.primitiveNodeIdx[primitiveIdx] = tree.structure.size(); |
|
|
|
tree.structure.emplace_back(organizer::Blob{1, 0, 0, 0, 1, 0}); |
|
|
|
} else { |
|
|
|
tree.structure.emplace_back(organizer::Blob{0, organizer::OP_INTERSECTION, 0, 0, 1, 0}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
void buildNearBalancedBlobTree(organizer::BlobTree& tree, int leafSize) |
|
|
|
{ |
|
|
|
std::vector<int> levelLeftBook; |
|
|
|
tree.primitiveNodeIdx.resize(leafSize); |
|
|
|
for (int i = 0; i < leafSize; ++i) { upwardGeneratingNodes(levelLeftBook, tree, 0, i, i == leafSize - 1); } |
|
|
|
}; |
|
|
|
|
|
|
|
void makeMesh(const MeshDesc& mesh, VisiblePrimitiveRep& visiblePrimitive) |
|
|
|
{ |
|
|
|
assert(visiblePrimitive.tensors.size() == mesh.indexInclusiveScan.size()); |
|
|
@ -987,6 +878,50 @@ void makeCone(const ConeDesc& coneDesc, VisiblePrimitiveRep& visiblePrimitive) |
|
|
|
buildNearBalancedBlobTree(visiblePrimitive.subBlobTree, 3); |
|
|
|
} |
|
|
|
|
|
|
|
void mergeSubtree2Leaf(BlobTree& blobTree, |
|
|
|
std::vector<MinimalPrimitiveRep>& minimalReps, |
|
|
|
const std::vector<VisiblePrimitiveRep>& visiblePrimitiveReps) |
|
|
|
{ |
|
|
|
std::vector<int> realLeafIndices; |
|
|
|
for (int i = 0; i < blobTree.structure.size(); ++i) { |
|
|
|
int oldAncestor = blobTree.structure[i].ancestor; |
|
|
|
for (int j = visiblePrimitiveReps.size() - 1; blobTree.primitiveNodeIdx[j] > i; --j) { |
|
|
|
if (blobTree.structure[i].isLeft && oldAncestor + i > blobTree.primitiveNodeIdx[j]) { |
|
|
|
blobTree.structure[i].ancestor += std::max(int(visiblePrimitiveReps[j].subBlobTree.structure.size()) - 1, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
for (int i = 0; i < visiblePrimitiveReps.size(); ++i) { |
|
|
|
int originLeafIdx = blobTree.primitiveNodeIdx[i]; |
|
|
|
int subBlobTreeSize = visiblePrimitiveReps[i].subBlobTree.structure.size(); |
|
|
|
if (visiblePrimitiveReps[i].tensors.size() != 1) { |
|
|
|
for (int j = i + 1; j < visiblePrimitiveReps.size(); ++j) { |
|
|
|
blobTree.primitiveNodeIdx[j] += std::max(int(subBlobTreeSize) - 1, 0); |
|
|
|
} |
|
|
|
blobTree.structure[originLeafIdx].isPrimitive = false; |
|
|
|
blobTree.structure[originLeafIdx].nodeOp = visiblePrimitiveReps[i].subBlobTree.structure.back().nodeOp; |
|
|
|
blobTree.structure.insert(blobTree.structure.begin() + originLeafIdx, |
|
|
|
visiblePrimitiveReps[i].subBlobTree.structure.begin(), |
|
|
|
visiblePrimitiveReps[i].subBlobTree.structure.end() - 1); |
|
|
|
|
|
|
|
realLeafIndices.reserve(realLeafIndices.size() + visiblePrimitiveReps[i].subBlobTree.primitiveNodeIdx.size()); |
|
|
|
for (auto primitiveIdx : visiblePrimitiveReps[i].subBlobTree.primitiveNodeIdx) { |
|
|
|
realLeafIndices.push_back(primitiveIdx + originLeafIdx); |
|
|
|
} |
|
|
|
minimalReps.reserve(minimalReps.size() + visiblePrimitiveReps[i].tensors.size()); |
|
|
|
const auto& aabb = visiblePrimitiveReps[i].aabb; |
|
|
|
for (const auto& tensor : visiblePrimitiveReps[i].tensors) { |
|
|
|
minimalReps.emplace_back(MinimalPrimitiveRep{tensor, aabb}); |
|
|
|
} |
|
|
|
} else { |
|
|
|
blobTree.structure[originLeafIdx].isPrimitive = true; |
|
|
|
realLeafIndices.push_back(originLeafIdx); |
|
|
|
minimalReps.emplace_back(MinimalPrimitiveRep{visiblePrimitiveReps[i].tensors[0], visiblePrimitiveReps[i].aabb}); |
|
|
|
} |
|
|
|
} |
|
|
|
blobTree.primitiveNodeIdx = realLeafIndices; |
|
|
|
} |
|
|
|
|
|
|
|
// void makeMesh(const MeshDesc& mesh, xarray<real, 3>& tensor, std::vector<xarray<real, 3>>& planeTensors, AABB& aabb)
|
|
|
|
// {
|
|
|
|
// uvector3 ext(1 + mesh.indexInclusiveScan.size());
|
|
|
@ -1135,32 +1070,5 @@ void makeCone(const ConeDesc& coneDesc, VisiblePrimitiveRep& visiblePrimitive) |
|
|
|
// AABB aabb;
|
|
|
|
// };
|
|
|
|
|
|
|
|
const int CHILD_NUM = 8; |
|
|
|
|
|
|
|
struct OcTreeNode { |
|
|
|
std::vector<int> polyIntersectIndices; // 同一poly会出现在不同node的polyIndices中
|
|
|
|
// std::vector<int> polyFullyContainedIndices; // 完全包含该node的poly, 同样会出现在不同node的polyIndices中
|
|
|
|
// std::array<int, CHILD_NUM> children; // octree
|
|
|
|
AABB aabb; |
|
|
|
organizer::BlobTree blobTree; // 部分遍历过的octree,那些不属于该node的primitive的out信息已经在该blobtree种尽可能地向上传递
|
|
|
|
|
|
|
|
// Node() { children.fill(-1); }
|
|
|
|
OcTreeNode() = default; |
|
|
|
|
|
|
|
OcTreeNode(const uvector3& min_, const uvector3& max_, const organizer::BlobTree& blobTree_) |
|
|
|
: aabb(min_, max_), blobTree(blobTree_) {}; |
|
|
|
OcTreeNode(const AABB& aabb_, const organizer::BlobTree& blobTree_) : aabb(aabb_), blobTree(blobTree_) {}; |
|
|
|
|
|
|
|
// 深拷贝
|
|
|
|
OcTreeNode(const OcTreeNode& node) |
|
|
|
: polyIntersectIndices(node.polyIntersectIndices), |
|
|
|
// polyFullyContainedIndices(node.polyFullyContainedIndices),
|
|
|
|
aabb(node.aabb), |
|
|
|
blobTree(node.blobTree) |
|
|
|
{ |
|
|
|
int a = 1; |
|
|
|
int b = 2; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
} // namespace algoim::organizer
|