我正在尝试为我的C ++(DirectX)项目实现kd-tree以加速我的碰撞检测。 我的实现是一个非常原始的递归函数。 nth_element似乎工作正常(如果我评论它只有1 fps的差异)。我不太确定它来自哪里的罪魁祸首。
KDTreeNode Box::buildKDTree(std::vector<Ball> balls, int depth) {
if (balls.size() < 3) {
return KDTreeNode(balls[0].getPos(), KDTreeLeaf(), KDTreeLeaf());
}
Variables::currAxis = depth % 3;
size_t n = (balls.size() / 2);
std::nth_element(balls.begin(), balls.begin() + n, balls.end()); // SORTS FOR THE ACCORDING AXIS - SEE BALL.CPP FOR IMPLEMENTATION
std::vector<Ball> leftSide(balls.begin(), balls.begin() + n);
std::vector<Ball> rightSide(balls.begin() + n, balls.end());
return KDTreeNode(balls[n].getPos(), this->buildKDTree(leftSide, depth + 1), this->buildKDTree(rightSide, depth + 1));
}
我在Ball类中覆盖了bool运算符:
bool Ball::operator < (Ball& ball)
{
if (Variables::currAxis == 0) {
return (XMVectorGetX(this->getPos()) < XMVectorGetX(ball.getPos()));
} else if (Variables::currAxis == 1) {
return (XMVectorGetY(this->getPos()) < XMVectorGetY(ball.getPos()));
} else {
return (XMVectorGetZ(this->getPos()) < XMVectorGetZ(ball.getPos()));
}
}
我很确定这不是实时处理结构的最佳方式。 也许你可以帮助我走上正确的轨道。
另外还有一件我真正想知道的事情:说我在场景中有很多领域,我使用的是kd-tree。我如何确定它们属于哪种叶子?因为在建筑物上我只使用中心位置,而不是它们的实际直径?那我怎么办呢? 感谢
编辑:我已经实施了所有建议的更改,现在运行得非常好。谢谢! 这就是我所做的:
KDTreeNode Box::buildKDTree(std::vector<Ball>::iterator start, std::vector<Ball>::iterator end, int depth) {
if ((end-start) == 1) {
return KDTreeNode(balls[0].getPos(), &KDTreeLeaf(), &KDTreeLeaf());
}
Variables::currAxis = depth % 3;
size_t n = (abs(end-start) / 2);
std::nth_element(start, start + n, end); // SORTS FOR THE ACCORDING AXIS - SEE BALL.CPP FOR IMPLEMENTATION
return KDTreeNode(balls[n].getPos(), &this->buildKDTree(start, (start+n), depth + 1), &this->buildKDTree((start+n), end, depth + 1));
}
正如你所看到的,我不再复制向量了,我也将左右孩子作为参考传递,这样就不会复制它们。
答案 0 :(得分:1)
我看到两个可能的问题:
基本上,该函数会为kd-tree的每个级别复制初始向量中的所有球两次。这应该导致一些严重的减速,所以尽量避免请求这么多的内存。
解决这个问题的一种方法是直接访问向量的数据,使用nth_element
等,只将子向量的索引传递给递归调用。