KD-дерево очень медленно

Я пытаюсь реализовать kd-дерево для моего C ++ (DirectX) проекта, чтобы ускорить обнаружение столкновений.
Моя реализация — действительно примитивная рекурсивная функция. Элемент nth_element работает нормально (разница только в 1 кадр / с, если я его закомментирую). Я не совсем уверен, откуда виновник.

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));
}

Я переписал оператор bool в классе Ball:

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-дерево. Как определить, к какому листу они принадлежат? Потому что при строительстве я использую только центральное положение, а не их фактический диаметр? Как я могу пойти об этом тогда?
Спасибо

РЕДАКТИРОВАТЬ: Я реализовал все предложенные изменения, и теперь он работает очень хорошо. Спасибо!
Вот что я сделал:

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

Решение

Я вижу две возможные проблемы:

  1. Передача вектора в функцию в качестве значения (это эффективно копирует весь вектор)
  2. Создание новых векторов для меньших и больших элементов вместо некоторой обработки на месте

По сути, функция дважды копирует все шары в исходном векторе для каждого уровня вашего kd-дерева. Это должно вызвать серьезное замедление, поэтому старайтесь не запрашивать слишком много памяти.

Одним из способов решения этой проблемы является прямой доступ к данным вектора, использование nth_element и т. д. и передают только индексы субвекторов в рекурсивный вызов.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]