kd-tree构造非常慢

时间:2013-12-08 23:25:21

标签: c++ sorting kdtree

我正在尝试为我的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));
}

正如你所看到的,我不再复制向量了,我也将左右孩子作为参考传递,这样就不会复制它们。

1 个答案:

答案 0 :(得分:1)

我看到两个可能的问题:

  1. 将向量作为值传递给函数(这有效地复制了整个向量)
  2. 为越来越小的元素创建新的向量,而不是一些就地处理
  3. 基本上,该函数会为kd-tree的每个级别复制初始向量中的所有球两次。这应该导致一些严重的减速,所以尽量避免请求这么多的内存。

    解决这个问题的一种方法是直接访问向量的数据,使用nth_element等,只将子向量的索引传递给递归调用。