|
|
@ -93,41 +93,21 @@ int findFirst(const uvector<int, N>& v, int val, int startIdx = 0) |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
std::pair<uvector<real, 3>, uvector<real, 3>> getOneEightCellAABB(const uvector3& min, |
|
|
|
const uvector3& max, |
|
|
|
const uvector<int, 3> side, |
|
|
|
int negativeRep = -1) |
|
|
|
AABB getOneEightCellAABB(const AABB& fatherAABB, const uvector<int, 3> side, int negativeRep = -1) |
|
|
|
{ |
|
|
|
std::pair<uvector<real, 3>, uvector<real, 3>> res = {min, max}; |
|
|
|
uvector3 mid = (min + max) / 2; |
|
|
|
AABB res = fatherAABB; |
|
|
|
uvector3 mid = res.center(); |
|
|
|
for (int i = 0; i < 3; ++i) { |
|
|
|
if (side(i) == negativeRep) { |
|
|
|
res.second(i) = mid(i); |
|
|
|
res.max(i) = mid(i); |
|
|
|
} else { |
|
|
|
res.first(i) = mid(i); |
|
|
|
res.min(i) = mid(i); |
|
|
|
} |
|
|
|
} |
|
|
|
return res; |
|
|
|
} |
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
// TODO: delete it
|
|
|
|
bool isPointInside(const std::vector<tensor3>& originTensors, const uvector3& originPt) |
|
|
|
{ |
|
|
|
for (auto& t : originTensors) { |
|
|
|
if (evalPower(t, originPt) >= 0) { return false; } |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// bool isPointInside(const std::vector<CompleteTensorRep>& completeTensorReps, const uvector3& originPt)
|
|
|
|
// {
|
|
|
|
// for (auto& completeTensorRep : completeTensorReps) {
|
|
|
|
// if (isPointInside(completeTensorRep.originalPower, originPt)) { return false; }
|
|
|
|
// }
|
|
|
|
// return true;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// 这里blobTree是拷贝传参
|
|
|
|
bool keepQuadraturePoint(const Scene& scene, |
|
|
|
organizer::BlobTree blobTree, |
|
|
@ -138,7 +118,7 @@ bool keepQuadraturePoint(const Scene& scene, |
|
|
|
const auto& polyIntersectIndices = ocTreeNode.polyIntersectIndices; |
|
|
|
std::vector<bool> primitiveInOuts(polyIntersectIndices.size()); |
|
|
|
for (int i = 0; i < ocTreeNode.polyIntersectIndices.size(); ++i) { |
|
|
|
primitiveInOuts[i] = isPointInside(scene.polys[polyIntersectIndices[i]].rawPower, originPt); |
|
|
|
primitiveInOuts[i] = isInsidePowers(scene.polys[polyIntersectIndices[i]].rawPower, originPt); |
|
|
|
} |
|
|
|
int res = organizer::traverse(blobTree, ocTreeNode.polyIntersectIndices, primitiveInOuts); |
|
|
|
assert(res == organizer::NODE_IN || res == organizer::NODE_OUT); |
|
|
@ -149,7 +129,6 @@ bool keepQuadraturePoint(const Scene& scene, |
|
|
|
|
|
|
|
// BasicTask(std::vector<std::shared_ptr<PrimitiveDesc>> ps) {};
|
|
|
|
|
|
|
|
|
|
|
|
const std::array<int, 2> sides = {-1, 1}; |
|
|
|
|
|
|
|
struct BasicTaskRes { |
|
|
@ -174,11 +153,11 @@ void visitSubcellOnBothSidesOfDir(const uvector3& nodeMid, |
|
|
|
algoim_spark_alloc(real, halfCellPoly); |
|
|
|
int subIdx = detail::binaryToDecimal(mark, -1); |
|
|
|
auto& subNode = subNodes[subIdx]; |
|
|
|
bernstein::deCasteljau(poly, subNode.min, subNode.max, halfCellPoly); // 求1/8空间下的表达
|
|
|
|
bernstein::deCasteljau(poly, subNode.aabb.min, subNode.aabb.max, halfCellPoly); // 求1/8空间下的表达
|
|
|
|
if (bernstein::uniformSign(halfCellPoly) != 1) { |
|
|
|
subNode.polyIntersectIndices.emplace_back(polyIntersectIndex); |
|
|
|
} else { |
|
|
|
organizer::traverse(subNode.blobTree, polyIntersectIndex, organizer::NODE_OUT); |
|
|
|
organizer::traverse(subNode.blobTree, polyIntersectIndex, false); |
|
|
|
} |
|
|
|
} else { |
|
|
|
for (auto side : sides) { |
|
|
@ -199,19 +178,15 @@ void buildOcTreeV1(const Scene& scene, const OcTreeNode& node, std::vector<OcTre |
|
|
|
leaves.emplace_back(node); |
|
|
|
return; |
|
|
|
} |
|
|
|
const uvector3& nowNodeMin = node.min; |
|
|
|
const uvector3& nowNodeMax = node.max; |
|
|
|
std::vector<OcTreeNode> subNodes(CHILD_NUM); |
|
|
|
// std::array<OcTreeNode, CHILD_NUM> subNodes;
|
|
|
|
// intermediateNodes.resize(lastIdx + 8);
|
|
|
|
int subIdx = 0; |
|
|
|
for (MultiLoop<3> j(0, 2); ~j; ++j, ++subIdx) { |
|
|
|
auto nodeAABB = detail::getOneEightCellAABB(node.min, node.max, j(), 0); |
|
|
|
subNodes[subIdx].min = nodeAABB.first; |
|
|
|
subNodes[subIdx].max = nodeAABB.second; |
|
|
|
subNodes[subIdx].aabb = detail::getOneEightCellAABB(node.aabb, j(), 0); |
|
|
|
subNodes[subIdx].blobTree = node.blobTree; |
|
|
|
} |
|
|
|
uvector3 nodeMid = (nowNodeMin + nowNodeMax) / 2; |
|
|
|
uvector3 nodeMid = node.aabb.center(); |
|
|
|
for (int i = 0; i < polyIntersectIndices.size(); ++i) { |
|
|
|
const int polyIntersectIndex = polyIntersectIndices[i]; |
|
|
|
const auto& poly = scene.polys[polyIntersectIndex]; |
|
|
@ -229,18 +204,18 @@ void buildOcTreeV1(const Scene& scene, const OcTreeNode& node, std::vector<OcTre |
|
|
|
} else if (signOnHalfPlane == 1) { |
|
|
|
// primitive intersects either side or both sides of the centerface
|
|
|
|
// deCasteljau to transformation
|
|
|
|
uvector3 halfCellMin = nowNodeMin, halfCellMax = nowNodeMax; |
|
|
|
halfCellMax(faceAxis) = nodeMid(faceAxis); |
|
|
|
AABB halfCell = node.aabb; |
|
|
|
halfCell.max(faceAxis) = nodeMid(faceAxis); |
|
|
|
tensor3 halfCellPoly(nullptr, poly.compositedBernstein.ext()); |
|
|
|
algoim_spark_alloc(real, halfCellPoly); |
|
|
|
bernstein::deCasteljau(poly.compositedBernstein, halfCellMin, halfCellMax, halfCellPoly); |
|
|
|
bernstein::deCasteljau(poly.compositedBernstein, halfCell.min, halfCell.max, halfCellPoly); |
|
|
|
if (bernstein::uniformSign(halfCellPoly) != 1) { |
|
|
|
// 负空间有
|
|
|
|
mark(faceAxis) = -1; |
|
|
|
} |
|
|
|
halfCellMax(faceAxis) = nowNodeMax(faceAxis); |
|
|
|
halfCellMin(faceAxis) = nodeMid(faceAxis); |
|
|
|
bernstein::deCasteljau(poly.compositedBernstein, halfCellMin, halfCellMax, halfCellPoly); |
|
|
|
halfCell.max(faceAxis) = node.aabb.max(faceAxis); |
|
|
|
halfCell.min(faceAxis) = nodeMid(faceAxis); |
|
|
|
bernstein::deCasteljau(poly.compositedBernstein, halfCell.min, halfCell.max, halfCellPoly); |
|
|
|
if (bernstein::uniformSign(halfCellPoly) != 1) { |
|
|
|
// 正空间有
|
|
|
|
mark(faceAxis) += 1; // 当正负空间都有,记0
|
|
|
@ -253,10 +228,10 @@ void buildOcTreeV1(const Scene& scene, const OcTreeNode& node, std::vector<OcTre |
|
|
|
// fully containing cases
|
|
|
|
for (int i = 0; i < CHILD_NUM; ++i) { |
|
|
|
tensor3 subPoly(nullptr, poly.compositedBernstein.ext()); |
|
|
|
bernstein::deCasteljau(poly.compositedBernstein, subNodes[i].min, subNodes[i].max, subPoly); |
|
|
|
bernstein::deCasteljau(poly.compositedBernstein, subNodes[i].aabb.min, subNodes[i].aabb.max, subPoly); |
|
|
|
if (bernstein::uniformSign(subPoly) == -1) { |
|
|
|
// subNodes[i].polyFullyContainedIndices.emplace_back(polyIntersectIndex);
|
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, organizer::NODE_IN); |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, true); |
|
|
|
} else { |
|
|
|
subNodes[i].polyIntersectIndices.emplace_back(polyIntersectIndex); |
|
|
|
} |
|
|
@ -277,7 +252,7 @@ void buildOcTreeV1(const Scene& scene, const OcTreeNode& node, std::vector<OcTre |
|
|
|
if (subIdx == markIdx) |
|
|
|
subNodes[subIdx].polyIntersectIndices.emplace_back(polyIntersectIndex); |
|
|
|
else |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, organizer::NODE_OUT); |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, false); |
|
|
|
} |
|
|
|
} else if (zeroCount == 1) { |
|
|
|
// poly related to 2 subcells
|
|
|
@ -290,7 +265,7 @@ void buildOcTreeV1(const Scene& scene, const OcTreeNode& node, std::vector<OcTre |
|
|
|
subNodes[sideIdx2].polyIntersectIndices.emplace_back(polyIntersectIndex); |
|
|
|
for (int subIdx = 0; subIdx < CHILD_NUM; ++subIdx) { |
|
|
|
if (subIdx != sideIdx1 && subIdx != sideIdx2) { |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, organizer::NODE_OUT); |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, false); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
@ -311,39 +286,44 @@ void buildOcTreeV1(const Scene& scene, const OcTreeNode& node, std::vector<OcTre |
|
|
|
|
|
|
|
void buildOcTreeV0(const Scene& scene, const OcTreeNode& node, std::vector<OcTreeNode>& leaves) |
|
|
|
{ |
|
|
|
int a = 0; |
|
|
|
const std::vector<int>& polyIntersectIndices = node.polyIntersectIndices; |
|
|
|
if (polyIntersectIndices.size() <= 4) { |
|
|
|
if (polyIntersectIndices.size() <= 3) { |
|
|
|
leaves.emplace_back(node); |
|
|
|
return; |
|
|
|
} |
|
|
|
const uvector3& nowNodeMin = node.min; |
|
|
|
const uvector3& nowNodeMax = node.max; |
|
|
|
// std::array<OcTreeNode, CHILD_NUM> subNodes;
|
|
|
|
std::vector<OcTreeNode> subNodes(CHILD_NUM); |
|
|
|
// intermediateNodes.resize(lastIdx + 8);
|
|
|
|
int subIdx = 0; |
|
|
|
for (MultiLoop<3> j(0, 2); ~j; ++j, ++subIdx) { |
|
|
|
auto nodeAABB = detail::getOneEightCellAABB(node.min, node.max, j(), 0); |
|
|
|
subNodes[subIdx].min = nodeAABB.first; |
|
|
|
subNodes[subIdx].max = nodeAABB.second; |
|
|
|
subNodes[subIdx].aabb = detail::getOneEightCellAABB(node.aabb, j(), 0); |
|
|
|
subNodes[subIdx].blobTree = node.blobTree; |
|
|
|
subNodes[subIdx].polyIntersectIndices = std::vector<int>(); |
|
|
|
} |
|
|
|
uvector3 nodeMid = (nowNodeMin + nowNodeMax) / 2; |
|
|
|
uvector3 nodeMid = node.aabb.center(); |
|
|
|
for (int i = 0; i < polyIntersectIndices.size(); ++i) { |
|
|
|
const int polyIntersectIndex = polyIntersectIndices[i]; |
|
|
|
const auto& poly = scene.polys[polyIntersectIndex]; |
|
|
|
subIdx = 0; |
|
|
|
for (MultiLoop<3> j(0, 2); ~j; ++j, ++subIdx) { |
|
|
|
if (!poly.aabb.intersect(subNodes[subIdx].aabb)) { |
|
|
|
// out of the subcell
|
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, false); |
|
|
|
continue; |
|
|
|
} |
|
|
|
tensor3 subcellPoly(nullptr, poly.compositedBernstein.ext()); |
|
|
|
algoim_spark_alloc(real, subcellPoly); |
|
|
|
bernstein::deCasteljau(poly.compositedBernstein, subNodes[subIdx].min, subNodes[subIdx].max, subcellPoly); |
|
|
|
bernstein::deCasteljau(poly.compositedBernstein, subNodes[subIdx].aabb.min, subNodes[subIdx].aabb.max, subcellPoly); |
|
|
|
int sign = bernstein::uniformSign(subcellPoly); |
|
|
|
if (sign == 1) { |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, organizer::NODE_OUT); |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, false); |
|
|
|
} else if (sign == -1) { |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, organizer::NODE_IN); |
|
|
|
// 采样一个点,带入所有原始primitive看是否是冗余部分
|
|
|
|
uvector3 sampleX = subNodes[subIdx].aabb.center() * scene.boundary.size() + scene.boundary.min; |
|
|
|
if (isInsidePowers(poly.rawPower, sampleX)) |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, true); |
|
|
|
else |
|
|
|
organizer::traverse(subNodes[subIdx].blobTree, polyIntersectIndex, false); |
|
|
|
} else { |
|
|
|
subNodes[subIdx].polyIntersectIndices.emplace_back(polyIntersectIndex); |
|
|
|
} |
|
|
@ -479,7 +459,7 @@ void basicTask(const std::vector<std::shared_ptr<PrimitiveDesc>>& primitives, in |
|
|
|
|
|
|
|
ipquad.integrate(AutoMixed, q, [&](const uvector<real, 3>& x, real w) { |
|
|
|
auto realX = x * range + xmin; |
|
|
|
if (isPointInside(originTensors, realX)) volume += w * integrand(realX); |
|
|
|
if (isInsidePowers(originTensors, realX)) volume += w * integrand(realX); |
|
|
|
}); |
|
|
|
volume *= pow(xmax - xmin, 3); |
|
|
|
std::cout << "Volume xxx: " << volume << std::endl; |
|
|
@ -489,18 +469,18 @@ void basicTask(const std::vector<std::shared_ptr<PrimitiveDesc>>& primitives, in |
|
|
|
for (auto& p : originTensorStacks) delete p; |
|
|
|
}; |
|
|
|
|
|
|
|
BasicTaskRes basicTask(const Scene& scene, const organizer::BlobTree& blobTree, const OcTreeNode& node, int q = 20) |
|
|
|
BasicTaskRes basicTask(const Scene& scene, const organizer::BlobTree& blobTree, const OcTreeNode& node, int q = 10) |
|
|
|
{ |
|
|
|
auto integrand = [](const uvector<real, 3>& x) { return 1.0; }; |
|
|
|
real volume = 0., surf = 0.; |
|
|
|
auto range = node.max - node.min; |
|
|
|
ImplicitPolyQuadrature<3> ipquad(scene.polys); |
|
|
|
auto range = node.aabb.size(); |
|
|
|
ImplicitPolyQuadrature<3> ipquad(scene.polys, node.polyIntersectIndices); |
|
|
|
ipquad.integrate(AutoMixed, q, [&](const uvector<real, 3>& x, real w) { |
|
|
|
auto realX = x * range + node.min; |
|
|
|
auto realX = x * range + node.aabb.min; |
|
|
|
if (keepQuadraturePoint(scene, blobTree, node, realX)) { volume += w * integrand(realX); } |
|
|
|
}); |
|
|
|
ipquad.integrate_surf(AutoMixed, q, [&](const uvector<real, 3>& x, real w, const uvector<real, 3>& wn) { |
|
|
|
surf += w * integrand(x * range + node.min); |
|
|
|
surf += w * integrand(x * range + node.aabb.min); |
|
|
|
}); |
|
|
|
return {volume, surf}; |
|
|
|
} |
|
|
@ -534,6 +514,7 @@ void quadratureScene(const std::vector<std::shared_ptr<PrimitiveDesc>>& primitiv |
|
|
|
AABB aabb; |
|
|
|
makeSphere(*pt, originTensor, aabb); |
|
|
|
detail::powerTransformation(range, xmin, originTensor, transformedTensor); |
|
|
|
aabb.normalize(range, xmin); |
|
|
|
|
|
|
|
real testEvaOri = evalPower(originTensor, testX); |
|
|
|
|
|
|
@ -553,7 +534,9 @@ void quadratureScene(const std::vector<std::shared_ptr<PrimitiveDesc>>& primitiv |
|
|
|
algoim_spark_alloc(real, compositeTensor); |
|
|
|
AABB aabb; |
|
|
|
makeMesh(*pt, compositeTensor, planeTensors, aabb); |
|
|
|
|
|
|
|
detail::powerTransformation(range, xmin, compositeTensor); |
|
|
|
aabb.normalize(range, xmin); |
|
|
|
|
|
|
|
real testEvalPower = evalPower(compositeTensor, testX); |
|
|
|
|
|
|
@ -576,6 +559,8 @@ void quadratureScene(const std::vector<std::shared_ptr<PrimitiveDesc>>& primitiv |
|
|
|
AABB aabb; |
|
|
|
makeCylinder(*pt, compositeTensor, rawTensors, aabb); |
|
|
|
detail::powerTransformation(range, xmin, compositeTensor); |
|
|
|
aabb.normalize(range, xmin); |
|
|
|
|
|
|
|
real testEvalPower = evalPower(compositeTensor, testX); |
|
|
|
|
|
|
|
detail::power2BernsteinTensor(compositeTensor, phi); |
|
|
@ -595,6 +580,8 @@ void quadratureScene(const std::vector<std::shared_ptr<PrimitiveDesc>>& primitiv |
|
|
|
AABB aabb; |
|
|
|
makeCone(*pt, compositeTensor, rawTensors, aabb); |
|
|
|
detail::powerTransformation(range, xmin, compositeTensor); |
|
|
|
aabb.normalize(range, xmin); |
|
|
|
|
|
|
|
real testEvalPower = evalPower(compositeTensor, testX); |
|
|
|
|
|
|
|
detail::power2BernsteinTensor(compositeTensor, phi); |
|
|
@ -605,14 +592,14 @@ void quadratureScene(const std::vector<std::shared_ptr<PrimitiveDesc>>& primitiv |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Scene scene{completeTensorReps, blobTree}; |
|
|
|
Scene scene{completeTensorReps, AABB(xmin, xmax)}; |
|
|
|
OcTreeNode rootNode(0, 1, blobTree); |
|
|
|
for (int i = 0; i < completeTensorReps.size(); ++i) { rootNode.polyIntersectIndices.emplace_back(i); } |
|
|
|
buildOcTreeV0(scene, rootNode, leaves); |
|
|
|
|
|
|
|
for (const auto& leaf : leaves) { |
|
|
|
auto basicRes = basicTask(scene, blobTree, leaf, q); |
|
|
|
volume += basicRes.volume * prod(leaf.max - leaf.min); |
|
|
|
volume += basicRes.volume * prod(leaf.aabb.max - leaf.aabb.min); |
|
|
|
} |
|
|
|
|
|
|
|
volume *= prod(xmax - xmin); |
|
|
|