#pragma once #include #include #include namespace algoim::organizer { const int NODE_IN_OUT_UNKNOWN = 0; const int NODE_IN = 1; const int NODE_OUT = 2; const int OP_UNION = 0; const int OP_INTERSECTION = 1; const int OP_DIFFERENCE = 2; // bitfield struct Blob { unsigned int isPrimitive : 1; // 1 for leaf unsigned int nodeOp : 2; // 0 for union, 1 for intersection, 2 for difference // unsigned int ignoreMod : 2; // 目前用不到 unsigned int inOut : 2; // 0 for unknown, 1 for in, 2 for out unsigned int oneChildInOut : 2; // 0 for unknown, 1 for in, 2 for out unsigned int isLeft : 1; unsigned int ancestor : 24; }; bool isPrimitive(Blob b) { return b.isPrimitive == 1; } unsigned int type(Blob b) { return 0; } bool isLeft(Blob b) { return b.isLeft == 1; } class BlobTree { public: std::vector structure; std::vector primitiveNodeIdx; // 由primitive数组下标指向node中对应leaf的下标 BlobTree(const BlobTree& other) { structure = other.structure; primitiveNodeIdx = other.primitiveNodeIdx; } BlobTree& operator=(const BlobTree& other) { if (this != &other) { structure = other.structure; primitiveNodeIdx = other.primitiveNodeIdx; } return *this; } BlobTree() {} void clear() { structure.clear(); primitiveNodeIdx.clear(); } }; void propagate(BlobTree& tree, unsigned int nodeIdx, bool in) { const std::size_t rootIdx = tree.structure.size() - 1; auto& node = tree.structure[nodeIdx]; if (nodeIdx == 4) { int aaa = 1; int bbb = 1; } if (node.inOut != NODE_IN_OUT_UNKNOWN) { int aaa = 1; int bb = 1; } // assert(node.inOut == NODE_IN_OUT_UNKNOWN); node.inOut = in ? NODE_IN : NODE_OUT; for (unsigned int nowIdx = nodeIdx; nowIdx != rootIdx;) { const auto& nowNode = tree.structure[nowIdx]; unsigned int nextIdx = isLeft(nowNode) ? nowIdx + nowNode.ancestor : nowIdx + 1; auto& nextNode = tree.structure[nextIdx]; // father if (nextNode.inOut != 0) { return; } if (nowNode.inOut == NODE_OUT) { if (nextNode.nodeOp == OP_INTERSECTION) { nextNode.inOut = NODE_OUT; } else if (nextNode.nodeOp == OP_DIFFERENCE && isLeft(nowNode)) { nextNode.inOut = NODE_OUT; } else if (nextNode.oneChildInOut == NODE_IN) { // 两种情况,Union: in, Difference: NowNode一定是right,in-out,还是in nextNode.inOut = NODE_IN; } else if (nextNode.oneChildInOut == NODE_OUT) { // 两种情况,Union: out, Difference: out-out, 还是out nextNode.inOut = NODE_OUT; } else { nextNode.oneChildInOut = NODE_OUT; return; } } else if (nowNode.inOut == NODE_IN) { if (nextNode.nodeOp == OP_UNION) { nextNode.inOut = NODE_IN; } else if (nextNode.nodeOp == OP_DIFFERENCE && !isLeft(nowNode)) { // difference and right nextNode.inOut = NODE_OUT; } else if (nextNode.oneChildInOut == NODE_IN) { // 两种情况,Intersection: in, Difference: in-in,out nextNode.inOut = nextNode.nodeOp == OP_INTERSECTION ? NODE_IN : NODE_OUT; } else if (nextNode.oneChildInOut == NODE_OUT) { // 两种情况,Intersection: out, Difference: NowNode一定是left,in-out,in nextNode.inOut = nextNode.nodeOp == OP_INTERSECTION ? NODE_OUT : NODE_IN; } else { nextNode.oneChildInOut = NODE_IN; return; } } nowIdx = nextIdx; } return; } // TODO: std::vector 浪费内存,应实现动态大小的bitset /** * relatedPrimitives 是当次traversal需要care的primitives的索引,例如OcTree子问题中关联的Primitive */ int traverse(BlobTree& tree, const std::vector& relatedPrimitives, const std::vector& primitiveInout) { assert(relatedPrimitives.size() == primitiveInout.size()); for (int i = 0; i < relatedPrimitives.size(); ++i) { propagate(tree, tree.primitiveNodeIdx[relatedPrimitives[i]], static_cast(primitiveInout[i])); if (tree.structure.back().inOut != NODE_IN_OUT_UNKNOWN) { return tree.structure.back().inOut; } } return NODE_IN_OUT_UNKNOWN; } int traverse(BlobTree& tree, const int relatedPrimitive, const bool in) { int bbb = 1; propagate(tree, tree.primitiveNodeIdx[relatedPrimitive], in); if (tree.structure[tree.primitiveNodeIdx[relatedPrimitive]].inOut == NODE_IN_OUT_UNKNOWN) { int aaa = 1; int bbb = 1; } return tree.structure.back().inOut; } // void mergeSubtree2Leaf(BlobTree& blobTree, const std::vector& visiblePrimitiveReps) // { // std::vector minimalReps; // std::vector 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 upwardGeneratingNodes(std::vector& 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 levelLeftBook; tree.primitiveNodeIdx.resize(leafSize); for (int i = 0; i < leafSize; ++i) { upwardGeneratingNodes(levelLeftBook, tree, 0, i, i == leafSize - 1); } }; }; // namespace algoim::organizer